mirror of
https://github.com/RGBCube/serenity
synced 2025-05-30 23:08:11 +00:00
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.
This commit is contained in:
parent
73d6a69b3f
commit
66a2b582c3
3 changed files with 84 additions and 7 deletions
|
@ -1,7 +1,9 @@
|
||||||
|
#include <AK/Atomic.h>
|
||||||
#include <AK/StdLibExtras.h>
|
#include <AK/StdLibExtras.h>
|
||||||
#include <Kernel/Syscall.h>
|
#include <Kernel/Syscall.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
extern "C" {
|
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);
|
int rc = syscall(SC_join_thread, thread, exit_value_ptr);
|
||||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
__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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
@ -8,7 +9,7 @@ __BEGIN_DECLS
|
||||||
typedef int 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 uint32_t pthread_mutex_t;
|
||||||
typedef void* pthread_attr_t;
|
typedef void* pthread_attr_t;
|
||||||
typedef void* pthread_mutexattr_t;
|
typedef void* pthread_mutexattr_t;
|
||||||
typedef void* pthread_cond_t;
|
typedef void* pthread_cond_t;
|
||||||
|
|
|
@ -1,15 +1,24 @@
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdio.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");
|
printf("Hello from the first thread!\n");
|
||||||
pthread_t thread_id;
|
pthread_t thread_id;
|
||||||
int rc = pthread_create(&thread_id, nullptr, [](void*) -> void* {
|
int rc = pthread_create(
|
||||||
printf("Hi there, from the second thread!\n");
|
&thread_id, nullptr, [](void*) -> void* {
|
||||||
pthread_exit((void*)0xDEADBEEF);
|
printf("Hi there, from the second thread!\n");
|
||||||
return nullptr;
|
pthread_exit((void*)0xDEADBEEF);
|
||||||
}, nullptr);
|
return nullptr;
|
||||||
|
},
|
||||||
|
nullptr);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
perror("pthread_create");
|
perror("pthread_create");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -23,3 +32,41 @@ int main(int, char**)
|
||||||
printf("Okay, joined and got retval=%p\n", retval);
|
printf("Okay, joined and got retval=%p\n", retval);
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue