summaryrefslogtreecommitdiff
path: root/Libraries/LibPthread/pthread.cpp
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-12-22 14:21:59 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-12-22 14:25:41 +0100
commit0c97380ee638f0cd545b1853533de5cc41e21f4f (patch)
tree9c758a2c722bb8a3d970fecc6dfeeb99f5193dfe /Libraries/LibPthread/pthread.cpp
parent523fd6533e008cce85229b59ee58c552d565b87b (diff)
downloadserenity-0c97380ee638f0cd545b1853533de5cc41e21f4f.zip
LibPthread+LibC: Support PTHREAD_MUTEX_RECURSIVE
This allows SDL to build against our native recursive mutex instead of providing its own. Also it's just a nice feature to have. :^)
Diffstat (limited to 'Libraries/LibPthread/pthread.cpp')
-rw-r--r--Libraries/LibPthread/pthread.cpp57
1 files changed, 44 insertions, 13 deletions
diff --git a/Libraries/LibPthread/pthread.cpp b/Libraries/LibPthread/pthread.cpp
index 7aeaa49b6d..266f61a5e1 100644
--- a/Libraries/LibPthread/pthread.cpp
+++ b/Libraries/LibPthread/pthread.cpp
@@ -100,9 +100,10 @@ int pthread_sigmask(int how, const sigset_t* set, sigset_t* old_set)
int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attributes)
{
- // FIXME: Implement mutex attributes
- UNUSED_PARAM(attributes);
- *mutex = 0;
+ mutex->lock = 0;
+ mutex->owner = 0;
+ mutex->level = 0;
+ mutex->type = attributes ? attributes->type : PTHREAD_MUTEX_NORMAL;
return 0;
}
@@ -114,27 +115,47 @@ int pthread_mutex_destroy(pthread_mutex_t*)
int pthread_mutex_lock(pthread_mutex_t* mutex)
{
auto* atomic = reinterpret_cast<Atomic<u32>*>(mutex);
+ pthread_t this_thread = pthread_self();
for (;;) {
u32 expected = false;
- if (atomic->compare_exchange_strong(expected, true, AK::memory_order_acq_rel))
- return 0;
- sched_yield();
+ if (!atomic->compare_exchange_strong(expected, true, AK::memory_order_acq_rel)) {
+ if (mutex->type == PTHREAD_MUTEX_RECURSIVE && mutex->owner == this_thread) {
+ mutex->level++;
+ return 0;
+ }
+ sched_yield();
+ continue;
+ }
+ mutex->owner = this_thread;
+ mutex->level = 0;
+ return 0;
}
}
int pthread_mutex_trylock(pthread_mutex_t* mutex)
{
- auto* atomic = reinterpret_cast<Atomic<u32>*>(mutex);
+ auto* atomic = reinterpret_cast<Atomic<u32>*>(mutex->lock);
u32 expected = false;
- if (atomic->compare_exchange_strong(expected, true, AK::memory_order_acq_rel))
- return 0;
- return EBUSY;
+ if (!atomic->compare_exchange_strong(expected, true, AK::memory_order_acq_rel)) {
+ if (mutex->type == PTHREAD_MUTEX_RECURSIVE && mutex->owner == pthread_self()) {
+ mutex->level++;
+ return 0;
+ }
+ return EBUSY;
+ }
+ mutex->owner = pthread_self();
+ mutex->level = 0;
+ return 0;
}
int pthread_mutex_unlock(pthread_mutex_t* mutex)
{
- auto* atomic = reinterpret_cast<Atomic<u32>*>(mutex);
- atomic->store(false, AK::memory_order_release);
+ if (mutex->type == PTHREAD_MUTEX_RECURSIVE && mutex->level > 0) {
+ mutex->level--;
+ return 0;
+ }
+ mutex->owner = 0;
+ mutex->lock = 0;
return 0;
}
@@ -149,6 +170,16 @@ int pthread_mutexattr_destroy(pthread_mutexattr_t*)
return 0;
}
+int pthread_mutexattr_settype(pthread_mutexattr_t* attr, int type)
+{
+ if (!attr)
+ return EINVAL;
+ if (type != PTHREAD_MUTEX_NORMAL && type != PTHREAD_MUTEX_RECURSIVE)
+ return EINVAL;
+ attr->type = type;
+ return 0;
+}
+
int pthread_attr_init(pthread_attr_t* attributes)
{
auto* impl = new PthreadAttrImpl {};
@@ -492,7 +523,7 @@ struct KeyTable {
// FIXME: Invoke key destructors on thread exit!
KeyDestructor destructors[64] { nullptr };
int next { 0 };
- pthread_mutex_t mutex { PTHREAD_MUTEX_INITIALIZER };
+ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
};
struct SpecificTable {