Skip to content

Commit 76173b1

Browse files
authored
[libc] Add Linux mman extension remap_file_pages. (#110307)
Fixes #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
1 parent db57fc4 commit 76173b1

File tree

11 files changed

+216
-0
lines changed

11 files changed

+216
-0
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ set(TARGET_LIBC_ENTRYPOINTS
250250
libc.src.sys.mman.munlock
251251
libc.src.sys.mman.munlockall
252252
libc.src.sys.mman.munmap
253+
libc.src.sys.mman.remap_file_pages
253254
libc.src.sys.mman.posix_madvise
254255
libc.src.sys.mman.shm_open
255256
libc.src.sys.mman.shm_unlink

libc/config/linux/riscv/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ set(TARGET_LIBC_ENTRYPOINTS
249249
libc.src.sys.mman.munlock
250250
libc.src.sys.mman.munlockall
251251
libc.src.sys.mman.munmap
252+
libc.src.sys.mman.remap_file_pages
252253
libc.src.sys.mman.posix_madvise
253254
libc.src.sys.mman.shm_open
254255
libc.src.sys.mman.shm_unlink

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ set(TARGET_LIBC_ENTRYPOINTS
249249
libc.src.sys.mman.munlock
250250
libc.src.sys.mman.munlockall
251251
libc.src.sys.mman.munmap
252+
libc.src.sys.mman.remap_file_pages
252253
libc.src.sys.mman.posix_madvise
253254
libc.src.sys.mman.shm_open
254255
libc.src.sys.mman.shm_unlink

libc/newhdrgen/yaml/sys/mman.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,16 @@ functions:
9898
- type: void *
9999
- type: size_t
100100
- type: int
101+
- name: remap_file_pages
102+
standards:
103+
- Linux
104+
return_type: int
105+
arguments:
106+
- type: void *
107+
- type: size_t
108+
- type: int
109+
- type: size_t
110+
- type: int
101111
- name: shm_open
102112
standards:
103113
- POSIX

libc/spec/linux.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,17 @@ def Linux : StandardSpec<"Linux"> {
103103
ArgSpec<UnsignedIntType>,
104104
]
105105
>,
106+
FunctionSpec<
107+
"remap_file_pages",
108+
RetValSpec<IntType>,
109+
[
110+
ArgSpec<VoidPtr>,
111+
ArgSpec<SizeTType>,
112+
ArgSpec<IntType>,
113+
ArgSpec<SizeTType>,
114+
ArgSpec<IntType>,
115+
]
116+
>,
106117
] // Functions
107118
>;
108119

libc/src/sys/mman/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@ add_entrypoint_object(
8686
.${LIBC_TARGET_OS}.msync
8787
)
8888

89+
add_entrypoint_object(
90+
remap_file_pages
91+
ALIAS
92+
DEPENDS
93+
.${LIBC_TARGET_OS}.remap_file_pages
94+
)
95+
8996
add_entrypoint_object(
9097
shm_open
9198
ALIAS

libc/src/sys/mman/linux/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,19 @@ add_entrypoint_object(
153153
libc.src.errno.errno
154154
)
155155

156+
add_entrypoint_object(
157+
remap_file_pages
158+
SRCS
159+
remap_file_pages.cpp
160+
HDRS
161+
../remap_file_pages.h
162+
DEPENDS
163+
libc.include.sys_mman
164+
libc.include.sys_syscall
165+
libc.src.__support.OSUtil.osutil
166+
libc.src.errno.errno
167+
)
168+
156169
add_header_library(
157170
shm_common
158171
HDRS
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===------- Linux implementation of the remap_file_pages function --------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/sys/mman/remap_file_pages.h"
10+
11+
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
12+
#include "src/__support/common.h"
13+
#include "src/__support/macros/config.h"
14+
#include "src/errno/libc_errno.h"
15+
#include <sys/syscall.h> // For syscall numbers.
16+
17+
namespace LIBC_NAMESPACE_DECL {
18+
19+
LLVM_LIBC_FUNCTION(int, remap_file_pages,
20+
(void *addr, size_t size, int prot, size_t pgoff,
21+
int flags)) {
22+
#ifdef SYS_remap_file_pages
23+
int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_remap_file_pages,
24+
reinterpret_cast<long>(addr),
25+
size, prot, pgoff, flags);
26+
#else
27+
#error "remap_file_pages syscall is not available."
28+
#endif
29+
30+
// A negative return value indicates an error with the magnitude of the
31+
// value being the error code.
32+
if (ret < 0) {
33+
libc_errno = -ret;
34+
return -1;
35+
}
36+
37+
return 0;
38+
}
39+
40+
} // namespace LIBC_NAMESPACE_DECL

libc/src/sys/mman/remap_file_pages.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===-- Implementation header for remap_file_pages function -----*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_SYS_MMAN_REMAP_FILE_PAGES_H
10+
#define LLVM_LIBC_SRC_SYS_MMAN_REMAP_FILE_PAGES_H
11+
12+
#include "src/__support/macros/config.h"
13+
#include <stddef.h>
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
17+
int remap_file_pages(void *addr, size_t size, int prot, size_t pgoff,
18+
int flags);
19+
20+
} // namespace LIBC_NAMESPACE_DECL
21+
22+
#endif // LLVM_LIBC_SRC_SYS_MMAN_REMAP_FILE_PAGES_H

libc/test/src/sys/mman/linux/CMakeLists.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,23 @@ add_libc_unittest(
128128
libc.test.UnitTest.ErrnoSetterMatcher
129129
)
130130

131+
add_libc_unittest(
132+
remap_file_pages_test
133+
SUITE
134+
libc_sys_mman_unittests
135+
SRCS
136+
remap_file_pages_test.cpp
137+
DEPENDS
138+
libc.include.sys_mman
139+
libc.include.sys_stat
140+
libc.src.unistd.sysconf
141+
libc.test.UnitTest.ErrnoSetterMatcher
142+
libc.src.sys.mman.remap_file_pages
143+
libc.src.errno.errno
144+
libc.src.sys.mman.mmap
145+
libc.src.sys.mman.munmap
146+
)
147+
131148
add_libc_unittest(
132149
shm_test
133150
SUITE
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
//===-- Unittests for remap_file_pages ------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/errno/libc_errno.h"
10+
#include "src/fcntl/open.h"
11+
#include "src/sys/mman/mmap.h"
12+
#include "src/sys/mman/munmap.h"
13+
#include "src/sys/mman/remap_file_pages.h"
14+
#include "src/unistd/close.h"
15+
#include "src/unistd/sysconf.h"
16+
#include "test/UnitTest/ErrnoSetterMatcher.h"
17+
#include "test/UnitTest/Test.h"
18+
19+
#include <sys/mman.h>
20+
#include <sys/stat.h> // For S_IRWXU
21+
22+
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
23+
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
24+
25+
TEST(LlvmLibcRemapFilePagesTest, NoError) {
26+
size_t page_size = sysconf(_SC_PAGE_SIZE);
27+
ASSERT_GT(page_size, size_t(0));
28+
29+
// Create a file-backed mapping
30+
constexpr const char *file_name = "remap_file_pages.test.noerror";
31+
auto test_file = libc_make_test_file_path(file_name);
32+
int fd = LIBC_NAMESPACE::open(test_file, O_RDWR | O_CREAT, S_IRWXU);
33+
ASSERT_GT(fd, 0);
34+
35+
// First, allocate some memory using mmap
36+
size_t alloc_size = 2 * page_size;
37+
LIBC_NAMESPACE::libc_errno = 0;
38+
void *addr = LIBC_NAMESPACE::mmap(nullptr, alloc_size, PROT_READ | PROT_WRITE,
39+
MAP_SHARED, fd, 0);
40+
ASSERT_ERRNO_SUCCESS();
41+
EXPECT_NE(addr, MAP_FAILED);
42+
43+
// Now try to remap the pages
44+
EXPECT_THAT(LIBC_NAMESPACE::remap_file_pages(addr, page_size, 0, 1, 0),
45+
Succeeds());
46+
47+
// Reset error number for the new function
48+
LIBC_NAMESPACE::libc_errno = 0;
49+
50+
// Clean up
51+
EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, alloc_size), Succeeds());
52+
EXPECT_THAT(LIBC_NAMESPACE::close(fd), Succeeds());
53+
}
54+
55+
TEST(LlvmLibcRemapFilePagesTest, ErrorInvalidFlags) {
56+
size_t page_size = sysconf(_SC_PAGE_SIZE);
57+
ASSERT_GT(page_size, size_t(0));
58+
59+
// Create a file-backed mapping
60+
constexpr const char *file_name = "remap_file_pages.test.error";
61+
auto test_file = libc_make_test_file_path(file_name);
62+
int fd = LIBC_NAMESPACE::open(test_file, O_RDWR | O_CREAT, S_IRWXU);
63+
ASSERT_GT(fd, 0);
64+
65+
// First, allocate some memory using mmap
66+
size_t alloc_size = 2 * page_size;
67+
LIBC_NAMESPACE::libc_errno = 0;
68+
void *addr = LIBC_NAMESPACE::mmap(nullptr, alloc_size, PROT_READ | PROT_WRITE,
69+
MAP_SHARED, fd, 0);
70+
ASSERT_ERRNO_SUCCESS();
71+
EXPECT_NE(addr, MAP_FAILED);
72+
73+
// Try to remap pages with an invalid flag MAP_PRIVATE
74+
EXPECT_THAT(LIBC_NAMESPACE::remap_file_pages(addr, page_size, PROT_READ, 0,
75+
MAP_PRIVATE),
76+
Fails(EINVAL));
77+
78+
// Clean up
79+
EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds());
80+
EXPECT_THAT(LIBC_NAMESPACE::close(fd), Succeeds());
81+
}
82+
83+
TEST(LlvmLibcRemapFilePagesTest, ErrorInvalidAddress) {
84+
size_t page_size = sysconf(_SC_PAGESIZE);
85+
ASSERT_GT(page_size, size_t(0));
86+
87+
// Use an address that we haven't mapped
88+
void *invalid_addr = reinterpret_cast<void *>(0x12345000);
89+
90+
EXPECT_THAT(LIBC_NAMESPACE::remap_file_pages(invalid_addr, page_size,
91+
PROT_READ, 0, 0),
92+
Fails(EINVAL));
93+
}

0 commit comments

Comments
 (0)