[libc-commits] [libc] be4e425 - [libc] Add select.h and the implementation of the select function for Linux.

Siva Chandra Reddy via libc-commits libc-commits at lists.llvm.org
Fri Oct 21 20:17:57 PDT 2022


Author: Siva Chandra Reddy
Date: 2022-10-22T03:17:48Z
New Revision: be4e425758afb926c63eadcfa6bf054bc33c0e4c

URL: https://github.com/llvm/llvm-project/commit/be4e425758afb926c63eadcfa6bf054bc33c0e4c
DIFF: https://github.com/llvm/llvm-project/commit/be4e425758afb926c63eadcfa6bf054bc33c0e4c.diff

LOG: [libc] Add select.h and the implementation of the select function for Linux.

Reviewed By: michaelrj

Differential Revision: https://reviews.llvm.org/D136375

Added: 
    libc/include/llvm-libc-macros/sys-select-macros.h
    libc/include/llvm-libc-types/fd_set.h
    libc/include/sys/select.h.def
    libc/src/sys/select/CMakeLists.txt
    libc/src/sys/select/linux/CMakeLists.txt
    libc/src/sys/select/linux/select.cpp
    libc/src/sys/select/select.h
    libc/test/src/sys/select/CMakeLists.txt
    libc/test/src/sys/select/select_failure_test.cpp
    libc/test/src/sys/select/select_ui_test.cpp
    libc/test/src/sys/select/testdata/CMakeLists.txt

Modified: 
    libc/config/linux/api.td
    libc/config/linux/x86_64/entrypoints.txt
    libc/config/linux/x86_64/headers.txt
    libc/include/CMakeLists.txt
    libc/include/llvm-libc-macros/CMakeLists.txt
    libc/include/llvm-libc-types/CMakeLists.txt
    libc/spec/linux.td
    libc/spec/posix.td
    libc/spec/spec.td
    libc/src/sys/CMakeLists.txt
    libc/test/src/sys/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index 2b5b033593330..8d2e64fb00fb0 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -274,6 +274,10 @@ def SysRandomAPI : PublicAPI<"sys/random.h"> {
   let Types = ["size_t", "ssize_t"];
 }
 
+def SysSelectAPI : PublicAPI<"sys/select.h"> {
+  let Types = ["fd_set", "sigset_t", "suseconds_t", "time_t", "struct timespec", "struct timeval"];
+}
+
 def SysResourceAPI : PublicAPI<"sys/resource.h"> {
   let Types = ["rlim_t", "struct rlimit"];
 }

diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index a05c451c9d1b7..2637faf9be01d 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -452,6 +452,9 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.unistd.execv
     libc.src.unistd.fork
     libc.src.unistd.__llvm_libc_syscall
+
+    # sys/select.h entrypoints
+    libc.src.sys.select.select
   )
 endif()
 

diff  --git a/libc/config/linux/x86_64/headers.txt b/libc/config/linux/x86_64/headers.txt
index d968b053ef2fe..a44ea884b9028 100644
--- a/libc/config/linux/x86_64/headers.txt
+++ b/libc/config/linux/x86_64/headers.txt
@@ -25,6 +25,7 @@ set(TARGET_PUBLIC_HEADERS
     libc.include.sys_prctl
     libc.include.sys_random
     libc.include.sys_resource
+    libc.include.sys_select
     libc.include.sys_stat
     libc.include.sys_syscall
     libc.include.sys_time

diff  --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index cd614ab81bfd0..cd00565aa13cb 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -301,6 +301,22 @@ add_gen_header(
     .llvm-libc-types.struct_stat
 )
 
+add_gen_header(
+  sys_select
+  DEF_FILE sys/select.h.def
+  GEN_HDR sys/select.h
+  DEPENDS
+    .llvm_libc_common_h
+    .llvm-libc-macros.sys_select_macros
+    .llvm-libc-types.fd_set
+    .llvm-libc-types.sigset_t
+    .llvm-libc-types.struct_timespec
+    .llvm-libc-types.struct_timeval
+    .llvm-libc-types.suseconds_t
+    .llvm-libc-types.time_t
+    .llvm-libc-types.ssize_t
+)
+
 add_gen_header(
   sys_sendfile
   DEF_FILE sys/sendfile.h.def

diff  --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt
index 84453664325c3..7469145098e51 100644
--- a/libc/include/llvm-libc-macros/CMakeLists.txt
+++ b/libc/include/llvm-libc-macros/CMakeLists.txt
@@ -83,6 +83,12 @@ add_header(
     .linux.sys_resource_macros
 )
 
+add_header(
+  sys_select_macros
+  HDR
+    sys-select-macros.h
+)
+
 add_header(
   sys_time_macros
   HDR

diff  --git a/libc/include/llvm-libc-macros/sys-select-macros.h b/libc/include/llvm-libc-macros/sys-select-macros.h
new file mode 100644
index 0000000000000..5d6592c1c281c
--- /dev/null
+++ b/libc/include/llvm-libc-macros/sys-select-macros.h
@@ -0,0 +1,35 @@
+//===-- Macros defined in sys/select.h header file ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __LLVM_LIBC_MACROS_SYS_SELECT_MACROS_H
+#define __LLVM_LIBC_MACROS_SYS_SELECT_MACROS_H
+
+#define FD_SETSIZE 1024
+#define __FD_SET_WORD_TYPE unsigned long
+#define __FD_SET_WORD_SIZE (sizeof(__FD_SET_WORD_TYPE) * 8)
+#define __FD_SET_ARRAYSIZE (FD_SETSIZE / __FD_SET_WORD_SIZE)
+
+#define FD_ZERO(set)                                                           \
+  do {                                                                         \
+    unsigned i;                                                                \
+    for (i = 0; i < __FD_SET_ARRAYSIZE; ++i)                                   \
+      (set)->__set[i] = 0;                                                     \
+  } while (0)
+
+#define __FD_WORD(fd) ((fd) / __FD_SET_WORD_SIZE)
+#define __FD_MASK(fd)                                                          \
+  ((__FD_SET_WORD_TYPE)1) << ((__FD_SET_WORD_TYPE)((fd) % __FD_SET_WORD_SIZE))
+
+#define FD_CLR(fd, set) (void)((set)->__set[__FD_WORD(fd)] &= ~__FD_MASK(fd))
+
+#define FD_SET(fd, set) (void)((set)->__set[__FD_WORD(fd)] |= __FD_MASK(fd))
+
+#define FD_ISSET(fd, set)                                                      \
+  (int)(((set)->__set[__FD_WORD(fd)] & __FD_MASK(fd)) != 0)
+
+#endif // __LLVM_LIBC_MACROS_SYS_SELECT_MACROS_H

diff  --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 40717f7549400..aa3fe46507787 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -27,6 +27,7 @@ add_header(div_t HDR div_t.h)
 add_header(ldiv_t HDR ldiv_t.h)
 add_header(lldiv_t HDR lldiv_t.h)
 add_header(FILE HDR FILE.h)
+add_header(fd_set HDR fd_set.h DEPENDS libc.include.llvm-libc-macros.sys_select_macros)
 add_header(fenv_t HDR fenv_t.h)
 add_header(fexcept_t HDR fexcept_t.h)
 add_header(float_t HDR float_t.h)

diff  --git a/libc/include/llvm-libc-types/fd_set.h b/libc/include/llvm-libc-types/fd_set.h
new file mode 100644
index 0000000000000..54e3fc654c067
--- /dev/null
+++ b/libc/include/llvm-libc-types/fd_set.h
@@ -0,0 +1,18 @@
+//===-- Definition of fd_set type -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __LLVM_LIBC_TYPES_FD_SET_H__
+#define __LLVM_LIBC_TYPES_FD_SET_H__
+
+#include <llvm-libc-macros/sys-select-macros.h> // FD_SETSIZE
+
+typedef struct {
+  __FD_SET_WORD_TYPE __set[__FD_SET_ARRAYSIZE];
+} fd_set;
+
+#endif // __LLVM_LIBC_TYPES_FD_SET_H__

diff  --git a/libc/include/sys/select.h.def b/libc/include/sys/select.h.def
new file mode 100644
index 0000000000000..4f3cebaecbb93
--- /dev/null
+++ b/libc/include/sys/select.h.def
@@ -0,0 +1,18 @@
+//===-- Linux sys/select.h ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SYS_SELECT_H
+#define LLVM_LIBC_SYS_SELECT_H
+
+#include <__llvm-libc-common.h>
+
+#include <llvm-libc-macros/sys-select-macros.h>
+
+%%public_api()
+
+#endif // LLVM_LIBC_SYS_SELECT_H

diff  --git a/libc/spec/linux.td b/libc/spec/linux.td
index d43bc88bbb558..7c4740ac7dbee 100644
--- a/libc/spec/linux.td
+++ b/libc/spec/linux.td
@@ -1,5 +1,3 @@
-def StructTimevalType : NamedType<"struct timeval">;
-
 def Linux : StandardSpec<"Linux"> {
   HeaderSpec Errno = HeaderSpec<
       "errno.h",

diff  --git a/libc/spec/posix.td b/libc/spec/posix.td
index 38ca165fb5f70..32e411372e4f4 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -70,6 +70,10 @@ def StackTPtr : PtrType<StackT>;
 def RestrictedStackTPtr : RestrictedPtrType<StackT>;
 def ConstRestrictedStackTPtr : ConstType<RestrictedStackTPtr>;
 
+def FdSet : NamedType<"fd_set">;
+def FdSetPtr : PtrType<FdSet>;
+def RestrictedFdSetPtr : RestrictedPtrType<FdSet>;
+
 def POSIX : StandardSpec<"POSIX"> {
   PtrType CharPtr = PtrType<CharType>;
   RestrictedPtrType RestrictedCharPtr = RestrictedPtrType<CharType>;
@@ -1184,6 +1188,23 @@ def POSIX : StandardSpec<"POSIX"> {
     ]
   >;
 
+  HeaderSpec SysSelect = HeaderSpec<
+    "sys/select.h",
+    [], // Macros
+    [FdSet, SigSetType, StructTimevalType, StructTimeSpec, SuSecondsT, TimeTType],
+    [], // Enumerations
+    [
+      FunctionSpec<
+        "select",
+        RetValSpec<IntType>,
+        [
+            ArgSpec<IntType>, ArgSpec<RestrictedFdSetPtr>, ArgSpec<RestrictedFdSetPtr>,
+            ArgSpec<RestrictedFdSetPtr>, ArgSpec<RestrictedStructTimevalPtr>
+        ]
+      >
+    ]
+  >;
+
   let Headers = [
     CType,
     Dirent,
@@ -1197,6 +1218,7 @@ def POSIX : StandardSpec<"POSIX"> {
     SysIOctl,
     SysMMan,
     SysResource,
+    SysSelect,
     SysStat,
     SysUtsName,
     SysWait,

diff  --git a/libc/spec/spec.td b/libc/spec/spec.td
index 1c39bbaa17b9f..017056d7d7738 100644
--- a/libc/spec/spec.td
+++ b/libc/spec/spec.td
@@ -121,6 +121,12 @@ def RestrictedPidTPtr : RestrictedPtrType<PidT>;
 def StructRUsage : NamedType<"struct rusage">;
 def StructRUsagePtr : PtrType<StructRUsage>;
 
+def StructTimevalType : NamedType<"struct timeval">;
+def StructTimevalPtr : PtrType<StructTimevalType>;
+def RestrictedStructTimevalPtr : RestrictedPtrType<StructTimevalType>;
+
+def SuSecondsT : NamedType<"suseconds_t">;
+
 //added because __assert_fail needs it.
 def UnsignedType : NamedType<"unsigned">;
 

diff  --git a/libc/src/sys/CMakeLists.txt b/libc/src/sys/CMakeLists.txt
index bf6283df87acb..94f62123d2c40 100644
--- a/libc/src/sys/CMakeLists.txt
+++ b/libc/src/sys/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_subdirectory(mman)
 add_subdirectory(random)
 add_subdirectory(resource)
+add_subdirectory(select)
 add_subdirectory(sendfile)
 add_subdirectory(stat)
 add_subdirectory(utsname)

diff  --git a/libc/src/sys/select/CMakeLists.txt b/libc/src/sys/select/CMakeLists.txt
new file mode 100644
index 0000000000000..ce36c66b255b0
--- /dev/null
+++ b/libc/src/sys/select/CMakeLists.txt
@@ -0,0 +1,10 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+endif()
+
+add_entrypoint_object(
+  select
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.select
+)

diff  --git a/libc/src/sys/select/linux/CMakeLists.txt b/libc/src/sys/select/linux/CMakeLists.txt
new file mode 100644
index 0000000000000..9d4a3beaeccc2
--- /dev/null
+++ b/libc/src/sys/select/linux/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_entrypoint_object(
+  select
+  SRCS
+    select.cpp
+  HDRS
+    ../select.h
+  DEPENDS
+    libc.include.sys_select
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.errno.errno
+)

diff  --git a/libc/src/sys/select/linux/select.cpp b/libc/src/sys/select/linux/select.cpp
new file mode 100644
index 0000000000000..ba81f9ba188ce
--- /dev/null
+++ b/libc/src/sys/select/linux/select.cpp
@@ -0,0 +1,65 @@
+//===-- Linux implementation of select ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/select/select.h"
+
+#include "src/__support/CPP/limits.h"
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include <errno.h>
+#include <signal.h>
+#include <stddef.h> // For size_t
+#include <sys/select.h>
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace __llvm_libc {
+
+struct pselect6_sigset_t {
+  sigset_t *ss;
+  size_t ss_len;
+};
+
+LLVM_LIBC_FUNCTION(int, select,
+                   (int nfds, fd_set *__restrict read_set,
+                    fd_set *__restrict write_set, fd_set *__restrict error_set,
+                    struct timeval *__restrict timeout)) {
+  // Linux has a SYS_select syscall but it is not available on all
+  // architectures. So, we use the SYS_pselect6 syscall which is more
+  // widely available. However, SYS_pselect6 takes a struct timespec argument
+  // instead of a struct timeval argument. Also, it takes an additional
+  // argument which is a pointer to an object of a type defined above as
+  // "pselect6_sigset_t".
+  struct timespec ts {
+    0, 0
+  };
+  if (timeout != nullptr) {
+    // In general, if the tv_sec and tv_usec in |timeout| are correctly set,
+    // then converting tv_usec to nanoseconds will not be a problem. However,
+    // if tv_usec in |timeout| is more than a second, it can lead to overflows.
+    // So, we detect such cases and adjust.
+    constexpr time_t TIME_MAX = cpp::numeric_limits<time_t>::max();
+    if ((TIME_MAX - timeout->tv_sec) < (timeout->tv_usec / 1000000)) {
+      ts.tv_sec = TIME_MAX;
+      ts.tv_nsec = 999999999;
+    } else {
+      ts.tv_sec = timeout->tv_sec + timeout->tv_usec / 1000000;
+      ts.tv_nsec = timeout->tv_usec * 1000;
+    }
+  }
+  pselect6_sigset_t pss{nullptr, sizeof(sigset_t)};
+  long ret = __llvm_libc::syscall_impl(SYS_pselect6, nfds, read_set, write_set,
+                                       error_set, &ts, &pss);
+  if (ret < 0) {
+    errno = -ret;
+    return -1;
+  }
+  return ret;
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/sys/select/select.h b/libc/src/sys/select/select.h
new file mode 100644
index 0000000000000..ca81c0bbd5d74
--- /dev/null
+++ b/libc/src/sys/select/select.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for select ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SELECT_SELECT_H
+#define LLVM_LIBC_SRC_SYS_SELECT_SELECT_H
+
+#include <sys/select.h>
+
+namespace __llvm_libc {
+
+int select(int nfds, fd_set *__restrict read_set, fd_set *__restrict write_set,
+           fd_set *__restrict error_set, struct timeval *__restrict timeout);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SYS_SELECT_SELECT_H

diff  --git a/libc/test/src/sys/CMakeLists.txt b/libc/test/src/sys/CMakeLists.txt
index bf6283df87acb..94f62123d2c40 100644
--- a/libc/test/src/sys/CMakeLists.txt
+++ b/libc/test/src/sys/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_subdirectory(mman)
 add_subdirectory(random)
 add_subdirectory(resource)
+add_subdirectory(select)
 add_subdirectory(sendfile)
 add_subdirectory(stat)
 add_subdirectory(utsname)

diff  --git a/libc/test/src/sys/select/CMakeLists.txt b/libc/test/src/sys/select/CMakeLists.txt
new file mode 100644
index 0000000000000..9d45a447797b7
--- /dev/null
+++ b/libc/test/src/sys/select/CMakeLists.txt
@@ -0,0 +1,31 @@
+add_libc_testsuite(libc_sys_select_unittests)
+
+add_libc_unittest(
+  select_ui_test
+  NO_RUN_POSTBUILD
+  SUITE
+    libc_sys_select_unittests
+  SRCS
+    select_ui_test.cpp
+  DEPENDS
+    libc.include.errno
+    libc.include.unistd
+    libc.src.sys.select.select
+    libc.src.unistd.read
+)
+
+add_libc_unittest(
+  select_failure_test
+  SUITE
+    libc_sys_select_unittests
+  SRCS
+    select_failure_test.cpp
+  DEPENDS
+    libc.include.errno
+    libc.include.unistd
+    libc.src.sys.select.select
+    libc.src.unistd.read
+    libc.test.errno_setter_matcher
+)
+
+add_subdirectory(testdata)

diff  --git a/libc/test/src/sys/select/select_failure_test.cpp b/libc/test/src/sys/select/select_failure_test.cpp
new file mode 100644
index 0000000000000..86863544a0ce3
--- /dev/null
+++ b/libc/test/src/sys/select/select_failure_test.cpp
@@ -0,0 +1,28 @@
+//===-- Failure unittests for select --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/select/select.h"
+#include "src/unistd/read.h"
+#include "test/ErrnoSetterMatcher.h"
+#include "utils/UnitTest/Test.h"
+
+#include <errno.h>
+#include <sys/select.h>
+#include <unistd.h>
+
+using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
+
+TEST(LlvmLibcSelectTest, SelectInvalidFD) {
+  fd_set set;
+  FD_ZERO(&set);
+  struct timeval timeout {
+    0, 0
+  };
+  ASSERT_THAT(__llvm_libc::select(-1, &set, nullptr, nullptr, &timeout),
+              Fails(EINVAL));
+}

diff  --git a/libc/test/src/sys/select/select_ui_test.cpp b/libc/test/src/sys/select/select_ui_test.cpp
new file mode 100644
index 0000000000000..200b29173be78
--- /dev/null
+++ b/libc/test/src/sys/select/select_ui_test.cpp
@@ -0,0 +1,49 @@
+//===-- Interactive unittests for select ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/select/select.h"
+#include "src/unistd/read.h"
+#include "utils/UnitTest/Test.h"
+
+#include <errno.h>
+#include <sys/select.h>
+#include <unistd.h>
+
+// This test is not be run automatically as part of the libc testsuite.
+// Instead, one has to run it manually and press a key on the keyboard
+// to make the test succeed.
+TEST(LlvmLibcSelectTest, ReadStdinAfterSelect) {
+  errno = 0;
+  constexpr int STDIN_FD = 0;
+  fd_set set;
+  FD_ZERO(&set);
+  FD_SET(STDIN_FD, &set);
+  struct timeval zero {
+    0, 0
+  }; // No wait
+  struct timeval hr {
+    3600, 0
+  }; // Wait for an hour.
+
+  // Zero timeout means we don't wait for input. So, select should return
+  // immediately.
+  int count = __llvm_libc::select(STDIN_FD + 1, &set, nullptr, nullptr, &zero);
+  // The set should indicate that stdin is NOT ready for reading.
+  ASSERT_EQ(0, FD_ISSET(STDIN_FD, &set));
+
+  FD_SET(STDIN_FD, &set);
+  // Wait for an hour and give the user a chance to hit a key.
+  count = __llvm_libc::select(STDIN_FD + 1, &set, nullptr, nullptr, &hr);
+  ASSERT_EQ(count, 1);
+  // The set should indicate that stdin is ready for reading.
+  ASSERT_EQ(1, FD_ISSET(STDIN_FD, &set));
+
+  // Verify that atleast one character can be read.
+  char c;
+  ASSERT_EQ(__llvm_libc::read(STDIN_FD, &c, 1), ssize_t(1));
+}

diff  --git a/libc/test/src/sys/select/testdata/CMakeLists.txt b/libc/test/src/sys/select/testdata/CMakeLists.txt
new file mode 100644
index 0000000000000..e69de29bb2d1d


        


More information about the libc-commits mailing list