Successfully added mutexes protecting freelist access. No behaviour change.

This commit is contained in:
Simon Brooke 2026-04-20 13:59:47 +01:00
parent c59825d7fe
commit f05d1af9d6
14 changed files with 132 additions and 69 deletions

View file

@ -19,6 +19,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "debug.h"
@ -35,15 +36,24 @@
/**
* @brief Allocate an object of this size_class with this tag.
*
* All objects that are allocated (after completion of init)) should be linked
* onto the `locals` slot on a stack frame. This guarantees
* 1. that they get `inc_ref`ed; and that,
* 2. if nothing else hangs onto them they will be reclaimed when that stack
* frame is reclaimed.
* for some objects (e.g. those cons cells on the locals list) this isn't
* possible due to infinite recursion, but those special cases need to be
* audited carefully
*
* @param stack_pointer C (NOT Lisp!) pointer to an active stack frame (or
* NULL, but only during initialisation).
* @param tag The tag. Only the first three bytes will be used;
* @param size_class The size class for the object to be allocated;
* @return struct pso_pointer a pointer to the newly allocated object
*/
struct pso_pointer allocate( char *tag, uint8_t size_class ) {
struct pso_pointer allocate( /* struct pso4 * stack_pointer,*/ char *tag, uint8_t size_class ) {
// todo: issue #21: must have stack frame passed in.
// `t`, because if `allocate_page` fails it will be set to `nil`.
struct pso_pointer result = t;
#ifdef DEBUG
debug_printf( DEBUG_ALLOC, 0,
@ -51,41 +61,26 @@ struct pso_pointer allocate( char *tag, uint8_t size_class ) {
size_class, tag );
#endif
if ( size_class <= MAX_SIZE_CLASS ) {
if ( nilp( freelists[size_class] ) ) {
result = allocate_page( size_class );
}
struct pso_pointer result = pop_freelist(size_class);
if ( nilp( result ) ) {
fputws( L"FATAL: Page space exhausted\n", stderr );
exit( 1 ); // TODO: we don't want to do this! Somehow, we need to
// recover a workable environment, ideally by throwing a pre-made
// exception.
}
if ( !exceptionp( result ) && !nilp( result ) ) {
result = freelists[size_class];
struct pso2 *object = pointer_to_object( result );
freelists[size_class] = object->payload.free.next;
strncpy( ( char * ) ( object->header.tag.bytes.mnemonic ), tag,
TAGLENGTH );
debug_printf( DEBUG_ALLOC, 0, L"at page %d, offset %d... ",
result.page, result.offset );
/* the object ought already to have the right size class in its tag
* because it was popped off the freelist for that size class. */
if ( object->header.tag.bytes.size_class != size_class ) {
// TODO: return an exception instead? Or warn, set it, and continue?
}
/* the objext ought to have a reference count ot zero, because it's
* on the freelist, but again we should sanity check. */
if ( object->header.count != 0 ) {
// TODO: return an exception instead? Or warn, set it, and continue?
}
}
} // TODO: else throw exception
if (!nilp( result)) {
strncpy( ( char * ) ( pointer_to_object(result)->header.tag.bytes.mnemonic ), tag,
TAGLENGTH );
debug_printf( DEBUG_ALLOC, 0, L"at page %d, offset %d... ",
result.page, result.offset );
// if ( stack_pointer != NULL &&
// (stack_pointer->header.tag.value & 0xffffff) == STACKTV) {
// struct pso_pointer locals = make_cons(result,
// stack_pointer->payload.stack_frame.locals);
// stack_pointer->payload.stack_frame.locals = locals;
//
// } else {
// fputws( L"WARNING: No stack frame passed to `allocate`.\n", stderr);
// }
} else {
// TODO: throw exception
}
#ifdef DEBUG
debug_print( exceptionp( result ) ? L"fail\n" : L"success\n", DEBUG_ALLOC,
@ -208,19 +203,7 @@ struct pso_pointer free_object( struct pso_pointer p ) {
obj->payload.words[i] = 0;
}
strncpy( ( char * ) ( obj->header.tag.bytes.mnemonic ), FREETAG,
TAGLENGTH );
#ifdef DEBUG
debug_printf( DEBUG_ALLOC, 0,
L"Freeing object of size class %d at {%d, %d, %d}",
size_class, p.node, p.page, p.offset );
#endif
/* TODO: obtain mutex on freelist */
obj->payload.free.next = freelists[size_class];
freelists[size_class] = p;
push_freelist(p);
return result;
}