From 69ca9cfd78da8e27a958db1656b75bb9d1886e85 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 13 Nov 2019 21:49:24 +0100 Subject: [PATCH] LibPthread: Start working on a POSIX threading library This patch adds pthread_create() and pthread_exit(), which currently simply wrap our existing create_thread() and exit_thread() syscalls. LibThread is also ported to using LibPthread. --- Applications/Makefile.common | 2 +- DevTools/HackStudio/Makefile | 2 +- Kernel/Process.cpp | 8 +++++--- Kernel/Process.h | 4 ++-- Kernel/Syscall.cpp | 2 +- Kernel/makeall.sh | 1 + Libraries/LibC/unistd.cpp | 7 +++---- Libraries/LibC/unistd.h | 4 ++-- Libraries/LibPthread/Makefile | 19 +++++++++++++++++ Libraries/LibPthread/install.sh | 9 ++++++++ Libraries/LibPthread/pthread.cpp | 24 ++++++++++++++++++++++ Libraries/{LibC => LibPthread}/pthread.h | 5 ++--- Libraries/LibThread/Thread.cpp | 26 ++++++++++++++---------- Makefile.common | 3 ++- Servers/AudioServer/Makefile | 2 +- Servers/WindowServer/Makefile | 2 +- 16 files changed, 89 insertions(+), 31 deletions(-) create mode 100644 Libraries/LibPthread/Makefile create mode 100755 Libraries/LibPthread/install.sh create mode 100644 Libraries/LibPthread/pthread.cpp rename Libraries/{LibC => LibPthread}/pthread.h (94%) diff --git a/Applications/Makefile.common b/Applications/Makefile.common index 12b3670803..10f0cd31c6 100755 --- a/Applications/Makefile.common +++ b/Applications/Makefile.common @@ -3,7 +3,7 @@ DEFINES += -DUSERLAND all: $(APP) $(APP): $(OBJS) - $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lmarkdown -lhtml -laudio -lipc -lvt -lpcidb -lgui -ldraw -lthread -lcore -lc + $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lmarkdown -lhtml -laudio -lipc -lvt -lpcidb -lgui -ldraw -lthread -lpthread -lcore -lc .cpp.o: @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< diff --git a/DevTools/HackStudio/Makefile b/DevTools/HackStudio/Makefile index e4bc07f538..97756dac10 100644 --- a/DevTools/HackStudio/Makefile +++ b/DevTools/HackStudio/Makefile @@ -25,7 +25,7 @@ DEFINES += -DUSERLAND all: $(APP) $(APP): $(OBJS) - $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lvt -lhtml -lmarkdown -lgui -ldraw -lthread -lcore -lc + $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lvt -lhtml -lmarkdown -lgui -ldraw -lthread -lpthread -lcore -lc .cpp.o: @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 54afa1eadd..4de291cd4c 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -2807,7 +2807,7 @@ int Process::thread_count() const return count; } -int Process::sys$create_thread(int (*entry)(void*), void* argument) +int Process::sys$create_thread(void* (*entry)(void*), void* argument) { if (!validate_read((const void*)entry, sizeof(void*))) return -EFAULT; @@ -2822,11 +2822,13 @@ int Process::sys$create_thread(int (*entry)(void*), void* argument) return thread->tid(); } -void Process::sys$exit_thread(int code) +void Process::sys$exit_thread(void* code) { + UNUSED_PARAM(code); cli(); if (¤t->process().main_thread() == current) { - sys$exit(code); + // FIXME: For POSIXy reasons, we should only sys$exit once *all* threads have exited. + sys$exit(0); return; } current->set_state(Thread::State::Dying); diff --git a/Kernel/Process.h b/Kernel/Process.h index fb9e8585d9..c209423a96 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -204,8 +204,8 @@ 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(int (*)(void*), void*); - void sys$exit_thread(int code); + int sys$create_thread(void* (*)(void*), void*); + void sys$exit_thread(void*); int sys$rename(const char* oldpath, const char* newpath); int sys$systrace(pid_t); int sys$mknod(const char* pathname, mode_t, dev_t); diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 9cc6cd365d..dd71cc9eaa 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -67,7 +67,7 @@ int handle(RegisterDump& regs, u32 function, u32 arg1, u32 arg2, u32 arg3) if (function == SC_exit) process.sys$exit((int)arg1); else - process.sys$exit_thread((int)arg1); + process.sys$exit_thread((void*)arg1); ASSERT_NOT_REACHED(); return 0; } diff --git a/Kernel/makeall.sh b/Kernel/makeall.sh index b840174ff4..e6942443fb 100755 --- a/Kernel/makeall.sh +++ b/Kernel/makeall.sh @@ -24,6 +24,7 @@ build_targets="$build_targets ../Libraries/LibC" build_targets="$build_targets ../Libraries/LibCore" build_targets="$build_targets ../Libraries/LibIPC" build_targets="$build_targets ../Libraries/LibThread" +build_targets="$build_targets ../Libraries/LibPthread" # Build IPC servers before their client code to ensure the IPC definitions are available. build_targets="$build_targets ../Servers/AudioServer" diff --git a/Libraries/LibC/unistd.cpp b/Libraries/LibC/unistd.cpp index b7a846917c..2e19149d8f 100644 --- a/Libraries/LibC/unistd.cpp +++ b/Libraries/LibC/unistd.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include #include #include @@ -540,13 +540,13 @@ char* getlogin() return nullptr; } -int create_thread(int (*entry)(void*), void* argument) +int create_thread(void *(*entry)(void*), void* argument) { int rc = syscall(SC_create_thread, entry, argument); __RETURN_WITH_ERRNO(rc, rc, -1); } -void exit_thread(int code) +void exit_thread(void* code) { syscall(SC_exit_thread, code); ASSERT_NOT_REACHED(); @@ -633,5 +633,4 @@ int get_process_name(char* buffer, int buffer_size) int rc = syscall(SC_get_process_name, buffer, buffer_size); __RETURN_WITH_ERRNO(rc, rc, -1); } - } diff --git a/Libraries/LibC/unistd.h b/Libraries/LibC/unistd.h index 41f359d53d..7c64ac3de9 100644 --- a/Libraries/LibC/unistd.h +++ b/Libraries/LibC/unistd.h @@ -36,8 +36,8 @@ void sysbeep(); int systrace(pid_t); int gettid(); int donate(int tid); -int create_thread(int (*)(void*), void*); -void exit_thread(int); +int create_thread(void *(*)(void*), void* argument); +void exit_thread(void*); int create_shared_buffer(int, void** buffer); int share_buffer_with(int, pid_t peer_pid); int share_buffer_globally(int); diff --git a/Libraries/LibPthread/Makefile b/Libraries/LibPthread/Makefile new file mode 100644 index 0000000000..993ee2cdb9 --- /dev/null +++ b/Libraries/LibPthread/Makefile @@ -0,0 +1,19 @@ +include ../../Makefile.common + +OBJS = pthread.o + +LIBRARY = libpthread.a +DEFINES += -DUSERLAND + +all: $(LIBRARY) + +$(LIBRARY): $(OBJS) + @echo "LIB $@"; $(AR) rcs $@ $(OBJS) + +.cpp.o: + @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< + +-include $(OBJS:%.o=%.d) + +clean: + @echo "CLEAN"; rm -f $(LIBRARY) $(OBJS) *.d diff --git a/Libraries/LibPthread/install.sh b/Libraries/LibPthread/install.sh new file mode 100755 index 0000000000..4a7d00c6d1 --- /dev/null +++ b/Libraries/LibPthread/install.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +set -e +SERENITY_ROOT=../../ + +mkdir -p $SERENITY_ROOT/Root/usr/include/sys/ +mkdir -p $SERENITY_ROOT/Root/usr/lib/ +cp ./*.h $SERENITY_ROOT/Root/usr/include/ +cp libpthread.a $SERENITY_ROOT/Root/usr/lib/ diff --git a/Libraries/LibPthread/pthread.cpp b/Libraries/LibPthread/pthread.cpp new file mode 100644 index 0000000000..26761b8a02 --- /dev/null +++ b/Libraries/LibPthread/pthread.cpp @@ -0,0 +1,24 @@ +#include +#include +#include + +extern "C" { + +int pthread_create(pthread_t* thread, pthread_attr_t* attributes, void *(*start_routine)(void*), void* argument_to_start_routine) +{ + if (!thread) + return -EINVAL; + UNUSED_PARAM(attributes); + int rc = create_thread(start_routine, argument_to_start_routine); + if (rc < 0) + return rc; + *thread = rc; + return 0; +} + +void pthread_exit(void* value_ptr) +{ + exit_thread(value_ptr); +} + +} diff --git a/Libraries/LibC/pthread.h b/Libraries/LibPthread/pthread.h similarity index 94% rename from Libraries/LibC/pthread.h rename to Libraries/LibPthread/pthread.h index d5848d0821..19e6f88f19 100644 --- a/Libraries/LibC/pthread.h +++ b/Libraries/LibPthread/pthread.h @@ -5,7 +5,7 @@ __BEGIN_DECLS -typedef void* pthread_t; +typedef int pthread_t; typedef void* pthread_key_t; typedef void* pthread_once_t; typedef void* pthread_mutex_t; @@ -15,7 +15,7 @@ typedef void* pthread_cond_t; typedef void* pthread_spinlock_t; typedef void* pthread_condattr_t; -int pthread_create(pthread_t, pthread_attr_t*, void* (*)(void*), void*); +int pthread_create(pthread_t*, pthread_attr_t*, void* (*)(void*), void*); void pthread_exit(void*); int pthread_kill(pthread_t, int); void pthread_cleanup_push(void (*)(void*), void*); @@ -31,7 +31,6 @@ int pthread_attr_destroy(pthread_attr_t*); int pthread_once(pthread_once_t*, void (*)(void)); #define PTHREAD_ONCE_INIT 0 -pthread_once_t once_control = PTHREAD_ONCE_INIT; void* pthread_getspecific(pthread_key_t key); int pthread_setspecific(pthread_key_t key, const void* value); diff --git a/Libraries/LibThread/Thread.cpp b/Libraries/LibThread/Thread.cpp index de5296f353..7c2e515524 100644 --- a/Libraries/LibThread/Thread.cpp +++ b/Libraries/LibThread/Thread.cpp @@ -1,4 +1,5 @@ #include +#include #include LibThread::Thread::Thread(Function action) @@ -17,17 +18,20 @@ LibThread::Thread::~Thread() void LibThread::Thread::start() { - int rc = create_thread([](void* arg) { - Thread* self = static_cast(arg); - int exit_code = self->m_action(); - self->m_tid = -1; - exit_thread(exit_code); - return exit_code; - }, static_cast(this)); + int rc = pthread_create( + &m_tid, + nullptr, + [](void* arg) -> void* { + Thread* self = static_cast(arg); + int exit_code = self->m_action(); + self->m_tid = -1; + pthread_exit((void*)exit_code); + return (void*)exit_code; + }, + static_cast(this)); - ASSERT(rc > 0); - dbg() << "Started a thread, tid = " << rc; - m_tid = rc; + ASSERT(rc == 0); + dbg() << "Started a thread, tid = " << m_tid; } void LibThread::Thread::quit(int code) @@ -35,5 +39,5 @@ void LibThread::Thread::quit(int code) ASSERT(m_tid == gettid()); m_tid = -1; - exit_thread(code); + pthread_exit((void*)code); } diff --git a/Makefile.common b/Makefile.common index 5eeb67aede..ef118a6400 100644 --- a/Makefile.common +++ b/Makefile.common @@ -13,7 +13,8 @@ INCLUDE_FLAGS = \ -I$(SERENITY_BASE_DIR)/Libraries \ -I$(SERENITY_BASE_DIR)/Libraries/LibC \ -I$(SERENITY_BASE_DIR)/Servers \ - -I$(SERENITY_BASE_DIR)/Libraries/LibM + -I$(SERENITY_BASE_DIR)/Libraries/LibM \ + -I$(SERENITY_BASE_DIR)/Libraries/LibPthread LDFLAGS = \ -L$(SERENITY_BASE_DIR)/Libraries/LibC \ diff --git a/Servers/AudioServer/Makefile b/Servers/AudioServer/Makefile index 53e6ee811e..5319635f11 100644 --- a/Servers/AudioServer/Makefile +++ b/Servers/AudioServer/Makefile @@ -19,7 +19,7 @@ AudioServerEndpoint.h: AudioServer.ipc @echo "IPC $<"; $(IPCCOMPILER) $< > $@ $(APP): $(OBJS) - $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lc -lcore -lipc -lthread + $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lc -lcore -lipc -lthread -lpthread .cpp.o: @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< diff --git a/Servers/WindowServer/Makefile b/Servers/WindowServer/Makefile index a1cbbd8d67..4f88b53189 100644 --- a/Servers/WindowServer/Makefile +++ b/Servers/WindowServer/Makefile @@ -26,7 +26,7 @@ DEFINES += -DUSERLAND all: $(APP) $(APP): $(OBJS) - $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lc -lcore -ldraw -lthread + $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lc -lcore -ldraw -lthread -lpthread .cpp.o: @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<