diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 52f1d2bce34f4..ffb79aa4a252e 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -137,6 +137,11 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.sys.mman.munmap libc.src.sys.mman.posix_madvise libc.src.sys.mman.mincore + libc.src.sys.mman.mlock + libc.src.sys.mman.mlock2 + libc.src.sys.mman.munlock + libc.src.sys.mman.mlockall + libc.src.sys.mman.munlockall # sys/random.h entrypoints libc.src.sys.random.getrandom diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index a257f3f8d64ab..c9adc8852cb92 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -143,6 +143,11 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.sys.mman.munmap libc.src.sys.mman.posix_madvise libc.src.sys.mman.mincore + libc.src.sys.mman.mlock + libc.src.sys.mman.mlock2 + libc.src.sys.mman.munlock + libc.src.sys.mman.mlockall + libc.src.sys.mman.munlockall # sys/random.h entrypoints libc.src.sys.random.getrandom diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 3812d9586121e..9b3b134ef00ef 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -143,6 +143,11 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.sys.mman.munmap libc.src.sys.mman.posix_madvise libc.src.sys.mman.mincore + libc.src.sys.mman.mlock + libc.src.sys.mman.mlock2 + libc.src.sys.mman.munlock + libc.src.sys.mman.mlockall + libc.src.sys.mman.munlockall # sys/random.h entrypoints libc.src.sys.random.getrandom diff --git a/libc/src/sys/mman/CMakeLists.txt b/libc/src/sys/mman/CMakeLists.txt index 2d17429a26b45..f11f5ac9df9f2 100644 --- a/libc/src/sys/mman/CMakeLists.txt +++ b/libc/src/sys/mman/CMakeLists.txt @@ -43,3 +43,38 @@ add_entrypoint_object( DEPENDS .${LIBC_TARGET_OS}.mincore ) + +add_entrypoint_object( + mlock + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.mlock +) + +add_entrypoint_object( + mlock2 + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.mlock2 +) + +add_entrypoint_object( + munlock + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.munlock +) + +add_entrypoint_object( + mlockall + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.mlockall +) + +add_entrypoint_object( + munlockall + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.munlockall +) diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt index ce0cda7f22277..a6feff1f0bec1 100644 --- a/libc/src/sys/mman/linux/CMakeLists.txt +++ b/libc/src/sys/mman/linux/CMakeLists.txt @@ -74,3 +74,68 @@ add_entrypoint_object( libc.src.__support.OSUtil.osutil libc.src.errno.errno ) + +add_entrypoint_object( + mlock + SRCS + mlock.cpp + HDRS + ../mlock.h + DEPENDS + libc.include.sys_mman + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) + +add_entrypoint_object( + mlock2 + SRCS + mlock2.cpp + HDRS + ../mlock2.h + DEPENDS + libc.include.sys_mman + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) + +add_entrypoint_object( + munlock + SRCS + munlock.cpp + HDRS + ../munlock.h + DEPENDS + libc.include.sys_mman + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) + +add_entrypoint_object( + mlockall + SRCS + mlockall.cpp + HDRS + ../mlockall.h + DEPENDS + libc.include.sys_mman + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) + +add_entrypoint_object( + munlockall + SRCS + munlockall.cpp + HDRS + ../munlockall.h + DEPENDS + libc.include.sys_mman + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) diff --git a/libc/src/sys/mman/linux/mlock.cpp b/libc/src/sys/mman/linux/mlock.cpp new file mode 100644 index 0000000000000..61ceedfcdd16d --- /dev/null +++ b/libc/src/sys/mman/linux/mlock.cpp @@ -0,0 +1,28 @@ +//===------------- Linux implementation of the mlock 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/mlock.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. + +#include "src/errno/libc_errno.h" +#include // For syscall numbers. + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, mlock, (const void *addr, size_t len)) { + long ret = LIBC_NAMESPACE::syscall_impl(SYS_mlock, + reinterpret_cast(addr), len); + if (ret < 0) { + libc_errno = static_cast(-ret); + return -1; + } + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/sys/mman/linux/mlock2.cpp b/libc/src/sys/mman/linux/mlock2.cpp new file mode 100644 index 0000000000000..1aa29970c2076 --- /dev/null +++ b/libc/src/sys/mman/linux/mlock2.cpp @@ -0,0 +1,29 @@ +//===------------- Linux implementation of the mlock2 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/mlock2.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. + +#include "src/errno/libc_errno.h" +#include // For syscall numbers. + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, mlock2, + (const void *addr, size_t len, unsigned int flags)) { + long ret = LIBC_NAMESPACE::syscall_impl( + SYS_mlock2, reinterpret_cast(addr), len, static_cast(flags)); + if (ret < 0) { + libc_errno = static_cast(-ret); + return -1; + } + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/sys/mman/linux/mlockall.cpp b/libc/src/sys/mman/linux/mlockall.cpp new file mode 100644 index 0000000000000..0de7896986c7b --- /dev/null +++ b/libc/src/sys/mman/linux/mlockall.cpp @@ -0,0 +1,28 @@ +//===------------ Linux implementation of the mlockall 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/mlockall.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. + +#include "src/errno/libc_errno.h" +#include // For syscall numbers. + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, mlockall, (int flags)) { + long ret = + LIBC_NAMESPACE::syscall_impl(SYS_mlockall, static_cast(flags)); + if (ret < 0) { + libc_errno = static_cast(-ret); + return -1; + } + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/sys/mman/linux/munlock.cpp b/libc/src/sys/mman/linux/munlock.cpp new file mode 100644 index 0000000000000..e6845d37d4e53 --- /dev/null +++ b/libc/src/sys/mman/linux/munlock.cpp @@ -0,0 +1,28 @@ +//===------------ Linux implementation of the munlock 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/munlock.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. + +#include "src/errno/libc_errno.h" +#include // For syscall numbers. + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, munlock, (const void *addr, size_t len)) { + long ret = LIBC_NAMESPACE::syscall_impl(SYS_munlock, + reinterpret_cast(addr), len); + if (ret < 0) { + libc_errno = static_cast(-ret); + return -1; + } + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/sys/mman/linux/munlockall.cpp b/libc/src/sys/mman/linux/munlockall.cpp new file mode 100644 index 0000000000000..e34a3e9eeb1e3 --- /dev/null +++ b/libc/src/sys/mman/linux/munlockall.cpp @@ -0,0 +1,27 @@ +//===----------- Linux implementation of the munlockall 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/munlockall.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. + +#include "src/errno/libc_errno.h" +#include // For syscall numbers. + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, munlockall, ()) { + long ret = LIBC_NAMESPACE::syscall_impl(SYS_munlockall); + if (ret < 0) { + libc_errno = static_cast(-ret); + return -1; + } + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/sys/mman/mlock.h b/libc/src/sys/mman/mlock.h new file mode 100644 index 0000000000000..d57c013778743 --- /dev/null +++ b/libc/src/sys/mman/mlock.h @@ -0,0 +1,20 @@ +//===-- Implementation header for mlock 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_MLOCK_H +#define LLVM_LIBC_SRC_SYS_MMAN_MLOCK_H + +#include // For size_t + +namespace LIBC_NAMESPACE { + +int mlock(const void *addr, size_t len); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_SYS_MMAN_MLOCK_H diff --git a/libc/src/sys/mman/mlock2.h b/libc/src/sys/mman/mlock2.h new file mode 100644 index 0000000000000..2069a8f694d77 --- /dev/null +++ b/libc/src/sys/mman/mlock2.h @@ -0,0 +1,20 @@ +//===-- Implementation header for mlock2 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_MLOCK2_H +#define LLVM_LIBC_SRC_SYS_MMAN_MLOCK2_H + +#include // For size_t + +namespace LIBC_NAMESPACE { + +int mlock2(const void *addr, size_t len, unsigned int flags); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_SYS_MMAN_MLOCK2_H diff --git a/libc/src/sys/mman/mlockall.h b/libc/src/sys/mman/mlockall.h new file mode 100644 index 0000000000000..2154658d83d86 --- /dev/null +++ b/libc/src/sys/mman/mlockall.h @@ -0,0 +1,18 @@ +//===-- Implementation header for mlockall 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_MLOCKALL_H +#define LLVM_LIBC_SRC_SYS_MMAN_MLOCKALL_H + +namespace LIBC_NAMESPACE { + +int mlockall(int flags); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_SYS_MMAN_MLOCKALL_H diff --git a/libc/src/sys/mman/munlock.h b/libc/src/sys/mman/munlock.h new file mode 100644 index 0000000000000..2fe01a94af586 --- /dev/null +++ b/libc/src/sys/mman/munlock.h @@ -0,0 +1,20 @@ +//===-- Implementation header for munlock 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_MUNLOCK_H +#define LLVM_LIBC_SRC_SYS_MMAN_MUNLOCK_H + +#include // For size_t + +namespace LIBC_NAMESPACE { + +int munlock(const void *addr, size_t len); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_SYS_MMAN_MUNLOCK_H diff --git a/libc/src/sys/mman/munlockall.h b/libc/src/sys/mman/munlockall.h new file mode 100644 index 0000000000000..4b64ac628456e --- /dev/null +++ b/libc/src/sys/mman/munlockall.h @@ -0,0 +1,18 @@ +//===-- Implementation header for munlockall 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_MUNLOCKALL_H +#define LLVM_LIBC_SRC_SYS_MMAN_MUNLOCKALL_H + +namespace LIBC_NAMESPACE { + +int munlockall(); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_SYS_MMAN_MUNLOCKALL_H diff --git a/libc/test/src/sys/mman/linux/CMakeLists.txt b/libc/test/src/sys/mman/linux/CMakeLists.txt index 36557695e503c..abab03625ad5b 100644 --- a/libc/test/src/sys/mman/linux/CMakeLists.txt +++ b/libc/test/src/sys/mman/linux/CMakeLists.txt @@ -80,3 +80,22 @@ add_libc_unittest( libc.src.unistd.sysconf libc.test.UnitTest.ErrnoSetterMatcher ) + +add_libc_unittest( + mlock_test + SUITE + libc_sys_mman_unittests + SRCS + mlock_test.cpp + DEPENDS + libc.include.sys_mman + libc.src.errno.errno + libc.src.sys.mman.mmap + libc.src.sys.mman.munmap + libc.src.sys.mman.mlock + libc.src.sys.mman.mlock2 + libc.src.sys.mman.munlock + libc.src.sys.mman.mlockall + libc.src.sys.mman.munlockall + libc.test.UnitTest.ErrnoSetterMatcher +) diff --git a/libc/test/src/sys/mman/linux/mlock_test.cpp b/libc/test/src/sys/mman/linux/mlock_test.cpp new file mode 100644 index 0000000000000..76d0a0be418af --- /dev/null +++ b/libc/test/src/sys/mman/linux/mlock_test.cpp @@ -0,0 +1,76 @@ +//===-- Unittests for mlock -----------------------------------------------===// +// +// 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/mlock.h" +#include "src/sys/mman/mlock2.h" +#include "src/sys/mman/mlockall.h" +#include "src/sys/mman/mmap.h" +#include "src/sys/mman/munlock.h" +#include "src/sys/mman/munlockall.h" +#include "src/sys/mman/munmap.h" +#include "test/UnitTest/ErrnoSetterMatcher.h" +#include "test/UnitTest/Test.h" + +#include + +using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; +using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; + +TEST(LlvmLibcMlockTest, NoError) { + size_t alloc_size = 128; + libc_errno = 0; + void *addr = LIBC_NAMESPACE::mmap(nullptr, alloc_size, PROT_READ, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + EXPECT_EQ(0, libc_errno); + EXPECT_NE(addr, MAP_FAILED); + + EXPECT_THAT(LIBC_NAMESPACE::mlock(addr, alloc_size), Succeeds()); + EXPECT_THAT(LIBC_NAMESPACE::munlock(addr, alloc_size), Succeeds()); + + EXPECT_THAT(LIBC_NAMESPACE::mlock2(addr, alloc_size, MLOCK_ONFAULT), + Succeeds()); + EXPECT_THAT(LIBC_NAMESPACE::munlock(addr, alloc_size), Succeeds()); + + EXPECT_THAT(LIBC_NAMESPACE::mlockall(MCL_CURRENT), Succeeds()); + EXPECT_THAT(LIBC_NAMESPACE::munlockall(), Succeeds()); + + EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, alloc_size), Succeeds()); +} + +TEST(LlvmLibcMlockTest, NoMem) { + size_t alloc_size = 4096; // page size + libc_errno = 0; + void *addr = LIBC_NAMESPACE::mmap(nullptr, alloc_size, PROT_READ, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + EXPECT_EQ(0, libc_errno); + EXPECT_NE(addr, MAP_FAILED); + LIBC_NAMESPACE::munmap(addr, alloc_size); + + // addr holds the address of an unmapped page. Calling mlock with such an + // address should get EINVAL. + EXPECT_THAT(LIBC_NAMESPACE::mlock(addr, alloc_size), Fails(ENOMEM)); +} + +TEST(LlvmLibcMlockTest, InvalidFlag) { + size_t alloc_size = 128; // page size + libc_errno = 0; + void *addr = LIBC_NAMESPACE::mmap(nullptr, alloc_size, PROT_READ, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + EXPECT_EQ(0, libc_errno); + EXPECT_NE(addr, MAP_FAILED); + + // Invalid mlock2 flags. + EXPECT_THAT(LIBC_NAMESPACE::mlock2(addr, alloc_size, 1234), Fails(EINVAL)); + + // Invalid mlockall flags. + EXPECT_THAT(LIBC_NAMESPACE::mlockall(1234), Fails(EINVAL)); + EXPECT_THAT(LIBC_NAMESPACE::mlockall(MCL_ONFAULT), Fails(EINVAL)); + + LIBC_NAMESPACE::munmap(addr, alloc_size); +}