2 * Copyright (C) 2009 Dan Carpenter.
3 * Copyright (C) 2019 Oracle.
4 * Copyright 2024 Linaro Ltd.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
23 #include "smatch_extra.h"
24 #include "smatch_slist.h"
32 bool IRQs_disabled(void)
34 if (get_state(my_id
, "irq", NULL
) == &locked
)
39 static void lock_hook(struct lock_info
*info
, struct expression
*expr
, const char *name
, struct symbol
*sym
)
41 set_state(my_id
, name
, sym
, &locked
);
44 static void unlock_hook(struct lock_info
*info
, struct expression
*expr
, const char *name
, struct symbol
*sym
)
46 set_state(my_id
, name
, sym
, &unlocked
);
49 static struct stree
*printed
;
50 static void call_info_callback(struct expression
*call
, int param
, char *printed_name
, struct sm_state
*sm
)
54 if (sm
->state
== &locked
)
56 else if (slist_has_state(sm
->possible
, &locked
) ||
57 slist_has_state(sm
->possible
, &half_locked
))
58 locked_type
= HALF_LOCKED2
;
62 avl_insert(&printed
, sm
);
63 sql_insert_caller_info(call
, locked_type
, param
, printed_name
, "");
66 static void match_call_info(struct expression
*expr
)
72 FOR_EACH_MY_SM(my_id
, __get_cur_stree(), sm
) {
73 if (sm
->state
== &locked
)
75 else if (sm
->state
== &half_locked
||
76 slist_has_state(sm
->possible
, &locked
))
77 locked_type
= HALF_LOCKED2
;
81 if (avl_lookup(printed
, sm
))
84 if (strcmp(sm
->name
, "bottom_half") == 0)
86 else if (strcmp(sm
->name
, "rcu_read") == 0)
87 name
= "rcu_read_lock";
91 if (strncmp(name
, "__fake_param", 12) == 0 ||
95 sql_insert_caller_info(expr
, locked_type
, -2, name
, "");
96 } END_FOR_EACH_SM(sm
);
100 static void set_locked(const char *name
, struct symbol
*sym
, char *value
)
102 set_state(my_id
, name
, sym
, &locked
);
105 static void set_half_locked(const char *name
, struct symbol
*sym
, char *value
)
107 set_state(my_id
, name
, sym
, &half_locked
);
110 void register_locking_info(int id
)
114 add_lock_hook(&lock_hook
);
115 add_unlock_hook(&unlock_hook
);
116 add_restore_hook(&unlock_hook
);
118 add_caller_info_callback(my_id
, call_info_callback
);
119 add_hook(&match_call_info
, FUNCTION_CALL_HOOK
);
121 select_caller_name_sym(set_locked
, LOCK2
);
122 select_caller_name_sym(set_half_locked
, HALF_LOCKED2
);
123 // check_locking.c records UNLOCKED but what is the point of that?