1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 09:47:35 +00:00

Kernel+LibPthread: pthread_create handles pthread_attr_t

Add an initial implementation of pthread attributes for:
  * detach state (joinable, detached)
  * schedule params (just priority)
  * guard page size (as skeleton) (requires kernel support maybe?)
  * stack size and user-provided stack location (4 or 8 MB only, must be aligned)

Add some tests too, to the thread test program.

Also, LibC: Move pthread declarations to sys/types.h, where they belong.
This commit is contained in:
Andrew Kaster 2019-11-17 20:08:10 -07:00 committed by Andreas Kling
parent aae26a3a1e
commit 618aebdd8a
9 changed files with 596 additions and 23 deletions

View file

@ -2851,18 +2851,42 @@ int Process::thread_count() const
return count;
}
int Process::sys$create_thread(void* (*entry)(void*), void* argument, void* stack)
int Process::sys$create_thread(void* (*entry)(void*), void* argument, const Syscall::SC_create_thread_params* params)
{
if (!validate_read((const void*)entry, sizeof(void*)))
return -EFAULT;
if (!MM.validate_user_stack(*this, VirtualAddress(((u32)stack) - 4)))
if (!validate_read_typed(params))
return -EFAULT;
u32 user_stack_address = reinterpret_cast<u32>(params->m_stack_location) + params->m_stack_size;
if (!MM.validate_user_stack(*this, VirtualAddress(user_stack_address - 4)))
return -EFAULT;
// FIXME: return EAGAIN if Thread::all_threads().size() is greater than PTHREAD_THREADS_MAX
ThreadPriority requested_thread_priority = static_cast<ThreadPriority>(params->m_schedule_priority);
if (requested_thread_priority < ThreadPriority::First || requested_thread_priority > ThreadPriority::Last)
return -EINVAL;
if (requested_thread_priority != ThreadPriority::Normal && !is_superuser())
return -EPERM;
bool is_thread_joinable = (0 == params->m_detach_state);
// FIXME: Do something with guard pages?
auto* thread = new Thread(*this);
thread->set_priority(requested_thread_priority);
thread->set_joinable(is_thread_joinable);
auto& tss = thread->tss();
tss.eip = (u32)entry;
tss.eflags = 0x0202;
tss.cr3 = page_directory().cr3();
tss.esp = (u32)stack;
tss.esp = user_stack_address;
// NOTE: The stack needs to be 16-byte aligned.
thread->push_value_on_stack((u32)argument);
@ -2915,7 +2939,8 @@ int Process::sys$join_thread(int tid, void** exit_value)
if (thread->m_joiner)
return -EINVAL;
// FIXME: EINVAL: 'thread' is not a joinable thread
if (!thread->is_joinable())
return -EINVAL;
void* joinee_exit_value = nullptr;

View file

@ -203,7 +203,7 @@ public:
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$restore_signal_mask(u32 mask);
int sys$create_thread(void* (*)(void*), void* argument, void* stack);
int sys$create_thread(void* (*)(void*), void* argument, const Syscall::SC_create_thread_params*);
void sys$exit_thread(void*);
int sys$join_thread(int tid, void** exit_value);
int sys$rename(const char* oldpath, const char* newpath);

View file

@ -248,6 +248,20 @@ struct SC_setsockopt_params {
socklen_t value_size;
};
struct SC_create_thread_params {
unsigned int m_detach_state = 0; // JOINABLE or DETACHED
int m_schedule_priority = 2; // ThreadPriority::Normal
// FIXME: Implment guard pages in create_thread (unreadable pages at "overflow" end of stack)
// "If an implementation rounds up the value of guardsize to a multiple of {PAGESIZE},
// a call to pthread_attr_getguardsize() specifying attr shall store in the guardsize
// parameter the guard size specified by the previous pthread_attr_setguardsize() function call"
// ... ok, if you say so posix. Guess we get to lie to people about guard page size
unsigned int m_guard_page_size = 0; // Rounded up to PAGE_SIZE
unsigned int m_reported_guard_page_size = 0; // The lie we tell callers
unsigned int m_stack_size = 4 * MB; // Default PTHREAD_STACK_MIN
void* m_stack_location = nullptr; // nullptr means any, o.w. process virtual address
};
void initialize();
int sync();

View file

@ -63,6 +63,9 @@ public:
void set_priority(ThreadPriority p) { m_priority = p; }
ThreadPriority priority() const { return m_priority; }
void set_joinable(bool j) { m_is_joinable = j; }
bool is_joinable() const { return m_is_joinable; }
Process& process() { return m_process; }
const Process& process() const { return m_process; }
@ -368,6 +371,7 @@ private:
SignalActionData m_signal_action_data[32];
Blocker* m_blocker { nullptr };
bool m_is_joinable { true };
Thread* m_joiner { nullptr };
Thread* m_joinee { nullptr };
void* m_exit_value { nullptr };