@@ -66,8 +66,8 @@ torture_param(long, loops, 10000000, "Number of loops per experiment.");
66
66
torture_param (int , nreaders , -1 , "Number of readers, -1 for 75% of CPUs." );
67
67
// Number of runs.
68
68
torture_param (int , nruns , 30 , "Number of experiments to run." );
69
- // Reader delay in nanoseconds , 0 for no delay.
70
- torture_param (int , readdelay , 0 , "Read-side delay in nanoseconds ." );
69
+ // Reader delay in microseconds , 0 for no delay.
70
+ torture_param (int , readdelay , 0 , "Read-side delay in microseconds ." );
71
71
72
72
#ifdef MODULE
73
73
# define REFPERF_SHUTDOWN 0
@@ -111,6 +111,7 @@ struct ref_perf_ops {
111
111
void (* init )(void );
112
112
void (* cleanup )(void );
113
113
void (* readsection )(const int nloops );
114
+ void (* delaysection )(const int nloops , const int ndelay );
114
115
const char * name ;
115
116
};
116
117
@@ -126,13 +127,25 @@ static void ref_rcu_read_section(const int nloops)
126
127
}
127
128
}
128
129
130
+ static void ref_rcu_delay_section (const int nloops , const int ndelay )
131
+ {
132
+ int i ;
133
+
134
+ for (i = nloops ; i >= 0 ; i -- ) {
135
+ rcu_read_lock ();
136
+ udelay (ndelay );
137
+ rcu_read_unlock ();
138
+ }
139
+ }
140
+
129
141
static void rcu_sync_perf_init (void )
130
142
{
131
143
}
132
144
133
145
static struct ref_perf_ops rcu_ops = {
134
146
.init = rcu_sync_perf_init ,
135
147
.readsection = ref_rcu_read_section ,
148
+ .delaysection = ref_rcu_delay_section ,
136
149
.name = "rcu"
137
150
};
138
151
@@ -141,7 +154,7 @@ static struct ref_perf_ops rcu_ops = {
141
154
DEFINE_STATIC_SRCU (srcu_refctl_perf );
142
155
static struct srcu_struct * srcu_ctlp = & srcu_refctl_perf ;
143
156
144
- static void srcu_ref_perf_read_section (int nloops )
157
+ static void srcu_ref_perf_read_section (const int nloops )
145
158
{
146
159
int i ;
147
160
int idx ;
@@ -152,16 +165,29 @@ static void srcu_ref_perf_read_section(int nloops)
152
165
}
153
166
}
154
167
168
+ static void srcu_ref_perf_delay_section (const int nloops , const int ndelay )
169
+ {
170
+ int i ;
171
+ int idx ;
172
+
173
+ for (i = nloops ; i >= 0 ; i -- ) {
174
+ idx = srcu_read_lock (srcu_ctlp );
175
+ udelay (ndelay );
176
+ srcu_read_unlock (srcu_ctlp , idx );
177
+ }
178
+ }
179
+
155
180
static struct ref_perf_ops srcu_ops = {
156
181
.init = rcu_sync_perf_init ,
157
182
.readsection = srcu_ref_perf_read_section ,
183
+ .delaysection = srcu_ref_perf_delay_section ,
158
184
.name = "srcu"
159
185
};
160
186
161
187
// Definitions for reference count
162
188
static atomic_t refcnt ;
163
189
164
- static void ref_perf_refcnt_section (const int nloops )
190
+ static void ref_refcnt_section (const int nloops )
165
191
{
166
192
int i ;
167
193
@@ -171,45 +197,69 @@ static void ref_perf_refcnt_section(const int nloops)
171
197
}
172
198
}
173
199
200
+ static void ref_refcnt_delay_section (const int nloops , const int ndelay )
201
+ {
202
+ int i ;
203
+
204
+ for (i = nloops ; i >= 0 ; i -- ) {
205
+ atomic_inc (& refcnt );
206
+ udelay (ndelay );
207
+ atomic_dec (& refcnt );
208
+ }
209
+ }
210
+
174
211
static struct ref_perf_ops refcnt_ops = {
175
212
.init = rcu_sync_perf_init ,
176
- .readsection = ref_perf_refcnt_section ,
213
+ .readsection = ref_refcnt_section ,
214
+ .delaysection = ref_refcnt_delay_section ,
177
215
.name = "refcnt"
178
216
};
179
217
180
218
// Definitions for rwlock
181
219
static rwlock_t test_rwlock ;
182
220
183
- static void ref_perf_rwlock_init (void )
221
+ static void ref_rwlock_init (void )
184
222
{
185
223
rwlock_init (& test_rwlock );
186
224
}
187
225
188
- static void ref_perf_rwlock_section (const int nloops )
226
+ static void ref_rwlock_section (const int nloops )
227
+ {
228
+ int i ;
229
+
230
+ for (i = nloops ; i >= 0 ; i -- ) {
231
+ read_lock (& test_rwlock );
232
+ read_unlock (& test_rwlock );
233
+ }
234
+ }
235
+
236
+ static void ref_rwlock_delay_section (const int nloops , const int ndelay )
189
237
{
190
238
int i ;
191
239
192
240
for (i = nloops ; i >= 0 ; i -- ) {
193
241
read_lock (& test_rwlock );
242
+ udelay (ndelay );
194
243
read_unlock (& test_rwlock );
195
244
}
196
245
}
197
246
198
247
static struct ref_perf_ops rwlock_ops = {
199
- .init = ref_perf_rwlock_init ,
200
- .readsection = ref_perf_rwlock_section ,
248
+ .init = ref_rwlock_init ,
249
+ .readsection = ref_rwlock_section ,
250
+ .delaysection = ref_rwlock_delay_section ,
201
251
.name = "rwlock"
202
252
};
203
253
204
254
// Definitions for rwsem
205
255
static struct rw_semaphore test_rwsem ;
206
256
207
- static void ref_perf_rwsem_init (void )
257
+ static void ref_rwsem_init (void )
208
258
{
209
259
init_rwsem (& test_rwsem );
210
260
}
211
261
212
- static void ref_perf_rwsem_section (const int nloops )
262
+ static void ref_rwsem_section (const int nloops )
213
263
{
214
264
int i ;
215
265
@@ -219,12 +269,32 @@ static void ref_perf_rwsem_section(const int nloops)
219
269
}
220
270
}
221
271
272
+ static void ref_rwsem_delay_section (const int nloops , const int ndelay )
273
+ {
274
+ int i ;
275
+
276
+ for (i = nloops ; i >= 0 ; i -- ) {
277
+ down_read (& test_rwsem );
278
+ udelay (ndelay );
279
+ up_read (& test_rwsem );
280
+ }
281
+ }
282
+
222
283
static struct ref_perf_ops rwsem_ops = {
223
- .init = ref_perf_rwsem_init ,
224
- .readsection = ref_perf_rwsem_section ,
284
+ .init = ref_rwsem_init ,
285
+ .readsection = ref_rwsem_section ,
286
+ .delaysection = ref_rwsem_delay_section ,
225
287
.name = "rwsem"
226
288
};
227
289
290
+ static void rcu_perf_one_reader (void )
291
+ {
292
+ if (readdelay <= 0 )
293
+ cur_ops -> readsection (loops );
294
+ else
295
+ cur_ops -> delaysection (loops , readdelay );
296
+ }
297
+
228
298
// Reader kthread. Repeatedly does empty RCU read-side
229
299
// critical section, minimizing update-side interference.
230
300
static int
@@ -265,16 +335,16 @@ ref_perf_reader(void *arg)
265
335
266
336
// To reduce noise, do an initial cache-warming invocation, check
267
337
// in, and then keep warming until everyone has checked in.
268
- cur_ops -> readsection ( loops );
338
+ rcu_perf_one_reader ( );
269
339
if (!atomic_dec_return (& n_warmedup ))
270
340
while (atomic_read_acquire (& n_warmedup ))
271
- cur_ops -> readsection ( loops );
341
+ rcu_perf_one_reader ( );
272
342
// Also keep interrupts disabled. This also has the effect
273
343
// of preventing entries into slow path for rcu_read_unlock().
274
344
local_irq_save (flags );
275
345
start = ktime_get_mono_fast_ns ();
276
346
277
- cur_ops -> readsection ( loops );
347
+ rcu_perf_one_reader ( );
278
348
279
349
duration = ktime_get_mono_fast_ns () - start ;
280
350
local_irq_restore (flags );
@@ -284,7 +354,7 @@ ref_perf_reader(void *arg)
284
354
// everyone is done.
285
355
if (!atomic_dec_return (& n_cooleddown ))
286
356
while (atomic_read_acquire (& n_cooleddown ))
287
- cur_ops -> readsection ( loops );
357
+ rcu_perf_one_reader ( );
288
358
289
359
if (atomic_dec_and_test (& nreaders_exp ))
290
360
wake_up (& main_wq );
@@ -449,8 +519,8 @@ static void
449
519
ref_perf_print_module_parms (struct ref_perf_ops * cur_ops , const char * tag )
450
520
{
451
521
pr_alert ("%s" PERF_FLAG
452
- "--- %s: verbose=%d shutdown=%d holdoff=%d loops=%ld nreaders=%d nruns=%d\n" , perf_type , tag ,
453
- verbose , shutdown , holdoff , loops , nreaders , nruns );
522
+ "--- %s: verbose=%d shutdown=%d holdoff=%d loops=%ld nreaders=%d nruns=%d readdelay=%d \n" , perf_type , tag ,
523
+ verbose , shutdown , holdoff , loops , nreaders , nruns , readdelay );
454
524
}
455
525
456
526
static void
0 commit comments