]>
git.proxmox.com Git - mirror_spl-debian.git/blob - modules/splat/splat-mutex.c
640f8f407154dc004d37c7fae8d74a0bd4193d37
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_SUBSYSTEM_MUTEX 0x0400
30 #define SPLAT_MUTEX_NAME "mutex"
31 #define SPLAT_MUTEX_DESC "Kernel Mutex Tests"
33 #define SPLAT_MUTEX_TEST1_ID 0x0401
34 #define SPLAT_MUTEX_TEST1_NAME "tryenter"
35 #define SPLAT_MUTEX_TEST1_DESC "Validate mutex_tryenter() correctness"
37 #define SPLAT_MUTEX_TEST2_ID 0x0402
38 #define SPLAT_MUTEX_TEST2_NAME "race"
39 #define SPLAT_MUTEX_TEST2_DESC "Many threads entering/exiting the mutex"
41 #define SPLAT_MUTEX_TEST3_ID 0x0403
42 #define SPLAT_MUTEX_TEST3_NAME "owned"
43 #define SPLAT_MUTEX_TEST3_DESC "Validate mutex_owned() correctness"
45 #define SPLAT_MUTEX_TEST4_ID 0x0404
46 #define SPLAT_MUTEX_TEST4_NAME "owner"
47 #define SPLAT_MUTEX_TEST4_DESC "Validate mutex_owner() correctness"
49 #define SPLAT_MUTEX_TEST_MAGIC 0x115599DDUL
50 #define SPLAT_MUTEX_TEST_NAME "mutex_test"
51 #define SPLAT_MUTEX_TEST_WORKQ "mutex_wq"
52 #define SPLAT_MUTEX_TEST_COUNT 128
54 typedef struct mutex_priv
{
55 unsigned long mp_magic
;
57 struct work_struct mp_work
[SPLAT_MUTEX_TEST_COUNT
];
62 #ifdef HAVE_3ARGS_INIT_WORK
64 splat_mutex_test1_work(void *priv
)
66 mutex_priv_t
*mp
= (mutex_priv_t
*)priv
;
68 ASSERT(mp
->mp_magic
== SPLAT_MUTEX_TEST_MAGIC
);
71 if (!mutex_tryenter(&mp
->mp_mtx
))
77 splat_mutex_test1(struct file
*file
, void *arg
)
80 #ifdef HAVE_3ARGS_INIT_WORK
81 struct workqueue_struct
*wq
;
82 struct work_struct work
;
85 mp
= (mutex_priv_t
*)kmalloc(sizeof(*mp
), GFP_KERNEL
);
89 wq
= create_singlethread_workqueue(SPLAT_MUTEX_TEST_WORKQ
);
95 mutex_init(&(mp
->mp_mtx
), SPLAT_MUTEX_TEST_NAME
, MUTEX_DEFAULT
, NULL
);
96 mutex_enter(&(mp
->mp_mtx
));
98 mp
->mp_magic
= SPLAT_MUTEX_TEST_MAGIC
;
100 INIT_WORK(&work
, splat_mutex_test1_work
, mp
);
102 /* Schedule a work item which will try and aquire the mutex via
103 * mutex_tryenter() while its held. This should fail and the work
104 * item will indicte this status in the passed private data. */
105 if (!queue_work(wq
, &work
)) {
106 mutex_exit(&(mp
->mp_mtx
));
112 mutex_exit(&(mp
->mp_mtx
));
114 /* Work item successfully aquired mutex, very bad! */
115 if (mp
->mp_rc
!= -EBUSY
) {
120 splat_vprint(file
, SPLAT_MUTEX_TEST1_NAME
, "%s",
121 "mutex_trylock() correctly failed when mutex held\n");
123 /* Schedule a work item which will try and aquire the mutex via
124 * mutex_tryenter() while it is not held. This should work and
125 * the item will indicte this status in the passed private data. */
126 if (!queue_work(wq
, &work
)) {
133 /* Work item failed to aquire mutex, very bad! */
134 if (mp
->mp_rc
!= 0) {
139 splat_vprint(file
, SPLAT_MUTEX_TEST1_NAME
, "%s",
140 "mutex_trylock() correctly succeeded when mutex unheld\n");
142 mutex_destroy(&(mp
->mp_mtx
));
143 destroy_workqueue(wq
);
150 #ifdef HAVE_3ARGS_INIT_WORK
152 splat_mutex_test2_work(void *priv
)
154 mutex_priv_t
*mp
= (mutex_priv_t
*)priv
;
157 ASSERT(mp
->mp_magic
== SPLAT_MUTEX_TEST_MAGIC
);
159 /* Read the value before sleeping and write it after we wake up to
160 * maximize the chance of a race if mutexs are not working properly */
161 mutex_enter(&mp
->mp_mtx
);
163 set_current_state(TASK_INTERRUPTIBLE
);
164 schedule_timeout(HZ
/ 100); /* 1/100 of a second */
166 mutex_exit(&mp
->mp_mtx
);
171 splat_mutex_test2(struct file
*file
, void *arg
)
174 #ifdef HAVE_3ARGS_INIT_WORK
175 struct workqueue_struct
*wq
;
179 mp
= (mutex_priv_t
*)kmalloc(sizeof(*mp
), GFP_KERNEL
);
183 /* Create a thread per CPU items on queue will race */
184 wq
= create_workqueue(SPLAT_MUTEX_TEST_WORKQ
);
190 mutex_init(&(mp
->mp_mtx
), SPLAT_MUTEX_TEST_NAME
, MUTEX_DEFAULT
, NULL
);
192 mp
->mp_magic
= SPLAT_MUTEX_TEST_MAGIC
;
196 /* Schedule N work items to the work queue each of which enters the
197 * mutex, sleeps briefly, then exits the mutex. On a multiprocessor
198 * box these work items will be handled by all available CPUs. The
199 * mutex is instrumented such that if any two processors are in the
200 * critical region at the same time the system will panic. If the
201 * mutex is implemented right this will never happy, that's a pass. */
202 for (i
= 0; i
< SPLAT_MUTEX_TEST_COUNT
; i
++) {
203 INIT_WORK(&(mp
->mp_work
[i
]), splat_mutex_test2_work
, mp
);
205 if (!queue_work(wq
, &(mp
->mp_work
[i
]))) {
206 splat_vprint(file
, SPLAT_MUTEX_TEST2_NAME
,
207 "Failed to queue work id %d\n", i
);
214 if (mp
->mp_rc
== SPLAT_MUTEX_TEST_COUNT
) {
215 splat_vprint(file
, SPLAT_MUTEX_TEST2_NAME
, "%d racing threads "
216 "correctly entered/exited the mutex %d times\n",
217 num_online_cpus(), mp
->mp_rc
);
219 splat_vprint(file
, SPLAT_MUTEX_TEST2_NAME
, "%d racing threads "
220 "only processed %d/%d mutex work items\n",
221 num_online_cpus(), mp
->mp_rc
, SPLAT_MUTEX_TEST_COUNT
);
225 mutex_destroy(&(mp
->mp_mtx
));
226 destroy_workqueue(wq
);
234 splat_mutex_test3(struct file
*file
, void *arg
)
239 mutex_init(&mtx
, SPLAT_MUTEX_TEST_NAME
, MUTEX_DEFAULT
, NULL
);
243 /* Mutex should be owned by current */
244 if (!mutex_owned(&mtx
)) {
245 splat_vprint(file
, SPLAT_MUTEX_TEST3_NAME
, "Mutex should "
246 "be owned by pid %d but is owned by pid %d\n",
247 current
->pid
, mtx
.km_owner
? mtx
.km_owner
->pid
: -1);
254 /* Mutex should not be owned by any task */
255 if (mutex_owned(&mtx
)) {
256 splat_vprint(file
, SPLAT_MUTEX_TEST3_NAME
, "Mutex should "
257 "not be owned but is owned by pid %d\n",
258 mtx
.km_owner
? mtx
.km_owner
->pid
: -1);
263 splat_vprint(file
, SPLAT_MUTEX_TEST3_NAME
, "%s",
264 "Correct mutex_owned() behavior\n");
272 splat_mutex_test4(struct file
*file
, void *arg
)
278 mutex_init(&mtx
, SPLAT_MUTEX_TEST_NAME
, MUTEX_DEFAULT
, NULL
);
282 /* Mutex should be owned by current */
283 owner
= mutex_owner(&mtx
);
284 if (current
!= owner
) {
285 splat_vprint(file
, SPLAT_MUTEX_TEST3_NAME
, "Mutex should "
286 "be owned by pid %d but is owned by pid %d\n",
287 current
->pid
, owner
? owner
->pid
: -1);
294 /* Mutex should not be owned by any task */
295 owner
= mutex_owner(&mtx
);
297 splat_vprint(file
, SPLAT_MUTEX_TEST3_NAME
, "Mutex should not "
298 "be owned but is owned by pid %d\n", owner
->pid
);
303 splat_vprint(file
, SPLAT_MUTEX_TEST3_NAME
, "%s",
304 "Correct mutex_owner() behavior\n");
312 splat_mutex_init(void)
314 splat_subsystem_t
*sub
;
316 sub
= kmalloc(sizeof(*sub
), GFP_KERNEL
);
320 memset(sub
, 0, sizeof(*sub
));
321 strncpy(sub
->desc
.name
, SPLAT_MUTEX_NAME
, SPLAT_NAME_SIZE
);
322 strncpy(sub
->desc
.desc
, SPLAT_MUTEX_DESC
, SPLAT_DESC_SIZE
);
323 INIT_LIST_HEAD(&sub
->subsystem_list
);
324 INIT_LIST_HEAD(&sub
->test_list
);
325 spin_lock_init(&sub
->test_lock
);
326 sub
->desc
.id
= SPLAT_SUBSYSTEM_MUTEX
;
328 SPLAT_TEST_INIT(sub
, SPLAT_MUTEX_TEST1_NAME
, SPLAT_MUTEX_TEST1_DESC
,
329 SPLAT_MUTEX_TEST1_ID
, splat_mutex_test1
);
330 SPLAT_TEST_INIT(sub
, SPLAT_MUTEX_TEST2_NAME
, SPLAT_MUTEX_TEST2_DESC
,
331 SPLAT_MUTEX_TEST2_ID
, splat_mutex_test2
);
332 SPLAT_TEST_INIT(sub
, SPLAT_MUTEX_TEST3_NAME
, SPLAT_MUTEX_TEST3_DESC
,
333 SPLAT_MUTEX_TEST3_ID
, splat_mutex_test3
);
334 SPLAT_TEST_INIT(sub
, SPLAT_MUTEX_TEST4_NAME
, SPLAT_MUTEX_TEST4_DESC
,
335 SPLAT_MUTEX_TEST4_ID
, splat_mutex_test4
);
341 splat_mutex_fini(splat_subsystem_t
*sub
)
344 SPLAT_TEST_FINI(sub
, SPLAT_MUTEX_TEST4_ID
);
345 SPLAT_TEST_FINI(sub
, SPLAT_MUTEX_TEST3_ID
);
346 SPLAT_TEST_FINI(sub
, SPLAT_MUTEX_TEST2_ID
);
347 SPLAT_TEST_FINI(sub
, SPLAT_MUTEX_TEST1_ID
);
353 splat_mutex_id(void) {
354 return SPLAT_SUBSYSTEM_MUTEX
;