[libc-commits] [libc] [libc] Add `shm_open/shm_unlink` (PR #84974)
Schrodinger ZHU Yifan via libc-commits
libc-commits at lists.llvm.org
Tue Mar 12 12:29:36 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 1/3] [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 2/3] 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 3/3] 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 {
More information about the libc-commits
mailing list