Add EFD_SEMAPHORE flag for eventfd.

Add a test for the new flag and add a test for the EFD_CLOEXEC flag.

Test: New unit tests pass on glibc and target.
Change-Id: Ib7a6ea4aadbd67ba8a523b6114a49fb8d6a43f12
diff --git a/libc/include/sys/eventfd.h b/libc/include/sys/eventfd.h
index 85f9877..1b6ad29 100644
--- a/libc/include/sys/eventfd.h
+++ b/libc/include/sys/eventfd.h
@@ -38,6 +38,8 @@
 
 __BEGIN_DECLS
 
+/** The eventfd() flag to provide semaphore-like semantics for reads. */
+#define EFD_SEMAPHORE (1 << 0)
 /** The eventfd() flag for a close-on-exec file descriptor. */
 #define EFD_CLOEXEC O_CLOEXEC
 /** The eventfd() flag for a non-blocking file descriptor. */
diff --git a/tests/eventfd_test.cpp b/tests/eventfd_test.cpp
index 68d9192..3c303c2 100644
--- a/tests/eventfd_test.cpp
+++ b/tests/eventfd_test.cpp
@@ -21,14 +21,16 @@
 
 #include <sys/eventfd.h>
 
+#include "utils.h"
+
 TEST(eventfd, smoke) {
-  unsigned int initial_value = 2;
-  int fd = eventfd(initial_value, O_NONBLOCK);
-  ASSERT_NE(fd, -1);
+  constexpr unsigned int kInitialValue = 2;
+  int fd = eventfd(kInitialValue, EFD_NONBLOCK);
+  ASSERT_NE(-1, fd);
 
   eventfd_t value = 123;
   ASSERT_EQ(0, eventfd_read(fd, &value));
-  ASSERT_EQ(initial_value, value);
+  ASSERT_EQ(kInitialValue, value);
 
   // Reading clears the counter.
   ASSERT_EQ(-1, eventfd_read(fd, &value));
@@ -44,3 +46,49 @@
 
   close(fd);
 }
+
+TEST(eventfd, cloexec) {
+  constexpr unsigned int kInitialValue = 2;
+  int fd = eventfd(kInitialValue, EFD_CLOEXEC);
+  ASSERT_NE(-1, fd);
+  AssertCloseOnExec(fd, true);
+
+  eventfd_t value = 123;
+  ASSERT_EQ(0, eventfd_read(fd, &value));
+  ASSERT_EQ(kInitialValue, value);
+
+  close(fd);
+
+  fd = eventfd(kInitialValue, EFD_NONBLOCK | EFD_CLOEXEC);
+  ASSERT_NE(-1, fd);
+  AssertCloseOnExec(fd, true);
+
+  value = 123;
+  ASSERT_EQ(0, eventfd_read(fd, &value));
+  ASSERT_EQ(kInitialValue, value);
+
+  close(fd);
+}
+
+TEST(eventfd, semaphore) {
+  int fd = eventfd(3, EFD_NONBLOCK | EFD_SEMAPHORE);
+  ASSERT_NE(-1, fd);
+
+  eventfd_t value = 123;
+  ASSERT_EQ(0, eventfd_read(fd, &value));
+  ASSERT_EQ(1U, value);
+
+  value = 123;
+  ASSERT_EQ(0, eventfd_read(fd, &value));
+  ASSERT_EQ(1U, value);
+
+  value = 123;
+  ASSERT_EQ(0, eventfd_read(fd, &value));
+  ASSERT_EQ(1U, value);
+
+  // The counter is cleared after the initial value decrements to 0.
+  ASSERT_EQ(-1, eventfd_read(fd, &value));
+  ASSERT_EQ(EAGAIN, errno);
+
+  close(fd);
+}