mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:57:45 +00:00
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.
This commit is contained in:
parent
4fe2ee0221
commit
69ca9cfd78
16 changed files with 89 additions and 31 deletions
|
@ -3,7 +3,7 @@ DEFINES += -DUSERLAND
|
||||||
all: $(APP)
|
all: $(APP)
|
||||||
|
|
||||||
$(APP): $(OBJS)
|
$(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:
|
.cpp.o:
|
||||||
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||||
|
|
|
@ -25,7 +25,7 @@ DEFINES += -DUSERLAND
|
||||||
all: $(APP)
|
all: $(APP)
|
||||||
|
|
||||||
$(APP): $(OBJS)
|
$(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:
|
.cpp.o:
|
||||||
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||||
|
|
|
@ -2807,7 +2807,7 @@ int Process::thread_count() const
|
||||||
return count;
|
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*)))
|
if (!validate_read((const void*)entry, sizeof(void*)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
@ -2822,11 +2822,13 @@ int Process::sys$create_thread(int (*entry)(void*), void* argument)
|
||||||
return thread->tid();
|
return thread->tid();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::sys$exit_thread(int code)
|
void Process::sys$exit_thread(void* code)
|
||||||
{
|
{
|
||||||
|
UNUSED_PARAM(code);
|
||||||
cli();
|
cli();
|
||||||
if (¤t->process().main_thread() == current) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
current->set_state(Thread::State::Dying);
|
current->set_state(Thread::State::Dying);
|
||||||
|
|
|
@ -204,8 +204,8 @@ public:
|
||||||
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$restore_signal_mask(u32 mask);
|
int sys$restore_signal_mask(u32 mask);
|
||||||
int sys$create_thread(int (*)(void*), void*);
|
int sys$create_thread(void* (*)(void*), void*);
|
||||||
void sys$exit_thread(int code);
|
void sys$exit_thread(void*);
|
||||||
int sys$rename(const char* oldpath, const char* newpath);
|
int sys$rename(const char* oldpath, const char* newpath);
|
||||||
int sys$systrace(pid_t);
|
int sys$systrace(pid_t);
|
||||||
int sys$mknod(const char* pathname, mode_t, dev_t);
|
int sys$mknod(const char* pathname, mode_t, dev_t);
|
||||||
|
|
|
@ -67,7 +67,7 @@ int handle(RegisterDump& regs, u32 function, u32 arg1, u32 arg2, u32 arg3)
|
||||||
if (function == SC_exit)
|
if (function == SC_exit)
|
||||||
process.sys$exit((int)arg1);
|
process.sys$exit((int)arg1);
|
||||||
else
|
else
|
||||||
process.sys$exit_thread((int)arg1);
|
process.sys$exit_thread((void*)arg1);
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ build_targets="$build_targets ../Libraries/LibC"
|
||||||
build_targets="$build_targets ../Libraries/LibCore"
|
build_targets="$build_targets ../Libraries/LibCore"
|
||||||
build_targets="$build_targets ../Libraries/LibIPC"
|
build_targets="$build_targets ../Libraries/LibIPC"
|
||||||
build_targets="$build_targets ../Libraries/LibThread"
|
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 IPC servers before their client code to ensure the IPC definitions are available.
|
||||||
build_targets="$build_targets ../Servers/AudioServer"
|
build_targets="$build_targets ../Servers/AudioServer"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include <AK/String.h>
|
|
||||||
#include <AK/ScopedValueRollback.h>
|
#include <AK/ScopedValueRollback.h>
|
||||||
|
#include <AK/String.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <Kernel/Syscall.h>
|
#include <Kernel/Syscall.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -540,13 +540,13 @@ char* getlogin()
|
||||||
return nullptr;
|
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);
|
int rc = syscall(SC_create_thread, entry, argument);
|
||||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void exit_thread(int code)
|
void exit_thread(void* code)
|
||||||
{
|
{
|
||||||
syscall(SC_exit_thread, code);
|
syscall(SC_exit_thread, code);
|
||||||
ASSERT_NOT_REACHED();
|
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);
|
int rc = syscall(SC_get_process_name, buffer, buffer_size);
|
||||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,8 @@ void sysbeep();
|
||||||
int systrace(pid_t);
|
int systrace(pid_t);
|
||||||
int gettid();
|
int gettid();
|
||||||
int donate(int tid);
|
int donate(int tid);
|
||||||
int create_thread(int (*)(void*), void*);
|
int create_thread(void *(*)(void*), void* argument);
|
||||||
void exit_thread(int);
|
void exit_thread(void*);
|
||||||
int create_shared_buffer(int, void** buffer);
|
int create_shared_buffer(int, void** buffer);
|
||||||
int share_buffer_with(int, pid_t peer_pid);
|
int share_buffer_with(int, pid_t peer_pid);
|
||||||
int share_buffer_globally(int);
|
int share_buffer_globally(int);
|
||||||
|
|
19
Libraries/LibPthread/Makefile
Normal file
19
Libraries/LibPthread/Makefile
Normal file
|
@ -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
Libraries/LibPthread/install.sh
Executable file
9
Libraries/LibPthread/install.sh
Executable file
|
@ -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
Libraries/LibPthread/pthread.cpp
Normal file
24
Libraries/LibPthread/pthread.cpp
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
typedef void* pthread_t;
|
typedef int pthread_t;
|
||||||
typedef void* pthread_key_t;
|
typedef void* pthread_key_t;
|
||||||
typedef void* pthread_once_t;
|
typedef void* pthread_once_t;
|
||||||
typedef void* pthread_mutex_t;
|
typedef void* pthread_mutex_t;
|
||||||
|
@ -15,7 +15,7 @@ typedef void* pthread_cond_t;
|
||||||
typedef void* pthread_spinlock_t;
|
typedef void* pthread_spinlock_t;
|
||||||
typedef void* pthread_condattr_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*);
|
void pthread_exit(void*);
|
||||||
int pthread_kill(pthread_t, int);
|
int pthread_kill(pthread_t, int);
|
||||||
void pthread_cleanup_push(void (*)(void*), void*);
|
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));
|
int pthread_once(pthread_once_t*, void (*)(void));
|
||||||
#define PTHREAD_ONCE_INIT 0
|
#define PTHREAD_ONCE_INIT 0
|
||||||
pthread_once_t once_control = PTHREAD_ONCE_INIT;
|
|
||||||
void* pthread_getspecific(pthread_key_t key);
|
void* pthread_getspecific(pthread_key_t key);
|
||||||
int pthread_setspecific(pthread_key_t key, const void* value);
|
int pthread_setspecific(pthread_key_t key, const void* value);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <LibThread/Thread.h>
|
#include <LibThread/Thread.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
LibThread::Thread::Thread(Function<int()> action)
|
LibThread::Thread::Thread(Function<int()> action)
|
||||||
|
@ -17,17 +18,20 @@ LibThread::Thread::~Thread()
|
||||||
|
|
||||||
void LibThread::Thread::start()
|
void LibThread::Thread::start()
|
||||||
{
|
{
|
||||||
int rc = create_thread([](void* arg) {
|
int rc = pthread_create(
|
||||||
|
&m_tid,
|
||||||
|
nullptr,
|
||||||
|
[](void* arg) -> void* {
|
||||||
Thread* self = static_cast<Thread*>(arg);
|
Thread* self = static_cast<Thread*>(arg);
|
||||||
int exit_code = self->m_action();
|
int exit_code = self->m_action();
|
||||||
self->m_tid = -1;
|
self->m_tid = -1;
|
||||||
exit_thread(exit_code);
|
pthread_exit((void*)exit_code);
|
||||||
return exit_code;
|
return (void*)exit_code;
|
||||||
}, static_cast<void*>(this));
|
},
|
||||||
|
static_cast<void*>(this));
|
||||||
|
|
||||||
ASSERT(rc > 0);
|
ASSERT(rc == 0);
|
||||||
dbg() << "Started a thread, tid = " << rc;
|
dbg() << "Started a thread, tid = " << m_tid;
|
||||||
m_tid = rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibThread::Thread::quit(int code)
|
void LibThread::Thread::quit(int code)
|
||||||
|
@ -35,5 +39,5 @@ void LibThread::Thread::quit(int code)
|
||||||
ASSERT(m_tid == gettid());
|
ASSERT(m_tid == gettid());
|
||||||
|
|
||||||
m_tid = -1;
|
m_tid = -1;
|
||||||
exit_thread(code);
|
pthread_exit((void*)code);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,8 @@ INCLUDE_FLAGS = \
|
||||||
-I$(SERENITY_BASE_DIR)/Libraries \
|
-I$(SERENITY_BASE_DIR)/Libraries \
|
||||||
-I$(SERENITY_BASE_DIR)/Libraries/LibC \
|
-I$(SERENITY_BASE_DIR)/Libraries/LibC \
|
||||||
-I$(SERENITY_BASE_DIR)/Servers \
|
-I$(SERENITY_BASE_DIR)/Servers \
|
||||||
-I$(SERENITY_BASE_DIR)/Libraries/LibM
|
-I$(SERENITY_BASE_DIR)/Libraries/LibM \
|
||||||
|
-I$(SERENITY_BASE_DIR)/Libraries/LibPthread
|
||||||
|
|
||||||
LDFLAGS = \
|
LDFLAGS = \
|
||||||
-L$(SERENITY_BASE_DIR)/Libraries/LibC \
|
-L$(SERENITY_BASE_DIR)/Libraries/LibC \
|
||||||
|
|
|
@ -19,7 +19,7 @@ AudioServerEndpoint.h: AudioServer.ipc
|
||||||
@echo "IPC $<"; $(IPCCOMPILER) $< > $@
|
@echo "IPC $<"; $(IPCCOMPILER) $< > $@
|
||||||
|
|
||||||
$(APP): $(OBJS)
|
$(APP): $(OBJS)
|
||||||
$(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lc -lcore -lipc -lthread
|
$(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lc -lcore -lipc -lthread -lpthread
|
||||||
|
|
||||||
.cpp.o:
|
.cpp.o:
|
||||||
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||||
|
|
|
@ -26,7 +26,7 @@ DEFINES += -DUSERLAND
|
||||||
all: $(APP)
|
all: $(APP)
|
||||||
|
|
||||||
$(APP): $(OBJS)
|
$(APP): $(OBJS)
|
||||||
$(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lc -lcore -ldraw -lthread
|
$(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lc -lcore -ldraw -lthread -lpthread
|
||||||
|
|
||||||
.cpp.o:
|
.cpp.o:
|
||||||
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue