TEXT
25
mtx lock
Guest on 24th January 2023 02:00:35 PM
mtx_lock(unsigned long *lock) {
unsigned long l;
retry:
l = *lock;
if (l == 0) {
if (cmpxchg(lock, 0, 1)) // cmpxchg returns 1 on failure
// cmpxchg(addr, old, new)
goto retry;
return;
}
current->next = l & MASK;
if (cmpxchg(lock, l, current | 1))
goto retry;
sleep_on_queue(current);
}
mtx_unlock(unsigned long *lock) {
unsigned long l;
struct thread *head, *p;
retry:
l = *lock;
if (l == 1) {
if (cmpxchg(lock, 1, 0))
goto retry;
return;
}
head = (struct thread *)(l & MASK);
// remove current from queue
list_for_each(p, head) {
if (p->next == current) {
p->next = current->next;
break;
}
}
if (cmpxchg(lock, head | 1, head->next))
goto retry;
wake_up_one(head);
}