Skip to content

[libc][mman] Implement msync #84700

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

Merged
merged 2 commits into from
Mar 10, 2024
Merged

Conversation

SchrodingerZhu
Copy link
Contributor

@SchrodingerZhu SchrodingerZhu self-assigned this Mar 10, 2024
@llvmbot llvmbot added the libc label Mar 10, 2024
@SchrodingerZhu SchrodingerZhu requested a review from lntue March 10, 2024 22:40
@llvmbot
Copy link
Member

llvmbot commented Mar 10, 2024

@llvm/pr-subscribers-libc

Author: Schrodinger ZHU Yifan (SchrodingerZhu)

Changes

Implement msync as specified in:

  1. https://www.man7.org/linux/man-pages/man2/msync.2.html
  2. https://pubs.opengroup.org/onlinepubs/9699919799/

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

10 Files Affected:

  • (modified) libc/config/linux/aarch64/entrypoints.txt (+1)
  • (modified) libc/config/linux/riscv/entrypoints.txt (+1)
  • (modified) libc/config/linux/x86_64/entrypoints.txt (+1)
  • (modified) libc/spec/posix.td (+5)
  • (modified) libc/src/sys/mman/CMakeLists.txt (+7)
  • (modified) libc/src/sys/mman/linux/CMakeLists.txt (+13)
  • (added) libc/src/sys/mman/linux/msync.cpp (+25)
  • (added) libc/src/sys/mman/msync.h (+21)
  • (modified) libc/test/src/sys/mman/linux/CMakeLists.txt (+20)
  • (added) libc/test/src/sys/mman/linux/msync_test.cpp (+69)
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index c24703840183af..b447b5dfe0989e 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -185,6 +185,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.mman.munlock
     libc.src.sys.mman.mlockall
     libc.src.sys.mman.munlockall
+    libc.src.sys.mman.msync
 
     # 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 f7a65615115f34..5175b14adf2e74 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -190,6 +190,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.mman.munlock
     libc.src.sys.mman.mlockall
     libc.src.sys.mman.munlockall
+    libc.src.sys.mman.msync
 
     # 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 b51227e5f25d74..b8bec14a3d2a6d 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -228,6 +228,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.mman.munlock
     libc.src.sys.mman.mlockall
     libc.src.sys.mman.munlockall
+    libc.src.sys.mman.msync
 
     # sys/random.h entrypoints
     libc.src.sys.random.getrandom
diff --git a/libc/spec/posix.td b/libc/spec/posix.td
index 70be692e208a88..d0f5a4584dd45b 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -309,6 +309,11 @@ def POSIX : StandardSpec<"POSIX"> {
           RetValSpec<IntType>,
           [ArgSpec<VoidType>]
         >,
+        FunctionSpec<
+          "msync",
+          RetValSpec<IntType>,
+          [ArgSpec<VoidPtr>, ArgSpec<SizeTType>, ArgSpec<IntType>]
+        >,
       ]
   >;
 
diff --git a/libc/src/sys/mman/CMakeLists.txt b/libc/src/sys/mman/CMakeLists.txt
index f11f5ac9df9f2f..b49f73873c2006 100644
--- a/libc/src/sys/mman/CMakeLists.txt
+++ b/libc/src/sys/mman/CMakeLists.txt
@@ -78,3 +78,10 @@ add_entrypoint_object(
   DEPENDS
     .${LIBC_TARGET_OS}.munlockall
 )
+
+add_entrypoint_object(
+  msync
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.msync
+)
diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt
index a6feff1f0bec19..04086ee5d33254 100644
--- a/libc/src/sys/mman/linux/CMakeLists.txt
+++ b/libc/src/sys/mman/linux/CMakeLists.txt
@@ -139,3 +139,16 @@ add_entrypoint_object(
     libc.src.__support.OSUtil.osutil
     libc.src.errno.errno
 )
+
+add_entrypoint_object(
+  msync
+  SRCS
+    msync.cpp
+  HDRS
+    ../msync.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/msync.cpp b/libc/src/sys/mman/linux/msync.cpp
new file mode 100644
index 00000000000000..1d2544f023c2c0
--- /dev/null
+++ b/libc/src/sys/mman/linux/msync.cpp
@@ -0,0 +1,25 @@
+//===---------- Linux implementation of the msync 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/msync.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, msync, (void *addr, size_t len, int flags)) {
+  long ret = syscall_impl(SYS_msync, cpp::bit_cast<long>(addr), len, flags);
+  if (ret < 0) {
+    libc_errno = static_cast<int>(-ret);
+    return -1;
+  }
+  return 0;
+}
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/mman/msync.h b/libc/src/sys/mman/msync.h
new file mode 100644
index 00000000000000..08afdd8c062857
--- /dev/null
+++ b/libc/src/sys/mman/msync.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for msync 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_MSYNC_H
+#define LLVM_LIBC_SRC_SYS_MMAN_MSYNC_H
+
+#include <sys/mman.h>
+#include <sys/syscall.h>
+
+namespace LIBC_NAMESPACE {
+
+int msync(void *addr, size_t len, int flags);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_MMAN_MSYNC_H
diff --git a/libc/test/src/sys/mman/linux/CMakeLists.txt b/libc/test/src/sys/mman/linux/CMakeLists.txt
index 09ab5b09be6403..6f7fc34d8d3ce3 100644
--- a/libc/test/src/sys/mman/linux/CMakeLists.txt
+++ b/libc/test/src/sys/mman/linux/CMakeLists.txt
@@ -107,3 +107,23 @@ add_libc_unittest(
     libc.src.unistd.sysconf
     libc.test.UnitTest.ErrnoSetterMatcher
 )
+
+add_libc_unittest(
+  msync_test
+  SUITE
+    libc_sys_mman_unittests
+  SRCS
+    msync_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.msync
+    libc.src.sys.mman.mincore
+    libc.src.sys.mman.mlock
+    libc.src.sys.mman.munlock
+    libc.src.unistd.sysconf
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
diff --git a/libc/test/src/sys/mman/linux/msync_test.cpp b/libc/test/src/sys/mman/linux/msync_test.cpp
new file mode 100644
index 00000000000000..cb334f84eaaf4d
--- /dev/null
+++ b/libc/test/src/sys/mman/linux/msync_test.cpp
@@ -0,0 +1,69 @@
+//===-- Unittests for msync -----------------------------------------------===//
+//
+// 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/mmap.h"
+#include "src/sys/mman/msync.h"
+#include "src/sys/mman/munlock.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"
+
+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(LlvmLibcMsyncTest, UnMappedMemory) {
+  EXPECT_THAT(LIBC_NAMESPACE::msync(nullptr, 1024, MS_SYNC), Fails(ENOMEM));
+  EXPECT_THAT(LIBC_NAMESPACE::msync(nullptr, 1024, MS_ASYNC), Fails(ENOMEM));
+}
+
+TEST(LlvmLibcMsyncTest, LockedPage) {
+  PageHolder page;
+  EXPECT_TRUE(page.is_valid());
+  EXPECT_THAT(LIBC_NAMESPACE::mlock(page.addr, page.size), Succeeds());
+  EXPECT_THAT(
+      LIBC_NAMESPACE::msync(page.addr, page.size, MS_SYNC | MS_INVALIDATE),
+      Fails(EBUSY));
+  EXPECT_THAT(LIBC_NAMESPACE::munlock(page.addr, page.size), Succeeds());
+  EXPECT_THAT(LIBC_NAMESPACE::msync(page.addr, page.size, MS_SYNC), Succeeds());
+}
+
+TEST(LlvmLibcMsyncTest, UnalignedAddress) {
+  PageHolder page;
+  EXPECT_TRUE(page.is_valid());
+  EXPECT_THAT(LIBC_NAMESPACE::msync(&page[1], page.size - 1, MS_SYNC),
+              Fails(EINVAL));
+}
+
+TEST(LlvmLibcMsyncTest, InvalidFlag) {
+  PageHolder page;
+  EXPECT_TRUE(page.is_valid());
+  EXPECT_THAT(LIBC_NAMESPACE::msync(page.addr, page.size, MS_SYNC | MS_ASYNC),
+              Fails(EINVAL));
+  EXPECT_THAT(LIBC_NAMESPACE::msync(page.addr, page.size, -1), Fails(EINVAL));
+}

Copy link
Contributor

@lntue lntue left a comment

Choose a reason for hiding this comment

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

LGTM with some nits on the test.

@lntue lntue changed the title [libc][mman] implement msync [libc][mman] Implement msync. Mar 10, 2024
@SchrodingerZhu
Copy link
Contributor Author

nice catch. updated the tests accordingly

@SchrodingerZhu SchrodingerZhu changed the title [libc][mman] Implement msync. [libc][mman] Implement msync Mar 10, 2024
@SchrodingerZhu SchrodingerZhu merged commit fe1645e into llvm:main Mar 10, 2024
@SchrodingerZhu SchrodingerZhu deleted the libc/msync branch March 10, 2024 23:01
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.

3 participants