Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc] implement mlock/mlock2/munlock/mlockall/munlockall #79645

Merged
merged 9 commits into from
Jan 30, 2024

Conversation

SchrodingerZhu
Copy link
Contributor

@SchrodingerZhu SchrodingerZhu commented Jan 26, 2024

fixes #79336

@SchrodingerZhu SchrodingerZhu force-pushed the libc/mlock branch 2 times, most recently from 8167dbc to 8d09876 Compare January 29, 2024 15:17
@SchrodingerZhu SchrodingerZhu marked this pull request as ready for review January 29, 2024 17:09
@llvmbot llvmbot added the libc label Jan 29, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Jan 29, 2024

@llvm/pr-subscribers-libc

Author: Schrodinger ZHU Yifan (SchrodingerZhu)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/79645.diff

18 Files Affected:

  • (modified) libc/config/linux/aarch64/entrypoints.txt (+4)
  • (modified) libc/config/linux/riscv/entrypoints.txt (+4)
  • (modified) libc/config/linux/x86_64/entrypoints.txt (+4)
  • (modified) libc/spec/linux.td (+9)
  • (modified) libc/spec/posix.td (+20)
  • (modified) libc/src/sys/mman/CMakeLists.txt (+28)
  • (modified) libc/src/sys/mman/linux/CMakeLists.txt (+52)
  • (added) libc/src/sys/mman/linux/mlock.cpp (+37)
  • (added) libc/src/sys/mman/linux/mlockall.cpp (+27)
  • (added) libc/src/sys/mman/linux/munlock.cpp (+27)
  • (added) libc/src/sys/mman/linux/munlockall.cpp (+27)
  • (added) libc/src/sys/mman/mlock.h (+25)
  • (added) libc/src/sys/mman/mlockall.h (+20)
  • (added) libc/src/sys/mman/munlock.h (+20)
  • (added) libc/src/sys/mman/munlockall.h (+20)
  • (modified) libc/test/src/sys/mman/linux/CMakeLists.txt (+24)
  • (modified) libc/test/src/sys/mman/linux/mincore_test.cpp (+4-7)
  • (added) libc/test/src/sys/mman/linux/mlock_test.cpp (+131)
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 52f1d2bce34f4c4..ad302dbd8c69da0 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -137,6 +137,10 @@ 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.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 a257f3f8d64ab98..60f34032f12feee 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -143,6 +143,10 @@ 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.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 3812d9586121e7d..64b146ad5f30bb8 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -143,6 +143,10 @@ 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.munlock
+    libc.src.sys.mman.mlockall
+    libc.src.sys.mman.munlockall
 
     # sys/random.h entrypoints
     libc.src.sys.random.getrandom
diff --git a/libc/spec/linux.td b/libc/spec/linux.td
index eab0a987b920cd9..0cb8b7f8bf5251b 100644
--- a/libc/spec/linux.td
+++ b/libc/spec/linux.td
@@ -89,6 +89,15 @@ def Linux : StandardSpec<"Linux"> {
               ArgSpec<UnsignedCharPtr>,
             ]
         >,
+        FunctionSpec<
+          "mlock2",
+          RetValSpec<IntType>,
+          [
+            ArgSpec<VoidPtr>,
+            ArgSpec<SizeTType>,
+            ArgSpec<UnsignedIntType>,
+          ]
+        >,
       ]  // Functions
   >;
 
diff --git a/libc/spec/posix.td b/libc/spec/posix.td
index 7e1cf892135acf9..40a663afd2595ca 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -289,6 +289,26 @@ def POSIX : StandardSpec<"POSIX"> {
              ArgSpec<SizeTType>,
              ArgSpec<IntType>]
         >,
+        FunctionSpec<
+          "mlock",
+          RetValSpec<IntType>,
+          [ArgSpec<VoidPtr>, ArgSpec<SizeTType>]
+        >,
+        FunctionSpec<
+          "munlock",
+          RetValSpec<IntType>,
+          [ArgSpec<VoidPtr>, ArgSpec<SizeTType>]
+        >,
+        FunctionSpec<
+          "mlockall",
+          RetValSpec<IntType>,
+          [ArgSpec<IntType>]
+        >,
+        FunctionSpec<
+          "munlockall",
+          RetValSpec<IntType>,
+          [ArgSpec<VoidType>]
+        >,
       ]
   >;
 
diff --git a/libc/src/sys/mman/CMakeLists.txt b/libc/src/sys/mman/CMakeLists.txt
index 2d17429a26b457b..5529157d05f99a3 100644
--- a/libc/src/sys/mman/CMakeLists.txt
+++ b/libc/src/sys/mman/CMakeLists.txt
@@ -43,3 +43,31 @@ add_entrypoint_object(
   DEPENDS
     .${LIBC_TARGET_OS}.mincore
 )
+
+add_entrypoint_object(
+  mlock
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.mlock
+)
+
+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 ce0cda7f2227708..5649b362c902d89 100644
--- a/libc/src/sys/mman/linux/CMakeLists.txt
+++ b/libc/src/sys/mman/linux/CMakeLists.txt
@@ -74,3 +74,55 @@ 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(
+  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 000000000000000..d81b19e9a3935e5
--- /dev/null
+++ b/libc/src/sys/mman/linux/mlock.cpp
@@ -0,0 +1,37 @@
+//===---------- 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 <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, mlock, (const void *addr, size_t len)) {
+  long ret = syscall_impl(SYS_mlock, cpp::bit_cast<long>(addr), len);
+  if (ret < 0) {
+    libc_errno = static_cast<int>(-ret);
+    return -1;
+  }
+  return 0;
+}
+
+#ifdef SYS_mlock2
+LLVM_LIBC_FUNCTION(int, mlock2, (const void *addr, size_t len, int flags)) {
+  long ret = syscall_impl(SYS_mlock2, cpp::bit_cast<long>(addr), len, flags);
+  if (ret < 0) {
+    libc_errno = static_cast<int>(-ret);
+    return -1;
+  }
+  return 0;
+}
+#endif
+} // 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 000000000000000..c4af7d8952738ee
--- /dev/null
+++ b/libc/src/sys/mman/linux/mlockall.cpp
@@ -0,0 +1,27 @@
+//===---------- 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 <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, mlockall, (int flags)) {
+  long ret = syscall_impl(SYS_mlockall, flags);
+  if (ret < 0) {
+    libc_errno = static_cast<int>(-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 000000000000000..9ee50805ac30ed7
--- /dev/null
+++ b/libc/src/sys/mman/linux/munlock.cpp
@@ -0,0 +1,27 @@
+//===---------- 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 <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, munlock, (const void *addr, size_t len)) {
+  long ret = syscall_impl(SYS_munlock, cpp::bit_cast<long>(addr), len);
+  if (ret < 0) {
+    libc_errno = static_cast<int>(-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 000000000000000..d1619d204a90d93
--- /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 <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, munlockall, (void)) {
+  long ret = syscall_impl(SYS_munlockall);
+  if (ret < 0) {
+    libc_errno = static_cast<int>(-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 000000000000000..f4861560171a35f
--- /dev/null
+++ b/libc/src/sys/mman/mlock.h
@@ -0,0 +1,25 @@
+//===-- 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 <sys/mman.h>
+#include <sys/syscall.h>
+
+namespace LIBC_NAMESPACE {
+
+int mlock(const void *addr, size_t len);
+
+#ifdef SYS_mlock2
+int mlock2(const void *addr, size_t len, int flags);
+#endif
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_MMAN_MLOCK_H
diff --git a/libc/src/sys/mman/mlockall.h b/libc/src/sys/mman/mlockall.h
new file mode 100644
index 000000000000000..bb4bd834310ee98
--- /dev/null
+++ b/libc/src/sys/mman/mlockall.h
@@ -0,0 +1,20 @@
+//===-- 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
+
+#include <sys/mman.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 000000000000000..6aca82dae4533b9
--- /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 <sys/mman.h>
+
+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 000000000000000..5abd4b873465e30
--- /dev/null
+++ b/libc/src/sys/mman/munlockall.h
@@ -0,0 +1,20 @@
+//===-- 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
+
+#include <sys/mman.h>
+
+namespace LIBC_NAMESPACE {
+
+int munlockall(void);
+
+} // 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 36557695e503c4c..64de25320c5211a 100644
--- a/libc/test/src/sys/mman/linux/CMakeLists.txt
+++ b/libc/test/src/sys/mman/linux/CMakeLists.txt
@@ -77,6 +77,30 @@ add_libc_unittest(
     libc.src.sys.mman.munmap
     libc.src.sys.mman.madvise
     libc.src.sys.mman.mincore
+    libc.src.sys.mman.mlock
+    libc.src.sys.mman.munlock
+    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.include.unistd
+    libc.src.errno.errno
+    libc.src.sys.mman.mmap
+    libc.src.sys.mman.munmap
+    libc.src.sys.mman.madvise
+    libc.src.sys.mman.mincore
+    libc.src.sys.mman.mlock
+    libc.src.sys.mman.munlock
+    libc.src.sys.mman.mlockall
+    libc.src.sys.mman.munlockall
     libc.src.unistd.sysconf
     libc.test.UnitTest.ErrnoSetterMatcher
 )
diff --git a/libc/test/src/sys/mman/linux/mincore_test.cpp b/libc/test/src/sys/mman/linux/mincore_test.cpp
index 493d748f2c98e65..2814694849fc60e 100644
--- a/libc/test/src/sys/mman/linux/mincore_test.cpp
+++ b/libc/test/src/sys/mman/linux/mincore_test.cpp
@@ -10,7 +10,9 @@
 #include "src/errno/libc_errno.h"
 #include "src/sys/mman/madvise.h"
 #include "src/sys/mman/mincore.h"
+#include "src/sys/mman/mlock.h"
 #include "src/sys/mman/mmap.h"
+#include "src/sys/mman/munlock.h"
 #include "src/sys/mman/munmap.h"
 #include "src/unistd/sysconf.h"
 #include "test/UnitTest/ErrnoSetterMatcher.h"
@@ -91,16 +93,11 @@ TEST(LlvmLibcMincoreTest, PageOut) {
   // touch the page
   {
     static_cast<char *>(addr)[0] = 0;
-    // TODO: use wrapper functions for mlock/munlock once implemented.
-    // See issue https://github.com/llvm/llvm-project/issues/79336
-    LIBC_NAMESPACE::syscall_impl(
-        SYS_mlock, reinterpret_cast<unsigned long>(addr), page_size);
-    libc_errno = 0;
+    EXPECT_THAT(LIBC_NAMESPACE::mlock(addr, page_size), Succeeds());
     int res = LIBC_NAMESPACE::mincore(addr, 1, &vec);
     EXPECT_EQ(vec & 1u, 1u);
     EXPECT_THAT(res, Succeeds());
-    LIBC_NAMESPACE::syscall_impl(
-        SYS_munlock, reinterpret_cast<unsigned long>(addr), page_size);
+    EXPECT_THAT(LIBC_NAMESPACE::munlock(addr, page_size), Succeeds());
   }
 
   // page out the memory
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 000000000000000..eec8446d9ce3f1d
--- /dev/null
+++ b/libc/test/src/sys/mman/linux/mlock_test.cpp
@@ -0,0 +1,131 @@
+//===-- 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/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/errno/libc_errno.h"
+#include "src/sys/mman/madvise.h"
+#include "src/sys/mman/mincore.h"
+#include "src/sys/mman/mlock.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 "src/unistd/sysconf.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/LibcTest.h"
+#include "test/UnitTest/Test.h"
+
+#include <asm-generic/errno-base.h>
+#include <asm-generic/mman.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
+
+struct PageHolder {
+  size_t size;
+  void *addr;
+
+  PageHolder()
+      : size(LIBC_NAMESPACE::sysconf(_SC_PAGESIZE)),
+        addr(LIBC_NAMESPACE::mmap(nullptr, size, PROT_READ | PROT_WRITE,
+                                  MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)) {}
+  ~PageHolder() {
+    if (addr != MAP_FAILED)
+      LIBC_NAMESPACE::munmap(addr, size);
+  }
+
+  char &operator[](size_t i) { return reinterpret_cast<char *>(addr)[i]; }
+
+  bool is_valid() { return addr != MAP_FAILED; }
+};
+
+TEST(LlvmLibcMlockTest, UnMappedMemory) {
+  EXPECT_THAT(LIBC_NAMESPACE::mlock(nullptr, 1024), Fails(ENOMEM));
+  EXPECT_THAT(LIBC_NAMESPACE::munlock(nullptr, 1024), Fails(ENOMEM));
+}
+
+TEST(LlvmLibcMlockTest, Overflow) {
+  PageHolder holder;
+  EXPECT_TRUE(holder.is_valid());
+  EXPECT_THAT(LIBC_NAMESPACE::mlock(holder.addr, -holder.size), Fails(EINVAL));
+  EXPECT_THAT(LIBC_NAMESPACE::munlock(holder.addr, -holder.size),
+              Fails(EINVAL));
+}
+
+#ifdef SYS_mlock2
+TEST(LlvmLibcMlockTest, MLock2) {
+  PageHolder holder;
+  EXPECT_TRUE(holder.is_valid());
+  EXPECT_THAT(LIBC_NAMESPACE::madvise(holder.addr, holder.size, MADV_DONTNEED),
+              Succeeds());
+  EXPECT_THAT(LIBC_NAMESPACE::mlock2(holder.addr, holder.size, 0), Succeeds());
+  unsigned char vec;
+  EXPECT_THAT(LIBC_NAMESPACE::mincore(holder.addr, holder.size, &vec),
+              Succeeds());
+  EXPECT_EQ(vec & 1, 1);
+  EXPECT_THAT(LIBC_NAMESPACE::munlock(holder.addr, holder.size), Succeeds());
+  EXPECT_THAT(LIBC_NAMESPACE::madvise(holder.addr, holder.size, MADV_DONTNEED),
+              Succeeds());
+  EXPECT_THAT(LIBC_NAMESPACE::mlock2(holder.addr, holder.size, MLOCK_ONFAULT),
+              Succeeds());
+  EXPECT_THAT(LIBC_NAMESPACE::mincore(holder.addr, holder.size, &vec),
+              Succeeds());
+  EXPECT_EQ(vec & 1, 0);
+  holder[0] = 1;
+  EXPECT_THAT(LIBC_NAMESPACE::mincore(holder.addr, holder.size, &vec),
+              Succeeds());
+  EXPECT_EQ(vec & 1, 1);
+  EXPECT_THAT(LIBC_NAMESPACE::munlock(holder.addr, holder.size), Succeeds());
+}
+#endif
+
+TEST(LlvmLibcMlockTest, MLockAll) {
+  {
+    PageHolder holder;
+    EXPECT_TRUE(holder.is_valid());
+    EXPECT_THAT(
+        LIBC_NAMESPACE::madvise(holder.addr, holder.size, MADV_DONTNEED),
+        Succeeds());
+    EXPECT_THAT(LIBC_NAMESPACE::mlockall(MCL_CURRENT), Succeeds());
+    unsigned char vec;
+    EXPECT_THAT(LIBC_NAMESPACE::mincore(holder.addr, holder.size, &vec),
+                Succeeds());
+    EXPECT_EQ(vec & 1, 1);
+    EXPECT_THAT(LIBC_NAMESPACE::munlockall(), Succeeds());
+  }
+  {
+    EXPECT_THAT(LIBC_NAMESPACE::mlockall(MCL_FUTURE), Succeeds());
+    PageHolder holder;
+    EXPECT_TRUE(holder.is_valid());
+    unsigned char vec;
+    EXPECT_THAT(LIBC_NAMESPACE::mincore(holder.addr, holder.size, &vec),
+                Succeeds());
+    EXPECT_EQ(vec & 1, 1);
+    EXPECT_THAT(LIBC_NAMESPACE::munlockall(), Succeeds());
+  }
+#ifdef MCL_ONFAULT
+  {
+    EXPECT_THAT(LIBC_NAMESPACE::mlockall(MCL_FUTURE | MCL_ONFAULT), Succeeds());
+    PageHolder holder;
+    EXPECT_TRUE(holder.is_valid());
+    unsigned char vec;
+    EXPECT_THAT(LIBC_NAMESPACE::mincore(holder.addr, holder.size, &vec),
+                Succeeds());
+    EXPECT_EQ(vec & 1, 0);
+    holder[0] = 1;
+    EXPECT_THAT(LIBC_NAMESPACE::mincore(holder.addr, holder.size, &vec),
+                Succeeds());
+    EXPECT_EQ(vec & 1, 1);
+    EXPECT_THAT(LIBC_NAMESPACE::munlockall(), Succeeds());
+  }
+#endif
+}

@SchrodingerZhu
Copy link
Contributor Author

@nickdesaulniers putting mlock2 inside mlock does not work as the header would not be generated properly. I will separate them.

libc/test/src/sys/mman/linux/mlock_test.cpp Show resolved Hide resolved
libc/test/src/sys/mman/linux/mlock_test.cpp Outdated Show resolved Hide resolved
libc/test/src/sys/mman/linux/mlock_test.cpp Outdated Show resolved Hide resolved
libc/test/src/sys/mman/linux/mlock_test.cpp Outdated Show resolved Hide resolved
libc/test/src/sys/mman/linux/mlock_test.cpp Outdated Show resolved Hide resolved
Co-authored-by: Sirui Mu <msrlancern@gmail.com>
@SchrodingerZhu
Copy link
Contributor Author

I will merge this since the absorbed test is relatively simple.

@SchrodingerZhu SchrodingerZhu merged commit 2492321 into llvm:main Jan 30, 2024
4 checks passed

// Invalid mlockall flags.
EXPECT_THAT(LIBC_NAMESPACE::mlockall(1234), Fails(EINVAL));
EXPECT_THAT(LIBC_NAMESPACE::mlockall(MCL_ONFAULT), Fails(EINVAL));
Copy link
Member

Choose a reason for hiding this comment

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

This is failing in post submit. PTAL

Copy link
Member

Choose a reason for hiding this comment

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[libc] implement mlock/munlock
3 participants