diff options
author | Tim Schumacher <timschumi@gmx.de> | 2022-05-05 10:37:29 +0200 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-06-10 19:06:46 +0100 |
commit | 2a27644220b5eb2c8446db75d8d0604e1befbc92 (patch) | |
tree | 15e63a42de5a5a26ade6bc617a68ca2a862d5ea8 /Userland | |
parent | b3e0aed91f1c15c1223b23864efac6d90f31324a (diff) | |
download | serenity-2a27644220b5eb2c8446db75d8d0604e1befbc92.zip |
LibPthread: Implement cleanup handlers
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibPthread/pthread.cpp | 49 |
1 files changed, 36 insertions, 13 deletions
diff --git a/Userland/Libraries/LibPthread/pthread.cpp b/Userland/Libraries/LibPthread/pthread.cpp index ea1b5b3227..e09f6a6850 100644 --- a/Userland/Libraries/LibPthread/pthread.cpp +++ b/Userland/Libraries/LibPthread/pthread.cpp @@ -8,6 +8,7 @@ #include <AK/Atomic.h> #include <AK/Debug.h> #include <AK/Format.h> +#include <AK/SinglyLinkedList.h> #include <AK/StdLibExtras.h> #include <Kernel/API/Syscall.h> #include <LibSystem/syscall.h> @@ -40,8 +41,27 @@ __thread size_t s_stack_size; #define __RETURN_PTHREAD_ERROR(rc) \ return ((rc) < 0 ? -(rc) : 0) +struct CleanupHandler { + void (*routine)(void*); + void* argument; +}; + +static thread_local SinglyLinkedList<CleanupHandler> cleanup_handlers; + 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) { // 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_size = stack_size; 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) @@ -91,13 +111,6 @@ static int create_thread(pthread_t* thread, void* (*entry)(void*), void* argumen __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 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 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 -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 -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 |