diff --git a/bump.c b/bump.c new file mode 100644 index 0000000..42a3ed0 --- /dev/null +++ b/bump.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include + +#define BUFSIZE (1024) +static uint8_t some_large_buf[BUFSIZE] = {0}; + +typedef struct { + uint8_t *buf; + size_t buflen; + size_t bufptr; +} fast_alloc_t; + +void *fast_alloc(fast_alloc_t *fa, size_t s) { + if (fa->bufptr + s > fa->buflen) { + return NULL; + } + void *p = fa->buf + fa->bufptr; + fa->bufptr += s; + return p; +} + +void fast_alloc_init(fast_alloc_t *fa, uint8_t *buf, size_t buflen) { + fa->buf = buf; + fa->buflen = buflen; + fa->bufptr = 0; +} + +void fast_alloc_wipe(fast_alloc_t *fa) { + fa->bufptr = 0; + memset(fa->buf, 0, fa->buflen); +} + +int main(void) { + fast_alloc_t fa = {0}; + fast_alloc_init(&fa, some_large_buf, BUFSIZE); + + int *a = fast_alloc(&fa, sizeof(int)); + *a = 10; + + int *b = fast_alloc(&fa, sizeof(int)); + *b = INT_MAX; + + printf("Number: %d\n", *a); + printf("Number: %d\n", *b); + assert(*a == 10); + assert(*b == INT_MAX); + + fast_alloc_wipe(&fa); + + printf("Number: %d\n", *a); + printf("Number: %d\n", *b); + assert(*a != 10); + assert(*b != INT_MAX); + + printf("All ok!\n"); +} diff --git a/prand.c b/prand.c index 9adf181..ba65868 100644 --- a/prand.c +++ b/prand.c @@ -2,14 +2,13 @@ #include #include #include +#include -#define BUILD_SEED \ +#define PRAND_BUILD_SEED \ ((uint64_t)(__TIME__[0]) * (uint64_t)(__TIME__[1]) * (uint64_t)(__TIME__[3]) * (uint64_t)(__TIME__[4]) * \ (uint64_t)(__TIME__[6]) * (uint64_t)(__TIME__[7])) -#define PRNG_SAVE_INTERVAL 50 // Save every 1000 calls to prand() - -static uint64_t seed = BUILD_SEED; +static uint64_t seed = PRAND_BUILD_SEED * 6364136223846793005ULL + 1; uint64_t prand() { seed = seed * 6364136223846793005ULL + 1; @@ -17,31 +16,44 @@ uint64_t prand() { } inline uint64_t prand_range(uint64_t min, uint64_t max) { - return min + (prand() % (max - min + 1)); + uint64_t range = max - min + 1; + uint64_t x; + uint64_t limit = UINT64_MAX - (UINT64_MAX % range); + + do { + x = prand(); + } while (x > limit); + + return min + (x % range); } void sprand(uint64_t s) { if (s) { - seed = s; + seed ^= (s * 0x9e3779b97f4a7c15ULL) + (seed << 6) + (seed >> 2); } else { - rand_reseed(); + seed ^= PRAND_BUILD_SEED; } } -void rand_reseed() { - seed = BUILD_SEED; -} +#undef PRAND_BUILD_SEED #define PRAND_MAIN #ifdef PRAND_MAIN int main() { // time(NULL) provides a somewhat unique seed at runtime sprand(time(NULL)); + sprand(getpid()); + sprand(0); uint64_t rn1 = prand(); uint64_t rn2 = prand(); printf("rn1 = %lu\n", rn1); printf("rn2 = %lu\n", rn2); + + for (int i = 0; i < 40; i++) { + uint64_t random = prand_range(0, 1000); + printf("random = %lu\n", random); + } } #endif diff --git a/signals/Makefile b/signals/Makefile new file mode 100644 index 0000000..33eef5b --- /dev/null +++ b/signals/Makefile @@ -0,0 +1,24 @@ +CC ?= gcc +CFLAGS ?= -Wall -O2 + +# This is not how makefiles should be written. +# Pretend you did not see this + +all: main.elf main_sigaction.elf + +TARGET = main.elf +SRC = main.c + +TARGET2 = main_sigaction.elf +SRC2 = main_sigaction.c + +$(TARGET): $(SRC) + @echo CC $@ + @$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +$(TARGET2): $(SRC2) + @echo CC $@ + @$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +clean: + rm -f *.elf diff --git a/signals/main.c b/signals/main.c new file mode 100644 index 0000000..b554fda --- /dev/null +++ b/signals/main.c @@ -0,0 +1,17 @@ +#include +#include +#include +#include + +void handler(int sig) { + printf("Caught signal %d\n", sig); + exit(1); +} + +int main() { + signal(SIGINT, handler); // Handle Ctrl+C + while (1) { + printf("Running...\n"); + sleep(1); + } +} diff --git a/signals/main_sigaction.c b/signals/main_sigaction.c new file mode 100644 index 0000000..7b8f128 --- /dev/null +++ b/signals/main_sigaction.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +void handler(int sig) { + write(1, "Caught SIGINT\n", 14); // Async-signal-safe output + exit(1); +} + +int main() { + struct sigaction sa; + sa.sa_handler = handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + + sigaction(SIGINT, &sa, NULL); + + while (1) { + printf("Running...\n"); + sleep(1); + } +} 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