diff options
| author | Ian Moffett <ian@osmora.org> | 2025-12-22 17:21:18 -0500 |
|---|---|---|
| committer | Ian Moffett <ian@osmora.org> | 2025-12-22 17:25:02 -0500 |
| commit | 7e1c513582fd05bd85f8f4dfa73e374f3ff351ec (patch) | |
| tree | d52fc7d57a19e18947433a799d2fdc7d789c1e40 | |
| parent | 9116998d45645d24237bd92c45307f7d76f28b59 (diff) | |
mos: kern: Add spinlock sources
Signed-off-by: Ian Moffett <ian@osmora.org>
| -rw-r--r-- | mos/sys/inc/kern/spinlock.h | 53 | ||||
| -rw-r--r-- | mos/sys/kern/kern_spinlock.c | 72 |
2 files changed, 125 insertions, 0 deletions
diff --git a/mos/sys/inc/kern/spinlock.h b/mos/sys/inc/kern/spinlock.h new file mode 100644 index 0000000..3168a1b --- /dev/null +++ b/mos/sys/inc/kern/spinlock.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025, Ian Moffett. + * Provided under the BSD-3 clause. + */ + +#ifndef _KERN_SPINLOCK_H_ +#define _KERN_SPINLOCK_H_ 1 + +#include <sdk/types.h> +#include <sdk/status.h> +#include <sdk/param.h> + +/* Parameters */ +#define SPINLOCK_NAMELEN 16 + +/* Flags */ +#define SPINLOCK_IRQMUT BIT(0) /* Mutate IRQ state */ + +/* + * Represents a spinlock + * + * @name: Spinlock name + * @lock: Actual lock + */ +typedef struct { + char name[SPINLOCK_NAMELEN]; + USIZE lock; +} SPINLOCK; + +/* + * Initialize a spinlock descriptor + * + * @name: Name of spinlock + * @res: Result is written here + */ +MOS_STATUS spinlock_init(const char *name, SPINLOCK *res); + +/* + * Acquire a spinlock + * + * @lock: Lock to acquire + * @flags: Optional flags + */ +void spinlock_acquire(SPINLOCK *lock, USHORT flags); + +/* + * Release a spinlock + * + * @lock: Lock to release + */ +void spinlock_release(SPINLOCK *lock); + +#endif /* !_KERN_SPINLOCK_H_ */ diff --git a/mos/sys/kern/kern_spinlock.c b/mos/sys/kern/kern_spinlock.c new file mode 100644 index 0000000..aaa80de --- /dev/null +++ b/mos/sys/kern/kern_spinlock.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2025, Ian Moffett. + * Provided under the BSD-3 clause. + */ + +#include <sdk/types.h> +#include <sdk/status.h> +#include <sdk/string.h> +#include <mu/cpu.h> +#include <kern/spinlock.h> + +MOS_STATUS +spinlock_init(const char *name, SPINLOCK *res) +{ + USIZE name_len; + + if (name == NULL || res == NULL) { + return STATUS_INVALID_ARG; + } + + name_len = strlen(name); + if (name_len >= SPINLOCK_NAMELEN - 1) { + return STATUS_NAME_TOO_LONG; + } + + memcpy(res->name, name, name_len); + res->lock = 0; + return STATUS_SUCCESS; +} + +void +spinlock_acquire(SPINLOCK *lock, USHORT flags) +{ + BOOL irq_state = false; + + if (lock == NULL) { + return; + } + + /* + * Usually this should be the default but this kind of thing should + * be somewhat deterministic. If we are to mutate, mask the interrupts. + */ + if (ISSET(flags, SPINLOCK_IRQMUT)) { + irq_state = mu_irq_state(); + mu_irq_setmask(true); + } + + /* + * Now we'll spin. And no, we will not put ourselves to sleep + * here. This needs to be invoked early on before there even + * is such thing as a process context. + */ + while (mu_cpu_aswap(&lock->lock, 1)) { + mu_cpu_pause(); + } + + /* Restore the state if we've mutated it */ + if (ISSET(flags, SPINLOCK_IRQMUT) && irq_state) { + mu_irq_setmask(false); + } +} + +void +spinlock_release(SPINLOCK *lock) +{ + if (lock == NULL) { + return; + } + + mu_cpu_aswap(&lock->lock, 0); +} |
