44 lines
1.0 KiB
C
44 lines
1.0 KiB
C
/*
|
|
* @author xamidev <xamidev@riseup.net>
|
|
* @brief Spinlock implementation
|
|
* @license GPL-3.0-only
|
|
*/
|
|
|
|
#include <stdatomic.h>
|
|
#include <stdbool.h>
|
|
#include <kernel.h>
|
|
#include <sched/spinlock.h>
|
|
|
|
/*
|
|
* spinlock_acquire - Lock a lock
|
|
* @lock: pointer to desired spinlock
|
|
*
|
|
* Saves the RFLAGS register, then acquires a lock.
|
|
* Pause instruction is used to ease the CPU.
|
|
*/
|
|
void spinlock_acquire(struct spinlock_t* lock)
|
|
{
|
|
uint64_t rflags;
|
|
asm volatile("pushfq ; pop %0 ; cli" : "=rm"(rflags) : : "memory");
|
|
|
|
while (__atomic_test_and_set(&lock->locked, __ATOMIC_ACQUIRE)) {
|
|
__builtin_ia32_pause();
|
|
}
|
|
|
|
lock->rflags = rflags;
|
|
}
|
|
|
|
/*
|
|
* spinlock_release - Unlock a lock
|
|
* @lock: pointer to desired spinlock
|
|
*
|
|
* Gets saved RFLAGS register from the lock and
|
|
* unlocks it (clears locked state).
|
|
* RFLAGS is then restored.
|
|
*/
|
|
void spinlock_release(struct spinlock_t* lock)
|
|
{
|
|
uint64_t rflags = lock->rflags;
|
|
__atomic_clear(&lock->locked, __ATOMIC_RELEASE);
|
|
asm volatile("push %0 ; popfq" : : "rm"(rflags) : "memory");
|
|
} |