mirror of
https://github.com/BoredDevNL/BoredOS.git
synced 2026-05-15 18:58:40 +00:00
62 lines
2 KiB
C
62 lines
2 KiB
C
// Copyright (c) 2023-2026 Chris (boreddevnl)
|
|
// This software is released under the GNU General Public License v3.0. See LICENSE file for details.
|
|
// This header needs to maintain in any file it is present in, as per the GPL license terms.
|
|
#ifndef SPINLOCK_H
|
|
#define SPINLOCK_H
|
|
|
|
#include <stdint.h>
|
|
|
|
// Simple test-and-set spinlock for x86_64 SMP.
|
|
// Uses 'lock xchg' for acquire and a plain store for release.
|
|
// Includes 'pause' to reduce bus contention while spinning.
|
|
|
|
typedef volatile uint32_t spinlock_t;
|
|
|
|
#define SPINLOCK_INIT 0
|
|
|
|
static inline void spinlock_acquire(spinlock_t *lock) {
|
|
while (1) {
|
|
// Try to set the lock from 0 -> 1
|
|
uint32_t prev;
|
|
asm volatile("lock xchgl %0, %1"
|
|
: "=r"(prev), "+m"(*lock)
|
|
: "0"((uint32_t)1)
|
|
: "memory");
|
|
if (prev == 0) return; // We got the lock
|
|
// Spin with pause (reduces power and bus traffic)
|
|
while (*lock) {
|
|
asm volatile("pause" ::: "memory");
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline void spinlock_release(spinlock_t *lock) {
|
|
asm volatile("" ::: "memory"); // compiler barrier
|
|
*lock = 0;
|
|
}
|
|
|
|
// Try to acquire without blocking. Returns 1 if acquired, 0 if not.
|
|
static inline int spinlock_try(spinlock_t *lock) {
|
|
uint32_t prev;
|
|
asm volatile("lock xchgl %0, %1"
|
|
: "=r"(prev), "+m"(*lock)
|
|
: "0"((uint32_t)1)
|
|
: "memory");
|
|
return (prev == 0);
|
|
}
|
|
|
|
// IRQ-safe spinlock: saves flags, disables interrupts, then acquires.
|
|
// Use when the lock may be contended from interrupt context.
|
|
static inline uint64_t spinlock_acquire_irqsave(spinlock_t *lock) {
|
|
uint64_t flags;
|
|
asm volatile("pushfq; pop %0; cli" : "=r"(flags) :: "memory");
|
|
spinlock_acquire(lock);
|
|
return flags;
|
|
}
|
|
|
|
static inline void spinlock_release_irqrestore(spinlock_t *lock, uint64_t flags) {
|
|
spinlock_release(lock);
|
|
asm volatile("push %0; popfq" : : "r"(flags) : "memory");
|
|
}
|
|
|
|
#endif
|