2 * smatch/check_readl_hotplug.c
4 * Copyright (C) 2014 Oracle.
6 * Licensed under the Open Software License version 1.1
11 #include "smatch_extra.h"
19 DECLARE_PTR_LIST(state_stack
, struct smatch_state
);
20 struct state_stack
*state_at_start
;
22 static int readl_has_been_called
;
25 static int is_readl_call(struct expression
*expr
)
29 expr
= strip_expr(expr
);
30 if (expr
->type
!= EXPR_CALL
)
32 if (expr
->fn
->type
!= EXPR_SYMBOL
)
34 sym
= expr
->fn
->symbol
;
35 if (!sym
|| !sym
->ident
)
37 if (strcmp(sym
->ident
->name
, "readl") != 0)
42 static int is_readl(struct expression
*expr
)
44 if (is_readl_call(expr
))
46 if (get_state_expr(my_id
, expr
) == &readl
)
51 static void match_assign(struct expression
*expr
)
53 if (is_readl(expr
->right
))
54 set_state_expr(my_id
, expr
->left
, &readl
);
55 else if (get_state_expr(my_id
, expr
->left
))
56 set_state_expr(my_id
, expr
->left
, &undefined
);
59 static int condition_depends_on_readl(struct expression
*expr
)
61 if (expr
->type
== EXPR_BINOP
) {
62 if (condition_depends_on_readl(expr
->left
))
64 if (condition_depends_on_readl(expr
->right
))
73 static void check_condition(struct expression
*expr
)
77 if (!condition_depends_on_readl(expr
))
79 readl_has_been_called
= 1;
80 set_true_false_states(my_id
, "depends on", NULL
, &readl_ff
, &readl_00
);
83 static void match_return(struct expression
*expr
)
90 struct smatch_state
*tmp
;
92 if (!readl_has_been_called
)
95 FOR_EACH_PTR(state_at_start
, tmp
) {
96 REPLACE_CURRENT_PTR(tmp
, NULL
);
101 static void push_state_at_start(struct smatch_state
*state
)
103 add_ptr_list(&state_at_start
, state
);
106 static struct smatch_state
*pop_state_at_start(void)
108 struct smatch_state
*state
;
110 state
= last_ptr_list((struct ptr_list
*)state_at_start
);
111 delete_ptr_list_last((struct ptr_list
**)&state_at_start
);
115 static void before_loop(struct statement
*stmt
)
117 struct smatch_state
*state
;
119 if (!stmt
|| stmt
->type
!= STMT_ITERATOR
)
121 if (ptr_list_empty(state_at_start
))
123 state
= get_state(my_id
, "depends on", NULL
);
124 push_state_at_start(state
);
127 static void after_loop(struct statement
*stmt
)
129 struct smatch_state
*old_state
;
131 if (!stmt
|| stmt
->type
!= STMT_ITERATOR
)
133 old_state
= pop_state_at_start();
134 if (old_state
== &readl_00
)
138 if (get_state(my_id
, "depends on", NULL
) != &readl_00
)
140 sm_msg("warn: this loop depends on readl() succeeding");
143 void check_readl_infinite_loops(int id
)
145 if (option_project
!= PROJ_KERNEL
)
150 add_hook(match_assign
, ASSIGNMENT_HOOK
);
151 add_hook(check_condition
, CONDITION_HOOK
);
153 add_hook(&match_return
, RETURN_HOOK
);
155 add_hook(before_loop
, STMT_HOOK
);
156 add_hook(after_loop
, STMT_HOOK_AFTER
);