mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 00:37:35 +00:00
LibPthread: Implement cleanup handlers
This commit is contained in:
parent
b3e0aed91f
commit
2a27644220
1 changed files with 36 additions and 13 deletions
|
@ -8,6 +8,7 @@
|
||||||
#include <AK/Atomic.h>
|
#include <AK/Atomic.h>
|
||||||
#include <AK/Debug.h>
|
#include <AK/Debug.h>
|
||||||
#include <AK/Format.h>
|
#include <AK/Format.h>
|
||||||
|
#include <AK/SinglyLinkedList.h>
|
||||||
#include <AK/StdLibExtras.h>
|
#include <AK/StdLibExtras.h>
|
||||||
#include <Kernel/API/Syscall.h>
|
#include <Kernel/API/Syscall.h>
|
||||||
#include <LibSystem/syscall.h>
|
#include <LibSystem/syscall.h>
|
||||||
|
@ -40,8 +41,27 @@ __thread size_t s_stack_size;
|
||||||
#define __RETURN_PTHREAD_ERROR(rc) \
|
#define __RETURN_PTHREAD_ERROR(rc) \
|
||||||
return ((rc) < 0 ? -(rc) : 0)
|
return ((rc) < 0 ? -(rc) : 0)
|
||||||
|
|
||||||
|
struct CleanupHandler {
|
||||||
|
void (*routine)(void*);
|
||||||
|
void* argument;
|
||||||
|
};
|
||||||
|
|
||||||
|
static thread_local SinglyLinkedList<CleanupHandler> cleanup_handlers;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
[[noreturn]] static void exit_thread(void* code, void* stack_location, size_t stack_size)
|
||||||
|
{
|
||||||
|
__pthread_key_destroy_for_current_thread();
|
||||||
|
syscall(SC_exit_thread, code, stack_location, stack_size);
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[noreturn]] static void pthread_exit_without_cleanup_handlers(void* value_ptr)
|
||||||
|
{
|
||||||
|
exit_thread(value_ptr, s_stack_location, s_stack_size);
|
||||||
|
}
|
||||||
|
|
||||||
static void* pthread_create_helper(void* (*routine)(void*), void* argument, void* stack_location, size_t stack_size)
|
static void* pthread_create_helper(void* (*routine)(void*), void* argument, void* stack_location, size_t stack_size)
|
||||||
{
|
{
|
||||||
// HACK: This is a __thread - marked thread-local variable. If we initialize it globally, VERY weird errors happen.
|
// HACK: This is a __thread - marked thread-local variable. If we initialize it globally, VERY weird errors happen.
|
||||||
|
@ -50,7 +70,7 @@ static void* pthread_create_helper(void* (*routine)(void*), void* argument, void
|
||||||
s_stack_location = stack_location;
|
s_stack_location = stack_location;
|
||||||
s_stack_size = stack_size;
|
s_stack_size = stack_size;
|
||||||
void* ret_val = routine(argument);
|
void* ret_val = routine(argument);
|
||||||
pthread_exit(ret_val);
|
pthread_exit_without_cleanup_handlers(ret_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int create_thread(pthread_t* thread, void* (*entry)(void*), void* argument, PthreadAttrImpl* thread_params)
|
static int create_thread(pthread_t* thread, void* (*entry)(void*), void* argument, PthreadAttrImpl* thread_params)
|
||||||
|
@ -91,13 +111,6 @@ static int create_thread(pthread_t* thread, void* (*entry)(void*), void* argumen
|
||||||
__RETURN_PTHREAD_ERROR(rc);
|
__RETURN_PTHREAD_ERROR(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[noreturn]] static void exit_thread(void* code, void* stack_location, size_t stack_size)
|
|
||||||
{
|
|
||||||
__pthread_key_destroy_for_current_thread();
|
|
||||||
syscall(SC_exit_thread, code, stack_location, stack_size);
|
|
||||||
VERIFY_NOT_REACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_self.html
|
// https://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_self.html
|
||||||
int pthread_self()
|
int pthread_self()
|
||||||
{
|
{
|
||||||
|
@ -139,19 +152,29 @@ int pthread_create(pthread_t* thread, pthread_attr_t* attributes, void* (*start_
|
||||||
// https://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_exit.html
|
// https://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_exit.html
|
||||||
void pthread_exit(void* value_ptr)
|
void pthread_exit(void* value_ptr)
|
||||||
{
|
{
|
||||||
exit_thread(value_ptr, s_stack_location, s_stack_size);
|
while (!cleanup_handlers.is_empty()) {
|
||||||
|
auto handler = cleanup_handlers.take_first();
|
||||||
|
handler.routine(handler.argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_exit_without_cleanup_handlers(value_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_cleanup_push.html
|
// https://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_cleanup_push.html
|
||||||
void pthread_cleanup_push([[maybe_unused]] void (*routine)(void*), [[maybe_unused]] void* arg)
|
void pthread_cleanup_push(void (*routine)(void*), void* arg)
|
||||||
{
|
{
|
||||||
TODO();
|
cleanup_handlers.prepend({ routine, arg });
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_cleanup_pop.html
|
// https://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_cleanup_pop.html
|
||||||
void pthread_cleanup_pop([[maybe_unused]] int execute)
|
void pthread_cleanup_pop(int execute)
|
||||||
{
|
{
|
||||||
TODO();
|
VERIFY(!cleanup_handlers.is_empty());
|
||||||
|
|
||||||
|
auto handler = cleanup_handlers.take_first();
|
||||||
|
|
||||||
|
if (execute)
|
||||||
|
handler.routine(handler.argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_join.html
|
// https://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_join.html
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue