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