1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 08:54:58 +00:00

AK+LibC+LibPthread: Introduce NoAllocationGuard

NoAllocationGuard is an RAII stack guard that prevents allocations
while it exists. This is done through a thread-local global flag which
causes malloc to crash on a VERIFY if it is false. The guard allows for
recursion.

The intended use case for this class is in real-time audio code. In such
code, allocations are really bad, and this is an easy way of dynamically
enforcing the no-allocations rule while giving the user good feedback if
it is violated. Before real-time audio code is executed, e.g. in LibDSP,
a NoAllocationGuard is instantiated. This is not done with this commit,
as currently some code in LibDSP may still incorrectly allocate in real-
time situations.

Other use cases for the Kernel have also been added, so this commit
builds on the previous to add the support both in Userland and in the
Kernel.
This commit is contained in:
kleines Filmröllchen 2022-01-09 13:01:27 +01:00 committed by Linus Groh
parent e2c9578390
commit 2f50d8f4d3
4 changed files with 91 additions and 0 deletions

View file

@ -198,8 +198,18 @@ enum class CallerWillInitializeMemory {
Yes,
};
#ifndef NO_TLS
// HACK: This is a __thread - marked thread-local variable. If we initialize it globally here, VERY weird errors happen.
// The initialization happens in __malloc_init() and pthread_create_helper().
__thread bool s_allocation_enabled;
#endif
static void* malloc_impl(size_t size, CallerWillInitializeMemory caller_will_initialize_memory)
{
#ifndef NO_TLS
VERIFY(s_allocation_enabled);
#endif
if (s_log_malloc)
dbgln("LibC: malloc({})", size);
@ -330,6 +340,10 @@ static void* malloc_impl(size_t size, CallerWillInitializeMemory caller_will_ini
static void free_impl(void* ptr)
{
#ifndef NO_TLS
VERIFY(s_allocation_enabled);
#endif
ScopedValueRollback rollback(errno);
if (!ptr)
@ -534,6 +548,12 @@ void* realloc(void* ptr, size_t size)
void __malloc_init()
{
#ifndef NO_TLS
// HACK: This is a __thread - marked thread-local variable. If we initialize it globally, VERY weird errors happen.
// Therefore, we need to do the initialization here and in pthread_create_helper().
s_allocation_enabled = true;
#endif
s_in_userspace_emulator = (int)syscall(SC_emuctl, 0) != -ENOSYS;
if (s_in_userspace_emulator) {
// Don't bother scrubbing memory if we're running in UE since it