4 * Rune locking implementation. The inlines try the easy cases and punt to a
5 * real procedure for the harder cases.
7 * NOTE: lklist_t defined in thread.h
10 void _RuneLockEx(runelock_t *lock, int hard);
11 void _RuneUnlockEx(runelock_t *lock, int hard);
12 void _RuneLockReacquire(runethr_t *td);
13 void _RuneAutostealLock(runethr_t *otd, runethr_t *ntd, runelock_t *lock);
16 * Initialize a lock. The caller must have already pre-zerod the lock.
20 initLock(runelock_t *lock __unused)
22 /* RUNE_INIT(&lock->rl_Blocked); */
26 * Insert the lock onto the thread's locklist using the supplied tlc.
30 RuneInsertTLC(runethr_t *td, runelock_t *lock, runetlc_t *tlc)
33 tlc->count = lock->rl_Count & RLCOUNTF_MASK;
34 tlc->next = td->td_TLC;
39 * The idle lock is pre-initialized and locked to the specified thread, which
40 * might not be the current thread.
44 initInitialLock(runethr_t *td, runelock_t *lock, runetlc_t *tlc)
47 lock->rl_Count = RLCOUNT_INCR;
48 RuneInsertTLC(td, lock, tlc);
53 * Dispose of a TLC after its lock has been released.
55 * Asserts if the tlc crosses a semantic (lock == NULL) boundary.
59 RuneDisposeTLC(rgd_t *rgd, runethr_t *td, runelock_t *lock)
67 if (tlc->lock == lock)
69 dassert(tlc->lock != NULL);
73 tlc->next = rgd->FreeTLC;
82 RuneLockEx(runelock_t *lock, int hard)
84 rgd_t *rgd = getrgd();
85 runethr_t *td = rgd->CurThread;
86 runetlc_t *tlc = rgd->FreeTLC;
90 * Try to acquire the lock quickly
92 if (lock->rl_Owner == td) {
93 dassert(lock->rl_Count & RLCOUNTF_MASK);
94 atomic_add_rune(&lock->rl_Count, RLCOUNT_INCR);
95 lock->rl_Hard += hard;
96 rgd->FreeTLC = tlc->next;
97 RuneInsertTLC(td, lock, tlc);
98 #ifdef DEBUG_RUNELOCKS
99 printf("%p LOCK %p by %p\n", rgd, lock, td);
102 if (lock == (void *)(uintptr_t) 0x8018b0180LLU)
111 count = lock->rl_Count;
115 if (atomic_cmpset_rune(&lock->rl_Count, 0, RLCOUNT_INCR)) {
116 dassert(lock->rl_Owner == NULL &&
119 lock->rl_Hard = hard;
120 rgd->FreeTLC = tlc->next;
121 RuneInsertTLC(td, lock, tlc);
122 #ifdef DEBUG_RUNELOCKS
123 printf("%p LOCK %p by %p\n", rgd, lock, td);
134 _RuneLockEx(lock, hard);
139 * Release a Rune lock
143 RuneUnlockEx(runelock_t *lock, int hard)
145 rgd_t *rgd = getrgd();
146 runethr_t *td = rgd->CurThread;
148 dassert(lock->rl_Owner == td && lock->rl_Hard >= hard);
152 count = lock->rl_Count;
158 if (count > (RLCOUNT_INCR | ~RLCOUNTF_MASK)) {
159 lock->rl_Hard -= hard;
160 atomic_add_rune(&lock->rl_Count, -RLCOUNT_INCR);
161 RuneDisposeTLC(rgd, td, lock);
162 #ifdef DEBUG_RUNELOCKS
163 printf("%p UNLCK %p(%08lx) by %p\n",
164 rgd, lock, lock->rl_Count, td);
170 * If waiters pending punt to the real procedure.
172 if (count & RLCOUNTF_EXREQ)
178 lock->rl_Owner = NULL;
179 lock->rl_Hard -= hard;
180 dassert(lock->rl_Hard == 0);
181 if (atomic_cmpset_rune(&lock->rl_Count, count, 0)) {
182 RuneDisposeTLC(rgd, td, lock);
183 #ifdef DEBUG_RUNELOCKS
184 printf("%p UNLCK %p(%08lx) by %p\n",
185 rgd, lock, lock->rl_Count, td);
189 lock->rl_Hard += hard;
196 _RuneUnlockEx(lock, hard);
201 * The lock is dead (the memory is gone), causes an assertion if anyone
202 * attempts to obtain it.
206 RuneLockDead(runelock_t *lock)
208 atomic_set_rune(&lock->rl_Count, RLCOUNTF_DEAD);
209 atomic_add_rune(&lock->rl_Count, RLCOUNT_INCR);