[libc-commits] [libc] [libc] implement mlock/mlock2/munlock/mlockall/munlockall (PR #79645)

Schrodinger ZHU Yifan via libc-commits libc-commits at lists.llvm.org
Mon Jan 29 09:09:40 PST 2024


https://github.com/SchrodingerZhu updated https://github.com/llvm/llvm-project/pull/79645

>From 40e8b2bc5192b8695038ff988d9b99b9d1d8ecf3 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Fri, 26 Jan 2024 15:41:28 -0500
Subject: [PATCH 1/2] [libc] implement mlock/mlock2/munlock/mlockall/munlockall

---
 libc/spec/linux.td |  9 +++++++++
 libc/spec/posix.td | 20 ++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/libc/spec/linux.td b/libc/spec/linux.td
index eab0a987b920cd..0cb8b7f8bf5251 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 7e1cf892135acf..40a663afd2595c 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>]
+        >,
       ]
   >;
 

>From 18a3a8811bc449513683fe7a7f651266a1fad734 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Mon, 29 Jan 2024 12:09:23 -0500
Subject: [PATCH 2/2] add implementations

---
 libc/config/linux/aarch64/entrypoints.txt     |   4 +
 libc/config/linux/riscv/entrypoints.txt       |   4 +
 libc/config/linux/x86_64/entrypoints.txt      |   4 +
 libc/src/sys/mman/CMakeLists.txt              |  28 ++++
 libc/src/sys/mman/linux/CMakeLists.txt        |  52 +++++++
 libc/src/sys/mman/linux/mlock.cpp             |  37 +++++
 libc/src/sys/mman/linux/mlockall.cpp          |  27 ++++
 libc/src/sys/mman/linux/munlock.cpp           |  27 ++++
 libc/src/sys/mman/linux/munlockall.cpp        |  27 ++++
 libc/src/sys/mman/mlock.h                     |  25 ++++
 libc/src/sys/mman/mlockall.h                  |  20 +++
 libc/src/sys/mman/munlock.h                   |  20 +++
 libc/src/sys/mman/munlockall.h                |  20 +++
 libc/test/src/sys/mman/linux/CMakeLists.txt   |  24 ++++
 libc/test/src/sys/mman/linux/mincore_test.cpp |  11 +-
 libc/test/src/sys/mman/linux/mlock_test.cpp   | 131 ++++++++++++++++++
 16 files changed, 454 insertions(+), 7 deletions(-)
 create mode 100644 libc/src/sys/mman/linux/mlock.cpp
 create mode 100644 libc/src/sys/mman/linux/mlockall.cpp
 create mode 100644 libc/src/sys/mman/linux/munlock.cpp
 create mode 100644 libc/src/sys/mman/linux/munlockall.cpp
 create mode 100644 libc/src/sys/mman/mlock.h
 create mode 100644 libc/src/sys/mman/mlockall.h
 create mode 100644 libc/src/sys/mman/munlock.h
 create mode 100644 libc/src/sys/mman/munlockall.h
 create mode 100644 libc/test/src/sys/mman/linux/mlock_test.cpp

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 52f1d2bce34f4c..ad302dbd8c69da 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 a257f3f8d64ab9..60f34032f12fee 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 3812d9586121e7..64b146ad5f30bb 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/src/sys/mman/CMakeLists.txt b/libc/src/sys/mman/CMakeLists.txt
index 2d17429a26b457..5529157d05f99a 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 ce0cda7f222770..5649b362c902d8 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 00000000000000..d81b19e9a3935e
--- /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 00000000000000..c4af7d8952738e
--- /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 00000000000000..9ee50805ac30ed
--- /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 00000000000000..d1619d204a90d9
--- /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 00000000000000..f4861560171a35
--- /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 00000000000000..bb4bd834310ee9
--- /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 00000000000000..6aca82dae4533b
--- /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 00000000000000..5abd4b873465e3
--- /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 36557695e503c4..64de25320c5211 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 493d748f2c98e6..2814694849fc60 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 00000000000000..eec8446d9ce3f1
--- /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
+}



More information about the libc-commits mailing list