bond/kern/spin_lock.c

61 lines
1.1 KiB
C
Raw Normal View History

2019-06-26 05:47:18 +00:00
#include <kern/cdef.h>
#include <kern/spin_lock.h>
2019-11-28 18:02:52 +00:00
static inline uint32
_spin_lock_get_ticket(uint32 val)
2019-06-26 05:47:18 +00:00
{
2019-11-28 18:02:52 +00:00
return val & 0xFFFFu;
2019-06-26 05:47:18 +00:00
}
2019-11-28 18:02:52 +00:00
static inline uint32
_spin_lock_get_owner(uint32 val)
{
return val >> 16u;
}
2019-06-26 05:47:18 +00:00
void
2019-11-28 18:02:52 +00:00
spin_lock_init(struct spin_lock *lock)
2019-06-26 05:47:18 +00:00
{
2019-11-28 18:02:52 +00:00
atomic_store(&lock->val, 0);
2019-06-26 05:47:18 +00:00
}
2019-11-28 18:02:52 +00:00
void
spin_lock_acq(struct spin_lock *lock)
{
uint32 val;
do {
val = atomic_load(&lock->val);
} while (!atomic_compare_exchange_weak(&lock->val, &val, val + (1u << 16u)));
// val now contains cur ticket and target ticket
while (_spin_lock_get_ticket(val) != _spin_lock_get_owner(val)) {
val = atomic_load(&lock->val);
}
// owner = ticket, we've acquired the lock
}
2019-06-26 05:47:18 +00:00
void
2019-11-28 18:02:52 +00:00
spin_lock_rel(struct spin_lock *lock)
2019-06-26 05:47:18 +00:00
{
2019-11-28 18:02:52 +00:00
// increment ticket
atomic_fetch_add(&lock->val, 1);
}
int
spin_lock_try_acq(struct spin_lock *lock)
{
uint32 val;
val = atomic_load(&lock->val);
if ((_spin_lock_get_owner(val) == _spin_lock_get_ticket(val)) &&
atomic_compare_exchange_weak(&lock->val, &val, val + (1u << 16u))) {
return 1;
2019-06-26 05:47:18 +00:00
}
2019-11-28 18:02:52 +00:00
return 0;
2019-06-26 05:47:18 +00:00
}