[libc-commits] [libc] Add Linux sys call wrapper in LibC [ Issue #110122 ] (PR #110307)
Aly ElAshram via libc-commits
libc-commits at lists.llvm.org
Fri Sep 27 11:06:30 PDT 2024
https://github.com/AlyElashram created https://github.com/llvm/llvm-project/pull/110307
- 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
>From 50bf5e92716bfca96c311da021dace6688f98fcd Mon Sep 17 00:00:00 2001
From: Aly Elashram <alyahelashram at gmail.com>
Date: Fri, 27 Sep 2024 20:46:11 +0300
Subject: [PATCH] - Create remap_file_pages wrapper for the linux sys call. -
Add UnitTest for remap_file_pages - Add function to libc/spec/linux.td - Add
Function spec to mman.yaml
---
libc/newhdrgen/yaml/sys/mman.yaml | 10 +++
libc/spec/linux.td | 11 +++
libc/src/sys/mman/CMakeLists.txt | 7 ++
libc/src/sys/mman/linux/CMakeLists.txt | 13 ++++
libc/src/sys/mman/linux/remap_file_pages.cpp | 44 +++++++++++
libc/src/sys/mman/remap_file_pages.h | 21 ++++++
libc/test/src/sys/mman/linux/CMakeLists.txt | 17 +++++
.../sys/mman/linux/remap_file_pages_test.cpp | 74 +++++++++++++++++++
8 files changed, 197 insertions(+)
create mode 100644 libc/src/sys/mman/linux/remap_file_pages.cpp
create mode 100644 libc/src/sys/mman/remap_file_pages.h
create mode 100644 libc/test/src/sys/mman/linux/remap_file_pages_test.cpp
diff --git a/libc/newhdrgen/yaml/sys/mman.yaml b/libc/newhdrgen/yaml/sys/mman.yaml
index 272e7e2af16aaf..2f5f199bddec83 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..f673d47ba96aef 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.cpp
+ HDRS
+ ../remap_file_pages.h.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..074d24d7c9b435
--- /dev/null
+++ b/libc/src/sys/mman/linux/remap_file_pages.cpp
@@ -0,0 +1,44 @@
+//===----- Linux implementation of the POSIX 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 {
+
+// This function is currently linux only. It has to be refactored suitably if
+// remap_file_pages is to be supported on non-linux operating systems also.
+LLVM_LIBC_FUNCTION(int, remap_file_pages,
+ (void *addr, size_t size, int prot, size_t pgoff, int flags))
+ {
+#ifdef SYS_remap_file_pages
+ long syscall_number = SYS_remap_file_pages;
+#else
+#error "remap_file_pages syscall is not available."
+#endif
+
+
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(
+ syscall_number, reinterpret_cast<long>(addr), size, prot, pgoff, flags);
+
+ // 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
\ No newline at end of file
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..cfb540fd904140
--- /dev/null
+++ b/libc/src/sys/mman/remap_file_pages.h
@@ -0,0 +1,21 @@
+//===-- 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 <sys/mman.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..3718f732b425f6 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.src.unistd.sysconf
+ libc.test.UnitTest.Test
+ 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..270ae4b6701e97
--- /dev/null
+++ b/libc/test/src/sys/mman/linux/remap_file_pages_test.cpp
@@ -0,0 +1,74 @@
+//===-- 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/sys/mman/mmap.h"
+#include "src/sys/mman/munmap.h"
+#include "src/sys/mman/remap_file_pages.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "src/unistd/sysconf.h"
+
+#include <sys/mman.h>
+
+
+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));
+
+ // 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_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_NE(addr, MAP_FAILED);
+
+ // Reset error number for the new function
+ LIBC_NAMESPACE::libc_errno = 0;
+
+ // Now try to remap the pages
+ EXPECT_THAT(LIBC_NAMESPACE::remap_file_pages(addr, page_size, PROT_READ, page_size, 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());
+}
+
+TEST(LlvmLibcRemapFilePagesTest, ErrorInvalidFlags) {
+ size_t page_size = sysconf(_SC_PAGESIZE);
+ ASSERT_GT(page_size, size_t(0));
+
+ void *addr = LIBC_NAMESPACE::mmap(nullptr, page_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ ASSERT_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());
+}
+
+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));
+}
\ No newline at end of file
More information about the libc-commits
mailing list