summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-11-16 12:19:58 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-11-16 12:23:36 +0100
commit66a2b582c36e3b0f7af80defd5507c01f7040b56 (patch)
tree896435087b0d72fe7ab50cbba94328943df54995
parent73d6a69b3fec21052c8d1059f350394b30e440b6 (diff)
downloadserenity-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.cpp29
-rw-r--r--Libraries/LibPthread/pthread.h3
-rw-r--r--Userland/tt.cpp59
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;
+}