1#include "sync/tests/test_internal.h"
2
3#include <sync/seqlock.h>
4
5LOCK_CHK_CLASS_DECLARE_LOCAL(lock_reinit_class);
6static MUTEX_SIMPLE_DEFINE(static_simple_mutex);
7
8#ifdef DEBUG_LOCK_CHK
9
10static bool lock_init_state_valid(struct spinlock *spin,
11 struct qspinlock *qspin, struct mutex *mutex,
12 struct mutex_simple *simple,
13 struct rwlock *rw, struct seqlock *seq) {
14 return spin->chk.initialized && spin->chk.flags == LOCK_CHKD_FULL &&
15 spin->chk.map.class != NULL && qspin->chk.initialized &&
16 qspin->chk.flags == LOCK_CHKD_FULL && qspin->chk.map.class != NULL &&
17 mutex->chk.initialized && mutex->chk.flags == LOCK_CHKD_FULL &&
18 mutex->chk.map.class != NULL && simple->chk.initialized &&
19 simple->chk.flags == LOCK_CHKD_FULL &&
20 simple->chk.map.class != NULL && rw->chk.initialized &&
21 rw->chk.flags == LOCK_CHKD_FULL && rw->chk.map.class != NULL &&
22 seq->lock.chk.initialized && seq->lock.chk.flags == LOCK_CHKD_FULL &&
23 seq->lock.chk.map.class != NULL;
24}
25
26static bool lock_reinit_state_valid(struct spinlock *spin,
27 struct qspinlock *qspin,
28 struct mutex *mutex,
29 struct mutex_simple *simple,
30 struct rwlock *rw) {
31 const struct lock_chk_class *class = LOCK_CHK_CLASS(lock_reinit_class);
32
33 return spin->chk.flags == LOCK_CHKD_FULL && spin->chk.map.class == class &&
34 qspin->chk.flags == LOCK_CHKD_FULL &&
35 qspin->chk.map.class == class &&
36 mutex->chk.flags == LOCK_CHKD_FULL &&
37 mutex->chk.map.class == class &&
38 simple->chk.flags == LOCK_CHKD_FULL &&
39 simple->chk.map.class == class && rw->chk.flags == LOCK_CHKD_FULL &&
40 rw->chk.map.class == class;
41}
42
43#else /* !defined(DEBUG_LOCK_CHK) */
44
45static bool lock_init_state_valid(struct spinlock *spin,
46 struct qspinlock *qspin, struct mutex *mutex,
47 struct mutex_simple *simple,
48 struct rwlock *rw, struct seqlock *seq) {
49 unused(spin, qspin, mutex, simple, rw, seq);
50 return true;
51}
52
53static bool lock_reinit_state_valid(struct spinlock *spin,
54 struct qspinlock *qspin,
55 struct mutex *mutex,
56 struct mutex_simple *simple,
57 struct rwlock *rw) {
58 unused(spin, qspin, mutex, simple, rw);
59 return true;
60}
61
62#endif /* DEBUG_LOCK_CHK */
63
64TEST_DECLARE_UNIT(lock_chk, initializers_install_policy) {
65 struct spinlock spin;
66 struct qspinlock qspin;
67 struct mutex mutex;
68 struct mutex_simple simple;
69 struct rwlock rw;
70 struct seqlock seq;
71
72 spinlock_init(&spin);
73 qspinlock_init(&qspin);
74 mutex_init(&mutex);
75 mutex_simple_init(&simple);
76 rwlock_init(&rw, THREAD_PRIO_CLASS_TIMESHARE);
77 seqlock_init(&seq);
78
79 TEST_ASSERT(list_empty(&static_simple_mutex.waiters.list));
80 TEST_ASSERT(
81 lock_init_state_valid(&spin, &qspin, &mutex, &simple, &rw, &seq));
82 return TEST_SUCCESS;
83}
84
85TEST_DECLARE_UNIT(lock_chk, policy_mutation_and_reinit) {
86 struct spinlock spin;
87 struct qspinlock qspin;
88 struct mutex mutex;
89 struct mutex_simple simple;
90 struct rwlock rw;
91 const struct lock_chk_class *class = LOCK_CHK_CLASS(lock_reinit_class);
92
93 spinlock_init(&spin);
94 qspinlock_init(&qspin);
95 mutex_init(&mutex);
96 mutex_simple_init(&simple);
97 rwlock_init(&rw, THREAD_PRIO_CLASS_TIMESHARE);
98
99 spinlock_set_chk_flags(lock: &spin, flags: LOCK_CHKD_ORDER);
100 qspinlock_set_chk_flags(lock: &qspin, flags: LOCK_CHKD_ORDER);
101 mutex_set_chk_flags(mtx: &mutex, flags: LOCK_CHKD_THREAD);
102 mutex_simple_set_chk_flags(m: &simple, flags: LOCK_CHKD_THREAD);
103 rwlock_set_chk_flags(lock: &rw, flags: LOCK_CHKD_THREAD);
104
105 spinlock_reinit_chk(lock: &spin, class, flags: LOCK_CHKD_FULL);
106 qspinlock_reinit_chk(lock: &qspin, class, flags: LOCK_CHKD_FULL);
107 mutex_reinit_chk(mtx: &mutex, class, flags: LOCK_CHKD_FULL);
108 mutex_simple_reinit_chk(m: &simple, class, flags: LOCK_CHKD_FULL);
109 rwlock_reinit_chk(lock: &rw, ceiling: THREAD_PRIO_CLASS_URGENT, class, flags: LOCK_CHKD_FULL);
110
111 TEST_ASSERT(lock_reinit_state_valid(&spin, &qspin, &mutex, &simple, &rw));
112 return TEST_SUCCESS;
113}
114