CloverBootloader/rEFIt_UEFI/cpp_util/globals_dtor.cpp

106 lines
3.0 KiB
C++
Raw Normal View History

#include <Platform/Platform.h>
#if 0
#define DBG(...) DebugLog(2, __VA_ARGS__)
#else
#define DBG(...)
#endif
#if defined(__clang__)
typedef void (destructor_func_t)();
#elif defined(__GNUC__)
typedef void (destructor_func_t)(void*);
#else
# error compiler not supported
#endif
typedef destructor_func_t* destructor_func_ptr_t;
struct atexit_func_entry_t
{
destructor_func_ptr_t destructor_func;
#if !defined(__clang__) && defined(__GNUC__)
void *obj_ptr;
void *dso_handle;
#endif
};
static atexit_func_entry_t*atexit_func_entry_array = NULL;
static UINTN atexit_func_entry_count = 0;
static UINTN atexit_func_entry_size = 0;
#if defined (__clang__)
extern "C" int atexit(destructor_func_ptr_t destructor_func)
{
DBG("atexit(%p) sizeof=%d\n", destructor_func, sizeof(atexit_func_entry_t));
#elif defined(__GNUC__)
extern "C" int __cxa_atexit(destructor_func_ptr_t destructor_func, void *objptr, void *dso)
{
DBG("atexit(%p, %p, %p, %d)\n", destructor_func, objptr, dso, sizeof(atexit_func_entry_t));
#endif
if ( !atexit_func_entry_array )
{
DBG("atexit : allocate\n");
atexit_func_entry_array = (atexit_func_entry_t*)AllocatePool(16*sizeof(atexit_func_entry_t));
if ( !atexit_func_entry_array ) {
DBG("atexit : allocate returned NULL\n");
CpuDeadLoop();
}
atexit_func_entry_count = 0;
atexit_func_entry_size = 16;
}
if (atexit_func_entry_count >= atexit_func_entry_size)
{
DBG("atexit : reallocate atexit_func_entry_array=%d\n", (UINTN)atexit_func_entry_array);
atexit_func_entry_array = (atexit_func_entry_t *)ReallocatePool(atexit_func_entry_size*sizeof(atexit_func_entry_t), (atexit_func_entry_size+16)*sizeof(atexit_func_entry_t), atexit_func_entry_array);
if ( !atexit_func_entry_array ) {
DBG("atexit : reallocate returned NULL\n");
CpuDeadLoop();
}
atexit_func_entry_size += 16;
}
atexit_func_entry_array[atexit_func_entry_count].destructor_func = destructor_func;
#if !defined(__clang__) && defined(__GNUC__)
atexit_func_entry_array[atexit_func_entry_count].obj_ptr = objptr;
atexit_func_entry_array[atexit_func_entry_count].dso_handle = dso;
#endif
atexit_func_entry_count++;
DBG("atexit : exit (atexit_func_entry_count=%d)\n", atexit_func_entry_count);
return 0; /*I would prefer if functions returned 1 on success, but the ABI says...*/
}
void destruct_globals_objects(void *f)
{
UINTN i = atexit_func_entry_count;
while (i--)
{
# if defined(__clang__)
DBG("destruct_globals_objects: idx=%d %p\n", i, atexit_func_entry_array[i].destructor_func);
(*atexit_func_entry_array[i].destructor_func)();
atexit_func_entry_array[i].destructor_func = NULL;
atexit_func_entry_count--;
# elif defined(__GNUC__)
DBG("destruct_globals_objects: idx=%d %d, %p, %p\n", i, atexit_func_entry_array[i].destructor_func, atexit_func_entry_array[i].obj_ptr, atexit_func_entry_array[i].dso_handle);
(*atexit_func_entry_array[i].destructor_func)(atexit_func_entry_array[i].obj_ptr);
atexit_func_entry_array[i].destructor_func = NULL;
atexit_func_entry_count--;
# endif
}
}