diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-11-16 12:19:58 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-11-16 12:23:36 +0100 |
commit | 66a2b582c36e3b0f7af80defd5507c01f7040b56 (patch) | |
tree | 896435087b0d72fe7ab50cbba94328943df54995 | |
parent | 73d6a69b3fec21052c8d1059f350394b30e440b6 (diff) | |
download | serenity-66a2b582c36e3b0f7af80defd5507c01f7040b56.zip |
LibPthread: Implement a basic first pthread mutex
This patch adds these API's:
- pthread_mutex_init()
- pthread_mutex_lock()
- pthread_mutex_unlock()
No mutex attributes are supported yet, so we only do the simplest mutex
wihout recursive locking.
-rw-r--r-- | Libraries/LibPthread/pthread.cpp | 29 | ||||
-rw-r--r-- | Libraries/LibPthread/pthread.h | 3 | ||||
-rw-r--r-- | Userland/tt.cpp | 59 |
3 files changed, 84 insertions, 7 deletions
diff --git a/Libraries/LibPthread/pthread.cpp b/Libraries/LibPthread/pthread.cpp index b659d376d1..b1e17b1f61 100644 --- a/Libraries/LibPthread/pthread.cpp +++ b/Libraries/LibPthread/pthread.cpp @@ -1,7 +1,9 @@ +#include <AK/Atomic.h> #include <AK/StdLibExtras.h> #include <Kernel/Syscall.h> #include <pthread.h> #include <unistd.h> +#include <stdio.h> 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<Atomic<u32>*>(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<Atomic<u32>*>(mutex); + atomic->store(false, AK::memory_order_release); + return 0; +} + } diff --git a/Libraries/LibPthread/pthread.h b/Libraries/LibPthread/pthread.h index 19e6f88f19..5320a88539 100644 --- a/Libraries/LibPthread/pthread.h +++ b/Libraries/LibPthread/pthread.h @@ -1,6 +1,7 @@ #pragma once #include <sched.h> +#include <stdint.h> #include <sys/cdefs.h> __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 e8e56f8c8d..2823a19103 100644 --- a/Userland/tt.cpp +++ b/Userland/tt.cpp @@ -1,15 +1,24 @@ #include <pthread.h> #include <stdio.h> +#include <unistd.h> +#include <stdlib.h> -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; +} |