diff --git a/Libraries/LibPthread/pthread.cpp b/Libraries/LibPthread/pthread.cpp index b659d376d1d..b1e17b1f617 100644 --- a/Libraries/LibPthread/pthread.cpp +++ b/Libraries/LibPthread/pthread.cpp @@ -1,7 +1,9 @@ +#include #include #include #include #include +#include extern "C" { @@ -27,4 +29,31 @@ int pthread_join(pthread_t thread, void** exit_value_ptr) int rc = syscall(SC_join_thread, thread, exit_value_ptr); __RETURN_WITH_ERRNO(rc, rc, -1); } + +int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attributes) +{ + // FIXME: Implement mutex attributes + UNUSED_PARAM(attributes); + *mutex = 0; + return 0; +} + +int pthread_mutex_lock(pthread_mutex_t* mutex) +{ + auto* atomic = reinterpret_cast*>(mutex); + for (;;) { + u32 expected = false; + if (atomic->compare_exchange_strong(expected, true, AK::memory_order_acq_rel)) + return 0; + sched_yield(); + } +} + +int pthread_mutex_unlock(pthread_mutex_t* mutex) +{ + auto* atomic = reinterpret_cast*>(mutex); + atomic->store(false, AK::memory_order_release); + return 0; +} + } diff --git a/Libraries/LibPthread/pthread.h b/Libraries/LibPthread/pthread.h index 19e6f88f199..5320a885399 100644 --- a/Libraries/LibPthread/pthread.h +++ b/Libraries/LibPthread/pthread.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include __BEGIN_DECLS @@ -8,7 +9,7 @@ __BEGIN_DECLS typedef int pthread_t; typedef void* pthread_key_t; typedef void* pthread_once_t; -typedef void* pthread_mutex_t; +typedef uint32_t pthread_mutex_t; typedef void* pthread_attr_t; typedef void* pthread_mutexattr_t; typedef void* pthread_cond_t; diff --git a/Userland/tt.cpp b/Userland/tt.cpp index e8e56f8c8df..2823a19103b 100644 --- a/Userland/tt.cpp +++ b/Userland/tt.cpp @@ -1,15 +1,24 @@ #include #include +#include +#include -int main(int, char**) +static int mutex_test(); + +int main(int argc, char** argv) { + if (argc == 2 && *argv[1] == 'm') + return mutex_test(); + printf("Hello from the first thread!\n"); pthread_t thread_id; - int rc = pthread_create(&thread_id, nullptr, [](void*) -> void* { - printf("Hi there, from the second thread!\n"); - pthread_exit((void*)0xDEADBEEF); - return nullptr; - }, nullptr); + int rc = pthread_create( + &thread_id, nullptr, [](void*) -> void* { + printf("Hi there, from the second thread!\n"); + pthread_exit((void*)0xDEADBEEF); + return nullptr; + }, + nullptr); if (rc < 0) { perror("pthread_create"); return 1; @@ -23,3 +32,41 @@ int main(int, char**) printf("Okay, joined and got retval=%p\n", retval); return 0; } + +static pthread_mutex_t mutex; + +int mutex_test() +{ + int rc = pthread_mutex_init(&mutex, nullptr); + if (rc < 0) { + perror("pthread_mutex_init"); + return 1; + } + pthread_t thread_id; + rc = pthread_create( + &thread_id, nullptr, [](void*) -> void* { + printf("I'm the secondary thread :^)\n"); + for (;;) { + pthread_mutex_lock(&mutex); + printf("Second thread stole mutex\n"); + sleep(1); + printf("Second thread giving back mutex\n"); + pthread_mutex_unlock(&mutex); + sleep(1); + } + pthread_exit((void*)0xDEADBEEF); + return nullptr; + }, + nullptr); + if (rc < 0) { + perror("pthread_create"); + return 1; + } + for (;;) { + pthread_mutex_lock(&mutex); + printf("Obnoxious spam!\n"); + pthread_mutex_unlock(&mutex); + usleep(10000); + } + return 0; +}