kernel-printf: add printf format %pra for struct range
[smatch.git] / smatch_locking_info.c
blobf45da0468756205d34605b76f061ff0d6d3bd277
1 /*
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
20 #include <ctype.h>
21 #include "parse.h"
22 #include "smatch.h"
23 #include "smatch_extra.h"
24 #include "smatch_slist.h"
26 static int my_id;
28 STATE(half_locked);
29 STATE(locked);
30 STATE(unlocked);
32 bool IRQs_disabled(void)
34 if (get_state(my_id, "irq", NULL) == &locked)
35 return true;
36 return false;
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)
52 int locked_type = 0;
54 if (sm->state == &locked)
55 locked_type = LOCK2;
56 else if (slist_has_state(sm->possible, &locked) ||
57 slist_has_state(sm->possible, &half_locked))
58 locked_type = HALF_LOCKED2;
59 else
60 return;
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)
68 struct sm_state *sm;
69 const char *name;
70 int locked_type;
72 FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) {
73 if (sm->state == &locked)
74 locked_type = LOCK2;
75 else if (sm->state == &half_locked ||
76 slist_has_state(sm->possible, &locked))
77 locked_type = HALF_LOCKED2;
78 else
79 continue;
81 if (avl_lookup(printed, sm))
82 continue;
84 if (strcmp(sm->name, "bottom_half") == 0)
85 name = "bh";
86 else if (strcmp(sm->name, "rcu_read") == 0)
87 name = "rcu_read_lock";
88 else
89 name = sm->name;
91 if (strncmp(name, "__fake_param", 12) == 0 ||
92 strchr(name, '$'))
93 continue;
95 sql_insert_caller_info(expr, locked_type, -2, name, "");
96 } END_FOR_EACH_SM(sm);
97 free_stree(&printed);
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)
112 my_id = 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?