1 #include <stdio.h>
2
3 volatile unsigned long jiffies;
4 #define ULONG_MAX (~0UL)
5 #define ULONG_CMP_GE(a, b) (ULONG_MAX / 2 >= (a) - (b))
6 #define ULONG_CMP_LT(a, b) (ULONG_MAX / 2 < (a) - (b))
7
8 struct task_struct {
9 int boost_kthread_status;
10 int rcu_wake_cond_been_called;
11 };
12
13 struct task_struct t1;
14 struct task_struct t2;
15
16 struct rcu_node {
17 void *exp_tasks;
18 void *gp_tasks;
19 void *boost_tasks;
20 unsigned long qsmask;
21 unsigned long boost_time;
22 int boost_kthread_status;
23 struct task_struct *boost_kthread_task;
24 int rcu_initiate_boost_trace_been_called;
25 };
26
27 struct rcu_node rn1;
28 struct rcu_node rn2;
29
30 void rcu_wake_cond(struct task_struct *t, int bks)
31 {
32 t->rcu_wake_cond_been_called = 1;
33 t->boost_kthread_status = bks;
34 }
35
36 void rcu_initiate_boost_trace(struct rcu_node *rnp)
37 {
38 rnp->rcu_initiate_boost_trace_been_called = 1;
39 }
40
41 void initialize(char *argv[], struct task_struct *t, struct rcu_node *rnp)
42 {
43 rnp->exp_tasks = argv[0];
44 rnp->gp_tasks = argv[1];
45 rnp->boost_tasks = argv[2];
46 rnp->qsmask = (unsigned long)argv[3];
47 rnp->boost_time = (unsigned long)argv[4];
48 rnp->boost_kthread_status = (int)argv[5];
49 rnp->boost_kthread_task = t;
50 rnp->rcu_initiate_boost_trace_been_called = 0;
51 t->rcu_wake_cond_been_called = 0;
52 }
53
54 void do_old_if(char *argv[], struct task_struct *t_in, struct rcu_node *rnp)
55 {
56 struct task_struct *t;
57
58 /* --- Code under test, original. --- */
59 if (rnp->exp_tasks != NULL ||
60 (rnp->gp_tasks != NULL &&
61 rnp->boost_tasks == NULL &&
62 rnp->qsmask == 0 &&
63 ULONG_CMP_GE(jiffies, rnp->boost_time))) {
64 if (rnp->exp_tasks == NULL)
65 rnp->boost_tasks = rnp->gp_tasks;
66 /* raw_spin_unlock_irqrestore(&rnp->lock, flags); */
67 t = rnp->boost_kthread_task;
68 if (t)
69 rcu_wake_cond(t, rnp->boost_kthread_status);
70 } else {
71 rcu_initiate_boost_trace(rnp);
72 /* raw_spin_unlock_irqrestore(&rnp->lock, flags); */
73 }
74 }
75
76 void do_new_if(char *argv[], struct task_struct *t_in, struct rcu_node *rnp)
77 {
78 struct task_struct *t;
79
80 /* --- Code under test, new. --- */
81 if (rnp->exp_tasks == NULL &&
82 (rnp->gp_tasks == NULL ||
83 rnp->boost_tasks != NULL ||
84 rnp->qsmask != 0 &&
85 ULONG_CMP_LT(jiffies, rnp->boost_time))) {
86 rcu_initiate_boost_trace(rnp);
87 /* raw_spin_unlock_irqrestore(&rnp->lock, flags); */
88 } else {
89 if (rnp->exp_tasks == NULL)
90 rnp->boost_tasks = rnp->gp_tasks;
91 /* raw_spin_unlock_irqrestore(&rnp->lock, flags); */
92 t = rnp->boost_kthread_task;
93 if (t)
94 rcu_wake_cond(t, rnp->boost_kthread_status);
95 }
96 }
97
98 void check(void)
99 {
100 assert(rn1.exp_tasks == rn2.exp_tasks);
101 assert(rn1.gp_tasks == rn2.gp_tasks);
102 assert(rn1.boost_tasks == rn2.boost_tasks);
103 assert(rn1.qsmask == rn2.qsmask);
104 assert(rn1.boost_time == rn2.boost_time);
105 assert(rn1.boost_kthread_status == rn2.boost_kthread_status);
106 assert(rn1.rcu_initiate_boost_trace_been_called ==
107 rn2.rcu_initiate_boost_trace_been_called);
108 assert(t1.boost_kthread_status == t2.boost_kthread_status);
109 assert(t1.rcu_wake_cond_been_called == t2.rcu_wake_cond_been_called);
110 }
111
112 int main(int argc, char *argv[])
113 {
114 initialize(argv, &t1, &rn1);
115 initialize(argv, &t2, &rn2);
116 check();
117
118 do_old_if(argv, &t1, &rn1);
119 do_new_if(argv, &t2, &rn2);
120 check();
121 }