mirror of
https://github.com/RGBCube/serenity
synced 2025-05-23 19:05:08 +00:00
LibPthread: implicitly call pthread_exit on return from start routine.
Previously, when returning from a pthread's start_routine, we would segfault. Now we instead implicitly call pthread_exit as specified in the standard. pthread_create now creates a thread running the new pthread_create_helper, which properly manages the calling and exiting of the start_routine supplied to pthread_create. To accomplish this, the thread's stack initialization has been moved out of sys$create_thread and into the userspace function create_thread.
This commit is contained in:
parent
4cb765e520
commit
4a37362249
3 changed files with 32 additions and 8 deletions
|
@ -3754,7 +3754,7 @@ void Process::send_signal(u8 signal, Process* sender)
|
||||||
thread->send_signal(signal, sender);
|
thread->send_signal(signal, sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Process::sys$create_thread(void* (*entry)(void*), void* argument, const Syscall::SC_create_thread_params* user_params)
|
int Process::sys$create_thread(void* (*entry)(void*), const Syscall::SC_create_thread_params* user_params)
|
||||||
{
|
{
|
||||||
REQUIRE_PROMISE(thread);
|
REQUIRE_PROMISE(thread);
|
||||||
if (!validate_read((const void*)entry, sizeof(void*)))
|
if (!validate_read((const void*)entry, sizeof(void*)))
|
||||||
|
@ -3806,10 +3806,6 @@ int Process::sys$create_thread(void* (*entry)(void*), void* argument, const Sysc
|
||||||
tss.cr3 = page_directory().cr3();
|
tss.cr3 = page_directory().cr3();
|
||||||
tss.esp = user_stack_address;
|
tss.esp = user_stack_address;
|
||||||
|
|
||||||
// NOTE: The stack needs to be 16-byte aligned.
|
|
||||||
thread->push_value_on_stack((FlatPtr)argument);
|
|
||||||
thread->push_value_on_stack(0);
|
|
||||||
|
|
||||||
thread->make_thread_specific_region({});
|
thread->make_thread_specific_region({});
|
||||||
thread->set_state(Thread::State::Runnable);
|
thread->set_state(Thread::State::Runnable);
|
||||||
return thread->tid();
|
return thread->tid();
|
||||||
|
|
|
@ -272,7 +272,7 @@ public:
|
||||||
int sys$getpeername(const Syscall::SC_getpeername_params*);
|
int sys$getpeername(const Syscall::SC_getpeername_params*);
|
||||||
int sys$sched_setparam(pid_t pid, const struct sched_param* param);
|
int sys$sched_setparam(pid_t pid, const struct sched_param* param);
|
||||||
int sys$sched_getparam(pid_t pid, struct sched_param* param);
|
int sys$sched_getparam(pid_t pid, struct sched_param* param);
|
||||||
int sys$create_thread(void* (*)(void*), void* argument, const Syscall::SC_create_thread_params*);
|
int sys$create_thread(void* (*)(void*), const Syscall::SC_create_thread_params*);
|
||||||
void sys$exit_thread(void*);
|
void sys$exit_thread(void*);
|
||||||
int sys$join_thread(int tid, void** exit_value);
|
int sys$join_thread(int tid, void** exit_value);
|
||||||
int sys$detach_thread(int tid);
|
int sys$detach_thread(int tid);
|
||||||
|
|
|
@ -50,9 +50,37 @@ constexpr size_t highest_reasonable_stack_size = 8 * MB; // That's the default i
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
static int create_thread(void* (*entry)(void*), void* argument, void* thread_params)
|
static void* pthread_create_helper(void* (*routine)(void*), void* argument)
|
||||||
{
|
{
|
||||||
return syscall(SC_create_thread, entry, argument, thread_params);
|
void* ret_val = routine(argument);
|
||||||
|
pthread_exit(ret_val);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int create_thread(void* (*entry)(void*), void* argument, PthreadAttrImpl* thread_params)
|
||||||
|
{
|
||||||
|
void** stack = (void**)((uintptr_t)thread_params->m_stack_location + thread_params->m_stack_size);
|
||||||
|
|
||||||
|
auto push_on_stack = [&](void* data) {
|
||||||
|
stack--;
|
||||||
|
*stack = data;
|
||||||
|
thread_params->m_stack_size -= sizeof(void*);
|
||||||
|
};
|
||||||
|
|
||||||
|
// We set up the stack for pthread_create_helper.
|
||||||
|
// Note that we need to align the stack to 16B, accounting for
|
||||||
|
// the fact that we also push 8 bytes.
|
||||||
|
while (((uintptr_t)stack - 8) % 16 != 0)
|
||||||
|
push_on_stack(nullptr);
|
||||||
|
|
||||||
|
push_on_stack(argument);
|
||||||
|
push_on_stack((void*)entry);
|
||||||
|
ASSERT((uintptr_t)stack % 16 == 0);
|
||||||
|
|
||||||
|
// Push a fake return address
|
||||||
|
push_on_stack(nullptr);
|
||||||
|
|
||||||
|
return syscall(SC_create_thread, pthread_create_helper, thread_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void exit_thread(void* code)
|
static void exit_thread(void* code)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue