2 * This file is part of the SPL: Solaris Porting Layer.
4 * Copyright (c) 2008 Lawrence Livermore National Security, LLC.
5 * Produced at Lawrence Livermore National Laboratory
7 * Brian Behlendorf <behlendorf1@llnl.gov>,
8 * Herb Wartens <wartens2@llnl.gov>,
9 * Jim Garlick <garlick@llnl.gov>
12 * This is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "splat-internal.h"
29 #define SPLAT_RWLOCK_NAME "rwlock"
30 #define SPLAT_RWLOCK_DESC "Kernel RW Lock Tests"
32 #define SPLAT_RWLOCK_TEST1_ID 0x0701
33 #define SPLAT_RWLOCK_TEST1_NAME "N-rd/1-wr"
34 #define SPLAT_RWLOCK_TEST1_DESC "Multiple readers one writer"
36 #define SPLAT_RWLOCK_TEST2_ID 0x0702
37 #define SPLAT_RWLOCK_TEST2_NAME "0-rd/N-wr"
38 #define SPLAT_RWLOCK_TEST2_DESC "Multiple writers"
40 #define SPLAT_RWLOCK_TEST3_ID 0x0703
41 #define SPLAT_RWLOCK_TEST3_NAME "held"
42 #define SPLAT_RWLOCK_TEST3_DESC "RW_{LOCK|READ|WRITE}_HELD"
44 #define SPLAT_RWLOCK_TEST4_ID 0x0704
45 #define SPLAT_RWLOCK_TEST4_NAME "tryenter"
46 #define SPLAT_RWLOCK_TEST4_DESC "Tryenter"
48 #define SPLAT_RWLOCK_TEST5_ID 0x0705
49 #define SPLAT_RWLOCK_TEST5_NAME "rw_downgrade"
50 #define SPLAT_RWLOCK_TEST5_DESC "Write downgrade"
52 #define SPLAT_RWLOCK_TEST6_ID 0x0706
53 #define SPLAT_RWLOCK_TEST6_NAME "rw_tryupgrade"
54 #define SPLAT_RWLOCK_TEST6_DESC "Read upgrade"
56 #define SPLAT_RWLOCK_TEST_MAGIC 0x115599DDUL
57 #define SPLAT_RWLOCK_TEST_NAME "rwlock_test"
58 #define SPLAT_RWLOCK_TEST_TASKQ "rwlock_taskq"
59 #define SPLAT_RWLOCK_TEST_COUNT 8
61 #define SPLAT_RWLOCK_RELEASE_INIT 0
62 #define SPLAT_RWLOCK_RELEASE_WR 1
63 #define SPLAT_RWLOCK_RELEASE_RD 2
65 typedef struct rw_priv
{
66 unsigned long rw_magic
;
70 wait_queue_head_t rw_waitq
;
79 typedef struct rw_thr
{
85 void splat_init_rw_priv(rw_priv_t
*rwp
, struct file
*file
)
87 rwp
->rw_magic
= SPLAT_RWLOCK_TEST_MAGIC
;
89 rw_init(&rwp
->rw_rwlock
, SPLAT_RWLOCK_TEST_NAME
, RW_DEFAULT
, NULL
);
90 spin_lock_init(&rwp
->rw_lock
);
91 init_waitqueue_head(&rwp
->rw_waitq
);
92 rwp
->rw_completed
= 0;
95 rwp
->rw_release
= SPLAT_RWLOCK_RELEASE_INIT
;
101 splat_rwlock_wr_thr(void *arg
)
103 rw_thr_t
*rwt
= (rw_thr_t
*)arg
;
104 rw_priv_t
*rwp
= rwt
->rwt_rwp
;
108 ASSERT(rwp
->rw_magic
== SPLAT_RWLOCK_TEST_MAGIC
);
109 snprintf(name
, sizeof(name
), "rwlock_wr_thr%d", rwt
->rwt_id
);
111 get_random_bytes((void *)&rnd
, 1);
112 msleep((unsigned int)rnd
);
114 splat_vprint(rwp
->rw_file
, rwt
->rwt_name
,
115 "%s trying to acquire rwlock (%d holding/%d waiting)\n",
116 name
, rwp
->rw_holders
, rwp
->rw_waiters
);
117 spin_lock(&rwp
->rw_lock
);
119 spin_unlock(&rwp
->rw_lock
);
120 rw_enter(&rwp
->rw_rwlock
, RW_WRITER
);
122 spin_lock(&rwp
->rw_lock
);
125 spin_unlock(&rwp
->rw_lock
);
126 splat_vprint(rwp
->rw_file
, rwt
->rwt_name
,
127 "%s acquired rwlock (%d holding/%d waiting)\n",
128 name
, rwp
->rw_holders
, rwp
->rw_waiters
);
130 /* Wait for control thread to signal we can release the write lock */
131 wait_event_interruptible(rwp
->rw_waitq
, splat_locked_test(&rwp
->rw_lock
,
132 rwp
->rw_release
== SPLAT_RWLOCK_RELEASE_WR
));
134 spin_lock(&rwp
->rw_lock
);
137 spin_unlock(&rwp
->rw_lock
);
138 splat_vprint(rwp
->rw_file
, rwt
->rwt_name
,
139 "%s dropped rwlock (%d holding/%d waiting)\n",
140 name
, rwp
->rw_holders
, rwp
->rw_waiters
);
142 rw_exit(&rwp
->rw_rwlock
);
148 splat_rwlock_rd_thr(void *arg
)
150 rw_thr_t
*rwt
= (rw_thr_t
*)arg
;
151 rw_priv_t
*rwp
= rwt
->rwt_rwp
;
155 ASSERT(rwp
->rw_magic
== SPLAT_RWLOCK_TEST_MAGIC
);
156 snprintf(name
, sizeof(name
), "rwlock_rd_thr%d", rwt
->rwt_id
);
158 get_random_bytes((void *)&rnd
, 1);
159 msleep((unsigned int)rnd
);
161 /* Don't try and take the semaphore until after someone has it */
162 wait_event_interruptible(rwp
->rw_waitq
, splat_locked_test(&rwp
->rw_lock
,
163 rwp
->rw_holders
> 0));
165 splat_vprint(rwp
->rw_file
, rwt
->rwt_name
,
166 "%s trying to acquire rwlock (%d holding/%d waiting)\n",
167 name
, rwp
->rw_holders
, rwp
->rw_waiters
);
168 spin_lock(&rwp
->rw_lock
);
170 spin_unlock(&rwp
->rw_lock
);
171 rw_enter(&rwp
->rw_rwlock
, RW_READER
);
173 spin_lock(&rwp
->rw_lock
);
176 spin_unlock(&rwp
->rw_lock
);
177 splat_vprint(rwp
->rw_file
, rwt
->rwt_name
,
178 "%s acquired rwlock (%d holding/%d waiting)\n",
179 name
, rwp
->rw_holders
, rwp
->rw_waiters
);
181 /* Wait for control thread to signal we can release the read lock */
182 wait_event_interruptible(rwp
->rw_waitq
, splat_locked_test(&rwp
->rw_lock
,
183 rwp
->rw_release
== SPLAT_RWLOCK_RELEASE_RD
));
185 spin_lock(&rwp
->rw_lock
);
188 spin_unlock(&rwp
->rw_lock
);
189 splat_vprint(rwp
->rw_file
, rwt
->rwt_name
,
190 "%s dropped rwlock (%d holding/%d waiting)\n",
191 name
, rwp
->rw_holders
, rwp
->rw_waiters
);
193 rw_exit(&rwp
->rw_rwlock
);
199 splat_rwlock_test1(struct file
*file
, void *arg
)
201 int i
, count
= 0, rc
= 0;
202 long pids
[SPLAT_RWLOCK_TEST_COUNT
];
203 rw_thr_t rwt
[SPLAT_RWLOCK_TEST_COUNT
];
206 rwp
= (rw_priv_t
*)kmalloc(sizeof(*rwp
), GFP_KERNEL
);
210 splat_init_rw_priv(rwp
, file
);
212 /* Create some threads, the exact number isn't important just as
213 * long as we know how many we managed to create and should expect. */
217 for (i
= 0; i
< SPLAT_RWLOCK_TEST_COUNT
; i
++) {
218 rwt
[i
].rwt_rwp
= rwp
;
220 rwt
[i
].rwt_name
= SPLAT_RWLOCK_TEST1_NAME
;
222 /* The first thread will be the writer */
224 pids
[i
] = kernel_thread(splat_rwlock_wr_thr
, &rwt
[i
], 0);
226 pids
[i
] = kernel_thread(splat_rwlock_rd_thr
, &rwt
[i
], 0);
232 /* Wait for the writer */
233 while (splat_locked_test(&rwp
->rw_lock
, rwp
->rw_holders
== 0)) {
234 wake_up_interruptible(&rwp
->rw_waitq
);
238 /* Wait for 'count-1' readers */
239 while (splat_locked_test(&rwp
->rw_lock
, rwp
->rw_waiters
< count
- 1)) {
240 wake_up_interruptible(&rwp
->rw_waitq
);
244 /* Verify there is only one lock holder */
245 if (splat_locked_test(&rwp
->rw_lock
, rwp
->rw_holders
) != 1) {
246 splat_vprint(file
, SPLAT_RWLOCK_TEST1_NAME
, "Only 1 holder "
247 "expected for rwlock (%d holding/%d waiting)\n",
248 rwp
->rw_holders
, rwp
->rw_waiters
);
252 /* Verify 'count-1' readers */
253 if (splat_locked_test(&rwp
->rw_lock
, rwp
->rw_waiters
!= count
- 1)) {
254 splat_vprint(file
, SPLAT_RWLOCK_TEST1_NAME
, "Only %d waiters "
255 "expected for rwlock (%d holding/%d waiting)\n",
256 count
- 1, rwp
->rw_holders
, rwp
->rw_waiters
);
260 /* Signal the writer to release, allows readers to acquire */
261 spin_lock(&rwp
->rw_lock
);
262 rwp
->rw_release
= SPLAT_RWLOCK_RELEASE_WR
;
263 wake_up_interruptible(&rwp
->rw_waitq
);
264 spin_unlock(&rwp
->rw_lock
);
266 /* Wait for 'count-1' readers to hold the lock */
267 while (splat_locked_test(&rwp
->rw_lock
, rwp
->rw_holders
< count
- 1)) {
268 wake_up_interruptible(&rwp
->rw_waitq
);
272 /* Verify there are 'count-1' readers */
273 if (splat_locked_test(&rwp
->rw_lock
, rwp
->rw_holders
!= count
- 1)) {
274 splat_vprint(file
, SPLAT_RWLOCK_TEST1_NAME
, "Only %d holders "
275 "expected for rwlock (%d holding/%d waiting)\n",
276 count
- 1, rwp
->rw_holders
, rwp
->rw_waiters
);
280 /* Release 'count-1' readers */
281 spin_lock(&rwp
->rw_lock
);
282 rwp
->rw_release
= SPLAT_RWLOCK_RELEASE_RD
;
283 wake_up_interruptible(&rwp
->rw_waitq
);
284 spin_unlock(&rwp
->rw_lock
);
286 /* Wait for the test to complete */
287 while (splat_locked_test(&rwp
->rw_lock
,
288 rwp
->rw_holders
>0 || rwp
->rw_waiters
>0))
291 rw_destroy(&(rwp
->rw_rwlock
));
298 splat_rwlock_test2_func(void *arg
)
300 rw_priv_t
*rwp
= (rw_priv_t
*)arg
;
302 ASSERT(rwp
->rw_magic
== SPLAT_RWLOCK_TEST_MAGIC
);
304 /* Read the value before sleeping and write it after we wake up to
305 * maximize the chance of a race if rwlocks are not working properly */
306 rw_enter(&rwp
->rw_rwlock
, RW_WRITER
);
308 set_current_state(TASK_INTERRUPTIBLE
);
309 schedule_timeout(HZ
/ 100); /* 1/100 of a second */
310 VERIFY(rwp
->rw_rc
== rc
);
312 rw_exit(&rwp
->rw_rwlock
);
316 splat_rwlock_test2(struct file
*file
, void *arg
)
320 int i
, rc
= 0, tq_count
= 256;
322 rwp
= (rw_priv_t
*)kmalloc(sizeof(*rwp
), GFP_KERNEL
);
326 splat_init_rw_priv(rwp
, file
);
328 /* Create several threads allowing tasks to race with each other */
329 tq
= taskq_create(SPLAT_RWLOCK_TEST_TASKQ
, num_online_cpus(),
330 maxclsyspri
, 50, INT_MAX
, TASKQ_PREPOPULATE
);
337 * Schedule N work items to the work queue each of which enters the
338 * writer rwlock, sleeps briefly, then exits the writer rwlock. On a
339 * multiprocessor box these work items will be handled by all available
340 * CPUs. The task function checks to ensure the tracked shared variable
341 * is always only incremented by one. Additionally, the rwlock itself
342 * is instrumented such that if any two processors are in the
343 * critical region at the same time the system will panic. If the
344 * rwlock is implemented right this will never happy, that's a pass.
346 for (i
= 0; i
< tq_count
; i
++) {
347 if (!taskq_dispatch(tq
,splat_rwlock_test2_func
,rwp
,TQ_SLEEP
)) {
348 splat_vprint(file
, SPLAT_RWLOCK_TEST2_NAME
,
349 "Failed to queue task %d\n", i
);
356 if (rwp
->rw_rc
== tq_count
) {
357 splat_vprint(file
, SPLAT_RWLOCK_TEST2_NAME
, "%d racing threads "
358 "correctly entered/exited the rwlock %d times\n",
359 num_online_cpus(), rwp
->rw_rc
);
361 splat_vprint(file
, SPLAT_RWLOCK_TEST2_NAME
, "%d racing threads "
362 "only processed %d/%d w rwlock work items\n",
363 num_online_cpus(), rwp
->rw_rc
, tq_count
);
368 rw_destroy(&(rwp
->rw_rwlock
));
374 #define splat_rwlock_test3_helper(rwp,rex1,rex2,wex1,wex2,held_func,rc) \
376 int result, _rc1_, _rc2_, _rc3_, _rc4_; \
379 rw_enter(&(rwp)->rw_rwlock, RW_READER); \
380 _rc1_ = ((result = held_func(&(rwp)->rw_rwlock)) != rex1); \
381 splat_vprint(file, SPLAT_RWLOCK_TEST3_NAME, "%s" #held_func \
382 " returned %d (expected %d) when RW_READER\n", \
383 _rc1_ ? "Fail " : "", result, rex1); \
384 rw_exit(&(rwp)->rw_rwlock); \
385 _rc2_ = ((result = held_func(&(rwp)->rw_rwlock)) != rex2); \
386 splat_vprint(file, SPLAT_RWLOCK_TEST3_NAME, "%s" #held_func \
387 " returned %d (expected %d) when !RW_READER\n", \
388 _rc2_ ? "Fail " : "", result, rex2); \
390 rw_enter(&(rwp)->rw_rwlock, RW_WRITER); \
391 _rc3_ = ((result = held_func(&(rwp)->rw_rwlock)) != wex1); \
392 splat_vprint(file, SPLAT_RWLOCK_TEST3_NAME, "%s" #held_func \
393 " returned %d (expected %d) when RW_WRITER\n", \
394 _rc3_ ? "Fail " : "", result, wex1); \
395 rw_exit(&(rwp)->rw_rwlock); \
396 _rc4_ = ((result = held_func(&(rwp)->rw_rwlock)) != wex2); \
397 splat_vprint(file, SPLAT_RWLOCK_TEST3_NAME, "%s" #held_func \
398 " returned %d (expected %d) when !RW_WRITER\n", \
399 _rc4_ ? "Fail " : "", result, wex2); \
401 rc = ((_rc1_ || _rc2_ || _rc3_ || _rc4_) ? -EINVAL : 0); \
405 splat_rwlock_test3(struct file
*file
, void *arg
)
410 rwp
= (rw_priv_t
*)kmalloc(sizeof(*rwp
), GFP_KERNEL
);
414 splat_init_rw_priv(rwp
, file
);
416 splat_rwlock_test3_helper(rwp
, 1, 0, 1, 0, RW_LOCK_HELD
, rc1
);
417 splat_rwlock_test3_helper(rwp
, 1, 0, 0, 0, RW_READ_HELD
, rc2
);
418 splat_rwlock_test3_helper(rwp
, 0, 0, 1, 0, RW_WRITE_HELD
, rc3
);
420 rw_destroy(&rwp
->rw_rwlock
);
423 return ((rc1
|| rc2
|| rc3
) ? -EINVAL
: 0);
427 splat_rwlock_test4_func(void *arg
)
429 rw_priv_t
*rwp
= (rw_priv_t
*)arg
;
430 ASSERT(rwp
->rw_magic
== SPLAT_RWLOCK_TEST_MAGIC
);
432 if (rw_tryenter(&rwp
->rw_rwlock
, rwp
->rw_type
)) {
434 rw_exit(&rwp
->rw_rwlock
);
441 splat_rwlock_test4_name(krw_t type
)
444 case RW_NONE
: return "RW_NONE";
445 case RW_WRITER
: return "RW_WRITER";
446 case RW_READER
: return "RW_READER";
453 splat_rwlock_test4_type(taskq_t
*tq
, rw_priv_t
*rwp
, int expected_rc
,
454 krw_t holder_type
, krw_t try_type
)
458 /* Schedule a task function which will try and acquire the rwlock
459 * using type try_type while the rwlock is being held as holder_type.
460 * The result must match expected_rc for the test to pass */
461 rwp
->rw_rc
= -EINVAL
;
462 rwp
->rw_type
= try_type
;
464 if (holder_type
== RW_WRITER
|| holder_type
== RW_READER
)
465 rw_enter(&rwp
->rw_rwlock
, holder_type
);
467 id
= taskq_dispatch(tq
, splat_rwlock_test4_func
, rwp
, TQ_SLEEP
);
469 splat_vprint(rwp
->rw_file
, SPLAT_RWLOCK_TEST4_NAME
, "%s",
470 "taskq_dispatch() failed\n");
475 taskq_wait_id(tq
, id
);
477 if (rwp
->rw_rc
!= expected_rc
)
480 splat_vprint(rwp
->rw_file
, SPLAT_RWLOCK_TEST4_NAME
,
481 "%srw_tryenter(%s) returned %d (expected %d) when %s\n",
482 rc
? "Fail " : "", splat_rwlock_test4_name(try_type
),
483 rwp
->rw_rc
, expected_rc
,
484 splat_rwlock_test4_name(holder_type
));
486 if (holder_type
== RW_WRITER
|| holder_type
== RW_READER
)
487 rw_exit(&rwp
->rw_rwlock
);
493 splat_rwlock_test4(struct file
*file
, void *arg
)
497 int rc
= 0, rc1
, rc2
, rc3
, rc4
, rc5
, rc6
;
499 rwp
= (rw_priv_t
*)kmalloc(sizeof(*rwp
), GFP_KERNEL
);
503 tq
= taskq_create(SPLAT_RWLOCK_TEST_TASKQ
, 1, maxclsyspri
,
504 50, INT_MAX
, TASKQ_PREPOPULATE
);
510 splat_init_rw_priv(rwp
, file
);
512 /* Validate all combinations of rw_tryenter() contention */
513 rc1
= splat_rwlock_test4_type(tq
, rwp
, -EBUSY
, RW_WRITER
, RW_WRITER
);
514 rc2
= splat_rwlock_test4_type(tq
, rwp
, -EBUSY
, RW_WRITER
, RW_READER
);
515 rc3
= splat_rwlock_test4_type(tq
, rwp
, -EBUSY
, RW_READER
, RW_WRITER
);
516 rc4
= splat_rwlock_test4_type(tq
, rwp
, 0, RW_READER
, RW_READER
);
517 rc5
= splat_rwlock_test4_type(tq
, rwp
, 0, RW_NONE
, RW_WRITER
);
518 rc6
= splat_rwlock_test4_type(tq
, rwp
, 0, RW_NONE
, RW_READER
);
520 if (rc1
|| rc2
|| rc3
|| rc4
|| rc5
|| rc6
)
525 rw_destroy(&(rwp
->rw_rwlock
));
532 splat_rwlock_test5(struct file
*file
, void *arg
)
537 rwp
= (rw_priv_t
*)kmalloc(sizeof(*rwp
), GFP_KERNEL
);
541 splat_init_rw_priv(rwp
, file
);
543 rw_enter(&rwp
->rw_rwlock
, RW_WRITER
);
544 if (!RW_WRITE_HELD(&rwp
->rw_rwlock
)) {
545 splat_vprint(file
, SPLAT_RWLOCK_TEST5_NAME
,
546 "rwlock should be write lock: %d\n",
547 RW_WRITE_HELD(&rwp
->rw_rwlock
));
551 rw_downgrade(&rwp
->rw_rwlock
);
552 if (!RW_READ_HELD(&rwp
->rw_rwlock
)) {
553 splat_vprint(file
, SPLAT_RWLOCK_TEST5_NAME
,
554 "rwlock should be read lock: %d\n",
555 RW_READ_HELD(&rwp
->rw_rwlock
));
560 splat_vprint(file
, SPLAT_RWLOCK_TEST5_NAME
, "%s",
561 "rwlock properly downgraded\n");
563 rw_exit(&rwp
->rw_rwlock
);
564 rw_destroy(&rwp
->rw_rwlock
);
571 splat_rwlock_test6(struct file
*file
, void *arg
)
576 rwp
= (rw_priv_t
*)kmalloc(sizeof(*rwp
), GFP_KERNEL
);
580 splat_init_rw_priv(rwp
, file
);
582 rw_enter(&rwp
->rw_rwlock
, RW_READER
);
583 if (!RW_READ_HELD(&rwp
->rw_rwlock
)) {
584 splat_vprint(file
, SPLAT_RWLOCK_TEST6_NAME
,
585 "rwlock should be read lock: %d\n",
586 RW_READ_HELD(&rwp
->rw_rwlock
));
590 /* With one reader upgrade should never fail */
591 rc
= rw_tryupgrade(&rwp
->rw_rwlock
);
593 splat_vprint(file
, SPLAT_RWLOCK_TEST6_NAME
,
594 "rwlock contended preventing upgrade: %d\n",
595 RW_COUNT(&rwp
->rw_rwlock
));
599 if (RW_READ_HELD(&rwp
->rw_rwlock
) || !RW_WRITE_HELD(&rwp
->rw_rwlock
)) {
600 splat_vprint(file
, SPLAT_RWLOCK_TEST6_NAME
, "rwlock should "
601 "have 0 (not %d) reader and 1 (not %d) writer\n",
602 RW_READ_HELD(&rwp
->rw_rwlock
),
603 RW_WRITE_HELD(&rwp
->rw_rwlock
));
608 splat_vprint(file
, SPLAT_RWLOCK_TEST6_NAME
, "%s",
609 "rwlock properly upgraded\n");
611 rw_exit(&rwp
->rw_rwlock
);
612 rw_destroy(&rwp
->rw_rwlock
);
619 splat_rwlock_init(void)
621 splat_subsystem_t
*sub
;
623 sub
= kmalloc(sizeof(*sub
), GFP_KERNEL
);
627 memset(sub
, 0, sizeof(*sub
));
628 strncpy(sub
->desc
.name
, SPLAT_RWLOCK_NAME
, SPLAT_NAME_SIZE
);
629 strncpy(sub
->desc
.desc
, SPLAT_RWLOCK_DESC
, SPLAT_DESC_SIZE
);
630 INIT_LIST_HEAD(&sub
->subsystem_list
);
631 INIT_LIST_HEAD(&sub
->test_list
);
632 spin_lock_init(&sub
->test_lock
);
633 sub
->desc
.id
= SPLAT_SUBSYSTEM_RWLOCK
;
635 SPLAT_TEST_INIT(sub
, SPLAT_RWLOCK_TEST1_NAME
, SPLAT_RWLOCK_TEST1_DESC
,
636 SPLAT_RWLOCK_TEST1_ID
, splat_rwlock_test1
);
637 SPLAT_TEST_INIT(sub
, SPLAT_RWLOCK_TEST2_NAME
, SPLAT_RWLOCK_TEST2_DESC
,
638 SPLAT_RWLOCK_TEST2_ID
, splat_rwlock_test2
);
639 SPLAT_TEST_INIT(sub
, SPLAT_RWLOCK_TEST3_NAME
, SPLAT_RWLOCK_TEST3_DESC
,
640 SPLAT_RWLOCK_TEST3_ID
, splat_rwlock_test3
);
641 SPLAT_TEST_INIT(sub
, SPLAT_RWLOCK_TEST4_NAME
, SPLAT_RWLOCK_TEST4_DESC
,
642 SPLAT_RWLOCK_TEST4_ID
, splat_rwlock_test4
);
643 SPLAT_TEST_INIT(sub
, SPLAT_RWLOCK_TEST5_NAME
, SPLAT_RWLOCK_TEST5_DESC
,
644 SPLAT_RWLOCK_TEST5_ID
, splat_rwlock_test5
);
645 SPLAT_TEST_INIT(sub
, SPLAT_RWLOCK_TEST6_NAME
, SPLAT_RWLOCK_TEST6_DESC
,
646 SPLAT_RWLOCK_TEST6_ID
, splat_rwlock_test6
);
652 splat_rwlock_fini(splat_subsystem_t
*sub
)
655 SPLAT_TEST_FINI(sub
, SPLAT_RWLOCK_TEST6_ID
);
656 SPLAT_TEST_FINI(sub
, SPLAT_RWLOCK_TEST5_ID
);
657 SPLAT_TEST_FINI(sub
, SPLAT_RWLOCK_TEST4_ID
);
658 SPLAT_TEST_FINI(sub
, SPLAT_RWLOCK_TEST3_ID
);
659 SPLAT_TEST_FINI(sub
, SPLAT_RWLOCK_TEST2_ID
);
660 SPLAT_TEST_FINI(sub
, SPLAT_RWLOCK_TEST1_ID
);
665 splat_rwlock_id(void) {
666 return SPLAT_SUBSYSTEM_RWLOCK
;