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 }