Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libc/config/linux/aarch64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/riscv/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions libc/newhdrgen/yaml/sys/mman.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions libc/spec/linux.td
Original file line number Diff line number Diff line change
Expand Up @@ -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
>;

Expand Down
7 changes: 7 additions & 0 deletions libc/src/sys/mman/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions libc/src/sys/mman/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
40 changes: 40 additions & 0 deletions libc/src/sys/mman/linux/remap_file_pages.cpp
Original file line number Diff line number Diff line change
@@ -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
22 changes: 22 additions & 0 deletions libc/src/sys/mman/remap_file_pages.h
Original file line number Diff line number Diff line change
@@ -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
16 changes: 16 additions & 0 deletions libc/test/src/sys/mman/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,22 @@ 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
libc.include.sys_mman
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
Expand Down
93 changes: 93 additions & 0 deletions libc/test/src/sys/mman/linux/remap_file_pages_test.cpp
Original file line number Diff line number Diff line change
@@ -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));
}
Loading