Skip to content

Commit fe1645e

Browse files
[libc][mman] Implement msync (#84700)
Implement `msync` as specified in: 1. https://www.man7.org/linux/man-pages/man2/msync.2.html 2. https://pubs.opengroup.org/onlinepubs/9699919799/
1 parent ea697dc commit fe1645e

File tree

10 files changed

+163
-0
lines changed

10 files changed

+163
-0
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ set(TARGET_LIBC_ENTRYPOINTS
185185
libc.src.sys.mman.munlock
186186
libc.src.sys.mman.mlockall
187187
libc.src.sys.mman.munlockall
188+
libc.src.sys.mman.msync
188189

189190
# sys/random.h entrypoints
190191
libc.src.sys.random.getrandom

libc/config/linux/riscv/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ set(TARGET_LIBC_ENTRYPOINTS
190190
libc.src.sys.mman.munlock
191191
libc.src.sys.mman.mlockall
192192
libc.src.sys.mman.munlockall
193+
libc.src.sys.mman.msync
193194

194195
# sys/random.h entrypoints
195196
libc.src.sys.random.getrandom

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ set(TARGET_LIBC_ENTRYPOINTS
228228
libc.src.sys.mman.munlock
229229
libc.src.sys.mman.mlockall
230230
libc.src.sys.mman.munlockall
231+
libc.src.sys.mman.msync
231232

232233
# sys/random.h entrypoints
233234
libc.src.sys.random.getrandom

libc/spec/posix.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,11 @@ def POSIX : StandardSpec<"POSIX"> {
309309
RetValSpec<IntType>,
310310
[ArgSpec<VoidType>]
311311
>,
312+
FunctionSpec<
313+
"msync",
314+
RetValSpec<IntType>,
315+
[ArgSpec<VoidPtr>, ArgSpec<SizeTType>, ArgSpec<IntType>]
316+
>,
312317
]
313318
>;
314319

libc/src/sys/mman/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,10 @@ add_entrypoint_object(
7878
DEPENDS
7979
.${LIBC_TARGET_OS}.munlockall
8080
)
81+
82+
add_entrypoint_object(
83+
msync
84+
ALIAS
85+
DEPENDS
86+
.${LIBC_TARGET_OS}.msync
87+
)

libc/src/sys/mman/linux/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,16 @@ add_entrypoint_object(
139139
libc.src.__support.OSUtil.osutil
140140
libc.src.errno.errno
141141
)
142+
143+
add_entrypoint_object(
144+
msync
145+
SRCS
146+
msync.cpp
147+
HDRS
148+
../msync.h
149+
DEPENDS
150+
libc.include.sys_mman
151+
libc.include.sys_syscall
152+
libc.src.__support.OSUtil.osutil
153+
libc.src.errno.errno
154+
)

libc/src/sys/mman/linux/msync.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//===---------- Linux implementation of the msync function ----------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/sys/mman/msync.h"
10+
11+
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
12+
13+
#include "src/errno/libc_errno.h"
14+
#include <sys/syscall.h> // For syscall numbers.
15+
16+
namespace LIBC_NAMESPACE {
17+
LLVM_LIBC_FUNCTION(int, msync, (void *addr, size_t len, int flags)) {
18+
long ret = syscall_impl(SYS_msync, cpp::bit_cast<long>(addr), len, flags);
19+
if (ret < 0) {
20+
libc_errno = static_cast<int>(-ret);
21+
return -1;
22+
}
23+
return 0;
24+
}
25+
} // namespace LIBC_NAMESPACE

libc/src/sys/mman/msync.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- Implementation header for msync function ----------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_SYS_MMAN_MSYNC_H
10+
#define LLVM_LIBC_SRC_SYS_MMAN_MSYNC_H
11+
12+
#include <sys/mman.h>
13+
#include <sys/syscall.h>
14+
15+
namespace LIBC_NAMESPACE {
16+
17+
int msync(void *addr, size_t len, int flags);
18+
19+
} // namespace LIBC_NAMESPACE
20+
21+
#endif // LLVM_LIBC_SRC_SYS_MMAN_MSYNC_H

libc/test/src/sys/mman/linux/CMakeLists.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,23 @@ add_libc_unittest(
107107
libc.src.unistd.sysconf
108108
libc.test.UnitTest.ErrnoSetterMatcher
109109
)
110+
111+
add_libc_unittest(
112+
msync_test
113+
SUITE
114+
libc_sys_mman_unittests
115+
SRCS
116+
msync_test.cpp
117+
DEPENDS
118+
libc.include.sys_mman
119+
libc.include.unistd
120+
libc.src.errno.errno
121+
libc.src.sys.mman.mmap
122+
libc.src.sys.mman.munmap
123+
libc.src.sys.mman.msync
124+
libc.src.sys.mman.mincore
125+
libc.src.sys.mman.mlock
126+
libc.src.sys.mman.munlock
127+
libc.src.unistd.sysconf
128+
libc.test.UnitTest.ErrnoSetterMatcher
129+
)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//===-- Unittests for msync -----------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/errno/libc_errno.h"
10+
#include "src/sys/mman/mlock.h"
11+
#include "src/sys/mman/mmap.h"
12+
#include "src/sys/mman/msync.h"
13+
#include "src/sys/mman/munlock.h"
14+
#include "src/sys/mman/munmap.h"
15+
#include "src/unistd/sysconf.h"
16+
#include "test/UnitTest/ErrnoSetterMatcher.h"
17+
#include "test/UnitTest/LibcTest.h"
18+
#include "test/UnitTest/Test.h"
19+
20+
using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
21+
22+
struct PageHolder {
23+
size_t size;
24+
void *addr;
25+
26+
PageHolder()
27+
: size(LIBC_NAMESPACE::sysconf(_SC_PAGESIZE)),
28+
addr(LIBC_NAMESPACE::mmap(nullptr, size, PROT_READ | PROT_WRITE,
29+
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)) {}
30+
~PageHolder() {
31+
if (addr != MAP_FAILED)
32+
LIBC_NAMESPACE::munmap(addr, size);
33+
}
34+
35+
char &operator[](size_t i) { return reinterpret_cast<char *>(addr)[i]; }
36+
37+
bool is_valid() { return addr != MAP_FAILED; }
38+
};
39+
40+
TEST(LlvmLibcMsyncTest, UnMappedMemory) {
41+
EXPECT_THAT(LIBC_NAMESPACE::msync(nullptr, 1024, MS_SYNC), Fails(ENOMEM));
42+
EXPECT_THAT(LIBC_NAMESPACE::msync(nullptr, 1024, MS_ASYNC), Fails(ENOMEM));
43+
}
44+
45+
TEST(LlvmLibcMsyncTest, LockedPage) {
46+
PageHolder page;
47+
ASSERT_TRUE(page.is_valid());
48+
ASSERT_THAT(LIBC_NAMESPACE::mlock(page.addr, page.size), Succeeds());
49+
EXPECT_THAT(
50+
LIBC_NAMESPACE::msync(page.addr, page.size, MS_SYNC | MS_INVALIDATE),
51+
Fails(EBUSY));
52+
ASSERT_THAT(LIBC_NAMESPACE::munlock(page.addr, page.size), Succeeds());
53+
EXPECT_THAT(LIBC_NAMESPACE::msync(page.addr, page.size, MS_SYNC), Succeeds());
54+
}
55+
56+
TEST(LlvmLibcMsyncTest, UnalignedAddress) {
57+
PageHolder page;
58+
ASSERT_TRUE(page.is_valid());
59+
EXPECT_THAT(LIBC_NAMESPACE::msync(&page[1], page.size - 1, MS_SYNC),
60+
Fails(EINVAL));
61+
}
62+
63+
TEST(LlvmLibcMsyncTest, InvalidFlag) {
64+
PageHolder page;
65+
ASSERT_TRUE(page.is_valid());
66+
EXPECT_THAT(LIBC_NAMESPACE::msync(page.addr, page.size, MS_SYNC | MS_ASYNC),
67+
Fails(EINVAL));
68+
EXPECT_THAT(LIBC_NAMESPACE::msync(page.addr, page.size, -1), Fails(EINVAL));
69+
}

0 commit comments

Comments
 (0)