Jelajahi Sumber

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.
Andreas Kling 5 tahun lalu
induk
melakukan
69ca9cfd78

+ 1 - 1
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 $<

+ 1 - 1
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 $<

+ 5 - 3
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 (&current->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);

+ 2 - 2
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);

+ 1 - 1
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;
     }

+ 1 - 0
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"

+ 3 - 4
Libraries/LibC/unistd.cpp

@@ -1,5 +1,5 @@
-#include <AK/String.h>
 #include <AK/ScopedValueRollback.h>
+#include <AK/String.h>
 #include <AK/Vector.h>
 #include <Kernel/Syscall.h>
 #include <assert.h>
@@ -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);
 }
-
 }

+ 2 - 2
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);

+ 19 - 0
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

+ 9 - 0
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/

+ 24 - 0
Libraries/LibPthread/pthread.cpp

@@ -0,0 +1,24 @@
+#include <AK/StdLibExtras.h>
+#include <pthread.h>
+#include <unistd.h>
+
+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);
+}
+
+}

+ 2 - 3
Libraries/LibC/pthread.h → 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);
 

+ 15 - 11
Libraries/LibThread/Thread.cpp

@@ -1,4 +1,5 @@
 #include <LibThread/Thread.h>
+#include <pthread.h>
 #include <unistd.h>
 
 LibThread::Thread::Thread(Function<int()> action)
@@ -17,17 +18,20 @@ LibThread::Thread::~Thread()
 
 void LibThread::Thread::start()
 {
-    int rc = create_thread([](void* arg) {
-        Thread* self = static_cast<Thread*>(arg);
-        int exit_code = self->m_action();
-        self->m_tid = -1;
-        exit_thread(exit_code);
-        return exit_code;
-    }, static_cast<void*>(this));
+    int rc = pthread_create(
+        &m_tid,
+        nullptr,
+        [](void* arg) -> void* {
+            Thread* self = static_cast<Thread*>(arg);
+            int exit_code = self->m_action();
+            self->m_tid = -1;
+            pthread_exit((void*)exit_code);
+            return (void*)exit_code;
+        },
+        static_cast<void*>(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);
 }

+ 2 - 1
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 \

+ 1 - 1
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 $<

+ 1 - 1
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 $<