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); }