[libc-commits] [libc] 76173b1 - [libc] Add Linux mman extension remap_file_pages. (#110307)
via libc-commits
libc-commits at lists.llvm.org
Mon Oct 14 14:04:36 PDT 2024
Author: Aly ElAshram
Date: 2024-10-14T14:04:32-07:00
New Revision: 76173b1b6770801203e671a7fb25f56163b8829b
URL: https://github.com/llvm/llvm-project/commit/76173b1b6770801203e671a7fb25f56163b8829b
DIFF: https://github.com/llvm/llvm-project/commit/76173b1b6770801203e671a7fb25f56163b8829b.diff
LOG: [libc] Add Linux mman extension remap_file_pages. (#110307)
Fixes https://github.com/llvm/llvm-project/issues/110122
- Create remap_file_pages.h/.cpp wrapper for the linux sys call.
- Add UnitTests for remap_file_pages
- Add function to libc/spec/linux.td
- Add Function spec to mman.yaml
Added:
libc/src/sys/mman/linux/remap_file_pages.cpp
libc/src/sys/mman/remap_file_pages.h
libc/test/src/sys/mman/linux/remap_file_pages_test.cpp
Modified:
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/riscv/entrypoints.txt
libc/config/linux/x86_64/entrypoints.txt
libc/newhdrgen/yaml/sys/mman.yaml
libc/spec/linux.td
libc/src/sys/mman/CMakeLists.txt
libc/src/sys/mman/linux/CMakeLists.txt
libc/test/src/sys/mman/linux/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 72a4d9b65ce990..32c0d199489317 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -250,6 +250,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.sys.mman.munlock
libc.src.sys.mman.munlockall
libc.src.sys.mman.munmap
+ libc.src.sys.mman.remap_file_pages
libc.src.sys.mman.posix_madvise
libc.src.sys.mman.shm_open
libc.src.sys.mman.shm_unlink
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index b2e1aefccef66f..5c09edf7cfb266 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -249,6 +249,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.sys.mman.munlock
libc.src.sys.mman.munlockall
libc.src.sys.mman.munmap
+ libc.src.sys.mman.remap_file_pages
libc.src.sys.mman.posix_madvise
libc.src.sys.mman.shm_open
libc.src.sys.mman.shm_unlink
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index eb7d3883a8f711..1cd817171de4be 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -249,6 +249,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.sys.mman.munlock
libc.src.sys.mman.munlockall
libc.src.sys.mman.munmap
+ libc.src.sys.mman.remap_file_pages
libc.src.sys.mman.posix_madvise
libc.src.sys.mman.shm_open
libc.src.sys.mman.shm_unlink
diff --git a/libc/newhdrgen/yaml/sys/mman.yaml b/libc/newhdrgen/yaml/sys/mman.yaml
index 272e7e2af16aaf..7c4fb1ef09e791 100644
--- a/libc/newhdrgen/yaml/sys/mman.yaml
+++ b/libc/newhdrgen/yaml/sys/mman.yaml
@@ -98,6 +98,16 @@ functions:
- type: void *
- type: size_t
- type: int
+ - name: remap_file_pages
+ standards:
+ - Linux
+ return_type: int
+ arguments:
+ - type: void *
+ - type: size_t
+ - type: int
+ - type: size_t
+ - type: int
- name: shm_open
standards:
- POSIX
diff --git a/libc/spec/linux.td b/libc/spec/linux.td
index 395c2a6fe853a7..4aaf18b0803f3d 100644
--- a/libc/spec/linux.td
+++ b/libc/spec/linux.td
@@ -103,6 +103,17 @@ def Linux : StandardSpec<"Linux"> {
ArgSpec<UnsignedIntType>,
]
>,
+ FunctionSpec<
+ "remap_file_pages",
+ RetValSpec<IntType>,
+ [
+ ArgSpec<VoidPtr>,
+ ArgSpec<SizeTType>,
+ ArgSpec<IntType>,
+ ArgSpec<SizeTType>,
+ ArgSpec<IntType>,
+ ]
+ >,
] // Functions
>;
diff --git a/libc/src/sys/mman/CMakeLists.txt b/libc/src/sys/mman/CMakeLists.txt
index 9c74202a09f035..4ea43e14be0297 100644
--- a/libc/src/sys/mman/CMakeLists.txt
+++ b/libc/src/sys/mman/CMakeLists.txt
@@ -86,6 +86,13 @@ add_entrypoint_object(
.${LIBC_TARGET_OS}.msync
)
+add_entrypoint_object(
+ remap_file_pages
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.remap_file_pages
+)
+
add_entrypoint_object(
shm_open
ALIAS
diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt
index 00f4f0e64ec06b..11188254cfbd45 100644
--- a/libc/src/sys/mman/linux/CMakeLists.txt
+++ b/libc/src/sys/mman/linux/CMakeLists.txt
@@ -153,6 +153,19 @@ add_entrypoint_object(
libc.src.errno.errno
)
+add_entrypoint_object(
+ remap_file_pages
+ SRCS
+ remap_file_pages.cpp
+ HDRS
+ ../remap_file_pages.h
+ DEPENDS
+ libc.include.sys_mman
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
add_header_library(
shm_common
HDRS
diff --git a/libc/src/sys/mman/linux/remap_file_pages.cpp b/libc/src/sys/mman/linux/remap_file_pages.cpp
new file mode 100644
index 00000000000000..f616e1915ecc5e
--- /dev/null
+++ b/libc/src/sys/mman/linux/remap_file_pages.cpp
@@ -0,0 +1,40 @@
+//===------- Linux implementation of the remap_file_pages 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/remap_file_pages.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/errno/libc_errno.h"
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, remap_file_pages,
+ (void *addr, size_t size, int prot, size_t pgoff,
+ int flags)) {
+#ifdef SYS_remap_file_pages
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_remap_file_pages,
+ reinterpret_cast<long>(addr),
+ size, prot, pgoff, flags);
+#else
+#error "remap_file_pages syscall is not available."
+#endif
+
+ // A negative return value indicates an error with the magnitude of the
+ // value being the error code.
+ if (ret < 0) {
+ libc_errno = -ret;
+ return -1;
+ }
+
+ return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/mman/remap_file_pages.h b/libc/src/sys/mman/remap_file_pages.h
new file mode 100644
index 00000000000000..518502960d5cf1
--- /dev/null
+++ b/libc/src/sys/mman/remap_file_pages.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for remap_file_pages 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_REMAP_FILE_PAGES_H
+#define LLVM_LIBC_SRC_SYS_MMAN_REMAP_FILE_PAGES_H
+
+#include "src/__support/macros/config.h"
+#include <stddef.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+int remap_file_pages(void *addr, size_t size, int prot, size_t pgoff,
+ int flags);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_MMAN_REMAP_FILE_PAGES_H
diff --git a/libc/test/src/sys/mman/linux/CMakeLists.txt b/libc/test/src/sys/mman/linux/CMakeLists.txt
index b63c76f4306fac..a432d88ffb90c9 100644
--- a/libc/test/src/sys/mman/linux/CMakeLists.txt
+++ b/libc/test/src/sys/mman/linux/CMakeLists.txt
@@ -128,6 +128,23 @@ add_libc_unittest(
libc.test.UnitTest.ErrnoSetterMatcher
)
+add_libc_unittest(
+ remap_file_pages_test
+ SUITE
+ libc_sys_mman_unittests
+ SRCS
+ remap_file_pages_test.cpp
+ DEPENDS
+ libc.include.sys_mman
+ libc.include.sys_stat
+ libc.src.unistd.sysconf
+ libc.test.UnitTest.ErrnoSetterMatcher
+ libc.src.sys.mman.remap_file_pages
+ libc.src.errno.errno
+ libc.src.sys.mman.mmap
+ libc.src.sys.mman.munmap
+)
+
add_libc_unittest(
shm_test
SUITE
diff --git a/libc/test/src/sys/mman/linux/remap_file_pages_test.cpp b/libc/test/src/sys/mman/linux/remap_file_pages_test.cpp
new file mode 100644
index 00000000000000..267f7598ff70e6
--- /dev/null
+++ b/libc/test/src/sys/mman/linux/remap_file_pages_test.cpp
@@ -0,0 +1,93 @@
+//===-- Unittests for remap_file_pages ------------------------------------===//
+//
+// 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/errno/libc_errno.h"
+#include "src/fcntl/open.h"
+#include "src/sys/mman/mmap.h"
+#include "src/sys/mman/munmap.h"
+#include "src/sys/mman/remap_file_pages.h"
+#include "src/unistd/close.h"
+#include "src/unistd/sysconf.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+#include <sys/mman.h>
+#include <sys/stat.h> // For S_IRWXU
+
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
+
+TEST(LlvmLibcRemapFilePagesTest, NoError) {
+ size_t page_size = sysconf(_SC_PAGE_SIZE);
+ ASSERT_GT(page_size, size_t(0));
+
+ // Create a file-backed mapping
+ constexpr const char *file_name = "remap_file_pages.test.noerror";
+ auto test_file = libc_make_test_file_path(file_name);
+ int fd = LIBC_NAMESPACE::open(test_file, O_RDWR | O_CREAT, S_IRWXU);
+ ASSERT_GT(fd, 0);
+
+ // First, allocate some memory using mmap
+ size_t alloc_size = 2 * page_size;
+ LIBC_NAMESPACE::libc_errno = 0;
+ void *addr = LIBC_NAMESPACE::mmap(nullptr, alloc_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_NE(addr, MAP_FAILED);
+
+ // Now try to remap the pages
+ EXPECT_THAT(LIBC_NAMESPACE::remap_file_pages(addr, page_size, 0, 1, 0),
+ Succeeds());
+
+ // Reset error number for the new function
+ LIBC_NAMESPACE::libc_errno = 0;
+
+ // Clean up
+ EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, alloc_size), Succeeds());
+ EXPECT_THAT(LIBC_NAMESPACE::close(fd), Succeeds());
+}
+
+TEST(LlvmLibcRemapFilePagesTest, ErrorInvalidFlags) {
+ size_t page_size = sysconf(_SC_PAGE_SIZE);
+ ASSERT_GT(page_size, size_t(0));
+
+ // Create a file-backed mapping
+ constexpr const char *file_name = "remap_file_pages.test.error";
+ auto test_file = libc_make_test_file_path(file_name);
+ int fd = LIBC_NAMESPACE::open(test_file, O_RDWR | O_CREAT, S_IRWXU);
+ ASSERT_GT(fd, 0);
+
+ // First, allocate some memory using mmap
+ size_t alloc_size = 2 * page_size;
+ LIBC_NAMESPACE::libc_errno = 0;
+ void *addr = LIBC_NAMESPACE::mmap(nullptr, alloc_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_NE(addr, MAP_FAILED);
+
+ // Try to remap pages with an invalid flag MAP_PRIVATE
+ EXPECT_THAT(LIBC_NAMESPACE::remap_file_pages(addr, page_size, PROT_READ, 0,
+ MAP_PRIVATE),
+ Fails(EINVAL));
+
+ // Clean up
+ EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds());
+ EXPECT_THAT(LIBC_NAMESPACE::close(fd), Succeeds());
+}
+
+TEST(LlvmLibcRemapFilePagesTest, ErrorInvalidAddress) {
+ size_t page_size = sysconf(_SC_PAGESIZE);
+ ASSERT_GT(page_size, size_t(0));
+
+ // Use an address that we haven't mapped
+ void *invalid_addr = reinterpret_cast<void *>(0x12345000);
+
+ EXPECT_THAT(LIBC_NAMESPACE::remap_file_pages(invalid_addr, page_size,
+ PROT_READ, 0, 0),
+ Fails(EINVAL));
+}
More information about the libc-commits
mailing list