diff --git a/src/backend/backend.c b/src/backend/backend.c index b2100ebcd..baa3d49b6 100644 --- a/src/backend/backend.c +++ b/src/backend/backend.c @@ -89,6 +89,10 @@ lumiera_backend_init (void) mpool_init_hook = lumiera_backend_resourcecollector_register_mpool; mpool_destroy_hook = lumiera_backend_resourcecollector_unregister_mpool; + /* hook the resourcecollector into the safeclib allocation functions */ + lumiera_safeclib_set_resourcecollector (lumiera_resourcecollector_run); + + PLANNED("The resourcecollector aborts by default when there is no final strategy for recovery, TODO: initiate sane shutdown"); lumiera_threadpool_init (); PLANNED ("hook threadpool into the resourcecollector (maybe in threadpool_init() instead here"); @@ -144,6 +148,13 @@ lumiera_backend_destroy (void) lumiera_filedescriptorregistry_destroy (); lumiera_threadpool_destroy (); + lumiera_safeclib_set_resourcecollector (NULL); + + mpool_init_hook = NULL; + mpool_destroy_hook = NULL; + mpool_malloc_hook = malloc; + mpool_free_hook = free; + lumiera_resourcecollector_destroy (); lumiera_mutex_destroy (&lumiera_filecreate_mutex, &NOBUG_FLAG (mutex_dbg), NOBUG_CONTEXT); diff --git a/src/backend/resourcecollector.h b/src/backend/resourcecollector.h index eae4079ea..1d41e3e44 100644 --- a/src/backend/resourcecollector.h +++ b/src/backend/resourcecollector.h @@ -93,6 +93,7 @@ enum lumiera_resource_try * @return indication what the the handler really did (LUMIERA_RESOURCE_NONE when it didn't obey the request) */ typedef enum lumiera_resource_try (*lumiera_resource_handler_fn)(enum lumiera_resource_try itr, void* data, void* context); +typedef int (*lumiera_resourcecollector_run_fn) (enum lumiera_resource which, enum lumiera_resource_try* iteration, void* context); typedef struct lumiera_resourcehandler_struct lumiera_resourcehandler; typedef lumiera_resourcehandler* LumieraResourcehandler; diff --git a/src/lib/safeclib.c b/src/lib/safeclib.c index b6503a998..989648812 100644 --- a/src/lib/safeclib.c +++ b/src/lib/safeclib.c @@ -21,6 +21,8 @@ #include "lib/error.h" #include "lib/safeclib.h" +#include "backend/resourcecollector.h" + #include #include #include @@ -31,12 +33,40 @@ LUMIERA_ERROR_DEFINE (NO_MEMORY, "Out of Memory!"); + + +/* placeholder function until the resourcecollector gets hooked in */ +static int +die_no_mem (enum lumiera_resource which, enum lumiera_resource_try* iteration, void* context) +{ + (void) which; (void) iteration; (void) context; + LUMIERA_DIE (NO_MEMORY); + return 0; /* not reached */ +} + +static lumiera_resourcecollector_run_fn lumiera_safeclib_resourcecollector_run_hook = die_no_mem; + +void +lumiera_safeclib_set_resourcecollector (void* hook) +{ + if (hook) + lumiera_safeclib_resourcecollector_run_hook = (lumiera_resourcecollector_run_fn)hook; + else + lumiera_safeclib_resourcecollector_run_hook = die_no_mem; +} + + void* lumiera_malloc (size_t size) { - void* o = size ? malloc (size) : NULL; - if (!o) - LUMIERA_DIE (NO_MEMORY); + enum lumiera_resource_try iteration = LUMIERA_RESOURCE_ONE; + void* o = NULL; + + if (size) + do + o = malloc (size); + while (!o && lumiera_safeclib_resourcecollector_run_hook (LUMIERA_RESOURCE_MEMORY, &iteration, &size)); + return o; } @@ -44,9 +74,16 @@ lumiera_malloc (size_t size) void* lumiera_calloc (size_t n, size_t size) { - void* o = (n&&size)? calloc (n, size) : NULL; - if (!o) - LUMIERA_DIE (NO_MEMORY); + enum lumiera_resource_try iteration = LUMIERA_RESOURCE_ONE; + void* o = NULL; + + size_t gross = n*size; + + if (n&&size) + do + o = calloc (n, size); + while (!o && lumiera_safeclib_resourcecollector_run_hook (LUMIERA_RESOURCE_MEMORY, &iteration, &gross)); + return o; } @@ -54,9 +91,13 @@ lumiera_calloc (size_t n, size_t size) void* lumiera_realloc (void* ptr, size_t size) { - void* o = size ? realloc (ptr, size) : NULL; - if (!o) - LUMIERA_DIE (NO_MEMORY); + enum lumiera_resource_try iteration = LUMIERA_RESOURCE_ONE; + void* o = NULL; + + if (size) + do + o = realloc (ptr, size); + while (!o && lumiera_safeclib_resourcecollector_run_hook (LUMIERA_RESOURCE_MEMORY, &iteration, &size)); return o; } @@ -65,14 +106,16 @@ lumiera_realloc (void* ptr, size_t size) char* lumiera_strndup (const char* str, size_t len) { - char* o; - if (str) - o = strndup (str, len); - else - o = strdup (""); + enum lumiera_resource_try iteration = LUMIERA_RESOURCE_ONE; + void* o = NULL; + + do + if (str && len) + o = strndup (str, len); + else + o = strdup (""); + while (!o && lumiera_safeclib_resourcecollector_run_hook (LUMIERA_RESOURCE_MEMORY, &iteration, &len)); - if (!o) - LUMIERA_DIE (NO_MEMORY); return o; } @@ -234,3 +277,12 @@ lumiera_tmpbuf_tr (const char* in, const char* from, const char* to, const char* return ret; } + + +/* +// Local Variables: +// mode: C +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +*/ diff --git a/src/lib/safeclib.h b/src/lib/safeclib.h index ed0d73fd3..be322aa0b 100644 --- a/src/lib/safeclib.h +++ b/src/lib/safeclib.h @@ -29,6 +29,18 @@ */ LUMIERA_ERROR_DECLARE(NO_MEMORY); +/** + * Install the resourcecollector run hook. + * The resourcecollectr must be hooked into the safeclib at bootup after it got + * initialized and removed from it before shut down. Without resourcecollector + * failed allocations will abort(). + * @param hook pointer to the resourcecollector_run function, must be of type + * lumiera_resourcecollector_run_fn but we dont want a dependency on backend in this header + */ +void +lumiera_safeclib_set_resourcecollector (void* hook); + + /** * Allocate memory. * always succeeds or dies