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 }