LAPACKE: add runtime allocator override (LAPACKE_set_alloc)

Route the LAPACKE_malloc / LAPACKE_free defaults through function
pointers so the LAPACKE test suite can inject allocation failures at
run time, mirroring LAPACKE_set_nancheck. Compile-time macro overrides
are unaffected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Simon Maertens
2026-08-05 16:28:57 +01:00
co-authored by Claude Fable 5
parent f0f3e5f9a8
commit aa622d1183
4 changed files with 78 additions and 2 deletions
+15 -2
View File
@@ -39,11 +39,24 @@
extern "C" {
#endif /* __cplusplus */
/* All LAPACKE-internal allocations (workspaces, row-major transposition
* buffers) go through a replaceable allocator. Defining the LAPACKE_malloc /
* LAPACKE_free macros at compile time replaces the allocator entirely. */
/** \brief Allocate through the installed allocator (malloc by default). */
void *LAPACKE_malloc_proxy(size_t size);
/** \brief Release through the installed deallocator (free by default). */
void LAPACKE_free_proxy(void *ptr);
/** \brief Install a custom allocator: malloc_fn / free_fn must form a
* matching pair; NULL restores the defaults. Mutates global state and is
* not thread-safe. */
void LAPACKE_set_alloc(void *(*malloc_fn)(size_t), void (*free_fn)(void *));
#ifndef LAPACKE_malloc
#define LAPACKE_malloc( size ) malloc( size )
#define LAPACKE_malloc(size) LAPACKE_malloc_proxy(size)
#endif
#ifndef LAPACKE_free
#define LAPACKE_free( p ) free( p )
#define LAPACKE_free(p) LAPACKE_free_proxy(p)
#endif
#define LAPACK_C2INT( x ) (lapack_int)(*((float*)&x ))
+1
View File
@@ -1208,6 +1208,7 @@ lapacke_dtzrzf_work.c
)
set(COMMON_SOURCES
lapacke_alloc.c
lapacke_nancheck.c
)
set(SOURCES
+1
View File
@@ -43,6 +43,7 @@ include $(TOPSRCDIR)/make.inc
OBJ = \
lapacke_ilaver.o \
lapacke_alloc.o \
lapacke_nancheck.o
OBJ_C = \
+61
View File
@@ -0,0 +1,61 @@
/*****************************************************************************
* Replaceable allocator for LAPACKE-internal allocations.
*
* The LAPACKE_malloc / LAPACKE_free macros default to the functions below,
* which forward to a run-time replaceable allocator (malloc / free until
* changed via LAPACKE_set_alloc). Like the nancheck flag, the allocator is
* shared between all APIs, so this file must be compiled exactly once,
* without an API suffix.
*****************************************************************************/
#include <stdlib.h>
#include "lapacke.h"
static void *(*lapacke_malloc_fn)(size_t) = malloc;
static void (*lapacke_free_fn)(void *) = free;
/**
* \brief Allocate memory through the installed allocator.
*
* Default of the LAPACKE_malloc macro.
*
* \param[in] size Allocation size in bytes.
* \return The allocation, or NULL on failure.
*/
void *LAPACKE_malloc_proxy(size_t size)
{
return lapacke_malloc_fn(size);
}
/**
* \brief Release memory through the installed deallocator.
*
* Default of the LAPACKE_free macro.
*
* \param[in] ptr Allocation obtained through LAPACKE_malloc_proxy.
*/
void LAPACKE_free_proxy(void *ptr)
{
lapacke_free_fn(ptr);
}
/**
* \brief Install a custom allocator for LAPACKE-internal allocations.
*
* Subsequent LAPACKE-internal allocations (workspaces, row-major
* transposition buffers) are made with malloc_fn and released with
* free_fn. The two must form a matching pair: memory allocated with
* malloc_fn is released through free_fn, so pairing an allocator with an
* incompatible deallocator is undefined behavior. The setter mutates
* global state shared by all threads and is not thread-safe; call it
* during setup, like LAPACKE_set_nancheck.
*
* \param[in] malloc_fn Replacement for malloc; NULL restores malloc.
* \param[in] free_fn Replacement for free; NULL restores free.
*/
void LAPACKE_set_alloc(void *(*malloc_fn)(size_t), void (*free_fn)(void *))
{
lapacke_malloc_fn = (malloc_fn != NULL) ? malloc_fn : malloc;
lapacke_free_fn = (free_fn != NULL) ? free_fn : free;
}