Implement lock IRQ nesting via stack variables/contexts
All checks were successful
Build documentation / build-and-deploy (push) Successful in 21s

This commit is contained in:
2026-01-14 22:11:56 +01:00
parent 55166f9d5f
commit 270ff507d4
22 changed files with 197 additions and 145 deletions

View File

@@ -11,13 +11,13 @@
spin_lock_t _liballoc_lock = SPIN_LOCK_INIT;
int liballoc_lock (void) {
spin_lock (&_liballoc_lock);
int liballoc_lock (void* ctx) {
spin_lock (&_liballoc_lock, (spin_lock_ctx_t*)ctx);
return 0;
}
int liballoc_unlock (void) {
spin_unlock (&_liballoc_lock);
int liballoc_unlock (void* ctx) {
spin_unlock (&_liballoc_lock, (spin_lock_ctx_t*)ctx);
return 0;
}
@@ -243,8 +243,9 @@ void* malloc (size_t size) {
int index;
void* ptr;
struct boundary_tag* tag = NULL;
spin_lock_ctx_t ctxliba;
liballoc_lock ();
liballoc_lock (&ctxliba);
if (l_initialized == 0) {
for (index = 0; index < MAXEXP; index++) {
@@ -272,7 +273,7 @@ void* malloc (size_t size) {
// No page found. Make one.
if (tag == NULL) {
if ((tag = allocate_new_tag (size)) == NULL) {
liballoc_unlock ();
liballoc_unlock (&ctxliba);
return NULL;
}
@@ -305,23 +306,24 @@ void* malloc (size_t size) {
ptr = (void*)((uintptr_t)tag + sizeof (struct boundary_tag));
liballoc_unlock ();
liballoc_unlock (&ctxliba);
return ptr;
}
void free (void* ptr) {
int index;
struct boundary_tag* tag;
spin_lock_ctx_t ctxliba;
if (ptr == NULL)
return;
liballoc_lock ();
liballoc_lock (&ctxliba);
tag = (struct boundary_tag*)((uintptr_t)ptr - sizeof (struct boundary_tag));
if (tag->magic != LIBALLOC_MAGIC) {
liballoc_unlock (); // release the lock
liballoc_unlock (&ctxliba); // release the lock
return;
}
@@ -354,7 +356,7 @@ void free (void* ptr) {
liballoc_free (tag, pages);
liballoc_unlock ();
liballoc_unlock (&ctxliba);
return;
}
@@ -365,7 +367,7 @@ void free (void* ptr) {
insert_tag (tag, index);
liballoc_unlock ();
liballoc_unlock (&ctxliba);
}
void* calloc (size_t nobj, size_t size) {
@@ -385,6 +387,7 @@ void* realloc (void* p, size_t size) {
void* ptr;
struct boundary_tag* tag;
int real_size;
spin_lock_ctx_t ctxliba;
if (size == 0) {
free (p);
@@ -394,11 +397,11 @@ void* realloc (void* p, size_t size) {
return malloc (size);
if (&liballoc_lock != NULL)
liballoc_lock (); // lockit
liballoc_lock (&ctxliba); // lockit
tag = (struct boundary_tag*)((uintptr_t)p - sizeof (struct boundary_tag));
real_size = tag->size;
if (&liballoc_unlock != NULL)
liballoc_unlock ();
liballoc_unlock (&ctxliba);
if ((size_t)real_size > size)
real_size = size;

View File

@@ -47,7 +47,7 @@ struct boundary_tag {
* \return 0 if the lock was acquired successfully. Anything else is
* failure.
*/
extern int liballoc_lock ();
extern int liballoc_lock (void* ctx);
/** This function unlocks what was previously locked by the liballoc_lock
* function. If it disabled interrupts, it enables interrupts. If it
@@ -55,7 +55,7 @@ extern int liballoc_lock ();
*
* \return 0 if the lock was successfully released.
*/
extern int liballoc_unlock ();
extern int liballoc_unlock (void* ctx);
/** This is the hook into the local system which allocates pages. It
* accepts an integer parameter which is the number of pages

View File

@@ -100,6 +100,8 @@ static size_t pmm_find_free_space (struct pmm_region* pmm_region, size_t nblks)
}
physaddr_t pmm_alloc (size_t nblks) {
spin_lock_ctx_t ctxpmmr;
for (size_t region = 0; region < PMM_REGIONS_MAX; region++) {
struct pmm_region* pmm_region = &pmm.regions[region];
@@ -107,7 +109,7 @@ physaddr_t pmm_alloc (size_t nblks) {
if (!(pmm_region->flags & PMM_REGION_ACTIVE))
continue;
spin_lock (&pmm_region->lock);
spin_lock (&pmm_region->lock, &ctxpmmr);
/* Find starting bit of the free bit range */
size_t bit = pmm_find_free_space (pmm_region, nblks);
@@ -116,18 +118,19 @@ physaddr_t pmm_alloc (size_t nblks) {
if (bit != (size_t)-1) {
/* Mark it */
bm_set_region (&pmm_region->bm, bit, nblks);
spin_unlock (&pmm_region->lock);
spin_unlock (&pmm_region->lock, &ctxpmmr);
return pmm_region->membase + bit * PAGE_SIZE;
}
spin_unlock (&pmm_region->lock);
spin_unlock (&pmm_region->lock, &ctxpmmr);
}
return PMM_ALLOC_ERR;
}
void pmm_free (physaddr_t p_addr, size_t nblks) {
spin_lock_ctx_t ctxpmmr;
/* Round down to nearest page boundary */
physaddr_t aligned_p_addr = align_down (p_addr, PAGE_SIZE);
@@ -145,11 +148,11 @@ void pmm_free (physaddr_t p_addr, size_t nblks) {
size_t bit = div_align_up (addr, PAGE_SIZE);
spin_lock (&pmm_region->lock);
spin_lock (&pmm_region->lock, &ctxpmmr);
bm_clear_region (&pmm_region->bm, bit, nblks);
spin_unlock (&pmm_region->lock);
spin_unlock (&pmm_region->lock, &ctxpmmr);
break;
}