Skip to content

Commit

Permalink
feat(multi-cores): printf and malloc are now thread-safe
Browse files Browse the repository at this point in the history
  • Loading branch information
Siudya committed Dec 16, 2024
1 parent 9ff1bd0 commit 2af9064
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 1 deletion.
4 changes: 4 additions & 0 deletions libs/klib/include/klib.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ void free(void *ptr);

void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));

uint64_t compare_and_swap(volatile uint64_t*, uint64_t, uint64_t);
void lock(volatile uint64_t *);
void release(volatile uint64_t *);

// assert.h
#ifdef NDEBUG
#define assert(ignore) ((void)0)
Expand Down
30 changes: 30 additions & 0 deletions libs/klib/src/atomic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "klib.h"
#include <klib-macros.h>

uint64_t compare_and_swap(volatile uint64_t* addr, uint64_t old_val, uint64_t new_val) {
uint64_t check = 0;
uint64_t value = 0;
asm volatile (
"lr.d %[value], (%[addr]);"
: [value]"=r"(value)
: [addr]"p"(addr)
);
if (value != old_val) return 1;
asm volatile (
"sc.d %[check], %[write], (%[addr]);"
: [check]"=r"(check)
: [write]"r"(new_val), [addr]"p"(addr)
);
return check;
}

void lock(volatile uint64_t *addr) {
asm volatile("csrci mstatus, 0x8");
while(compare_and_swap(addr, 0, 1));
}

void release(volatile uint64_t *addr) {
*addr = 1;
asm volatile("fence");
asm volatile("csrsi mstatus, 0x8");
}
5 changes: 5 additions & 0 deletions libs/klib/src/printf.c
Original file line number Diff line number Diff line change
Expand Up @@ -859,13 +859,18 @@ static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const

///////////////////////////////////////////////////////////////////////////////
#ifndef NOPRINT
void lock(volatile uint64_t *);
void release(volatile uint64_t *);
volatile uint64_t print_lock = 0;
int printf_(const char* format, ...)
{
va_list va;
lock(&print_lock);
va_start(va, format);
char buffer[1];
const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va);
va_end(va);
release(&print_lock);
return ret;
}
#else
Expand Down
11 changes: 10 additions & 1 deletion libs/klib/src/stdlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ static struct {
uintptr_t size;
} last = { .ptr = NULL, .size = 0 };

volatile uint64_t malloc_lock = 0;

void *malloc(size_t size) {
lock(&malloc_lock);
if (last.ptr == NULL) {
last.ptr = _heap.start;
printf("heap start = %x\n", last.ptr);
Expand All @@ -44,14 +47,20 @@ void *malloc(size_t size) {

// skip the region allocated by the last call
last.ptr += last.size;
if (last.ptr + size >= _heap.end) return NULL;
if (last.ptr + size >= _heap.end) {
release(&malloc_lock);
return NULL;
}
void *ret = last.ptr;
last.size = size;
release(&malloc_lock);
return ret;
}

void free(void *ptr) {
lock(&malloc_lock);
if (ptr == last.ptr) last.size = 0;
release(&malloc_lock);
}

#endif

0 comments on commit 2af9064

Please sign in to comment.