HelenOS sources
This source file includes following definitions.
- owned_by_me
- not_owned_by_me
- claim
- unclaim
- owned_by_me
- not_owned_by_me
- claim
- unclaim
- irq_spinlock_initialize
- irq_spinlock_lock
- irq_spinlock_unlock
- irq_spinlock_trylock
- irq_spinlock_pass
- irq_spinlock_exchange
- irq_spinlock_locked
#include <arch/asm.h>
#include <synch/spinlock.h>
#include <cpu.h>
#ifdef CONFIG_DEBUG_SPINLOCK
#define CPU_OWNER ((CPU == NULL) ? (cpu_t *) UINTPTR_MAX : CPU)
static inline bool owned_by_me(irq_spinlock_t *lock)
{
return atomic_load_explicit(&lock->owner, memory_order_relaxed) == CPU_OWNER;
}
static inline bool not_owned_by_me(irq_spinlock_t *lock)
{
return !owned_by_me(lock);
}
static inline void claim(irq_spinlock_t *lock)
{
cpu_t *cpu = CPU_OWNER;
atomic_store_explicit(&lock->owner, cpu, memory_order_relaxed);
CURRENT->mutex_locks++;
}
static inline void unclaim(irq_spinlock_t *lock)
{
CURRENT->mutex_locks--;
atomic_store_explicit(&lock->owner, NULL, memory_order_relaxed);
}
#else
static inline bool owned_by_me(irq_spinlock_t *lock)
{
return true;
}
static inline bool not_owned_by_me(irq_spinlock_t *lock)
{
return true;
}
static inline void claim(irq_spinlock_t *lock)
{
}
static inline void unclaim(irq_spinlock_t *lock)
{
}
#endif
void irq_spinlock_initialize(irq_spinlock_t *lock, const char *name)
{
*lock = (irq_spinlock_t) IRQ_SPINLOCK_INITIALIZER(name);
}
void irq_spinlock_lock(irq_spinlock_t *lock, bool irq_dis)
{
ASSERT_IRQ_SPINLOCK(not_owned_by_me(lock), lock);
if (irq_dis) {
ipl_t ipl = interrupts_disable();
spinlock_lock(&(lock->lock));
lock->guard = true;
lock->ipl = ipl;
} else {
ASSERT_IRQ_SPINLOCK(interrupts_disabled(), lock);
spinlock_lock(&(lock->lock));
ASSERT_IRQ_SPINLOCK(!lock->guard, lock);
}
claim(lock);
}
void irq_spinlock_unlock(irq_spinlock_t *lock, bool irq_res)
{
ASSERT_IRQ_SPINLOCK(interrupts_disabled(), lock);
ASSERT_IRQ_SPINLOCK(owned_by_me(lock), lock);
unclaim(lock);
if (irq_res) {
ASSERT_IRQ_SPINLOCK(lock->guard, lock);
lock->guard = false;
ipl_t ipl = lock->ipl;
spinlock_unlock(&(lock->lock));
interrupts_restore(ipl);
} else {
ASSERT_IRQ_SPINLOCK(!lock->guard, lock);
spinlock_unlock(&(lock->lock));
}
}
bool irq_spinlock_trylock(irq_spinlock_t *lock)
{
ASSERT_IRQ_SPINLOCK(interrupts_disabled(), lock);
bool ret = spinlock_trylock(&(lock->lock));
if (ret)
claim(lock);
ASSERT_IRQ_SPINLOCK((!ret) || (!lock->guard), lock);
return ret;
}
void irq_spinlock_pass(irq_spinlock_t *unlock, irq_spinlock_t *lock)
{
ASSERT_IRQ_SPINLOCK(interrupts_disabled(), unlock);
ASSERT_IRQ_SPINLOCK(owned_by_me(unlock), unlock);
ASSERT_IRQ_SPINLOCK(not_owned_by_me(lock), lock);
bool guard = unlock->guard;
ipl_t ipl = unlock->ipl;
unlock->guard = false;
unclaim(unlock);
spinlock_unlock(&(unlock->lock));
spinlock_lock(&(lock->lock));
claim(lock);
ASSERT_IRQ_SPINLOCK(!lock->guard, lock);
if (guard) {
lock->guard = true;
lock->ipl = ipl;
}
}
void irq_spinlock_exchange(irq_spinlock_t *unlock, irq_spinlock_t *lock)
{
ASSERT_IRQ_SPINLOCK(interrupts_disabled(), unlock);
ASSERT_IRQ_SPINLOCK(owned_by_me(unlock), unlock);
ASSERT_IRQ_SPINLOCK(not_owned_by_me(lock), lock);
spinlock_lock(&(lock->lock));
ASSERT_IRQ_SPINLOCK(!lock->guard, lock);
if (unlock->guard) {
lock->guard = true;
lock->ipl = unlock->ipl;
unlock->guard = false;
}
claim(lock);
unclaim(unlock);
spinlock_unlock(&(unlock->lock));
}
bool irq_spinlock_locked(irq_spinlock_t *lock)
{
return owned_by_me(lock) && spinlock_locked(&lock->lock);
}
HelenOS homepage, sources at GitHub