2 * Copyright (C) 2021 Oracle.
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_extra.h"
20 #include "smatch_slist.h"
22 static struct expr_fn_list
*hooks
;
28 unsigned long GFP_DIRECT_RECLAIM(void)
30 static unsigned long saved_flags
= -1;
31 struct symbol
*macro_sym
;
33 if (saved_flags
!= -1)
36 macro_sym
= lookup_macro_symbol("___GFP_DIRECT_RECLAIM");
37 if (!macro_sym
|| !macro_sym
->expansion
)
39 if (token_type(macro_sym
->expansion
) != TOKEN_NUMBER
)
42 saved_flags
= strtoul(macro_sym
->expansion
->number
, NULL
, 0);
46 static void do_sleep(struct expression
*expr
)
48 call_expr_fns(hooks
, expr
);
50 if (!function_decrements_preempt())
51 set_state(my_id
, "sleep", NULL
, &sleep
);
55 static void match_sleep(const char *fn
, struct expression
*expr
, void *unused
)
60 static void match_might_sleep_fn(const char *fn
, struct expression
*expr
, void *unused
)
62 struct range_list
*rl
;
65 if (!get_implied_rl_from_call_str(expr
, "$0", &rl
))
67 if (!rl_to_sval(rl
, &sval
) || sval
.value
!= 0)
73 static void match_might_sleep_macro(struct statement
*stmt
)
77 macro
= get_macro_name(stmt
->pos
);
79 strcmp(macro
, "might_sleep") != 0)
85 static void select_sleep(struct expression
*call
, struct expression
*arg
, char *key
, char *unused
)
90 static void match_gfp_t(struct expression
*expr
)
92 struct expression
*arg
;
96 param
= get_gfp_param(expr
);
99 arg
= get_argument_from_call_expr(expr
->args
, param
);
100 if (!get_implied_value(arg
, &sval
))
103 if (!(sval
.value
& GFP_DIRECT_RECLAIM()))
109 static void insert_sleep(void)
111 if (get_state(my_id
, "sleep", NULL
) != &sleep
)
113 sql_insert_return_implies(SLEEP
, -1, "", "");
116 void add_sleep_callback(expr_func
*fn
)
118 add_ptr_list(&hooks
, fn
);
121 void check_sleep_info(int id
)
125 if (option_project
!= PROJ_KERNEL
)
128 add_function_hook("schedule", &match_sleep
, NULL
);
129 add_function_hook("msleep", &match_sleep
, NULL
);
130 add_function_hook("might_resched", &match_sleep
, NULL
);
131 add_function_hook("vfree", &match_sleep
, NULL
);
132 add_function_hook("__might_sleep", &match_might_sleep_fn
, NULL
);
133 add_function_hook("___might_sleep", &match_might_sleep_fn
, NULL
);
134 add_hook(&match_might_sleep_macro
, STMT_HOOK
);
136 add_hook(&match_gfp_t
, FUNCTION_CALL_HOOK
);
138 all_return_states_hook(&insert_sleep
);
139 select_return_implies_hook_early(SLEEP
, &select_sleep
);