[libc-commits] [libc] [libc] Add `shm_open/shm_unlink` (PR #84974)

Schrodinger ZHU Yifan via libc-commits libc-commits at lists.llvm.org
Mon Mar 18 07:50:13 PDT 2024


https://github.com/SchrodingerZhu updated https://github.com/llvm/llvm-project/pull/84974

>From 2dd697565fbdf6ecd50d051a41513e819067f3bb Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Tue, 12 Mar 2024 12:35:39 -0400
Subject: [PATCH 01/15] [libc] add shm_open

---
 libc/config/linux/aarch64/entrypoints.txt   |  2 +
 libc/config/linux/api.td                    |  2 +-
 libc/config/linux/riscv/entrypoints.txt     |  2 +
 libc/config/linux/x86_64/entrypoints.txt    |  2 +
 libc/spec/posix.td                          | 11 +++
 libc/src/__support/CPP/string_view.h        |  9 +++
 libc/src/sys/mman/CMakeLists.txt            | 14 ++++
 libc/src/sys/mman/linux/CMakeLists.txt      | 37 ++++++++++
 libc/src/sys/mman/linux/shm_common.h        | 51 +++++++++++++
 libc/src/sys/mman/linux/shm_open.cpp        | 27 +++++++
 libc/src/sys/mman/linux/shm_unlink.cpp      | 24 +++++++
 libc/src/sys/mman/shm_open.h                | 20 ++++++
 libc/src/sys/mman/shm_unlink.h              | 19 +++++
 libc/test/src/sys/mman/linux/CMakeLists.txt | 20 ++++++
 libc/test/src/sys/mman/linux/shm_test.cpp   | 79 +++++++++++++++++++++
 15 files changed, 318 insertions(+), 1 deletion(-)
 create mode 100644 libc/src/sys/mman/linux/shm_common.h
 create mode 100644 libc/src/sys/mman/linux/shm_open.cpp
 create mode 100644 libc/src/sys/mman/linux/shm_unlink.cpp
 create mode 100644 libc/src/sys/mman/shm_open.h
 create mode 100644 libc/src/sys/mman/shm_unlink.h
 create mode 100644 libc/test/src/sys/mman/linux/shm_test.cpp

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index b447b5dfe0989e..bfaee0cecf38ff 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -186,6 +186,8 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.mman.mlockall
     libc.src.sys.mman.munlockall
     libc.src.sys.mman.msync
+    libc.src.sys.mman.shm_open
+    libc.src.sys.mman.shm_unlink
 
     # sys/random.h entrypoints
     libc.src.sys.random.getrandom
diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index 75432a2a298652..96fea3bbac94e5 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -118,7 +118,7 @@ def SchedAPI : PublicAPI<"sched.h"> {
 }
 
 def SysMManAPI : PublicAPI<"sys/mman.h"> {
-  let Types = ["off_t", "size_t"];
+  let Types = ["off_t", "size_t", "mode_t"];
 }
 
 def SignalAPI : PublicAPI<"signal.h"> {
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 5175b14adf2e74..c3d4afe6b043f3 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -191,6 +191,8 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.mman.mlockall
     libc.src.sys.mman.munlockall
     libc.src.sys.mman.msync
+    libc.src.sys.mman.shm_open
+    libc.src.sys.mman.shm_unlink
 
     # sys/random.h entrypoints
     libc.src.sys.random.getrandom
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index b8bec14a3d2a6d..5779945bfee563 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -229,6 +229,8 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.mman.mlockall
     libc.src.sys.mman.munlockall
     libc.src.sys.mman.msync
+    libc.src.sys.mman.shm_open
+    libc.src.sys.mman.shm_unlink
 
     # sys/random.h entrypoints
     libc.src.sys.random.getrandom
diff --git a/libc/spec/posix.td b/libc/spec/posix.td
index d0f5a4584dd45b..d4187a7252d976 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -250,6 +250,7 @@ def POSIX : StandardSpec<"POSIX"> {
       [
         SizeTType,
         OffTType,
+        ModeTType,
       ],
       [], // Enumerations
       [
@@ -314,6 +315,16 @@ def POSIX : StandardSpec<"POSIX"> {
           RetValSpec<IntType>,
           [ArgSpec<VoidPtr>, ArgSpec<SizeTType>, ArgSpec<IntType>]
         >,
+        FunctionSpec<
+          "shm_open",
+          RetValSpec<IntType>,
+          [ArgSpec<ConstCharPtr>, ArgSpec<IntType>, ArgSpec<ModeTType>]
+        >,
+        FunctionSpec<
+          "shm_unlink",
+          RetValSpec<IntType>,
+          [ArgSpec<ConstCharPtr>]
+        >,
       ]
   >;
 
diff --git a/libc/src/__support/CPP/string_view.h b/libc/src/__support/CPP/string_view.h
index d23aa261ca0614..4a90de0f9a3a06 100644
--- a/libc/src/__support/CPP/string_view.h
+++ b/libc/src/__support/CPP/string_view.h
@@ -194,6 +194,15 @@ class string_view {
         return End - 1;
     return npos;
   }
+
+  // Finds the frist character not equal to c in this view, starting at position
+  // From.
+  LIBC_INLINE size_t find_first_not_of(const char c, size_t From = 0) const {
+    for (size_t Pos = From; Pos < size(); ++Pos)
+      if ((*this)[Pos] != c)
+        return Pos;
+    return npos;
+  }
 };
 
 } // namespace cpp
diff --git a/libc/src/sys/mman/CMakeLists.txt b/libc/src/sys/mman/CMakeLists.txt
index b49f73873c2006..9c74202a09f035 100644
--- a/libc/src/sys/mman/CMakeLists.txt
+++ b/libc/src/sys/mman/CMakeLists.txt
@@ -85,3 +85,17 @@ add_entrypoint_object(
   DEPENDS
     .${LIBC_TARGET_OS}.msync
 )
+
+add_entrypoint_object(
+  shm_open
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.shm_open
+)
+
+add_entrypoint_object(
+  shm_unlink
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.shm_unlink
+)
diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt
index 04086ee5d33254..01ea19ad9793ba 100644
--- a/libc/src/sys/mman/linux/CMakeLists.txt
+++ b/libc/src/sys/mman/linux/CMakeLists.txt
@@ -152,3 +152,40 @@ add_entrypoint_object(
     libc.src.__support.OSUtil.osutil
     libc.src.errno.errno
 )
+
+add_header_library(
+  shm_common
+  HDRS
+    shm_common.h
+  DEPENDS
+    libc.src.__support.CPP.array
+    libc.src.__support.CPP.string_view
+    libc.src.__support.CPP.optional
+    libc.src.__support.common
+    libc.src.errno.errno
+    libc.src.string.memcpy
+    libc.src.string.memchr
+)
+
+add_entrypoint_object(
+  shm_open
+  SRCS
+    shm_open.cpp
+  HDRS
+    ../shm_open.h
+  DEPENDS
+    libc.src.fcntl.open
+    libc.include.fcntl
+    .shm_common
+)
+
+add_entrypoint_object(
+  shm_unlink
+  SRCS
+    shm_unlink.cpp
+  HDRS
+    ../shm_unlink.h
+  DEPENDS
+    libc.src.unistd.unlink
+    .shm_common
+)
diff --git a/libc/src/sys/mman/linux/shm_common.h b/libc/src/sys/mman/linux/shm_common.h
new file mode 100644
index 00000000000000..f938fe474c2070
--- /dev/null
+++ b/libc/src/sys/mman/linux/shm_common.h
@@ -0,0 +1,51 @@
+//===---------- Shared implementations for shm_open/shm_unlink ------------===//
+//
+// 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/__support/CPP/array.h"
+#include "src/__support/CPP/optional.h"
+#include "src/__support/CPP/string_view.h"
+#include "src/errno/libc_errno.h"
+#include "src/string/memchr.h"
+#include "src/string/memcpy.h"
+#include <asm/errno.h>
+#include <linux/limits.h>
+
+namespace LIBC_NAMESPACE {
+
+LIBC_INLINE_VAR constexpr cpp::string_view SHM_PREFIX = "/dev/shm/";
+using SHMPath = cpp::array<char, NAME_MAX + SHM_PREFIX.size() + 1>;
+
+LIBC_INLINE cpp::optional<SHMPath> get_shm_name(cpp::string_view name) {
+  // trim leading slashes
+  size_t offset = name.find_first_not_of('/');
+  if (offset == cpp::string_view::npos) {
+    libc_errno = EINVAL;
+    return cpp::nullopt;
+  }
+  name = name.substr(offset);
+
+  // check the name
+  if (name.size() > NAME_MAX) {
+    libc_errno = ENAMETOOLONG;
+    return cpp::nullopt;
+  }
+  if (name == "." || name == ".." ||
+      memchr(name.data(), '/', name.size()) != nullptr) {
+    libc_errno = EINVAL;
+    return cpp::nullopt;
+  }
+
+  // prepend the prefix
+  SHMPath buffer;
+  memcpy(buffer.data(), SHM_PREFIX.data(), SHM_PREFIX.size());
+  memcpy(buffer.data() + SHM_PREFIX.size(), name.data(), name.size());
+  buffer[SHM_PREFIX.size() + name.size()] = '\0';
+  return buffer;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/mman/linux/shm_open.cpp b/libc/src/sys/mman/linux/shm_open.cpp
new file mode 100644
index 00000000000000..220c97be73ae65
--- /dev/null
+++ b/libc/src/sys/mman/linux/shm_open.cpp
@@ -0,0 +1,27 @@
+//===---------- Linux implementation of the shm_open function -------------===//
+//
+// 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/mman/shm_open.h"
+#include "src/fcntl/open.h"
+#include "src/sys/mman/linux/shm_common.h"
+#include <asm/fcntl.h>
+#include <linux/limits.h>
+
+namespace LIBC_NAMESPACE {
+
+static constexpr int DEFAULT_OFLAGS = O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK;
+
+LLVM_LIBC_FUNCTION(int, shm_open, (const char *name, int oflags, mode_t mode)) {
+  auto buffer = get_shm_name(name);
+  if (!buffer.has_value()) {
+    return -1;
+  }
+  return open(buffer->data(), oflags | DEFAULT_OFLAGS, mode);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/mman/linux/shm_unlink.cpp b/libc/src/sys/mman/linux/shm_unlink.cpp
new file mode 100644
index 00000000000000..cb6f5b9163d249
--- /dev/null
+++ b/libc/src/sys/mman/linux/shm_unlink.cpp
@@ -0,0 +1,24 @@
+//===---------- Linux implementation of the shm_unlink function
+//-------------===//
+//
+// 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/mman/shm_unlink.h"
+#include "src/sys/mman/linux/shm_common.h"
+#include "src/unistd/unlink.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, shm_unlink, (const char *name)) {
+  auto buffer = get_shm_name(name);
+  if (!buffer.has_value()) {
+    return -1;
+  }
+  return unlink(buffer->data());
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/mman/shm_open.h b/libc/src/sys/mman/shm_open.h
new file mode 100644
index 00000000000000..97a2b641450d88
--- /dev/null
+++ b/libc/src/sys/mman/shm_open.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for shm_open function -------------*- 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_MMAN_SHM_OPEN_H
+#define LLVM_LIBC_SRC_SYS_MMAN_SHM_OPEN_H
+
+#include <fcntl.h> // For mode_t.
+
+namespace LIBC_NAMESPACE {
+
+int shm_open(const char *name, int oflag, mode_t mode);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_MMAN_SHM_OPEN_H
diff --git a/libc/src/sys/mman/shm_unlink.h b/libc/src/sys/mman/shm_unlink.h
new file mode 100644
index 00000000000000..9c40917405fbce
--- /dev/null
+++ b/libc/src/sys/mman/shm_unlink.h
@@ -0,0 +1,19 @@
+//===-- Implementation header for shm_unlink function -------------*- 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_MMAN_SHM_UNLINK_H
+#define LLVM_LIBC_SRC_SYS_MMAN_SHM_UNLINK_H
+
+namespace LIBC_NAMESPACE {
+
+int shm_unlink(const char *name);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_MMAN_SHM_UNLINK_H
diff --git a/libc/test/src/sys/mman/linux/CMakeLists.txt b/libc/test/src/sys/mman/linux/CMakeLists.txt
index 6f7fc34d8d3ce3..0762a2d846a8e0 100644
--- a/libc/test/src/sys/mman/linux/CMakeLists.txt
+++ b/libc/test/src/sys/mman/linux/CMakeLists.txt
@@ -127,3 +127,23 @@ add_libc_unittest(
     libc.src.unistd.sysconf
     libc.test.UnitTest.ErrnoSetterMatcher
 )
+
+add_libc_unittest(
+  shm_test
+  SUITE
+    libc_sys_mman_unittests
+  SRCS
+    shm_test.cpp
+  DEPENDS
+    libc.include.sys_mman
+    libc.include.sys_syscall
+    libc.src.errno.errno
+    libc.src.sys.mman.shm_open
+    libc.src.sys.mman.shm_unlink
+    libc.src.sys.mman.mmap
+    libc.src.sys.mman.munmap
+    libc.src.unistd.ftruncate
+    libc.src.unistd.close
+    libc.src.__support.OSUtil.osutil
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
diff --git a/libc/test/src/sys/mman/linux/shm_test.cpp b/libc/test/src/sys/mman/linux/shm_test.cpp
new file mode 100644
index 00000000000000..9d05066f778288
--- /dev/null
+++ b/libc/test/src/sys/mman/linux/shm_test.cpp
@@ -0,0 +1,79 @@
+//===-- Unittests for shm_open/shm_unlink ---------------------------------===//
+//
+// 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/__support/OSUtil/syscall.h"
+#include "src/sys/mman/mmap.h"
+#include "src/sys/mman/munmap.h"
+#include "src/sys/mman/shm_open.h"
+#include "src/sys/mman/shm_unlink.h"
+#include "src/unistd/close.h"
+#include "src/unistd/ftruncate.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/LibcTest.h"
+#include <asm-generic/fcntl.h>
+#include <sys/syscall.h>
+
+using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
+// since shm_open/shm_unlink are wrappers around open/unlink, we only focus on
+// testing basic cases and name conversions.
+
+TEST(LlvmLibcShmTest, Basic) {
+  const char *name = "/test_shm_open";
+  int fd;
+  ASSERT_THAT(fd = LIBC_NAMESPACE::shm_open(name, O_CREAT | O_RDWR, 0666),
+              returns(GE(0)).with_errno(EQ(0)));
+
+  // check that FD_CLOEXEC is set by default.
+  // TODO: use fcntl when implemented.
+  // https://github.com/llvm/llvm-project/issues/84968
+  long flag = LIBC_NAMESPACE::syscall_impl(SYS_fcntl, fd, F_GETFD);
+  ASSERT_GE(static_cast<int>(flag), 0);
+  EXPECT_NE(static_cast<int>(flag) & FD_CLOEXEC, 0);
+
+  // allocate space using ftruncate
+  ASSERT_THAT(LIBC_NAMESPACE::ftruncate(fd, 4096), Succeeds());
+  // map the shared memory
+  void *addr = LIBC_NAMESPACE::mmap(nullptr, 4096, PROT_READ | PROT_WRITE,
+                                    MAP_SHARED, fd, 0);
+  ASSERT_NE(addr, MAP_FAILED);
+  // just write random data to the shared memory
+  char data[] = "Despite its name, LLVM has little to do with traditional "
+                "virtual machines.";
+  for (size_t i = 0; i < sizeof(data); ++i) {
+    static_cast<char *>(addr)[i] = data[i];
+  }
+
+  // close fd does not affect the mapping
+  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds());
+  for (size_t i = 0; i < sizeof(data); ++i) {
+    EXPECT_EQ(static_cast<char *>(addr)[i], data[i]);
+  }
+
+  // unmap the shared memory
+  ASSERT_THAT(LIBC_NAMESPACE::munmap(addr, 4096), Succeeds());
+  // remove the shared memory
+  ASSERT_THAT(LIBC_NAMESPACE::shm_unlink(name), Succeeds());
+}
+
+TEST(LlvmLibcShmTest, NameConversion) {
+  const char *name = "////test_shm_open";
+  int fd;
+  ASSERT_THAT(fd = LIBC_NAMESPACE::shm_open(name, O_CREAT | O_RDWR, 0666),
+              returns(GE(0)).with_errno(EQ(0)));
+  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds());
+  ASSERT_THAT(LIBC_NAMESPACE::shm_unlink(name), Succeeds());
+
+  ASSERT_THAT(LIBC_NAMESPACE::shm_open("/123/123", O_CREAT | O_RDWR, 0666),
+              Fails(EINVAL));
+
+  ASSERT_THAT(LIBC_NAMESPACE::shm_open("/.", O_CREAT | O_RDWR, 0666),
+              Fails(EINVAL));
+
+  ASSERT_THAT(LIBC_NAMESPACE::shm_open("/..", O_CREAT | O_RDWR, 0666),
+              Fails(EINVAL));
+}

>From 628c04b2969dbbc81df0bf113f1dace4fd35b30d Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Tue, 12 Mar 2024 15:12:31 -0400
Subject: [PATCH 02/15] fix header

---
 libc/src/sys/mman/linux/shm_unlink.cpp | 3 +--
 libc/src/sys/mman/shm_unlink.h         | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/libc/src/sys/mman/linux/shm_unlink.cpp b/libc/src/sys/mman/linux/shm_unlink.cpp
index cb6f5b9163d249..952415c3959052 100644
--- a/libc/src/sys/mman/linux/shm_unlink.cpp
+++ b/libc/src/sys/mman/linux/shm_unlink.cpp
@@ -1,5 +1,4 @@
-//===---------- Linux implementation of the shm_unlink function
-//-------------===//
+//===---------- Linux implementation of the shm_unlink function -----------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/libc/src/sys/mman/shm_unlink.h b/libc/src/sys/mman/shm_unlink.h
index 9c40917405fbce..c38c06adbaa292 100644
--- a/libc/src/sys/mman/shm_unlink.h
+++ b/libc/src/sys/mman/shm_unlink.h
@@ -1,5 +1,4 @@
-//===-- Implementation header for shm_unlink function -------------*- C++
-//-*-===//
+//===-- Implementation header for shm_unlink function ------------*- C++-*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.

>From 62d954389ed0bb980e9a3c9b01e6430e09336768 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Tue, 12 Mar 2024 15:29:21 -0400
Subject: [PATCH 03/15] remove extra include

---
 libc/src/sys/mman/linux/shm_open.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libc/src/sys/mman/linux/shm_open.cpp b/libc/src/sys/mman/linux/shm_open.cpp
index 220c97be73ae65..0bd769c8d8da55 100644
--- a/libc/src/sys/mman/linux/shm_open.cpp
+++ b/libc/src/sys/mman/linux/shm_open.cpp
@@ -10,7 +10,6 @@
 #include "src/fcntl/open.h"
 #include "src/sys/mman/linux/shm_common.h"
 #include <asm/fcntl.h>
-#include <linux/limits.h>
 
 namespace LIBC_NAMESPACE {
 

>From 31ef3dde9699d76bccdefe9f351c57906a34f068 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Tue, 12 Mar 2024 19:34:18 -0400
Subject: [PATCH 04/15] partially address CR

---
 libc/docs/dev/undefined_behavior.rst      |  4 ++++
 libc/src/__support/CPP/string_view.h      | 16 ++++++++++++----
 libc/src/sys/mman/linux/CMakeLists.txt    |  3 +--
 libc/src/sys/mman/linux/shm_common.h      | 10 ++++------
 libc/test/src/sys/mman/linux/shm_test.cpp |  6 ++----
 5 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/libc/docs/dev/undefined_behavior.rst b/libc/docs/dev/undefined_behavior.rst
index 6e73a305e8e054..9025ec28823e53 100644
--- a/libc/docs/dev/undefined_behavior.rst
+++ b/libc/docs/dev/undefined_behavior.rst
@@ -70,3 +70,7 @@ Design Decisions
 Resizable Tables for hsearch
 ----------------------------
 The POSIX.1 standard does not delineate the behavior consequent to invoking hsearch or hdestroy without prior initialization of the hash table via hcreate. Furthermore, the standard does not specify the outcomes of successive invocations of hsearch absent intervening hdestroy calls. Libraries such as MUSL and Glibc do not apply checks to these scenarios, potentially leading to memory corruption or leakage. Conversely, FreeBSD's libc and Bionic automatically initialize the hash table to a minimal size if it is found uninitialized, and proceeding to destroy the table only if initialization has occurred. This approach also avoids redundant table allocation if an initialized hash table is already present. Given that the hash table starts with a minimal size, resizing becomes necessary to accommodate additional user insertions. LLVM's libc mirrors the approach of FreeBSD's libc and Bionic, owing to its enhanced robustness and user-friendliness. Notably, such resizing behavior itself aligns with POSIX.1 standards, which explicitly permit implementations to modify the capacity of the hash table.
+
+Path without Leading Slashs in shm_open
+----------------------------------------
+POSIX.1 leaves that when the name of a shared memory object does not begin with a slash, the behavior is implementation defined. In such cases, the shm_open in LLVM libc is implemented to behave as if the name began with a slash.
\ No newline at end of file
diff --git a/libc/src/__support/CPP/string_view.h b/libc/src/__support/CPP/string_view.h
index 4a90de0f9a3a06..8aa96fa87f6986 100644
--- a/libc/src/__support/CPP/string_view.h
+++ b/libc/src/__support/CPP/string_view.h
@@ -179,7 +179,8 @@ class string_view {
   LIBC_INLINE char back() const { return Data[Len - 1]; }
 
   // Finds the first occurence of c in this view, starting at position From.
-  LIBC_INLINE size_t find_first_of(const char c, size_t From = 0) const {
+  LIBC_INLINE constexpr size_t find_first_of(const char c,
+                                             size_t From = 0) const {
     for (size_t Pos = From; Pos < size(); ++Pos)
       if ((*this)[Pos] == c)
         return Pos;
@@ -187,7 +188,8 @@ class string_view {
   }
 
   // Finds the last occurence of c in this view, ending at position End.
-  LIBC_INLINE size_t find_last_of(const char c, size_t End = npos) const {
+  LIBC_INLINE constexpr size_t find_last_of(const char c,
+                                            size_t End = npos) const {
     End = End >= size() ? size() : End + 1;
     for (; End > 0; --End)
       if ((*this)[End - 1] == c)
@@ -195,14 +197,20 @@ class string_view {
     return npos;
   }
 
-  // Finds the frist character not equal to c in this view, starting at position
+  // Finds the first character not equal to c in this view, starting at position
   // From.
-  LIBC_INLINE size_t find_first_not_of(const char c, size_t From = 0) const {
+  LIBC_INLINE constexpr size_t find_first_not_of(const char c,
+                                                 size_t From = 0) const {
     for (size_t Pos = From; Pos < size(); ++Pos)
       if ((*this)[Pos] != c)
         return Pos;
     return npos;
   }
+
+  // Check if this view contains the given character.
+  LIBC_INLINE constexpr bool contains(char c) const {
+    return find_first_of(c) != npos;
+  }
 };
 
 } // namespace cpp
diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt
index 01ea19ad9793ba..c995c107f4d1d0 100644
--- a/libc/src/sys/mman/linux/CMakeLists.txt
+++ b/libc/src/sys/mman/linux/CMakeLists.txt
@@ -163,8 +163,7 @@ add_header_library(
     libc.src.__support.CPP.optional
     libc.src.__support.common
     libc.src.errno.errno
-    libc.src.string.memcpy
-    libc.src.string.memchr
+    libc.src.string.memory_utils.inline_memcpy
 )
 
 add_entrypoint_object(
diff --git a/libc/src/sys/mman/linux/shm_common.h b/libc/src/sys/mman/linux/shm_common.h
index f938fe474c2070..85a1b2b667e876 100644
--- a/libc/src/sys/mman/linux/shm_common.h
+++ b/libc/src/sys/mman/linux/shm_common.h
@@ -10,8 +10,7 @@
 #include "src/__support/CPP/optional.h"
 #include "src/__support/CPP/string_view.h"
 #include "src/errno/libc_errno.h"
-#include "src/string/memchr.h"
-#include "src/string/memcpy.h"
+#include "src/string/memory_utils/inline_memcpy.h"
 #include <asm/errno.h>
 #include <linux/limits.h>
 
@@ -34,16 +33,15 @@ LIBC_INLINE cpp::optional<SHMPath> get_shm_name(cpp::string_view name) {
     libc_errno = ENAMETOOLONG;
     return cpp::nullopt;
   }
-  if (name == "." || name == ".." ||
-      memchr(name.data(), '/', name.size()) != nullptr) {
+  if (name == "." || name == ".." || name.contains('/')) {
     libc_errno = EINVAL;
     return cpp::nullopt;
   }
 
   // prepend the prefix
   SHMPath buffer;
-  memcpy(buffer.data(), SHM_PREFIX.data(), SHM_PREFIX.size());
-  memcpy(buffer.data() + SHM_PREFIX.size(), name.data(), name.size());
+  inline_memcpy(buffer.data(), SHM_PREFIX.data(), SHM_PREFIX.size());
+  inline_memcpy(buffer.data() + SHM_PREFIX.size(), name.data(), name.size());
   buffer[SHM_PREFIX.size() + name.size()] = '\0';
   return buffer;
 }
diff --git a/libc/test/src/sys/mman/linux/shm_test.cpp b/libc/test/src/sys/mman/linux/shm_test.cpp
index 9d05066f778288..3b1a2aa33b56ad 100644
--- a/libc/test/src/sys/mman/linux/shm_test.cpp
+++ b/libc/test/src/sys/mman/linux/shm_test.cpp
@@ -44,15 +44,13 @@ TEST(LlvmLibcShmTest, Basic) {
   // just write random data to the shared memory
   char data[] = "Despite its name, LLVM has little to do with traditional "
                 "virtual machines.";
-  for (size_t i = 0; i < sizeof(data); ++i) {
+  for (size_t i = 0; i < sizeof(data); ++i)
     static_cast<char *>(addr)[i] = data[i];
-  }
 
   // close fd does not affect the mapping
   ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds());
-  for (size_t i = 0; i < sizeof(data); ++i) {
+  for (size_t i = 0; i < sizeof(data); ++i)
     EXPECT_EQ(static_cast<char *>(addr)[i], data[i]);
-  }
 
   // unmap the shared memory
   ASSERT_THAT(LIBC_NAMESPACE::munmap(addr, 4096), Succeeds());

>From 91b84309fa0a8a1bcb3ee61cc6dd762bf8717feb Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Tue, 12 Mar 2024 20:19:34 -0400
Subject: [PATCH 05/15] add missing trailing space

---
 libc/docs/dev/undefined_behavior.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/docs/dev/undefined_behavior.rst b/libc/docs/dev/undefined_behavior.rst
index 9025ec28823e53..3a06b7007febd4 100644
--- a/libc/docs/dev/undefined_behavior.rst
+++ b/libc/docs/dev/undefined_behavior.rst
@@ -73,4 +73,4 @@ The POSIX.1 standard does not delineate the behavior consequent to invoking hsea
 
 Path without Leading Slashs in shm_open
 ----------------------------------------
-POSIX.1 leaves that when the name of a shared memory object does not begin with a slash, the behavior is implementation defined. In such cases, the shm_open in LLVM libc is implemented to behave as if the name began with a slash.
\ No newline at end of file
+POSIX.1 leaves that when the name of a shared memory object does not begin with a slash, the behavior is implementation defined. In such cases, the shm_open in LLVM libc is implemented to behave as if the name began with a slash.

>From 3e3650f5921fb20cb292438a3e4b7f2153f6d0b2 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Tue, 12 Mar 2024 20:32:25 -0400
Subject: [PATCH 06/15] address more reviews

---
 .../include/llvm-libc-macros/generic-error-number-macros.h | 2 +-
 libc/src/sys/mman/linux/shm_common.h                       | 1 -
 libc/src/sys/mman/linux/shm_open.cpp                       | 7 +++----
 libc/src/sys/mman/linux/shm_unlink.cpp                     | 3 +--
 libc/src/sys/mman/shm_open.h                               | 2 +-
 5 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/libc/include/llvm-libc-macros/generic-error-number-macros.h b/libc/include/llvm-libc-macros/generic-error-number-macros.h
index 7ee0352669b8a9..11c7b241f90f20 100644
--- a/libc/include/llvm-libc-macros/generic-error-number-macros.h
+++ b/libc/include/llvm-libc-macros/generic-error-number-macros.h
@@ -44,5 +44,5 @@
 #define EDOM 33
 #define ERANGE 34
 #define EILSEQ 35
-
+#define ENAMETOOLONG 36
 #endif // LLVM_LIBC_MACROS_GENERIC_ERROR_NUMBER_MACROS_H
diff --git a/libc/src/sys/mman/linux/shm_common.h b/libc/src/sys/mman/linux/shm_common.h
index 85a1b2b667e876..e73d991b0549cb 100644
--- a/libc/src/sys/mman/linux/shm_common.h
+++ b/libc/src/sys/mman/linux/shm_common.h
@@ -11,7 +11,6 @@
 #include "src/__support/CPP/string_view.h"
 #include "src/errno/libc_errno.h"
 #include "src/string/memory_utils/inline_memcpy.h"
-#include <asm/errno.h>
 #include <linux/limits.h>
 
 namespace LIBC_NAMESPACE {
diff --git a/libc/src/sys/mman/linux/shm_open.cpp b/libc/src/sys/mman/linux/shm_open.cpp
index 0bd769c8d8da55..eaf111d1c325f6 100644
--- a/libc/src/sys/mman/linux/shm_open.cpp
+++ b/libc/src/sys/mman/linux/shm_open.cpp
@@ -9,17 +9,16 @@
 #include "src/sys/mman/shm_open.h"
 #include "src/fcntl/open.h"
 #include "src/sys/mman/linux/shm_common.h"
-#include <asm/fcntl.h>
+#include <fcntl.h>
 
 namespace LIBC_NAMESPACE {
 
 static constexpr int DEFAULT_OFLAGS = O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK;
 
 LLVM_LIBC_FUNCTION(int, shm_open, (const char *name, int oflags, mode_t mode)) {
-  auto buffer = get_shm_name(name);
-  if (!buffer.has_value()) {
+  cpp::optional<SHMPath> buffer = get_shm_name(name);
+  if (!buffer.has_value())
     return -1;
-  }
   return open(buffer->data(), oflags | DEFAULT_OFLAGS, mode);
 }
 
diff --git a/libc/src/sys/mman/linux/shm_unlink.cpp b/libc/src/sys/mman/linux/shm_unlink.cpp
index 952415c3959052..3e8f14e2d7cb53 100644
--- a/libc/src/sys/mman/linux/shm_unlink.cpp
+++ b/libc/src/sys/mman/linux/shm_unlink.cpp
@@ -14,9 +14,8 @@ namespace LIBC_NAMESPACE {
 
 LLVM_LIBC_FUNCTION(int, shm_unlink, (const char *name)) {
   auto buffer = get_shm_name(name);
-  if (!buffer.has_value()) {
+  if (!buffer.has_value())
     return -1;
-  }
   return unlink(buffer->data());
 }
 
diff --git a/libc/src/sys/mman/shm_open.h b/libc/src/sys/mman/shm_open.h
index 97a2b641450d88..5064266d1f1cef 100644
--- a/libc/src/sys/mman/shm_open.h
+++ b/libc/src/sys/mman/shm_open.h
@@ -9,7 +9,7 @@
 #ifndef LLVM_LIBC_SRC_SYS_MMAN_SHM_OPEN_H
 #define LLVM_LIBC_SRC_SYS_MMAN_SHM_OPEN_H
 
-#include <fcntl.h> // For mode_t.
+#include <sys/mman.h>
 
 namespace LIBC_NAMESPACE {
 

>From 329ea45cd481df496611591181281598f4af62d8 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Tue, 12 Mar 2024 20:36:48 -0400
Subject: [PATCH 07/15] undo enametoolong change for now

---
 libc/include/llvm-libc-macros/generic-error-number-macros.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/include/llvm-libc-macros/generic-error-number-macros.h b/libc/include/llvm-libc-macros/generic-error-number-macros.h
index 11c7b241f90f20..7ee0352669b8a9 100644
--- a/libc/include/llvm-libc-macros/generic-error-number-macros.h
+++ b/libc/include/llvm-libc-macros/generic-error-number-macros.h
@@ -44,5 +44,5 @@
 #define EDOM 33
 #define ERANGE 34
 #define EILSEQ 35
-#define ENAMETOOLONG 36
+
 #endif // LLVM_LIBC_MACROS_GENERIC_ERROR_NUMBER_MACROS_H

>From 1929661ecf4dcfd21f52c918e861e6445d5ae760 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Tue, 12 Mar 2024 20:40:29 -0400
Subject: [PATCH 08/15] expand another auto type

---
 libc/src/sys/mman/linux/shm_unlink.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/src/sys/mman/linux/shm_unlink.cpp b/libc/src/sys/mman/linux/shm_unlink.cpp
index 3e8f14e2d7cb53..b3ca2b9325c6e8 100644
--- a/libc/src/sys/mman/linux/shm_unlink.cpp
+++ b/libc/src/sys/mman/linux/shm_unlink.cpp
@@ -13,7 +13,7 @@
 namespace LIBC_NAMESPACE {
 
 LLVM_LIBC_FUNCTION(int, shm_unlink, (const char *name)) {
-  auto buffer = get_shm_name(name);
+  cpp::optional<SHMPath> buffer = get_shm_name(name);
   if (!buffer.has_value())
     return -1;
   return unlink(buffer->data());

>From 8a8e9644d92a8930c4aee25182cd1aac9b6962fd Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Wed, 13 Mar 2024 14:37:00 -0400
Subject: [PATCH 09/15] add string_view tests

---
 .../src/__support/CPP/stringview_test.cpp     | 109 ++++++++++++++++++
 1 file changed, 109 insertions(+)

diff --git a/libc/test/src/__support/CPP/stringview_test.cpp b/libc/test/src/__support/CPP/stringview_test.cpp
index 33eb8ab4765728..12d808ef9a7574 100644
--- a/libc/test/src/__support/CPP/stringview_test.cpp
+++ b/libc/test/src/__support/CPP/stringview_test.cpp
@@ -174,3 +174,112 @@ TEST(LlvmLibcStringViewTest, FindLastOf) {
   ASSERT_EQ(Empty1.find_last_of('a', 0), string_view::npos);
   ASSERT_EQ(Empty1.find_last_of('a', 123), string_view::npos);
 }
+
+TEST(LlvmLibcStringViewTest, FindFirstNotOf) {
+  string_view Tmp("abada");
+
+  EXPECT_EQ(Tmp.find_first_not_of('a'), size_t(1));
+  EXPECT_EQ(Tmp.find_first_not_of('a', 123), string_view::npos);
+  EXPECT_EQ(Tmp.find_first_not_of('a', 5), string_view::npos);
+  EXPECT_EQ(Tmp.find_first_not_of('a', 4), string_view::npos);
+  EXPECT_EQ(Tmp.find_first_not_of('a', 3), size_t(3));
+  EXPECT_EQ(Tmp.find_first_not_of('a', 2), size_t(3));
+  EXPECT_EQ(Tmp.find_first_not_of('a', 1), size_t(1));
+  EXPECT_EQ(Tmp.find_first_not_of('a', 0), size_t(1));
+
+  EXPECT_EQ(Tmp.find_first_not_of('b'), size_t(0));
+  EXPECT_EQ(Tmp.find_first_not_of('b', 123), string_view::npos);
+  EXPECT_EQ(Tmp.find_first_not_of('b', 5), string_view::npos);
+  EXPECT_EQ(Tmp.find_first_not_of('b', 4), size_t(4));
+  EXPECT_EQ(Tmp.find_first_not_of('b', 3), size_t(3));
+  EXPECT_EQ(Tmp.find_first_not_of('b', 2), size_t(2));
+  EXPECT_EQ(Tmp.find_first_not_of('b', 1), size_t(2));
+  EXPECT_EQ(Tmp.find_first_not_of('b', 0), size_t(0));
+
+  EXPECT_EQ(Tmp.find_first_not_of('d'), size_t(0));
+  EXPECT_EQ(Tmp.find_first_not_of('d', 123), string_view::npos);
+  EXPECT_EQ(Tmp.find_first_not_of('d', 5), string_view::npos);
+  EXPECT_EQ(Tmp.find_first_not_of('d', 4), size_t(4));
+  EXPECT_EQ(Tmp.find_first_not_of('d', 3), size_t(4));
+  EXPECT_EQ(Tmp.find_first_not_of('d', 2), size_t(2));
+  EXPECT_EQ(Tmp.find_first_not_of('d', 1), size_t(1));
+  EXPECT_EQ(Tmp.find_first_not_of('d', 0), size_t(0));
+
+  EXPECT_EQ(Tmp.find_first_not_of('e'), size_t(0));
+  EXPECT_EQ(Tmp.find_first_not_of('e', 123), string_view::npos);
+  EXPECT_EQ(Tmp.find_first_not_of('e', 5), string_view::npos);
+  EXPECT_EQ(Tmp.find_first_not_of('e', 4), size_t(4));
+  EXPECT_EQ(Tmp.find_first_not_of('e', 3), size_t(3));
+  EXPECT_EQ(Tmp.find_first_not_of('e', 2), size_t(2));
+  EXPECT_EQ(Tmp.find_first_not_of('e', 1), size_t(1));
+  EXPECT_EQ(Tmp.find_first_not_of('e', 0), size_t(0));
+
+  string_view Empty;
+  EXPECT_EQ(Empty.find_first_not_of('a'), string_view::npos);
+  EXPECT_EQ(Empty.find_first_not_of('a', 0), string_view::npos);
+  EXPECT_EQ(Empty.find_first_not_of('a', 123), string_view::npos);
+
+  string_view Empty1("");
+  EXPECT_EQ(Empty1.find_first_not_of('a'), string_view::npos);
+  EXPECT_EQ(Empty1.find_first_not_of('a', 0), string_view::npos);
+  EXPECT_EQ(Empty1.find_first_not_of('a', 123), string_view::npos);
+
+  string_view Full("aaaaaaa");
+  EXPECT_EQ(Full.find_first_not_of('a'), string_view::npos);
+  EXPECT_EQ(Full.find_first_not_of('a', 0), string_view::npos);
+  EXPECT_EQ(Full.find_first_not_of('a', 123), string_view::npos);
+
+  EXPECT_EQ(Full.find_first_not_of('b'), size_t(0));
+  EXPECT_EQ(Full.find_first_not_of('b', 0), size_t(0));
+  EXPECT_EQ(Full.find_first_not_of('b', 123), string_view::npos);
+}
+
+TEST(LlvmLibcStringViewTest, Contains) {
+  string_view Empty;
+  for (char c = 'a'; c < 'z'; ++c)
+    for (size_t i = 0; i < 256; ++i)
+      EXPECT_FALSE(Empty.contains(c));
+
+  string_view Tmp("abada");
+  EXPECT_TRUE(Tmp.contains('a'));
+  EXPECT_TRUE(Tmp.contains('b'));
+  EXPECT_FALSE(Tmp.contains('c'));
+  EXPECT_TRUE(Tmp.contains('d'));
+  EXPECT_FALSE(Tmp.contains('e'));
+
+  EXPECT_TRUE(Tmp.substr(1).contains('a'));
+  EXPECT_TRUE(Tmp.substr(1).contains('b'));
+  EXPECT_FALSE(Tmp.substr(1).contains('c'));
+  EXPECT_TRUE(Tmp.substr(1).contains('d'));
+  EXPECT_FALSE(Tmp.substr(1).contains('e'));
+
+  EXPECT_TRUE(Tmp.substr(2).contains('a'));
+  EXPECT_FALSE(Tmp.substr(2).contains('b'));
+  EXPECT_FALSE(Tmp.substr(2).contains('c'));
+  EXPECT_TRUE(Tmp.substr(2).contains('d'));
+  EXPECT_FALSE(Tmp.substr(2).contains('e'));
+
+  EXPECT_TRUE(Tmp.substr(3).contains('a'));
+  EXPECT_FALSE(Tmp.substr(3).contains('b'));
+  EXPECT_FALSE(Tmp.substr(3).contains('c'));
+  EXPECT_TRUE(Tmp.substr(3).contains('d'));
+  EXPECT_FALSE(Tmp.substr(3).contains('e'));
+
+  EXPECT_TRUE(Tmp.substr(4).contains('a'));
+  EXPECT_FALSE(Tmp.substr(4).contains('b'));
+  EXPECT_FALSE(Tmp.substr(4).contains('c'));
+  EXPECT_FALSE(Tmp.substr(4).contains('d'));
+  EXPECT_FALSE(Tmp.substr(4).contains('e'));
+
+  EXPECT_FALSE(Tmp.substr(5).contains('a'));
+  EXPECT_FALSE(Tmp.substr(5).contains('b'));
+  EXPECT_FALSE(Tmp.substr(5).contains('c'));
+  EXPECT_FALSE(Tmp.substr(5).contains('d'));
+  EXPECT_FALSE(Tmp.substr(5).contains('e'));
+
+  EXPECT_FALSE(Tmp.substr(6).contains('a'));
+  EXPECT_FALSE(Tmp.substr(6).contains('b'));
+  EXPECT_FALSE(Tmp.substr(6).contains('c'));
+  EXPECT_FALSE(Tmp.substr(6).contains('d'));
+  EXPECT_FALSE(Tmp.substr(6).contains('e'));
+}
\ No newline at end of file

>From 7504b21c5af45124b2860759a439b612dfc7f88d Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Wed, 13 Mar 2024 14:44:20 -0400
Subject: [PATCH 10/15] adjust macros

---
 libc/src/sys/mman/linux/CMakeLists.txt | 3 ++-
 libc/src/sys/mman/linux/shm_open.cpp   | 2 +-
 libc/src/sys/mman/shm_open.h           | 2 +-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt
index c995c107f4d1d0..00f4f0e64ec06b 100644
--- a/libc/src/sys/mman/linux/CMakeLists.txt
+++ b/libc/src/sys/mman/linux/CMakeLists.txt
@@ -174,7 +174,8 @@ add_entrypoint_object(
     ../shm_open.h
   DEPENDS
     libc.src.fcntl.open
-    libc.include.fcntl
+    libc.include.llvm-libc-macros.fcntl_macros
+    libc.include.llvm-libc-types.mode_t
     .shm_common
 )
 
diff --git a/libc/src/sys/mman/linux/shm_open.cpp b/libc/src/sys/mman/linux/shm_open.cpp
index eaf111d1c325f6..bfbcf7489cdf43 100644
--- a/libc/src/sys/mman/linux/shm_open.cpp
+++ b/libc/src/sys/mman/linux/shm_open.cpp
@@ -7,9 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/sys/mman/shm_open.h"
+#include "llvm-libc-macros/fcntl-macros.h"
 #include "src/fcntl/open.h"
 #include "src/sys/mman/linux/shm_common.h"
-#include <fcntl.h>
 
 namespace LIBC_NAMESPACE {
 
diff --git a/libc/src/sys/mman/shm_open.h b/libc/src/sys/mman/shm_open.h
index 5064266d1f1cef..91796d7b5c0501 100644
--- a/libc/src/sys/mman/shm_open.h
+++ b/libc/src/sys/mman/shm_open.h
@@ -9,7 +9,7 @@
 #ifndef LLVM_LIBC_SRC_SYS_MMAN_SHM_OPEN_H
 #define LLVM_LIBC_SRC_SYS_MMAN_SHM_OPEN_H
 
-#include <sys/mman.h>
+#include <llvm-libc-types/mode_t.h>
 
 namespace LIBC_NAMESPACE {
 

>From ec47dc438a0cadd261b2173fe11abda60fb04902 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Wed, 13 Mar 2024 14:58:41 -0400
Subject: [PATCH 11/15] mention NAME_MAX

---
 libc/src/sys/mman/linux/shm_common.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libc/src/sys/mman/linux/shm_common.h b/libc/src/sys/mman/linux/shm_common.h
index e73d991b0549cb..6f8acf65ccac97 100644
--- a/libc/src/sys/mman/linux/shm_common.h
+++ b/libc/src/sys/mman/linux/shm_common.h
@@ -11,6 +11,8 @@
 #include "src/__support/CPP/string_view.h"
 #include "src/errno/libc_errno.h"
 #include "src/string/memory_utils/inline_memcpy.h"
+
+// TODO: Get PATH_MAX via https://github.com/llvm/llvm-project/issues/85121
 #include <linux/limits.h>
 
 namespace LIBC_NAMESPACE {

>From e4f434b784f113587e37860c35a766fe9577e3d2 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Wed, 13 Mar 2024 15:04:24 -0400
Subject: [PATCH 12/15] add missing space

---
 libc/test/src/__support/CPP/stringview_test.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/test/src/__support/CPP/stringview_test.cpp b/libc/test/src/__support/CPP/stringview_test.cpp
index 12d808ef9a7574..bfc22b170dfeb7 100644
--- a/libc/test/src/__support/CPP/stringview_test.cpp
+++ b/libc/test/src/__support/CPP/stringview_test.cpp
@@ -282,4 +282,4 @@ TEST(LlvmLibcStringViewTest, Contains) {
   EXPECT_FALSE(Tmp.substr(6).contains('c'));
   EXPECT_FALSE(Tmp.substr(6).contains('d'));
   EXPECT_FALSE(Tmp.substr(6).contains('e'));
-}
\ No newline at end of file
+}

>From edde0371d95f8eaa62279176aa1eab0882b9ffbf Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Fri, 15 Mar 2024 15:33:57 -0400
Subject: [PATCH 13/15] wrap common ABIs in namespace

---
 libc/src/sys/mman/linux/shm_common.h   | 5 ++++-
 libc/src/sys/mman/linux/shm_open.cpp   | 2 +-
 libc/src/sys/mman/linux/shm_unlink.cpp | 2 +-
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/libc/src/sys/mman/linux/shm_common.h b/libc/src/sys/mman/linux/shm_common.h
index 6f8acf65ccac97..6f2a3fdc71b647 100644
--- a/libc/src/sys/mman/linux/shm_common.h
+++ b/libc/src/sys/mman/linux/shm_common.h
@@ -17,10 +17,12 @@
 
 namespace LIBC_NAMESPACE {
 
+namespace shm_common {
+
 LIBC_INLINE_VAR constexpr cpp::string_view SHM_PREFIX = "/dev/shm/";
 using SHMPath = cpp::array<char, NAME_MAX + SHM_PREFIX.size() + 1>;
 
-LIBC_INLINE cpp::optional<SHMPath> get_shm_name(cpp::string_view name) {
+LIBC_INLINE cpp::optional<SHMPath> translate_name(cpp::string_view name) {
   // trim leading slashes
   size_t offset = name.find_first_not_of('/');
   if (offset == cpp::string_view::npos) {
@@ -46,5 +48,6 @@ LIBC_INLINE cpp::optional<SHMPath> get_shm_name(cpp::string_view name) {
   buffer[SHM_PREFIX.size() + name.size()] = '\0';
   return buffer;
 }
+} // namespace shm_common
 
 } // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/mman/linux/shm_open.cpp b/libc/src/sys/mman/linux/shm_open.cpp
index bfbcf7489cdf43..270dbe23a21f2b 100644
--- a/libc/src/sys/mman/linux/shm_open.cpp
+++ b/libc/src/sys/mman/linux/shm_open.cpp
@@ -16,7 +16,7 @@ namespace LIBC_NAMESPACE {
 static constexpr int DEFAULT_OFLAGS = O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK;
 
 LLVM_LIBC_FUNCTION(int, shm_open, (const char *name, int oflags, mode_t mode)) {
-  cpp::optional<SHMPath> buffer = get_shm_name(name);
+  cpp::optional<shm_common::SHMPath> buffer = shm_common::translate_name(name);
   if (!buffer.has_value())
     return -1;
   return open(buffer->data(), oflags | DEFAULT_OFLAGS, mode);
diff --git a/libc/src/sys/mman/linux/shm_unlink.cpp b/libc/src/sys/mman/linux/shm_unlink.cpp
index b3ca2b9325c6e8..dc52e9f3460e62 100644
--- a/libc/src/sys/mman/linux/shm_unlink.cpp
+++ b/libc/src/sys/mman/linux/shm_unlink.cpp
@@ -13,7 +13,7 @@
 namespace LIBC_NAMESPACE {
 
 LLVM_LIBC_FUNCTION(int, shm_unlink, (const char *name)) {
-  cpp::optional<SHMPath> buffer = get_shm_name(name);
+  cpp::optional<shm_common::SHMPath> buffer = shm_common::translate_name(name);
   if (!buffer.has_value())
     return -1;
   return unlink(buffer->data());

>From 8a255c3eed9c4c4b228fe708b78033c6688b37da Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Fri, 15 Mar 2024 15:40:42 -0400
Subject: [PATCH 14/15] address code reviews

---
 libc/src/sys/mman/linux/shm_open.cpp            | 9 +++++----
 libc/src/sys/mman/linux/shm_unlink.cpp          | 8 ++++----
 libc/test/src/__support/CPP/stringview_test.cpp | 3 +--
 libc/test/src/sys/mman/linux/shm_test.cpp       | 4 ++--
 4 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/libc/src/sys/mman/linux/shm_open.cpp b/libc/src/sys/mman/linux/shm_open.cpp
index 270dbe23a21f2b..587750dde15f52 100644
--- a/libc/src/sys/mman/linux/shm_open.cpp
+++ b/libc/src/sys/mman/linux/shm_open.cpp
@@ -16,10 +16,11 @@ namespace LIBC_NAMESPACE {
 static constexpr int DEFAULT_OFLAGS = O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK;
 
 LLVM_LIBC_FUNCTION(int, shm_open, (const char *name, int oflags, mode_t mode)) {
-  cpp::optional<shm_common::SHMPath> buffer = shm_common::translate_name(name);
-  if (!buffer.has_value())
-    return -1;
-  return open(buffer->data(), oflags | DEFAULT_OFLAGS, mode);
+
+  if (cpp::optional<shm_common::SHMPath> buffer =
+          shm_common::translate_name(name))
+    return open(buffer->data(), oflags | DEFAULT_OFLAGS, mode);
+  return -1;
 }
 
 } // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/mman/linux/shm_unlink.cpp b/libc/src/sys/mman/linux/shm_unlink.cpp
index dc52e9f3460e62..6703030d7de51f 100644
--- a/libc/src/sys/mman/linux/shm_unlink.cpp
+++ b/libc/src/sys/mman/linux/shm_unlink.cpp
@@ -13,10 +13,10 @@
 namespace LIBC_NAMESPACE {
 
 LLVM_LIBC_FUNCTION(int, shm_unlink, (const char *name)) {
-  cpp::optional<shm_common::SHMPath> buffer = shm_common::translate_name(name);
-  if (!buffer.has_value())
-    return -1;
-  return unlink(buffer->data());
+  if (cpp::optional<shm_common::SHMPath> buffer =
+          shm_common::translate_name(name))
+    return unlink(buffer->data());
+  return -1;
 }
 
 } // namespace LIBC_NAMESPACE
diff --git a/libc/test/src/__support/CPP/stringview_test.cpp b/libc/test/src/__support/CPP/stringview_test.cpp
index bfc22b170dfeb7..6b68f2a1c47a9d 100644
--- a/libc/test/src/__support/CPP/stringview_test.cpp
+++ b/libc/test/src/__support/CPP/stringview_test.cpp
@@ -237,8 +237,7 @@ TEST(LlvmLibcStringViewTest, FindFirstNotOf) {
 TEST(LlvmLibcStringViewTest, Contains) {
   string_view Empty;
   for (char c = 'a'; c < 'z'; ++c)
-    for (size_t i = 0; i < 256; ++i)
-      EXPECT_FALSE(Empty.contains(c));
+    EXPECT_FALSE(Empty.contains(c));
 
   string_view Tmp("abada");
   EXPECT_TRUE(Tmp.contains('a'));
diff --git a/libc/test/src/sys/mman/linux/shm_test.cpp b/libc/test/src/sys/mman/linux/shm_test.cpp
index 3b1a2aa33b56ad..ec6443dae70697 100644
--- a/libc/test/src/sys/mman/linux/shm_test.cpp
+++ b/libc/test/src/sys/mman/linux/shm_test.cpp
@@ -26,7 +26,7 @@ TEST(LlvmLibcShmTest, Basic) {
   const char *name = "/test_shm_open";
   int fd;
   ASSERT_THAT(fd = LIBC_NAMESPACE::shm_open(name, O_CREAT | O_RDWR, 0666),
-              returns(GE(0)).with_errno(EQ(0)));
+              returns(GT(0)).with_errno(EQ(0)));
 
   // check that FD_CLOEXEC is set by default.
   // TODO: use fcntl when implemented.
@@ -62,7 +62,7 @@ TEST(LlvmLibcShmTest, NameConversion) {
   const char *name = "////test_shm_open";
   int fd;
   ASSERT_THAT(fd = LIBC_NAMESPACE::shm_open(name, O_CREAT | O_RDWR, 0666),
-              returns(GE(0)).with_errno(EQ(0)));
+              returns(GT(0)).with_errno(EQ(0)));
   ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds());
   ASSERT_THAT(LIBC_NAMESPACE::shm_unlink(name), Succeeds());
 

>From 1eaa414d3698b6743beaf94668041c886fec2525 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Mon, 18 Mar 2024 10:49:42 -0400
Subject: [PATCH 15/15] address CRs

---
 libc/src/sys/mman/linux/shm_open.cpp      | 5 ++---
 libc/src/sys/mman/linux/shm_unlink.cpp    | 4 ++--
 libc/test/src/sys/mman/linux/shm_test.cpp | 4 ++--
 3 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/libc/src/sys/mman/linux/shm_open.cpp b/libc/src/sys/mman/linux/shm_open.cpp
index 587750dde15f52..0d39b8b4e53dbf 100644
--- a/libc/src/sys/mman/linux/shm_open.cpp
+++ b/libc/src/sys/mman/linux/shm_open.cpp
@@ -16,9 +16,8 @@ namespace LIBC_NAMESPACE {
 static constexpr int DEFAULT_OFLAGS = O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK;
 
 LLVM_LIBC_FUNCTION(int, shm_open, (const char *name, int oflags, mode_t mode)) {
-
-  if (cpp::optional<shm_common::SHMPath> buffer =
-          shm_common::translate_name(name))
+  using namespace shm_common;
+  if (cpp::optional<SHMPath> buffer = translate_name(name))
     return open(buffer->data(), oflags | DEFAULT_OFLAGS, mode);
   return -1;
 }
diff --git a/libc/src/sys/mman/linux/shm_unlink.cpp b/libc/src/sys/mman/linux/shm_unlink.cpp
index 6703030d7de51f..32f48d3e3e7187 100644
--- a/libc/src/sys/mman/linux/shm_unlink.cpp
+++ b/libc/src/sys/mman/linux/shm_unlink.cpp
@@ -13,8 +13,8 @@
 namespace LIBC_NAMESPACE {
 
 LLVM_LIBC_FUNCTION(int, shm_unlink, (const char *name)) {
-  if (cpp::optional<shm_common::SHMPath> buffer =
-          shm_common::translate_name(name))
+  using namespace shm_common;
+  if (cpp::optional<SHMPath> buffer = translate_name(name))
     return unlink(buffer->data());
   return -1;
 }
diff --git a/libc/test/src/sys/mman/linux/shm_test.cpp b/libc/test/src/sys/mman/linux/shm_test.cpp
index ec6443dae70697..3b1a2aa33b56ad 100644
--- a/libc/test/src/sys/mman/linux/shm_test.cpp
+++ b/libc/test/src/sys/mman/linux/shm_test.cpp
@@ -26,7 +26,7 @@ TEST(LlvmLibcShmTest, Basic) {
   const char *name = "/test_shm_open";
   int fd;
   ASSERT_THAT(fd = LIBC_NAMESPACE::shm_open(name, O_CREAT | O_RDWR, 0666),
-              returns(GT(0)).with_errno(EQ(0)));
+              returns(GE(0)).with_errno(EQ(0)));
 
   // check that FD_CLOEXEC is set by default.
   // TODO: use fcntl when implemented.
@@ -62,7 +62,7 @@ TEST(LlvmLibcShmTest, NameConversion) {
   const char *name = "////test_shm_open";
   int fd;
   ASSERT_THAT(fd = LIBC_NAMESPACE::shm_open(name, O_CREAT | O_RDWR, 0666),
-              returns(GT(0)).with_errno(EQ(0)));
+              returns(GE(0)).with_errno(EQ(0)));
   ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds());
   ASSERT_THAT(LIBC_NAMESPACE::shm_unlink(name), Succeeds());
 



More information about the libc-commits mailing list