Spinlocks
This commit is contained in:
parent
080928d3fd
commit
33d55b2cd2
3 changed files with 111 additions and 0 deletions
14
spinlocks/Makefile
Normal file
14
spinlocks/Makefile
Normal file
|
|
@ -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)
|
||||
31
spinlocks/main.c
Normal file
31
spinlocks/main.c
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#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;
|
||||
}
|
||||
66
spinlocks/spinlock.h
Normal file
66
spinlocks/spinlock.h
Normal file
|
|
@ -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 <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
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
|
||||
Loading…
Add table
Add a link
Reference in a new issue