[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