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

@ -7,18 +7,23 @@
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "debug.h"
#include "memory/memory.h"
#include "memory/node.h"
#include "memory/page.h"
#include "memory/pointer.h"
#include "memory/pso.h"
#include "memory/pso2.h"
#include "memory/tags.h"
#include "ops/truth.h"
#include "payloads/exception.h"
#include "ops/bind.h"
@ -29,6 +34,11 @@
*/
struct pso_pointer freelists[MAX_SIZE_CLASS];
/**
* Mutices to lock the freelists during access.
*/
pthread_mutex_t freelists_mutices[MAX_SIZE_CLASS];
/**
* @brief Flag to prevent re-initialisation.
*/
@ -63,3 +73,64 @@ struct pso_pointer initialise_memory( uint32_t node ) {
return t;
}
/**
* @brief Pop an object off the freelist for the specified `size_class`.
*/
struct pso_pointer pop_freelist( uint8_t size_class) {
// `t`, because if `allocate_page` fails it will be set to `nil`.
struct pso_pointer result = t;
if ( size_class <= MAX_SIZE_CLASS ) {
if ( nilp( freelists[size_class] ) ) {
result = allocate_page( 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 ) ) {
pthread_mutex_lock( &freelists_mutices[size_class]);
result = freelists[size_class];
struct pso2 *object = pointer_to_object( result );
freelists[size_class] = object->payload.free.next;
pthread_mutex_unlock(&freelists_mutices[size_class]);
/* 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 ) {
fwprintf( stderr,
L"WARNING: Request to allocate object of size class %d, which is not implemented",
size_class);
}
}
} // TODO: else throw exception
return result;
}
void push_freelist( struct pso_pointer p) {
struct pso2 *obj = pointer_to_object( p );
uint8_t size_class = ( obj->header.tag.bytes.size_class );
strncpy( ( char * ) ( obj->header.tag.bytes.mnemonic ), FREETAG,
TAGLENGTH );
pthread_mutex_lock( &freelists_mutices[size_class]);
if ( size_class <= MAX_SIZE_CLASS ) {
obj->payload.free.next = freelists[size_class];
freelists[size_class] = p;
}
pthread_mutex_unlock(&freelists_mutices[size_class]);
}