فهرست منبع

LibC: Add futex_wait() and futex_wake() helpers

These are convinient wrappers over the most used futex operations.
futex_wait() also does some smarts for timeout and clock handling.

Use the new futex_wait() instead of a similar private helper in
LibPthread.
Sergey Bugaev 4 سال پیش
والد
کامیت
8fee93d868
2فایلهای تغییر یافته به همراه26 افزوده شده و 15 حذف شده
  1. 22 0
      Userland/Libraries/LibC/serenity.h
  2. 4 15
      Userland/Libraries/LibPthread/pthread.cpp

+ 22 - 0
Userland/Libraries/LibC/serenity.h

@@ -7,7 +7,9 @@
 #pragma once
 
 #include <stdio.h>
+#include <sys/cdefs.h>
 #include <sys/types.h>
+#include <time.h>
 #include <unistd.h>
 
 __BEGIN_DECLS
@@ -70,6 +72,26 @@ int profiling_free_buffer(pid_t);
 
 int futex(uint32_t* userspace_address, int futex_op, uint32_t value, const struct timespec* timeout, uint32_t* userspace_address2, uint32_t value3);
 
+static ALWAYS_INLINE int futex_wait(uint32_t* userspace_address, uint32_t value, const struct timespec* abstime, int clockid)
+{
+    int op;
+
+    if (abstime) {
+        // NOTE: FUTEX_WAIT takes a relative timeout, so use FUTEX_WAIT_BITSET instead!
+        op = FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG;
+        if (clockid == CLOCK_REALTIME || clockid == CLOCK_REALTIME_COARSE)
+            op |= FUTEX_CLOCK_REALTIME;
+    } else {
+        op = FUTEX_WAIT;
+    }
+    return futex(userspace_address, op, value, abstime, nullptr, FUTEX_BITSET_MATCH_ANY);
+}
+
+static ALWAYS_INLINE int futex_wake(uint32_t* userspace_address, uint32_t count)
+{
+    return futex(userspace_address, FUTEX_WAKE, count, NULL, NULL, 0);
+}
+
 #define PURGE_ALL_VOLATILE 0x1
 #define PURGE_ALL_CLEAN_INODE 0x2
 

+ 4 - 15
Userland/Libraries/LibPthread/pthread.cpp

@@ -458,27 +458,16 @@ int pthread_cond_destroy(pthread_cond_t*)
     return 0;
 }
 
-static int futex_wait(uint32_t& futex_addr, uint32_t value, const struct timespec* abstime)
-{
-    int saved_errno = errno;
-    // NOTE: FUTEX_WAIT takes a relative timeout, so use FUTEX_WAIT_BITSET instead!
-    int rc = futex(&futex_addr, FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, value, abstime, nullptr, FUTEX_BITSET_MATCH_ANY);
-    if (rc < 0 && errno == EAGAIN) {
-        // If we didn't wait, that's not an error
-        errno = saved_errno;
-        rc = 0;
-    }
-    return rc;
-}
-
 static int cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex, const struct timespec* abstime)
 {
     u32 value = cond->value;
     cond->previous = value;
     pthread_mutex_unlock(mutex);
-    int rc = futex_wait(cond->value, value, abstime);
+    int rc = futex_wait(&cond->value, value, abstime, cond->clockid);
     pthread_mutex_lock(mutex);
-    return rc;
+    if (rc < 0 && errno != EAGAIN)
+        return errno;
+    return 0;
 }
 
 int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex)