1#include "sync/lock_chk/internal.h"
2#include "sync/tests/test_internal.h"
3
4#ifdef DEBUG_LOCK_CHK
5
6#include <sync/mutex.h>
7#include <sync/mutex_simple.h>
8#include <sync/qspinlock.h>
9#include <sync/rwlock.h>
10#include <sync/spinlock.h>
11
12LOCK_CHK_CLASS_DEFINE_LOCAL(graph_test_class_a);
13LOCK_CHK_CLASS_DEFINE_LOCAL(graph_test_class_b);
14LOCK_CHK_CLASS_DEFINE_LOCAL(graph_test_class_c);
15
16static struct lock_chk_graph lock_chk_test_graph;
17
18#define TEST_CTX(g, ...) (&(struct lock_chk_ctx){.graph = (g), __VA_ARGS__})
19
20TEST_DEFINE_UNIT(lock_chk, graph_node_resolution) {
21 struct lock_chk_graph *graph = &lock_chk_test_graph;
22 lock_chk_graph_init(graph);
23
24 struct lock_chk_map map_a =
25 LOCK_CHK_MAP_VALUE_INIT(LOCK_CHK_CLASS(graph_test_class_a));
26 struct lock_chk_map map_b =
27 LOCK_CHK_MAP_VALUE_INIT(LOCK_CHK_CLASS(graph_test_class_b));
28
29 struct lock_chk_node *node_a0 = NULL;
30 struct lock_chk_node *node_a0_again = NULL;
31 struct lock_chk_node *node_a1 = NULL;
32 struct lock_chk_node *node_b0 = NULL;
33
34 TEST_ASSERT_EQ(
35 lock_chk_graph_resolve_node(TEST_CTX(graph), &map_a, 0, &node_a0),
36 LOCK_CHK_RESULT_OK);
37 TEST_ASSERT_NONNULL(node_a0);
38
39 TEST_ASSERT_EQ(
40 lock_chk_graph_resolve_node(TEST_CTX(graph), &map_a, 0, &node_a0_again),
41 LOCK_CHK_RESULT_OK);
42 TEST_ASSERT_PTR_EQ(node_a0, node_a0_again);
43
44 TEST_ASSERT_EQ(
45 lock_chk_graph_resolve_node(TEST_CTX(graph), &map_a, 1, &node_a1),
46 LOCK_CHK_RESULT_OK);
47 TEST_ASSERT_NONNULL(node_a1);
48 TEST_ASSERT_PTR_NE(node_a1, node_a0);
49 TEST_ASSERT_EQ(node_a1->subclass, 1);
50
51 TEST_ASSERT_EQ(
52 lock_chk_graph_resolve_node(TEST_CTX(graph), &map_b, 0, &node_b0),
53 LOCK_CHK_RESULT_OK);
54 TEST_ASSERT_NONNULL(node_b0);
55 TEST_ASSERT_PTR_NE(node_b0, node_a0);
56
57 return TEST_SUCCESS;
58}
59
60TEST_DEFINE_UNIT(lock_chk, graph_cycle_detection) {
61 struct lock_chk_graph *graph = &lock_chk_test_graph;
62 lock_chk_graph_init(graph);
63
64 struct lock_chk_map map_a =
65 LOCK_CHK_MAP_VALUE_INIT(LOCK_CHK_CLASS(graph_test_class_a));
66 struct lock_chk_map map_b =
67 LOCK_CHK_MAP_VALUE_INIT(LOCK_CHK_CLASS(graph_test_class_b));
68 struct lock_chk_map map_c =
69 LOCK_CHK_MAP_VALUE_INIT(LOCK_CHK_CLASS(graph_test_class_c));
70
71 struct lock_chk_node *node_a = NULL;
72 struct lock_chk_node *node_b = NULL;
73 struct lock_chk_node *node_c = NULL;
74
75 TEST_ASSERT_EQ(
76 lock_chk_graph_resolve_node(TEST_CTX(graph), &map_a, 0, &node_a),
77 LOCK_CHK_RESULT_OK);
78 TEST_ASSERT_EQ(
79 lock_chk_graph_resolve_node(TEST_CTX(graph), &map_b, 0, &node_b),
80 LOCK_CHK_RESULT_OK);
81 TEST_ASSERT_EQ(
82 lock_chk_graph_resolve_node(TEST_CTX(graph), &map_c, 0, &node_c),
83 LOCK_CHK_RESULT_OK);
84
85 /* A -> B */
86 TEST_ASSERT_EQ(lock_chk_graph_add_dep(
87 TEST_CTX(graph),
88 lock_chk_dep_make(node_a, LOCK_CHK_MODE_EXCLUSIVE),
89 lock_chk_dep_make(node_b, LOCK_CHK_MODE_EXCLUSIVE)),
90 LOCK_CHK_RESULT_OK);
91 TEST_ASSERT_EQ(graph->edge_count, 1);
92
93 /* Duplicate A -> B should be dedup without adding edge */
94 TEST_ASSERT_EQ(lock_chk_graph_add_dep(
95 TEST_CTX(graph),
96 lock_chk_dep_make(node_a, LOCK_CHK_MODE_EXCLUSIVE),
97 lock_chk_dep_make(node_b, LOCK_CHK_MODE_EXCLUSIVE)),
98 LOCK_CHK_RESULT_OK);
99 TEST_ASSERT_EQ(graph->edge_count, 1);
100
101 /* B -> C */
102 TEST_ASSERT_EQ(lock_chk_graph_add_dep(
103 TEST_CTX(graph),
104 lock_chk_dep_make(node_b, LOCK_CHK_MODE_EXCLUSIVE),
105 lock_chk_dep_make(node_c, LOCK_CHK_MODE_EXCLUSIVE)),
106 LOCK_CHK_RESULT_OK);
107 TEST_ASSERT_EQ(graph->edge_count, 2);
108
109 /* C -> A completes cycle A -> B -> C -> A reports CYCLE */
110 struct lock_chk_fault fail = {0};
111 TEST_ASSERT_EQ(lock_chk_graph_add_dep(
112 TEST_CTX(graph, .fault = &fail),
113 lock_chk_dep_make(node_c, LOCK_CHK_MODE_EXCLUSIVE),
114 lock_chk_dep_make(node_a, LOCK_CHK_MODE_EXCLUSIVE)),
115 LOCK_CHK_RESULT_CYCLE);
116 TEST_ASSERT_NONNULL(fail.report);
117 TEST_ASSERT_EQ(fail.report->cycle_len, 3);
118 TEST_ASSERT_NE(fail.report->signature, 0);
119 lock_chk_report_release();
120
121 /* Direct B -> A completes 2-node cycle: must report CYCLE */
122 TEST_ASSERT_EQ(lock_chk_graph_add_dep(
123 TEST_CTX(graph),
124 lock_chk_dep_make(node_b, LOCK_CHK_MODE_EXCLUSIVE),
125 lock_chk_dep_make(node_a, LOCK_CHK_MODE_EXCLUSIVE)),
126 LOCK_CHK_RESULT_CYCLE);
127
128 return TEST_SUCCESS;
129}
130
131TEST_DEFINE_UNIT(lock_chk, irq_safety_conflict) {
132 struct lock_chk_graph *graph = &lock_chk_test_graph;
133 lock_chk_graph_init(graph);
134
135 struct lock_chk_map map_disp =
136 LOCK_CHK_MAP_VALUE_INIT(LOCK_CHK_CLASS(graph_test_class_a));
137 struct lock_chk_map map_high =
138 LOCK_CHK_MAP_VALUE_INIT(LOCK_CHK_CLASS(graph_test_class_b));
139
140 struct lock_chk_acq_req req_disp = {
141 .lock.type = LOCK_CHK_TYPE_SPIN,
142 .prev_irql = IRQL_PASSIVE_LEVEL,
143 .irqs_enabled = true,
144 .op_flags = LOCK_OP_IRQ_DISPATCH,
145 .in_irq = false,
146 };
147 struct lock_chk_acq_req req_high = {
148 .lock.type = LOCK_CHK_TYPE_SPIN,
149 .prev_irql = IRQL_HIGH_LEVEL,
150 .irqs_enabled = false,
151 .op_flags = LOCK_OP_IRQ_HIGH,
152 .in_irq = false,
153 };
154
155 struct lock_chk_node *node = NULL;
156
157 TEST_ASSERT_EQ(lock_chk_graph_resolve_node(
158 TEST_CTX(graph, .req = &req_disp), &map_disp, 0, &node),
159 LOCK_CHK_RESULT_OK);
160 TEST_ASSERT_EQ(lock_chk_graph_resolve_node(
161 TEST_CTX(graph, .req = &req_high), &map_disp, 0, &node),
162 LOCK_CHK_RESULT_BAD_CONTEXT);
163
164 node = NULL;
165 TEST_ASSERT_EQ(lock_chk_graph_resolve_node(
166 TEST_CTX(graph, .req = &req_high), &map_high, 0, &node),
167 LOCK_CHK_RESULT_OK);
168 TEST_ASSERT_EQ(lock_chk_graph_resolve_node(
169 TEST_CTX(graph, .req = &req_disp), &map_high, 0, &node),
170 LOCK_CHK_RESULT_BAD_CONTEXT);
171
172 return TEST_SUCCESS;
173}
174
175TEST_DEFINE_UNIT(lock_chk, graph_acquire_dedup) {
176 struct lock_chk_graph *graph = &lock_chk_test_graph;
177 lock_chk_graph_init(graph);
178
179 struct lock_chk_map map_a =
180 LOCK_CHK_MAP_VALUE_INIT(LOCK_CHK_CLASS(graph_test_class_a));
181 struct lock_chk_map map_b =
182 LOCK_CHK_MAP_VALUE_INIT(LOCK_CHK_CLASS(graph_test_class_b));
183 struct lock_chk_node *node_a = NULL;
184 struct lock_chk_node *node_b = NULL;
185
186 TEST_ASSERT_EQ(
187 lock_chk_graph_resolve_node(TEST_CTX(graph), &map_a, 0, &node_a),
188 LOCK_CHK_RESULT_OK);
189
190 struct lock_chk_thread_data held = {
191 .held =
192 {
193 {.node = node_a,
194 .lock.flags = LOCK_CHKD_ORDER,
195 .mode = LOCK_CHK_MODE_EXCLUSIVE},
196 {.node = node_a,
197 .lock.flags = LOCK_CHKD_ORDER,
198 .mode = LOCK_CHK_MODE_EXCLUSIVE},
199 },
200 .depth = 2,
201 };
202 struct lock_chk_acq_req request = {
203 .map = &map_b,
204 .lock.flags = LOCK_CHKD_ORDER,
205 .lock.type = LOCK_CHK_TYPE_MUTEX,
206 .mode = LOCK_CHK_MODE_EXCLUSIVE,
207 .op_flags = LOCK_OP_KIND_BLOCKING,
208 };
209 struct lock_chk_fault failure = {0};
210
211 TEST_ASSERT_EQ(lock_chk_graph_prepare_acq(TEST_CTX(graph, .req = &request,
212 .thread_data = &held,
213 .fault = &failure),
214 &map_b, 0, &node_b),
215 LOCK_CHK_RESULT_OK);
216 TEST_ASSERT_NONNULL(node_b);
217 TEST_ASSERT_EQ(graph->edge_count, 1);
218 return TEST_SUCCESS;
219}
220
221TEST_DEFINE_UNIT(lock_chk, graph_acquire_cycle_fault_populated) {
222 struct lock_chk_graph *graph = &lock_chk_test_graph;
223 lock_chk_graph_init(graph);
224
225 struct lock_chk_map map_a =
226 LOCK_CHK_MAP_VALUE_INIT(LOCK_CHK_CLASS(graph_test_class_a));
227 struct lock_chk_map map_b =
228 LOCK_CHK_MAP_VALUE_INIT(LOCK_CHK_CLASS(graph_test_class_b));
229 struct lock_chk_node *node_a = NULL;
230 struct lock_chk_node *node_b = NULL;
231
232 TEST_ASSERT_EQ(
233 lock_chk_graph_resolve_node(TEST_CTX(graph), &map_a, 0, &node_a),
234 LOCK_CHK_RESULT_OK);
235 TEST_ASSERT_EQ(
236 lock_chk_graph_resolve_node(TEST_CTX(graph), &map_b, 0, &node_b),
237 LOCK_CHK_RESULT_OK);
238
239 TEST_ASSERT_EQ(lock_chk_graph_add_dep(
240 TEST_CTX(graph),
241 lock_chk_dep_make(node_b, LOCK_CHK_MODE_EXCLUSIVE),
242 lock_chk_dep_make(node_a, LOCK_CHK_MODE_EXCLUSIVE)),
243 LOCK_CHK_RESULT_OK);
244
245 struct lock_chk_thread_data held = {
246 .held = {{.node = node_a,
247 .lock.flags = LOCK_CHKD_ORDER,
248 .mode = LOCK_CHK_MODE_EXCLUSIVE}},
249 .depth = 1,
250 };
251 struct lock_chk_acq_req request = {
252 .map = &map_b,
253 .lock.flags = LOCK_CHKD_ORDER,
254 .lock.type = LOCK_CHK_TYPE_MUTEX,
255 .mode = LOCK_CHK_MODE_EXCLUSIVE,
256 .op_flags = LOCK_OP_KIND_BLOCKING,
257 .site = LOCK_CHK_SITE_HERE(),
258 };
259 struct lock_chk_fault fault = {0};
260 struct lock_chk_node *out = NULL;
261
262 TEST_ASSERT_EQ(lock_chk_graph_prepare_acq(
263 TEST_CTX(graph, .req = &request, .thread_data = &held,
264 .fault = &fault, .site = request.site),
265 &map_b, 0, &out),
266 LOCK_CHK_RESULT_CYCLE);
267
268 TEST_ASSERT_EQ(fault.kind, LOCK_CHK_FAIL_CYCLE);
269 TEST_ASSERT_NONNULL(fault.report);
270 TEST_ASSERT_NE(fault.report->cycle_len, 0);
271 TEST_ASSERT_NE(fault.report->signature, 0);
272 TEST_ASSERT_NE(fault.report->msg[0], '\0');
273 TEST_ASSERT_NONNULL(fault.class);
274 lock_chk_report_release();
275 return TEST_SUCCESS;
276}
277
278TEST_DEFINE_UNIT(lock_chk, graph_acquire_rollback) {
279 struct lock_chk_graph *graph = &lock_chk_test_graph;
280 lock_chk_graph_init(graph);
281
282 struct lock_chk_map map_a =
283 LOCK_CHK_MAP_VALUE_INIT(LOCK_CHK_CLASS(graph_test_class_a));
284 struct lock_chk_map map_b =
285 LOCK_CHK_MAP_VALUE_INIT(LOCK_CHK_CLASS(graph_test_class_b));
286 struct lock_chk_node *node_a = NULL;
287 struct lock_chk_node *node_b = NULL;
288
289 TEST_ASSERT_EQ(
290 lock_chk_graph_resolve_node(TEST_CTX(graph), &map_a, 0, &node_a),
291 LOCK_CHK_RESULT_OK);
292
293 struct lock_chk_thread_data held = {
294 .held = {{.node = node_a,
295 .lock.flags = LOCK_CHKD_ORDER,
296 .mode = LOCK_CHK_MODE_EXCLUSIVE}},
297 .depth = 1,
298 };
299 struct lock_chk_acq_req request = {
300 .map = &map_b,
301 .lock.flags = LOCK_CHKD_ORDER,
302 .lock.type = LOCK_CHK_TYPE_MUTEX,
303 .mode = LOCK_CHK_MODE_EXCLUSIVE,
304 .op_flags = LOCK_OP_KIND_BLOCKING,
305 };
306 struct lock_chk_fault failure = {0};
307 uint16_t nodes_before = graph->node_count;
308 graph->edge_count = LOCK_CHK_MAX_EDGES;
309
310 TEST_ASSERT_EQ(lock_chk_graph_prepare_acq(TEST_CTX(graph, .req = &request,
311 .thread_data = &held,
312 .fault = &failure),
313 &map_b, 0, &node_b),
314 LOCK_CHK_RESULT_EDGE_CAPACITY);
315 TEST_ASSERT_NULL(node_b);
316 TEST_ASSERT_EQ(graph->node_count, nodes_before);
317 TEST_ASSERT_NULL(atomic_load_rlx(&map_b.base_node));
318 TEST_ASSERT_EQ(failure.kind, LOCK_CHK_FAIL_CAPACITY);
319 lock_chk_report_release();
320 return TEST_SUCCESS;
321}
322
323TEST_DEFINE_UNIT(lock_chk, spin_qspin_lifecycle) {
324 struct spinlock spin_disp;
325 struct spinlock spin_irq;
326 struct spinlock spin_raw;
327 struct qspinlock qspin_disp;
328 struct qspinlock qspin_irq;
329 struct qspinlock qspin_raw;
330 enum irql irql;
331
332 spinlock_init(&spin_disp);
333 spinlock_init(&spin_irq);
334 spinlock_init(&spin_raw);
335 qspinlock_init(&qspin_disp);
336 qspinlock_init(&qspin_irq);
337 qspinlock_init(&qspin_raw);
338
339 irql = spin_lock(&spin_disp);
340 spin_unlock(&spin_disp, irql);
341
342 TEST_ASSERT(spin_trylock(&spin_disp, &irql));
343 spin_unlock(&spin_disp, irql);
344
345 irql = spin_lock_high(&spin_irq);
346 spin_unlock(&spin_irq, irql);
347
348 TEST_ASSERT(spin_trylock_high(&spin_irq, &irql));
349 spin_unlock(&spin_irq, irql);
350
351 spin_lock_raw(&spin_raw);
352 spin_unlock_raw(&spin_raw);
353
354 TEST_ASSERT(spin_trylock_raw(&spin_raw));
355 spin_unlock_raw(&spin_raw);
356
357 irql = qspin_lock(&qspin_disp);
358 qspin_unlock(&qspin_disp, irql);
359
360 TEST_ASSERT(qspin_trylock(&qspin_disp, &irql));
361 qspin_unlock(&qspin_disp, irql);
362
363 irql = qspin_lock_high(&qspin_irq);
364 qspin_unlock(&qspin_irq, irql);
365
366 TEST_ASSERT(qspin_trylock_high(&qspin_irq, &irql));
367 qspin_unlock(&qspin_irq, irql);
368
369 qspin_lock_raw(&qspin_raw);
370 qspin_unlock_raw(&qspin_raw);
371
372 TEST_ASSERT(qspin_trylock_raw(&qspin_raw));
373 qspin_unlock_raw(&qspin_raw);
374
375 return TEST_SUCCESS;
376}
377
378TEST_DEFINE_UNIT(lock_chk, mutex_out_of_order_release) {
379 struct mutex m1;
380 struct mutex m2;
381
382 mutex_init(&m1);
383 mutex_init(&m2);
384
385 mutex_lock(&m1);
386 mutex_lock(&m2);
387
388 mutex_unlock(&m1);
389 mutex_unlock(&m2);
390
391 return TEST_SUCCESS;
392}
393
394TEST_DEFINE_UNIT(lock_chk, mutex_simple_lifecycle) {
395 struct mutex_simple s1;
396 struct mutex_simple s2;
397
398 mutex_simple_init(&s1);
399 mutex_simple_init(&s2);
400
401 mutex_simple_lock(&s1);
402 mutex_simple_unlock(&s1);
403
404 mutex_simple_lock_subclass(&s1, 1);
405 mutex_simple_unlock(&s1);
406
407 mutex_simple_lock(&s1);
408 mutex_simple_lock(&s2);
409
410 mutex_simple_unlock(&s1);
411 mutex_simple_unlock(&s2);
412
413 return TEST_SUCCESS;
414}
415
416TEST_DEFINE_UNIT(lock_chk, rw_reader_ring_and_conflict) {
417 struct lock_chk_graph *graph = &lock_chk_test_graph;
418 lock_chk_graph_init(graph);
419
420 struct lock_chk_map map_a =
421 LOCK_CHK_MAP_VALUE_INIT(LOCK_CHK_CLASS(graph_test_class_a));
422 struct lock_chk_map map_b =
423 LOCK_CHK_MAP_VALUE_INIT(LOCK_CHK_CLASS(graph_test_class_b));
424
425 struct lock_chk_node *node_a = NULL;
426 struct lock_chk_node *node_b = NULL;
427
428 TEST_ASSERT_EQ(
429 lock_chk_graph_resolve_node(TEST_CTX(graph), &map_a, 0, &node_a),
430 LOCK_CHK_RESULT_OK);
431 TEST_ASSERT_EQ(
432 lock_chk_graph_resolve_node(TEST_CTX(graph), &map_b, 0, &node_b),
433 LOCK_CHK_RESULT_OK);
434
435 TEST_ASSERT_EQ(
436 lock_chk_graph_add_dep(TEST_CTX(graph),
437 lock_chk_dep_make(node_a, LOCK_CHK_MODE_SHARED),
438 lock_chk_dep_make(node_b, LOCK_CHK_MODE_SHARED)),
439 LOCK_CHK_RESULT_OK);
440 TEST_ASSERT_EQ(
441 lock_chk_graph_add_dep(TEST_CTX(graph),
442 lock_chk_dep_make(node_b, LOCK_CHK_MODE_SHARED),
443 lock_chk_dep_make(node_a, LOCK_CHK_MODE_SHARED)),
444 LOCK_CHK_RESULT_OK);
445
446 lock_chk_graph_init(graph);
447 TEST_ASSERT_EQ(
448 lock_chk_graph_resolve_node(TEST_CTX(graph), &map_a, 0, &node_a),
449 LOCK_CHK_RESULT_OK);
450 TEST_ASSERT_EQ(
451 lock_chk_graph_resolve_node(TEST_CTX(graph), &map_b, 0, &node_b),
452 LOCK_CHK_RESULT_OK);
453
454 TEST_ASSERT_EQ(lock_chk_graph_add_dep(
455 TEST_CTX(graph),
456 lock_chk_dep_make(node_a, LOCK_CHK_MODE_SHARED),
457 lock_chk_dep_make(node_b, LOCK_CHK_MODE_EXCLUSIVE)),
458 LOCK_CHK_RESULT_OK);
459 TEST_ASSERT_EQ(lock_chk_graph_add_dep(
460 TEST_CTX(graph),
461 lock_chk_dep_make(node_b, LOCK_CHK_MODE_SHARED),
462 lock_chk_dep_make(node_a, LOCK_CHK_MODE_EXCLUSIVE)),
463 LOCK_CHK_RESULT_CYCLE);
464
465 lock_chk_graph_init(graph);
466 TEST_ASSERT_EQ(
467 lock_chk_graph_resolve_node(TEST_CTX(graph), &map_a, 0, &node_a),
468 LOCK_CHK_RESULT_OK);
469 TEST_ASSERT_EQ(
470 lock_chk_graph_resolve_node(TEST_CTX(graph), &map_b, 0, &node_b),
471 LOCK_CHK_RESULT_OK);
472
473 TEST_ASSERT_EQ(lock_chk_graph_add_dep(
474 TEST_CTX(graph),
475 lock_chk_dep_make(node_a, LOCK_CHK_MODE_EXCLUSIVE),
476 lock_chk_dep_make(node_b, LOCK_CHK_MODE_EXCLUSIVE)),
477 LOCK_CHK_RESULT_OK);
478 TEST_ASSERT_EQ(lock_chk_graph_add_dep(
479 TEST_CTX(graph),
480 lock_chk_dep_make(node_b, LOCK_CHK_MODE_EXCLUSIVE),
481 lock_chk_dep_make(node_a, LOCK_CHK_MODE_EXCLUSIVE)),
482 LOCK_CHK_RESULT_CYCLE);
483
484 return TEST_SUCCESS;
485}
486
487TEST_DEFINE_UNIT(lock_chk, rwlock_lifecycle) {
488 struct rwlock rw;
489 rwlock_init(&rw, THREAD_PRIO_CLASS_TIMESHARE);
490
491 /* Read acquire and release */
492 rw_read_lock(&rw);
493 rw_unlock(&rw);
494
495 /* Write acquire and release */
496 rw_write_lock(&rw);
497 rw_unlock(&rw);
498
499 /* Subclass read and write */
500 rw_read_lock_subclass(&rw, 1);
501 rw_unlock(&rw);
502
503 rw_write_lock_subclass(&rw, 2);
504 rw_unlock(&rw);
505
506 return TEST_SUCCESS;
507}
508
509TEST_DEFINE_UNIT(lock_chk, subclasses_all_primitives) {
510 struct spinlock spin;
511 struct qspinlock qspin;
512 struct mutex mtx;
513 struct mutex_simple mtx_s;
514 struct rwlock rw;
515
516 spinlock_init(&spin);
517 qspinlock_init(&qspin);
518 mutex_init(&mtx);
519 mutex_simple_init(&mtx_s);
520 rwlock_init(&rw, THREAD_PRIO_CLASS_TIMESHARE);
521
522 for (unsigned int sc = 0; sc < 8; sc++) {
523 enum irql irql;
524
525 irql = spin_lock_subclass(&spin, sc);
526 spin_unlock(&spin, irql);
527
528 irql = qspin_lock_subclass(&qspin, sc);
529 qspin_unlock(&qspin, irql);
530
531 mutex_lock_subclass(&mtx, sc);
532 mutex_unlock(&mtx);
533
534 mutex_simple_lock_subclass(&mtx_s, sc);
535 mutex_simple_unlock(&mtx_s);
536
537 rw_read_lock_subclass(&rw, sc);
538 rw_unlock(&rw);
539
540 rw_write_lock_subclass(&rw, sc);
541 rw_unlock(&rw);
542 }
543
544 return TEST_SUCCESS;
545}
546
547#endif /* DEBUG_LOCK_CHK */
548