@@ -22,23 +22,61 @@ static struct perf_event_attr hw_attr = {
2222
2323static rqspinlock_t lock_a ;
2424static rqspinlock_t lock_b ;
25+ static rqspinlock_t lock_c ;
26+
27+ enum rqsl_mode {
28+ RQSL_MODE_AA = 0 ,
29+ RQSL_MODE_ABBA ,
30+ RQSL_MODE_ABBCCA ,
31+ };
32+
33+ static int test_mode = RQSL_MODE_AA ;
34+ module_param (test_mode , int , 0644 );
35+ MODULE_PARM_DESC (test_mode ,
36+ "rqspinlock test mode: 0 = AA, 1 = ABBA, 2 = ABBCCA" );
2537
2638static struct perf_event * * rqsl_evts ;
2739static int rqsl_nevts ;
2840
29- static bool test_ab = false;
30- module_param (test_ab , bool , 0644 );
31- MODULE_PARM_DESC (test_ab , "Test ABBA situations instead of AA situations" );
32-
3341static struct task_struct * * rqsl_threads ;
3442static int rqsl_nthreads ;
3543static atomic_t rqsl_ready_cpus = ATOMIC_INIT (0 );
3644
3745static int pause = 0 ;
3846
39- static bool nmi_locks_a (int cpu )
47+ static const char * rqsl_mode_names [] = {
48+ [RQSL_MODE_AA ] = "AA" ,
49+ [RQSL_MODE_ABBA ] = "ABBA" ,
50+ [RQSL_MODE_ABBCCA ] = "ABBCCA" ,
51+ };
52+
53+ struct rqsl_lock_pair {
54+ rqspinlock_t * worker_lock ;
55+ rqspinlock_t * nmi_lock ;
56+ };
57+
58+ static struct rqsl_lock_pair rqsl_get_lock_pair (int cpu )
4059{
41- return (cpu & 1 ) && test_ab ;
60+ int mode = READ_ONCE (test_mode );
61+
62+ switch (mode ) {
63+ default :
64+ case RQSL_MODE_AA :
65+ return (struct rqsl_lock_pair ){ & lock_a , & lock_a };
66+ case RQSL_MODE_ABBA :
67+ if (cpu & 1 )
68+ return (struct rqsl_lock_pair ){ & lock_b , & lock_a };
69+ return (struct rqsl_lock_pair ){ & lock_a , & lock_b };
70+ case RQSL_MODE_ABBCCA :
71+ switch (cpu % 3 ) {
72+ case 0 :
73+ return (struct rqsl_lock_pair ){ & lock_a , & lock_b };
74+ case 1 :
75+ return (struct rqsl_lock_pair ){ & lock_b , & lock_c };
76+ default :
77+ return (struct rqsl_lock_pair ){ & lock_c , & lock_a };
78+ }
79+ }
4280}
4381
4482static int rqspinlock_worker_fn (void * arg )
@@ -51,19 +89,17 @@ static int rqspinlock_worker_fn(void *arg)
5189 atomic_inc (& rqsl_ready_cpus );
5290
5391 while (!kthread_should_stop ()) {
92+ struct rqsl_lock_pair locks = rqsl_get_lock_pair (cpu );
93+ rqspinlock_t * worker_lock = locks .worker_lock ;
94+
5495 if (READ_ONCE (pause )) {
5596 msleep (1000 );
5697 continue ;
5798 }
58- if (nmi_locks_a (cpu ))
59- ret = raw_res_spin_lock_irqsave (& lock_b , flags );
60- else
61- ret = raw_res_spin_lock_irqsave (& lock_a , flags );
99+ ret = raw_res_spin_lock_irqsave (worker_lock , flags );
62100 mdelay (20 );
63- if (nmi_locks_a (cpu ) && !ret )
64- raw_res_spin_unlock_irqrestore (& lock_b , flags );
65- else if (!ret )
66- raw_res_spin_unlock_irqrestore (& lock_a , flags );
101+ if (!ret )
102+ raw_res_spin_unlock_irqrestore (worker_lock , flags );
67103 cpu_relax ();
68104 }
69105 return 0 ;
@@ -91,24 +127,21 @@ static int rqspinlock_worker_fn(void *arg)
91127static void nmi_cb (struct perf_event * event , struct perf_sample_data * data ,
92128 struct pt_regs * regs )
93129{
130+ struct rqsl_lock_pair locks ;
94131 int cpu = smp_processor_id ();
95132 unsigned long flags ;
96133 int ret ;
97134
98135 if (!cpu || READ_ONCE (pause ))
99136 return ;
100137
101- if (nmi_locks_a (cpu ))
102- ret = raw_res_spin_lock_irqsave (& lock_a , flags );
103- else
104- ret = raw_res_spin_lock_irqsave (test_ab ? & lock_b : & lock_a , flags );
138+ locks = rqsl_get_lock_pair (cpu );
139+ ret = raw_res_spin_lock_irqsave (locks .nmi_lock , flags );
105140
106141 mdelay (10 );
107142
108- if (nmi_locks_a (cpu ) && !ret )
109- raw_res_spin_unlock_irqrestore (& lock_a , flags );
110- else if (!ret )
111- raw_res_spin_unlock_irqrestore (test_ab ? & lock_b : & lock_a , flags );
143+ if (!ret )
144+ raw_res_spin_unlock_irqrestore (locks .nmi_lock , flags );
112145}
113146
114147static void free_rqsl_threads (void )
@@ -142,13 +175,19 @@ static int bpf_test_rqspinlock_init(void)
142175 int i , ret ;
143176 int ncpus = num_online_cpus ();
144177
145- pr_err ("Mode = %s\n" , test_ab ? "ABBA" : "AA" );
178+ if (test_mode < RQSL_MODE_AA || test_mode > RQSL_MODE_ABBCCA ) {
179+ pr_err ("Invalid mode %d\n" , test_mode );
180+ return - EINVAL ;
181+ }
182+
183+ pr_err ("Mode = %s\n" , rqsl_mode_names [test_mode ]);
146184
147185 if (ncpus < 3 )
148186 return - ENOTSUPP ;
149187
150188 raw_res_spin_lock_init (& lock_a );
151189 raw_res_spin_lock_init (& lock_b );
190+ raw_res_spin_lock_init (& lock_c );
152191
153192 rqsl_evts = kcalloc (ncpus - 1 , sizeof (* rqsl_evts ), GFP_KERNEL );
154193 if (!rqsl_evts )
0 commit comments