1 /*****************************************************************************\
2 * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
3 * Copyright (C) 2007 The Regents of the University of California.
4 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
5 * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
8 * This file is part of the SPL, Solaris Porting Layer.
9 * For details, see <http://zfsonlinux.org/>.
11 * The SPL is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
16 * The SPL is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * You should have received a copy of the GNU General Public License along
22 * with the SPL. If not, see <http://www.gnu.org/licenses/>.
23 *****************************************************************************
24 * Solaris Porting LAyer Tests (SPLAT) Read/Writer Lock Tests.
25 \*****************************************************************************/
27 #include <sys/random.h>
28 #include <sys/rwlock.h>
29 #include <sys/taskq.h>
30 #include <linux/delay.h>
31 #include <linux/mm_compat.h>
32 #include "splat-internal.h"
34 #define SPLAT_RWLOCK_NAME "rwlock"
35 #define SPLAT_RWLOCK_DESC "Kernel RW Lock Tests"
37 #define SPLAT_RWLOCK_TEST1_ID 0x0701
38 #define SPLAT_RWLOCK_TEST1_NAME "N-rd/1-wr"
39 #define SPLAT_RWLOCK_TEST1_DESC "Multiple readers one writer"
41 #define SPLAT_RWLOCK_TEST2_ID 0x0702
42 #define SPLAT_RWLOCK_TEST2_NAME "0-rd/N-wr"
43 #define SPLAT_RWLOCK_TEST2_DESC "Multiple writers"
45 #define SPLAT_RWLOCK_TEST3_ID 0x0703
46 #define SPLAT_RWLOCK_TEST3_NAME "held"
47 #define SPLAT_RWLOCK_TEST3_DESC "RW_{LOCK|READ|WRITE}_HELD"
49 #define SPLAT_RWLOCK_TEST4_ID 0x0704
50 #define SPLAT_RWLOCK_TEST4_NAME "tryenter"
51 #define SPLAT_RWLOCK_TEST4_DESC "Tryenter"
53 #define SPLAT_RWLOCK_TEST5_ID 0x0705
54 #define SPLAT_RWLOCK_TEST5_NAME "rw_downgrade"
55 #define SPLAT_RWLOCK_TEST5_DESC "Write downgrade"
57 #define SPLAT_RWLOCK_TEST6_ID 0x0706
58 #define SPLAT_RWLOCK_TEST6_NAME "rw_tryupgrade-1"
59 #define SPLAT_RWLOCK_TEST6_DESC "rwsem->count value"
61 #define SPLAT_RWLOCK_TEST7_ID 0x0707
62 #define SPLAT_RWLOCK_TEST7_NAME "rw_tryupgrade-2"
63 #define SPLAT_RWLOCK_TEST7_DESC "Read upgrade"
65 #define SPLAT_RWLOCK_TEST_MAGIC 0x115599DDUL
66 #define SPLAT_RWLOCK_TEST_NAME "rwlock_test"
67 #define SPLAT_RWLOCK_TEST_TASKQ "rwlock_taskq"
68 #define SPLAT_RWLOCK_TEST_COUNT 8
70 #define SPLAT_RWLOCK_RELEASE_INIT 0
71 #define SPLAT_RWLOCK_RELEASE_WR 1
72 #define SPLAT_RWLOCK_RELEASE_RD 2
74 typedef struct rw_priv {
75 unsigned long rw_magic;
79 wait_queue_head_t rw_waitq;
88 typedef struct rw_thr {
91 struct task_struct *rwt_thread;
94 void splat_init_rw_priv(rw_priv_t *rwp, struct file *file)
96 rwp->rw_magic = SPLAT_RWLOCK_TEST_MAGIC;
98 rw_init(&rwp->rw_rwlock, SPLAT_RWLOCK_TEST_NAME, RW_DEFAULT, NULL);
99 spin_lock_init(&rwp->rw_lock);
100 init_waitqueue_head(&rwp->rw_waitq);
101 rwp->rw_completed = 0;
104 rwp->rw_release = SPLAT_RWLOCK_RELEASE_INIT;
110 splat_rwlock_wr_thr(void *arg)
112 rw_thr_t *rwt = (rw_thr_t *)arg;
113 rw_priv_t *rwp = rwt->rwt_rwp;
116 ASSERT(rwp->rw_magic == SPLAT_RWLOCK_TEST_MAGIC);
118 get_random_bytes((void *)&rnd, 1);
119 msleep((unsigned int)rnd);
121 splat_vprint(rwp->rw_file, rwt->rwt_name,
122 "%s trying to acquire rwlock (%d holding/%d waiting)\n",
123 rwt->rwt_thread->comm, rwp->rw_holders, rwp->rw_waiters);
124 spin_lock(&rwp->rw_lock);
126 spin_unlock(&rwp->rw_lock);
127 rw_enter(&rwp->rw_rwlock, RW_WRITER);
129 spin_lock(&rwp->rw_lock);
132 spin_unlock(&rwp->rw_lock);
133 splat_vprint(rwp->rw_file, rwt->rwt_name,
134 "%s acquired rwlock (%d holding/%d waiting)\n",
135 rwt->rwt_thread->comm, rwp->rw_holders, rwp->rw_waiters);
137 /* Wait for control thread to signal we can release the write lock */
138 wait_event_interruptible(rwp->rw_waitq, splat_locked_test(&rwp->rw_lock,
139 rwp->rw_release == SPLAT_RWLOCK_RELEASE_WR));
141 spin_lock(&rwp->rw_lock);
144 spin_unlock(&rwp->rw_lock);
145 splat_vprint(rwp->rw_file, rwt->rwt_name,
146 "%s dropped rwlock (%d holding/%d waiting)\n",
147 rwt->rwt_thread->comm, rwp->rw_holders, rwp->rw_waiters);
149 rw_exit(&rwp->rw_rwlock);
155 splat_rwlock_rd_thr(void *arg)
157 rw_thr_t *rwt = (rw_thr_t *)arg;
158 rw_priv_t *rwp = rwt->rwt_rwp;
161 ASSERT(rwp->rw_magic == SPLAT_RWLOCK_TEST_MAGIC);
163 get_random_bytes((void *)&rnd, 1);
164 msleep((unsigned int)rnd);
166 /* Don't try and take the semaphore until after someone has it */
167 wait_event_interruptible(rwp->rw_waitq,
168 splat_locked_test(&rwp->rw_lock, rwp->rw_holders > 0));
170 splat_vprint(rwp->rw_file, rwt->rwt_name,
171 "%s trying to acquire rwlock (%d holding/%d waiting)\n",
172 rwt->rwt_thread->comm, rwp->rw_holders, rwp->rw_waiters);
173 spin_lock(&rwp->rw_lock);
175 spin_unlock(&rwp->rw_lock);
176 rw_enter(&rwp->rw_rwlock, RW_READER);
178 spin_lock(&rwp->rw_lock);
181 spin_unlock(&rwp->rw_lock);
182 splat_vprint(rwp->rw_file, rwt->rwt_name,
183 "%s acquired rwlock (%d holding/%d waiting)\n",
184 rwt->rwt_thread->comm, rwp->rw_holders, rwp->rw_waiters);
186 /* Wait for control thread to signal we can release the read lock */
187 wait_event_interruptible(rwp->rw_waitq, splat_locked_test(&rwp->rw_lock,
188 rwp->rw_release == SPLAT_RWLOCK_RELEASE_RD));
190 spin_lock(&rwp->rw_lock);
193 spin_unlock(&rwp->rw_lock);
194 splat_vprint(rwp->rw_file, rwt->rwt_name,
195 "%s dropped rwlock (%d holding/%d waiting)\n",
196 rwt->rwt_thread->comm, rwp->rw_holders, rwp->rw_waiters);
198 rw_exit(&rwp->rw_rwlock);
204 splat_rwlock_test1(struct file *file, void *arg)
206 int i, count = 0, rc = 0;
207 rw_thr_t rwt[SPLAT_RWLOCK_TEST_COUNT];
210 rwp = (rw_priv_t *)kmalloc(sizeof(*rwp), GFP_KERNEL);
214 splat_init_rw_priv(rwp, file);
216 /* Create some threads, the exact number isn't important just as
217 * long as we know how many we managed to create and should expect. */
218 for (i = 0; i < SPLAT_RWLOCK_TEST_COUNT; i++) {
219 rwt[i].rwt_rwp = rwp;
220 rwt[i].rwt_name = SPLAT_RWLOCK_TEST1_NAME;
222 /* The first thread will be the writer */
224 rwt[i].rwt_thread = spl_kthread_create(splat_rwlock_wr_thr,
225 &rwt[i], "%s/%d", SPLAT_RWLOCK_TEST_NAME, i);
227 rwt[i].rwt_thread = spl_kthread_create(splat_rwlock_rd_thr,
228 &rwt[i], "%s/%d", SPLAT_RWLOCK_TEST_NAME, i);
230 if (!IS_ERR(rwt[i].rwt_thread)) {
231 wake_up_process(rwt[i].rwt_thread);
236 /* Wait for the writer */
237 while (splat_locked_test(&rwp->rw_lock, rwp->rw_holders == 0)) {
238 wake_up_interruptible(&rwp->rw_waitq);
242 /* Wait for 'count-1' readers */
243 while (splat_locked_test(&rwp->rw_lock, rwp->rw_waiters < count - 1)) {
244 wake_up_interruptible(&rwp->rw_waitq);
248 /* Verify there is only one lock holder */
249 if (splat_locked_test(&rwp->rw_lock, rwp->rw_holders) != 1) {
250 splat_vprint(file, SPLAT_RWLOCK_TEST1_NAME, "Only 1 holder "
251 "expected for rwlock (%d holding/%d waiting)\n",
252 rwp->rw_holders, rwp->rw_waiters);
256 /* Verify 'count-1' readers */
257 if (splat_locked_test(&rwp->rw_lock, rwp->rw_waiters != count - 1)) {
258 splat_vprint(file, SPLAT_RWLOCK_TEST1_NAME, "Only %d waiters "
259 "expected for rwlock (%d holding/%d waiting)\n",
260 count - 1, rwp->rw_holders, rwp->rw_waiters);
264 /* Signal the writer to release, allows readers to acquire */
265 spin_lock(&rwp->rw_lock);
266 rwp->rw_release = SPLAT_RWLOCK_RELEASE_WR;
267 wake_up_interruptible(&rwp->rw_waitq);
268 spin_unlock(&rwp->rw_lock);
270 /* Wait for 'count-1' readers to hold the lock */
271 while (splat_locked_test(&rwp->rw_lock, rwp->rw_holders < count - 1)) {
272 wake_up_interruptible(&rwp->rw_waitq);
276 /* Verify there are 'count-1' readers */
277 if (splat_locked_test(&rwp->rw_lock, rwp->rw_holders != count - 1)) {
278 splat_vprint(file, SPLAT_RWLOCK_TEST1_NAME, "Only %d holders "
279 "expected for rwlock (%d holding/%d waiting)\n",
280 count - 1, rwp->rw_holders, rwp->rw_waiters);
284 /* Release 'count-1' readers */
285 spin_lock(&rwp->rw_lock);
286 rwp->rw_release = SPLAT_RWLOCK_RELEASE_RD;
287 wake_up_interruptible(&rwp->rw_waitq);
288 spin_unlock(&rwp->rw_lock);
290 /* Wait for the test to complete */
291 while (splat_locked_test(&rwp->rw_lock,
292 rwp->rw_holders>0 || rwp->rw_waiters>0))
295 rw_destroy(&(rwp->rw_rwlock));
302 splat_rwlock_test2_func(void *arg)
304 rw_priv_t *rwp = (rw_priv_t *)arg;
306 ASSERT(rwp->rw_magic == SPLAT_RWLOCK_TEST_MAGIC);
308 /* Read the value before sleeping and write it after we wake up to
309 * maximize the chance of a race if rwlocks are not working properly */
310 rw_enter(&rwp->rw_rwlock, RW_WRITER);
312 set_current_state(TASK_INTERRUPTIBLE);
313 schedule_timeout(HZ / 100); /* 1/100 of a second */
314 VERIFY(rwp->rw_rc == rc);
316 rw_exit(&rwp->rw_rwlock);
320 splat_rwlock_test2(struct file *file, void *arg)
324 int i, rc = 0, tq_count = 256;
326 rwp = (rw_priv_t *)kmalloc(sizeof(*rwp), GFP_KERNEL);
330 splat_init_rw_priv(rwp, file);
332 /* Create several threads allowing tasks to race with each other */
333 tq = taskq_create(SPLAT_RWLOCK_TEST_TASKQ, num_online_cpus(),
334 defclsyspri, 50, INT_MAX, TASKQ_PREPOPULATE);
341 * Schedule N work items to the work queue each of which enters the
342 * writer rwlock, sleeps briefly, then exits the writer rwlock. On a
343 * multiprocessor box these work items will be handled by all available
344 * CPUs. The task function checks to ensure the tracked shared variable
345 * is always only incremented by one. Additionally, the rwlock itself
346 * is instrumented such that if any two processors are in the
347 * critical region at the same time the system will panic. If the
348 * rwlock is implemented right this will never happy, that's a pass.
350 for (i = 0; i < tq_count; i++) {
351 if (taskq_dispatch(tq, splat_rwlock_test2_func, rwp,
352 TQ_SLEEP) == TASKQID_INVALID) {
353 splat_vprint(file, SPLAT_RWLOCK_TEST2_NAME,
354 "Failed to queue task %d\n", i);
361 if (rwp->rw_rc == tq_count) {
362 splat_vprint(file, SPLAT_RWLOCK_TEST2_NAME, "%d racing threads "
363 "correctly entered/exited the rwlock %d times\n",
364 num_online_cpus(), rwp->rw_rc);
366 splat_vprint(file, SPLAT_RWLOCK_TEST2_NAME, "%d racing threads "
367 "only processed %d/%d w rwlock work items\n",
368 num_online_cpus(), rwp->rw_rc, tq_count);
373 rw_destroy(&(rwp->rw_rwlock));
379 #define splat_rwlock_test3_helper(rwp,rex1,rex2,wex1,wex2,held_func,rc) \
381 int result, _rc1_, _rc2_, _rc3_, _rc4_; \
384 rw_enter(&(rwp)->rw_rwlock, RW_READER); \
385 _rc1_ = ((result = held_func(&(rwp)->rw_rwlock)) != rex1); \
386 splat_vprint(file, SPLAT_RWLOCK_TEST3_NAME, "%s" #held_func \
387 " returned %d (expected %d) when RW_READER\n", \
388 _rc1_ ? "Fail " : "", result, rex1); \
389 rw_exit(&(rwp)->rw_rwlock); \
390 _rc2_ = ((result = held_func(&(rwp)->rw_rwlock)) != rex2); \
391 splat_vprint(file, SPLAT_RWLOCK_TEST3_NAME, "%s" #held_func \
392 " returned %d (expected %d) when !RW_READER\n", \
393 _rc2_ ? "Fail " : "", result, rex2); \
395 rw_enter(&(rwp)->rw_rwlock, RW_WRITER); \
396 _rc3_ = ((result = held_func(&(rwp)->rw_rwlock)) != wex1); \
397 splat_vprint(file, SPLAT_RWLOCK_TEST3_NAME, "%s" #held_func \
398 " returned %d (expected %d) when RW_WRITER\n", \
399 _rc3_ ? "Fail " : "", result, wex1); \
400 rw_exit(&(rwp)->rw_rwlock); \
401 _rc4_ = ((result = held_func(&(rwp)->rw_rwlock)) != wex2); \
402 splat_vprint(file, SPLAT_RWLOCK_TEST3_NAME, "%s" #held_func \
403 " returned %d (expected %d) when !RW_WRITER\n", \
404 _rc4_ ? "Fail " : "", result, wex2); \
406 rc = ((_rc1_ || _rc2_ || _rc3_ || _rc4_) ? -EINVAL : 0); \
410 splat_rwlock_test3(struct file *file, void *arg)
415 rwp = (rw_priv_t *)kmalloc(sizeof(*rwp), GFP_KERNEL);
419 splat_init_rw_priv(rwp, file);
421 splat_rwlock_test3_helper(rwp, 1, 0, 1, 0, RW_LOCK_HELD, rc1);
422 splat_rwlock_test3_helper(rwp, 1, 0, 0, 0, RW_READ_HELD, rc2);
423 splat_rwlock_test3_helper(rwp, 0, 0, 1, 0, RW_WRITE_HELD, rc3);
425 rw_destroy(&rwp->rw_rwlock);
428 return ((rc1 || rc2 || rc3) ? -EINVAL : 0);
432 splat_rwlock_test4_func(void *arg)
434 rw_priv_t *rwp = (rw_priv_t *)arg;
435 ASSERT(rwp->rw_magic == SPLAT_RWLOCK_TEST_MAGIC);
437 if (rw_tryenter(&rwp->rw_rwlock, rwp->rw_type)) {
439 rw_exit(&rwp->rw_rwlock);
446 splat_rwlock_test4_name(krw_t type)
449 case RW_NONE: return "RW_NONE";
450 case RW_WRITER: return "RW_WRITER";
451 case RW_READER: return "RW_READER";
458 splat_rwlock_test4_type(taskq_t *tq, rw_priv_t *rwp, int expected_rc,
459 krw_t holder_type, krw_t try_type)
463 /* Schedule a task function which will try and acquire the rwlock
464 * using type try_type while the rwlock is being held as holder_type.
465 * The result must match expected_rc for the test to pass */
466 rwp->rw_rc = -EINVAL;
467 rwp->rw_type = try_type;
469 if (holder_type == RW_WRITER || holder_type == RW_READER)
470 rw_enter(&rwp->rw_rwlock, holder_type);
472 id = taskq_dispatch(tq, splat_rwlock_test4_func, rwp, TQ_SLEEP);
473 if (id == TASKQID_INVALID) {
474 splat_vprint(rwp->rw_file, SPLAT_RWLOCK_TEST4_NAME, "%s",
475 "taskq_dispatch() failed\n");
480 taskq_wait_id(tq, id);
482 if (rwp->rw_rc != expected_rc)
485 splat_vprint(rwp->rw_file, SPLAT_RWLOCK_TEST4_NAME,
486 "%srw_tryenter(%s) returned %d (expected %d) when %s\n",
487 rc ? "Fail " : "", splat_rwlock_test4_name(try_type),
488 rwp->rw_rc, expected_rc,
489 splat_rwlock_test4_name(holder_type));
491 if (holder_type == RW_WRITER || holder_type == RW_READER)
492 rw_exit(&rwp->rw_rwlock);
498 splat_rwlock_test4(struct file *file, void *arg)
502 int rc = 0, rc1, rc2, rc3, rc4, rc5, rc6;
504 rwp = (rw_priv_t *)kmalloc(sizeof(*rwp), GFP_KERNEL);
508 tq = taskq_create(SPLAT_RWLOCK_TEST_TASKQ, 1, defclsyspri,
509 50, INT_MAX, TASKQ_PREPOPULATE);
515 splat_init_rw_priv(rwp, file);
517 /* Validate all combinations of rw_tryenter() contention */
518 rc1 = splat_rwlock_test4_type(tq, rwp, -EBUSY, RW_WRITER, RW_WRITER);
519 rc2 = splat_rwlock_test4_type(tq, rwp, -EBUSY, RW_WRITER, RW_READER);
520 rc3 = splat_rwlock_test4_type(tq, rwp, -EBUSY, RW_READER, RW_WRITER);
521 rc4 = splat_rwlock_test4_type(tq, rwp, 0, RW_READER, RW_READER);
522 rc5 = splat_rwlock_test4_type(tq, rwp, 0, RW_NONE, RW_WRITER);
523 rc6 = splat_rwlock_test4_type(tq, rwp, 0, RW_NONE, RW_READER);
525 if (rc1 || rc2 || rc3 || rc4 || rc5 || rc6)
530 rw_destroy(&(rwp->rw_rwlock));
537 splat_rwlock_test5(struct file *file, void *arg)
542 rwp = (rw_priv_t *)kmalloc(sizeof(*rwp), GFP_KERNEL);
546 splat_init_rw_priv(rwp, file);
548 rw_enter(&rwp->rw_rwlock, RW_WRITER);
549 if (!RW_WRITE_HELD(&rwp->rw_rwlock)) {
550 splat_vprint(file, SPLAT_RWLOCK_TEST5_NAME,
551 "rwlock should be write lock: %d\n",
552 RW_WRITE_HELD(&rwp->rw_rwlock));
556 rw_downgrade(&rwp->rw_rwlock);
557 if (!RW_READ_HELD(&rwp->rw_rwlock)) {
558 splat_vprint(file, SPLAT_RWLOCK_TEST5_NAME,
559 "rwlock should be read lock: %d\n",
560 RW_READ_HELD(&rwp->rw_rwlock));
565 splat_vprint(file, SPLAT_RWLOCK_TEST5_NAME, "%s",
566 "rwlock properly downgraded\n");
568 rw_exit(&rwp->rw_rwlock);
569 rw_destroy(&rwp->rw_rwlock);
576 splat_rwlock_test6(struct file *file, void *arg)
581 rwp = (rw_priv_t *)kmalloc(sizeof(*rwp), GFP_KERNEL);
585 splat_init_rw_priv(rwp, file);
587 rw_enter(&rwp->rw_rwlock, RW_READER);
588 if (RWSEM_COUNT(SEM(&rwp->rw_rwlock)) !=
589 SPL_RWSEM_SINGLE_READER_VALUE) {
590 splat_vprint(file, SPLAT_RWLOCK_TEST6_NAME,
591 "We assumed single reader rwsem->count "
592 "should be %ld, but is %ld\n",
593 (long int)SPL_RWSEM_SINGLE_READER_VALUE,
594 (long int)RWSEM_COUNT(SEM(&rwp->rw_rwlock)));
598 rw_exit(&rwp->rw_rwlock);
600 rw_enter(&rwp->rw_rwlock, RW_WRITER);
601 if (RWSEM_COUNT(SEM(&rwp->rw_rwlock)) !=
602 SPL_RWSEM_SINGLE_WRITER_VALUE) {
603 splat_vprint(file, SPLAT_RWLOCK_TEST6_NAME,
604 "We assumed single writer rwsem->count "
605 "should be %ld, but is %ld\n",
606 (long int)SPL_RWSEM_SINGLE_WRITER_VALUE,
607 (long int)RWSEM_COUNT(SEM(&rwp->rw_rwlock)));
612 splat_vprint(file, SPLAT_RWLOCK_TEST6_NAME, "%s",
613 "rwsem->count same as we assumed\n");
615 rw_exit(&rwp->rw_rwlock);
616 rw_destroy(&rwp->rw_rwlock);
623 splat_rwlock_test7(struct file *file, void *arg)
628 rwp = (rw_priv_t *)kmalloc(sizeof(*rwp), GFP_KERNEL);
632 splat_init_rw_priv(rwp, file);
634 rw_enter(&rwp->rw_rwlock, RW_READER);
635 if (!RW_READ_HELD(&rwp->rw_rwlock)) {
636 splat_vprint(file, SPLAT_RWLOCK_TEST7_NAME,
637 "rwlock should be read lock: %d\n",
638 RW_READ_HELD(&rwp->rw_rwlock));
643 /* With one reader upgrade should never fail. */
644 rc = rw_tryupgrade(&rwp->rw_rwlock);
646 splat_vprint(file, SPLAT_RWLOCK_TEST7_NAME,
647 "rwlock failed upgrade from reader: %d\n",
648 RW_READ_HELD(&rwp->rw_rwlock));
653 if (RW_READ_HELD(&rwp->rw_rwlock) || !RW_WRITE_HELD(&rwp->rw_rwlock)) {
654 splat_vprint(file, SPLAT_RWLOCK_TEST7_NAME, "rwlock should "
655 "have 0 (not %d) reader and 1 (not %d) writer\n",
656 RW_READ_HELD(&rwp->rw_rwlock),
657 RW_WRITE_HELD(&rwp->rw_rwlock));
662 splat_vprint(file, SPLAT_RWLOCK_TEST7_NAME, "%s",
663 "rwlock properly upgraded\n");
665 rw_exit(&rwp->rw_rwlock);
666 rw_destroy(&rwp->rw_rwlock);
673 splat_rwlock_init(void)
675 splat_subsystem_t *sub;
677 sub = kmalloc(sizeof(*sub), GFP_KERNEL);
681 memset(sub, 0, sizeof(*sub));
682 strncpy(sub->desc.name, SPLAT_RWLOCK_NAME, SPLAT_NAME_SIZE);
683 strncpy(sub->desc.desc, SPLAT_RWLOCK_DESC, SPLAT_DESC_SIZE);
684 INIT_LIST_HEAD(&sub->subsystem_list);
685 INIT_LIST_HEAD(&sub->test_list);
686 spin_lock_init(&sub->test_lock);
687 sub->desc.id = SPLAT_SUBSYSTEM_RWLOCK;
689 SPLAT_TEST_INIT(sub, SPLAT_RWLOCK_TEST1_NAME, SPLAT_RWLOCK_TEST1_DESC,
690 SPLAT_RWLOCK_TEST1_ID, splat_rwlock_test1);
691 SPLAT_TEST_INIT(sub, SPLAT_RWLOCK_TEST2_NAME, SPLAT_RWLOCK_TEST2_DESC,
692 SPLAT_RWLOCK_TEST2_ID, splat_rwlock_test2);
693 SPLAT_TEST_INIT(sub, SPLAT_RWLOCK_TEST3_NAME, SPLAT_RWLOCK_TEST3_DESC,
694 SPLAT_RWLOCK_TEST3_ID, splat_rwlock_test3);
695 SPLAT_TEST_INIT(sub, SPLAT_RWLOCK_TEST4_NAME, SPLAT_RWLOCK_TEST4_DESC,
696 SPLAT_RWLOCK_TEST4_ID, splat_rwlock_test4);
697 SPLAT_TEST_INIT(sub, SPLAT_RWLOCK_TEST5_NAME, SPLAT_RWLOCK_TEST5_DESC,
698 SPLAT_RWLOCK_TEST5_ID, splat_rwlock_test5);
699 SPLAT_TEST_INIT(sub, SPLAT_RWLOCK_TEST6_NAME, SPLAT_RWLOCK_TEST6_DESC,
700 SPLAT_RWLOCK_TEST6_ID, splat_rwlock_test6);
701 SPLAT_TEST_INIT(sub, SPLAT_RWLOCK_TEST7_NAME, SPLAT_RWLOCK_TEST7_DESC,
702 SPLAT_RWLOCK_TEST7_ID, splat_rwlock_test7);
708 splat_rwlock_fini(splat_subsystem_t *sub)
711 SPLAT_TEST_FINI(sub, SPLAT_RWLOCK_TEST7_ID);
712 SPLAT_TEST_FINI(sub, SPLAT_RWLOCK_TEST6_ID);
713 SPLAT_TEST_FINI(sub, SPLAT_RWLOCK_TEST5_ID);
714 SPLAT_TEST_FINI(sub, SPLAT_RWLOCK_TEST4_ID);
715 SPLAT_TEST_FINI(sub, SPLAT_RWLOCK_TEST3_ID);
716 SPLAT_TEST_FINI(sub, SPLAT_RWLOCK_TEST2_ID);
717 SPLAT_TEST_FINI(sub, SPLAT_RWLOCK_TEST1_ID);
722 splat_rwlock_id(void) {
723 return SPLAT_SUBSYSTEM_RWLOCK;