[starnix] Use lutex on Fuchsia

This allows fuchsia component that use remote binder to use libfmq.

Bug: 297443970, 297431411

Change-Id: If2512194bf8f8389be5fab1b1a8409766f8e047b
Reviewed-on: https://fuchsia-review.googlesource.com/c/third_party/android.googlesource.com/platform/system/libfmq/+/895758
Reviewed-by: Adam Barth <abarth@google.com>
diff --git a/EventFlag.cpp b/EventFlag.cpp
index d353873..0a4e4c0 100644
--- a/EventFlag.cpp
+++ b/EventFlag.cpp
@@ -16,10 +16,8 @@
 
 #define LOG_TAG "FMQ_EventFlags"
 
-#include <linux/futex.h>
 #include <string.h>
 #include <sys/mman.h>
-#include <sys/syscall.h>
 #include <unistd.h>
 
 #include <limits>
@@ -29,9 +27,37 @@
 #include <utils/Log.h>
 #include <utils/SystemClock.h>
 
+#if defined(__Fuchsia__)
+#include "vendor/google/starnix/android/remote_binder/lutex.h"
+#else
+#include <linux/futex.h>
+#include <sys/syscall.h>
+#endif
+
 namespace android {
 namespace hardware {
 
+namespace {
+long futex_wake(void* futex_address, uint32_t count, uint32_t bitmask) {
+#if defined(__Fuchsia__)
+  return starnix::lutex_wake(futex_address, count, bitmask);
+#else
+  return syscall(__NR_futex, futex_address,  FUTEX_WAKE_BITSET, kIntMax, NULL,
+                 NULL, bitmask);
+#endif
+}
+
+long futex_wait(void* futex_address, uint32_t value, uint32_t bitmask,
+                const struct timespec* timeout) {
+#if defined(__Fuchsia__)
+  return starnix::lutex_wait(futex_address, value, bitmask, timeout);
+#else
+  return syscall(__NR_futex, futex_address, FUTEX_WAIT_BITSET, value, timeout,
+                 NULL, bitmask);
+#endif
+}
+}
+
 status_t EventFlag::createEventFlag(std::atomic<uint32_t>* fwAddr,
                                     EventFlag** flag) {
     if (flag == nullptr) {
@@ -86,7 +112,7 @@
      */
     constexpr size_t kIntMax = std::numeric_limits<int>::max();
     if ((~old & bitmask) != 0) {
-        int ret = syscall(__NR_futex, mEfWordPtr, FUTEX_WAKE_BITSET, kIntMax, NULL, NULL, bitmask);
+        int ret = futex_wake(mEfWordPtr, kIntMax, bitmask);
         if (ret == -1) {
             status = -errno;
             ALOGE("Error in event flag wake attempt: %s\n", strerror(errno));
@@ -131,10 +157,9 @@
         struct timespec waitTimeAbsolute;
         addNanosecondsToCurrentTime(timeoutNanoSeconds, &waitTimeAbsolute);
 
-        ret = syscall(__NR_futex, mEfWordPtr, FUTEX_WAIT_BITSET,
-                      efWord, &waitTimeAbsolute, NULL, bitmask);
+        ret = futex_wait(mEfWordPtr, efWord, bitmask, &waitTimeAbsolute);
     } else {
-        ret = syscall(__NR_futex, mEfWordPtr, FUTEX_WAIT_BITSET, efWord, NULL, NULL, bitmask);
+        ret = futex_wait(mEfWordPtr, efWord, bitmask, NULL);
     }
     if (ret == -1) {
         status = -errno;
diff --git a/include/fmq/MessageQueueBase.h b/include/fmq/MessageQueueBase.h
index f4bf7e2..f6d93c9 100644
--- a/include/fmq/MessageQueueBase.h
+++ b/include/fmq/MessageQueueBase.h
@@ -26,6 +26,10 @@
 #include <atomic>
 #include <new>
 
+#if defined(__Fuchsia__)
+#include "vendor/google/starnix/android/remote_binder/lutex.h"
+#endif
+
 using android::hardware::kSynchronizedReadWrite;
 using android::hardware::kUnsynchronizedWrite;
 using android::hardware::MQFlavor;
@@ -1293,7 +1297,13 @@
         hardware::details::logError(std::string("mmap failed: ") + std::to_string(errno));
         return nullptr;
     }
-    return reinterpret_cast<uint8_t*>(address) + (grantors[grantorIdx].offset - mapOffset);
+    void* result = reinterpret_cast<uint8_t*>(address) + (grantors[grantorIdx].offset - mapOffset);
+#if defined(__Fuchsia__)
+    if (grantorIdx == hardware::details::EVFLAGWORDPOS) {
+      starnix::register_lutex(handle->data[fdIndex], grantors[grantorIdx].offset, result);
+    }
+#endif
+    return result;
 }
 
 template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
@@ -1308,7 +1318,14 @@
     int mapLength = grantors[grantorIdx].offset - mapOffset + grantors[grantorIdx].extent;
     void* baseAddress =
             reinterpret_cast<uint8_t*>(address) - (grantors[grantorIdx].offset - mapOffset);
-    if (baseAddress) munmap(baseAddress, mapLength);
+    if (baseAddress) {
+#if defined(__Fuchsia__)
+    if (grantorIdx == hardware::details::EVFLAGWORDPOS) {
+      starnix::unregister_lutex(address);
+    }
+#endif
+      munmap(baseAddress, mapLength);
+    }
 }
 
 }  // namespace hardware