implied: fix get_tf_stacks_from_pool()
[smatch.git] / smatch_kernel_task_state_info.c
blob82fc91304f2d47dec472f40e8519fa7f955be08d
1 /*
2 * Copyright 2023 Linaro Ltd.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
18 #include "smatch.h"
19 #include "smatch_slist.h"
21 static int my_id;
23 STATE(running);
24 STATE(not_running);
26 static unsigned long complicated;
28 struct state_param {
29 const char *name;
30 int type;
31 int param;
32 const char *key;
33 const sval_t *implies_start, *implies_end;
34 func_hook *call_back;
37 static struct state_param func_table[] = {
38 { "prepare_to_wait_event", 0, 2, "$", &int_zero, &int_zero},
39 { "finish_wait", TASK_RUNNING },
42 static struct string_hook_list *hooks;
43 void add_set_current_state_hook(string_hook *hook)
45 add_ptr_list(&hooks, hook);
48 void set_task_state(struct expression *expr, struct smatch_state *state)
50 call_string_hooks(hooks, expr, state->name);
51 if (get_state(my_id, "task_state", NULL))
52 complicated = true;
53 set_state(my_id, "task_state", NULL, state);
56 static void do_set_current_state(struct expression *expr)
58 sval_t sval;
60 if (get_implied_value(expr, &sval)) {
61 if (sval.value == 0)
62 set_task_state(expr, &running);
63 else
64 set_task_state(expr, &not_running);
65 } else {
66 set_task_state(expr, &undefined);
70 static void match_declaration(struct symbol *sym)
72 char *name;
74 /* The set_current_state() macro is a pain in the butt */
75 if (!sym->initializer)
76 return;
77 if (!sym->ident || strcmp(sym->ident->name, "__ret") != 0)
78 return;
80 name = expr_to_var(sym->initializer);
81 if (!name)
82 return;
83 if (strcmp(name, "state") == 0)
84 do_set_current_state(sym->initializer);
85 free_string(name);
88 static void select_task_running(struct expression *expr, int param, char *key, char *value)
90 set_task_state(expr, &running);
93 static void select_task_not_running(struct expression *expr, int param, char *key, char *value)
95 set_task_state(expr, &not_running);
98 static void match_running(const char *fn, struct expression *expr, void *_info)
100 set_task_state(expr, &running);
103 static void match_not_running(const char *fn, struct expression *expr, void *_info)
105 set_task_state(expr, &not_running);
108 static void match_return_info(int return_id, char *return_ranges, struct expression *expr)
110 struct smatch_state *state;
112 if (complicated)
113 return;
115 state = get_state(my_id, "task_state", NULL);
116 if (state != &running && state != &not_running)
117 return;
119 sql_insert_return_states(return_id, return_ranges,
120 (state == &running) ? TASK_RUNNING : TASK_NOT_RUNNING,
121 -2, "", "");
124 void register_kernel_task_state_info(int id)
126 struct state_param *info;
127 int i;
129 my_id = id;
131 if (option_project != PROJ_KERNEL)
132 return;
134 add_function_data(&complicated);
135 add_hook(&match_declaration, DECLARATION_HOOK);
137 add_split_return_callback(&match_return_info);
138 select_return_states_hook(TASK_RUNNING, &select_task_running);
139 select_return_states_hook(TASK_NOT_RUNNING, &select_task_not_running);
141 for (i = 0; i < ARRAY_SIZE(func_table); i++) {
142 info = &func_table[i];
143 if (info->type == TASK_RUNNING)
144 add_function_hook(info->name, &match_running, info);
145 else if (info->type == TASK_NOT_RUNNING)
146 add_function_hook(info->name, &match_not_running, info);
147 else
148 return_implies_param_key_expr(info->name,
149 *info->implies_start, *info->implies_end,
150 &do_set_current_state,
151 info->param, info->key, info);