@@ -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