From 33d55b2cd2e059450ee786fea0cf309c9b9e9bc1 Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Thu, 28 Aug 2025 14:45:45 +0200 Subject: [PATCH] Spinlocks --- spinlocks/Makefile | 14 ++++++++++ spinlocks/main.c | 31 +++++++++++++++++++++ spinlocks/spinlock.h | 66 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 spinlocks/Makefile create mode 100644 spinlocks/main.c create mode 100644 spinlocks/spinlock.h diff --git a/spinlocks/Makefile b/spinlocks/Makefile new file mode 100644 index 0000000..d246f81 --- /dev/null +++ b/spinlocks/Makefile @@ -0,0 +1,14 @@ +CC = gcc +CFLAGS = -Wall -O2 + +TARGET = main.elf +SRC = main.c + +#LDFLAGS = + +$(TARGET): $(SRC) + @echo CC $@ + @$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +clean: + rm -f $(TARGET) diff --git a/spinlocks/main.c b/spinlocks/main.c new file mode 100644 index 0000000..baeb8bc --- /dev/null +++ b/spinlocks/main.c @@ -0,0 +1,31 @@ +#include +#include +#include "spinlock.h" + +spinlock_t lock; +int counter = 0; + +void *worker(void *arg) { + printf("Hello from %s!\n", (char *)arg); + for (int i = 0; i < 100000; i++) { + acquire(&lock); + counter++; + release(&lock); + } + return NULL; +} + +int main() { + pthread_t thread1, thread2; + + initlock(&lock); + + pthread_create(&thread1, NULL, worker, "Thread1"); + pthread_create(&thread2, NULL, worker, "Thread2"); + + pthread_join(thread1, NULL); + pthread_join(thread2, NULL); + + printf("Counter value: %d\n", counter); + return 0; +} diff --git a/spinlocks/spinlock.h b/spinlocks/spinlock.h new file mode 100644 index 0000000..d1eac05 --- /dev/null +++ b/spinlocks/spinlock.h @@ -0,0 +1,66 @@ +typedef struct { + volatile unsigned int locked; // 0 = unlocked, 1 = locked +} spinlock_t; + +static inline void initlock(spinlock_t *lk) { + lk->locked = 0; +} + +static inline void acquire(spinlock_t *lk) { + while (__sync_lock_test_and_set(&lk->locked, 1) != 0); // spin +} + +static inline void release(spinlock_t *lk) { + __sync_lock_release(&lk->locked); +} + +#ifdef ATOMIC_MUTEX + +#include +#include + +typedef struct { + atomic_int flag; +} mutex_t; + +void mutex_init(mutex_t *m) { + atomic_store(&m->flag, 0); +} + +void mutex_lock(mutex_t *m) { + int expected; + do { + expected = 0; + } while (!atomic_compare_exchange_weak(&m->flag, &expected, 1)); +} + +void mutex_unlock(mutex_t *m) { + atomic_store(&m->flag, 0); +} + +#endif +#ifdef ATOMIC_MUTEX_RISCV + +typedef struct { + volatile int locked; +} spinlock_t; + +void spinlock_init(spinlock_t *lk) { + lk->locked = 0; +} + +void spinlock_acquire(spinlock_t *lk) { + int tmp; + do { + __asm__ volatile("amoswap.w %0, %1, (%2)" + : "=r"(tmp) // old value in tmp + : "r"(1), "r"(&lk->locked) // store 1 into memory + : "memory"); + } while (tmp != 0); // spin until old value was 0 +} + +void spinlock_release(spinlock_t *lk) { + __asm__ volatile("amoswap.w zero, %1, (%0)" : : "r"(&lk->locked), "r"(0) : "memory"); +} + +#endif