mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 08:24:32 -08:00
Also updated spinlock interface to be an object, and added a scoped lock object that uses it as well.
50 lines
901 B
C++
50 lines
901 B
C++
#include "kutil/spinlock.h"
|
|
|
|
namespace kutil {
|
|
|
|
static constexpr int memorder = __ATOMIC_SEQ_CST;
|
|
|
|
spinlock::spinlock() : m_lock {nullptr} {}
|
|
spinlock::~spinlock() {}
|
|
|
|
void
|
|
spinlock::acquire(waiter *w)
|
|
{
|
|
w->next = nullptr;
|
|
w->locked = true;
|
|
|
|
// Point the lock at this waiter
|
|
waiter *prev = __atomic_exchange_n(&m_lock, w, memorder);
|
|
if (prev) {
|
|
// If there was a previous waiter, wait for them to
|
|
// unblock us
|
|
prev->next = w;
|
|
while (w->locked) {
|
|
asm ("pause");
|
|
}
|
|
} else {
|
|
w->locked = false;
|
|
}
|
|
}
|
|
|
|
void
|
|
spinlock::release(waiter *w)
|
|
{
|
|
if (!w->next) {
|
|
// If we're still the last waiter, we're done
|
|
if(__atomic_compare_exchange_n(&m_lock, &w, nullptr, false, memorder, memorder))
|
|
return;
|
|
}
|
|
|
|
// Wait for the subseqent waiter to tell us who they are
|
|
while (!w->next) {
|
|
asm ("pause");
|
|
}
|
|
|
|
// Unblock the subseqent waiter
|
|
w->next->locked = false;
|
|
}
|
|
|
|
|
|
} // namespace kutil
|