Title: [292225] trunk/Source/WebKit
Revision
292225
Author
commit-qu...@webkit.org
Date
2022-04-01 10:43:40 -0700 (Fri, 01 Apr 2022)

Log Message

[Linux] Implement IPC::Semaphore
https://bugs.webkit.org/show_bug.cgi?id=238596

Patch by Zan Dobersek <zdober...@igalia.com> on 2022-04-01
Reviewed by Adrian Perez de Castro.

Provide a Linux implementation for IPC::Semaphore that's based on
eventfd mechanics.

The IPC::Semaphore class now has a UNIX-specific file descriptor member
variable. For Linux, this file descriptor is an eventfd with semaphore
semantics (eventfd being Linux-specific). Signalling and waiting on
such semaphore is done through the read() and write() functions.
Non-Linux platforms are expected to provide something equivalent, if
possible.

For encoding and decoding that's necessary to move these semaphores
across process boundaries, IPC::Attachment is used. For encoding the
eventfd is simply duplicated and pushed into the Attachment, and for
decoding the Attachment's file descriptor is taken and adopted by the
Semaphore object.

* Platform/IPC/IPCSemaphore.h:
(IPC::Semaphore::operator bool const):
* Platform/IPC/unix/IPCSemaphoreUnix.cpp:
(IPC::Semaphore::Semaphore):
(IPC::Semaphore::~Semaphore):
(IPC::Semaphore::operator=):
(IPC::Semaphore::signal):
(IPC::waitImpl):
(IPC::Semaphore::wait):
(IPC::Semaphore::waitFor):
(IPC::Semaphore::encode const):
(IPC::Semaphore::decode):
(IPC::Semaphore::destroy):

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (292224 => 292225)


--- trunk/Source/WebKit/ChangeLog	2022-04-01 17:22:25 UTC (rev 292224)
+++ trunk/Source/WebKit/ChangeLog	2022-04-01 17:43:40 UTC (rev 292225)
@@ -1,3 +1,40 @@
+2022-04-01  Zan Dobersek  <zdober...@igalia.com>
+
+        [Linux] Implement IPC::Semaphore
+        https://bugs.webkit.org/show_bug.cgi?id=238596
+
+        Reviewed by Adrian Perez de Castro.
+
+        Provide a Linux implementation for IPC::Semaphore that's based on
+        eventfd mechanics.
+
+        The IPC::Semaphore class now has a UNIX-specific file descriptor member
+        variable. For Linux, this file descriptor is an eventfd with semaphore
+        semantics (eventfd being Linux-specific). Signalling and waiting on
+        such semaphore is done through the read() and write() functions.
+        Non-Linux platforms are expected to provide something equivalent, if
+        possible.
+
+        For encoding and decoding that's necessary to move these semaphores
+        across process boundaries, IPC::Attachment is used. For encoding the
+        eventfd is simply duplicated and pushed into the Attachment, and for
+        decoding the Attachment's file descriptor is taken and adopted by the
+        Semaphore object.
+
+        * Platform/IPC/IPCSemaphore.h:
+        (IPC::Semaphore::operator bool const):
+        * Platform/IPC/unix/IPCSemaphoreUnix.cpp:
+        (IPC::Semaphore::Semaphore):
+        (IPC::Semaphore::~Semaphore):
+        (IPC::Semaphore::operator=):
+        (IPC::Semaphore::signal):
+        (IPC::waitImpl):
+        (IPC::Semaphore::wait):
+        (IPC::Semaphore::waitFor):
+        (IPC::Semaphore::encode const):
+        (IPC::Semaphore::decode):
+        (IPC::Semaphore::destroy):
+
 2022-04-01  Youenn Fablet  <you...@apple.com>
 
         ServiceWorkerRegistration.getNotifications should list all persistent notifications

Modified: trunk/Source/WebKit/Platform/IPC/IPCSemaphore.h (292224 => 292225)


--- trunk/Source/WebKit/Platform/IPC/IPCSemaphore.h	2022-04-01 17:22:25 UTC (rev 292224)
+++ trunk/Source/WebKit/Platform/IPC/IPCSemaphore.h	2022-04-01 17:43:40 UTC (rev 292225)
@@ -64,6 +64,10 @@
     explicit operator bool() const { return m_sendRight || m_semaphore != SEMAPHORE_NULL; }
 #elif OS(WINDOWS)
     explicit Semaphore(HANDLE);
+#elif USE(UNIX_DOMAIN_SOCKETS)
+    explicit Semaphore(int fd);
+
+    explicit operator bool() const { return m_fd != -1; }
 #else
     explicit operator bool() const { return true; }
 #endif
@@ -75,6 +79,8 @@
     semaphore_t m_semaphore { SEMAPHORE_NULL };
 #elif OS(WINDOWS)
     HANDLE m_semaphoreHandle { nullptr };
+#elif USE(UNIX_DOMAIN_SOCKETS)
+    int m_fd { -1 };
 #endif
 };
 

Modified: trunk/Source/WebKit/Platform/IPC/unix/IPCSemaphoreUnix.cpp (292224 => 292225)


--- trunk/Source/WebKit/Platform/IPC/unix/IPCSemaphoreUnix.cpp	2022-04-01 17:22:25 UTC (rev 292224)
+++ trunk/Source/WebKit/Platform/IPC/unix/IPCSemaphoreUnix.cpp	2022-04-01 17:43:40 UTC (rev 292225)
@@ -26,47 +26,135 @@
 #include "config.h"
 #include "IPCSemaphore.h"
 
+#include <wtf/UniStdExtras.h>
+
+#if OS(LINUX)
+#include <sys/eventfd.h>
+#endif
+
 namespace IPC {
 
 Semaphore::Semaphore()
 {
-    ASSERT_NOT_REACHED();
+#if OS(LINUX)
+    m_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK | EFD_SEMAPHORE);
+#endif
 }
 
-Semaphore::Semaphore(Semaphore&&)
+Semaphore::Semaphore(int fd)
+    : m_fd(fd)
+{ }
+
+Semaphore::Semaphore(Semaphore&& o)
 {
-    ASSERT_NOT_REACHED();
+    m_fd = o.m_fd;
+    o.m_fd = -1;
 }
 
-Semaphore::~Semaphore() = default;
+Semaphore::~Semaphore()
+{
+    destroy();
+}
 
-Semaphore& Semaphore::operator=(Semaphore&&) = default;
+Semaphore& Semaphore::operator=(Semaphore&& o)
+{
+    if (&o == this)
+        return *this;
 
+    destroy();
+    m_fd = o.m_fd;
+    o.m_fd = -1;
+    return *this;
+}
+
 void Semaphore::signal()
 {
+#if OS(LINUX)
+    ASSERT_WITH_MESSAGE(m_fd >= 0, "Signalling on an invalid semaphore object");
+
+    // Matching waitImpl() and EFD_SEMAPHORE semantics, increment the semaphore value by 1.
+    uint64_t value = 1;
+    while (true) {
+        int ret = write(m_fd, &value, sizeof(uint64_t));
+        if (LIKELY(ret != -1 || errno != EINTR))
+            break;
+    }
+#endif
 }
 
+#if OS(LINUX)
+static bool waitImpl(int fd, int timeout)
+{
+    struct pollfd pollfdValue { .fd = fd, .events = POLLIN, .revents = 0 };
+    int ret = 0;
+
+    // Iterate on polling while interrupts are thrown, otherwise bail out of the loop immediately.
+    while (true) {
+        ret = poll(&pollfdValue, 1, timeout);
+        if (LIKELY(ret != -1 || errno != EINTR))
+            break;
+    }
+
+    // Fail if the return value doesn't indicate the single file descriptor with only input events available.
+    if (ret != 1 || !!(pollfdValue.revents ^ POLLIN))
+        return false;
+
+    // There should be data for reading -- due to EFD_SEMAPHORE, it should be 1 packed into an 8-byte value.
+    uint64_t value = 0;
+    ret = read(fd, &value, sizeof(uint64_t));
+    if (ret != sizeof(uint64_t) || value != 1)
+        return false;
+
+    return true;
+}
+#endif
+
 bool Semaphore::wait()
 {
+#if OS(LINUX)
+    ASSERT_WITH_MESSAGE(m_fd >= 0, "Waiting on an invalid semaphore object");
+
+    return waitImpl(m_fd, -1);
+#else
     return false;
+#endif
 }
 
-bool Semaphore::waitFor(Timeout)
+bool Semaphore::waitFor(Timeout timeout)
 {
+#if OS(LINUX)
+    ASSERT_WITH_MESSAGE(m_fd >= 0, "Waiting on an invalid semaphore object");
+
+    int timeoutValue = -1;
+    if (!timeout.isInfinity())
+        timeoutValue = int(timeout.secondsUntilDeadline().milliseconds());
+    return waitImpl(m_fd, timeoutValue);
+#else
     return false;
+#endif
 }
 
-void Semaphore::encode(Encoder&) const
+void Semaphore::encode(Encoder& encoder) const
 {
+    int duplicate = -1;
+    if (m_fd != -1)
+        duplicate = dupCloseOnExec(m_fd);
+
+    encoder.addAttachment(Attachment(duplicate));
 }
 
-std::optional<Semaphore> Semaphore::decode(Decoder&)
+std::optional<Semaphore> Semaphore::decode(Decoder& decoder)
 {
-    return Semaphore { };
+    auto attachment = decoder.takeLastAttachment();
+    if (!attachment)
+        return std::nullopt;
+    return std::optional<Semaphore> { std::in_place, attachment->releaseFileDescriptor() };
 }
 
 void Semaphore::destroy()
 {
+    if (m_fd >= 0)
+        closeWithRetry(m_fd);
 }
 
 } // namespace IPC
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to