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
19 #include "smatch_slist.h"
26 static unsigned long complicated
;
33 const sval_t
*implies_start
, *implies_end
;
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
))
53 set_state(my_id
, "task_state", NULL
, state
);
56 static void do_set_current_state(struct expression
*expr
)
60 if (get_implied_value(expr
, &sval
)) {
62 set_task_state(expr
, &running
);
64 set_task_state(expr
, ¬_running
);
66 set_task_state(expr
, &undefined
);
70 static void match_declaration(struct symbol
*sym
)
74 /* The set_current_state() macro is a pain in the butt */
75 if (!sym
->initializer
)
77 if (!sym
->ident
|| strcmp(sym
->ident
->name
, "__ret") != 0)
80 name
= expr_to_var(sym
->initializer
);
83 if (strcmp(name
, "state") == 0)
84 do_set_current_state(sym
->initializer
);
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
, ¬_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
, ¬_running
);
108 static void match_return_info(int return_id
, char *return_ranges
, struct expression
*expr
)
110 struct smatch_state
*state
;
115 state
= get_state(my_id
, "task_state", NULL
);
116 if (state
!= &running
&& state
!= ¬_running
)
119 sql_insert_return_states(return_id
, return_ranges
,
120 (state
== &running
) ? TASK_RUNNING
: TASK_NOT_RUNNING
,
124 void register_kernel_task_state_info(int id
)
126 struct state_param
*info
;
131 if (option_project
!= PROJ_KERNEL
)
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
);
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
);