2 * sparse/check_locking.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
11 * For this test let's look for functions that return a negative value
12 * with a spinlock held.
14 * One short coming is that it assumes a function isn't supposed
15 * to return negative with a lock held. Perhaps the function was
16 * called with the lock held. A more complicated script could check that.
22 #include "smatch_slist.h" // blast this was supposed to be internal only stuff
30 * merge_func() can go away when we fix the core to just store all the possible
33 * The parameters are passed in alphabetical order with NULL at the beginning
34 * of the alphabet. (s2 is never NULL).
37 static struct smatch_state
*merge_func(const char *name
, struct symbol
*sym
,
38 struct smatch_state
*s1
,
39 struct smatch_state
*s2
)
47 static void match_call(struct expression
*expr
)
50 struct expression
*spin_expr
;
53 fn_name
= get_variable_from_expr(expr
->fn
, NULL
);
54 if (!fn_name
|| (strcmp(fn_name
, "_spin_lock") && strcmp(fn_name
, "_spin_unlock")))
57 spin_expr
= get_argument_from_call_expr(expr
->args
, 0);
58 spin_name
= get_variable_from_expr(spin_expr
, NULL
);
59 if (!strcmp(fn_name
, "_spin_lock")) {
60 set_state(spin_name
, my_id
, NULL
, &lock
);
62 set_state(spin_name
, my_id
, NULL
, &unlock
);
67 static void match_condition(struct expression
*expr
)
69 /* __raw_spin_is_locked */
72 static int possibly_negative(struct expression
*expr
)
76 struct state_list
*slist
;
79 name
= get_variable_from_expr(expr
, &sym
);
82 slist
= get_possible_states(name
, SMATCH_EXTRA
, sym
);
83 FOR_EACH_PTR(slist
, tmp
) {
87 value
= *(int *)tmp
->state
->data
;
93 } END_FOR_EACH_PTR(tmp
);
97 static void match_return(struct statement
*stmt
)
100 struct state_list
*slist
;
101 struct sm_state
*tmp
;
103 ret_val
= get_value(stmt
->ret_value
);
107 if (ret_val
== UNDEFINED
) {
108 if (!possibly_negative(stmt
->ret_value
))
112 slist
= get_all_states(my_id
);
113 FOR_EACH_PTR(slist
, tmp
) {
114 if (tmp
->state
!= &unlock
)
115 smatch_msg("returned negative with %s spinlock held",
117 } END_FOR_EACH_PTR(tmp
);
120 void register_locking(int id
)
123 add_merge_hook(my_id
, &merge_func
);
124 add_hook(&match_call
, FUNCTION_CALL_HOOK
);
125 add_hook(&match_return
, RETURN_HOOK
);