forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[libc][SysMMan] implement mincore (llvm#73704)
Implement `mincore` as specified in https://man7.org/linux/man-pages/man2/mincore.2.html
- Loading branch information
1 parent
065796b
commit 418a3a4
Showing
11 changed files
with
218 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
//===---------- Linux implementation of the mincore 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/mincore.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, mincore, (void *addr, size_t len, unsigned char *vec)) { | ||
long ret = syscall_impl(SYS_mincore, reinterpret_cast<long>(addr), len, | ||
reinterpret_cast<long>(vec)); | ||
if (ret < 0) { | ||
libc_errno = static_cast<int>(-ret); | ||
return -1; | ||
} | ||
return 0; | ||
} | ||
|
||
} // namespace LIBC_NAMESPACE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
//===-- Implementation header for mincore 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_MINCORE_H | ||
#define LLVM_LIBC_SRC_SYS_MMAN_MINCORE_H | ||
|
||
#include <sys/mman.h> // For size_t | ||
|
||
namespace LIBC_NAMESPACE { | ||
|
||
int mincore(void *addr, size_t len, unsigned char *vec); | ||
|
||
} // namespace LIBC_NAMESPACE | ||
|
||
#endif // LLVM_LIBC_SRC_SYS_MMAN_MINCORE_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
//===-- Unittests for mincore ---------------------------------------------===// | ||
// | ||
// 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/madvise.h" | ||
#include "src/sys/mman/mincore.h" | ||
#include "src/sys/mman/mmap.h" | ||
#include "src/sys/mman/munmap.h" | ||
#include "test/UnitTest/ErrnoSetterMatcher.h" | ||
#include "test/UnitTest/LibcTest.h" | ||
#include "test/UnitTest/Test.h" | ||
|
||
#include <linux/param.h> // For EXEC_PAGESIZE | ||
#include <sys/mman.h> | ||
|
||
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; | ||
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; | ||
|
||
TEST(LlvmLibcMincoreTest, UnMappedMemory) { | ||
libc_errno = 0; | ||
unsigned char vec; | ||
int res = LIBC_NAMESPACE::mincore(nullptr, 1, &vec); | ||
EXPECT_THAT(res, Fails(ENOMEM, -1)); | ||
} | ||
|
||
TEST(LlvmLibcMincoreTest, InvalidVec) { | ||
void *addr = LIBC_NAMESPACE::mmap(nullptr, 4 * EXEC_PAGESIZE, PROT_READ, | ||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); | ||
EXPECT_NE(addr, MAP_FAILED); | ||
EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % EXEC_PAGESIZE, 0ul); | ||
libc_errno = 0; | ||
int res = LIBC_NAMESPACE::mincore(addr, 1, nullptr); | ||
EXPECT_THAT(res, Fails(EFAULT, -1)); | ||
void *area = | ||
LIBC_NAMESPACE::mmap(nullptr, EXEC_PAGESIZE, PROT_READ | PROT_WRITE, | ||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); | ||
EXPECT_NE(area, MAP_FAILED); | ||
unsigned char *ptr = static_cast<unsigned char *>(area) + EXEC_PAGESIZE - 3; | ||
res = LIBC_NAMESPACE::mincore(addr, 4 * EXEC_PAGESIZE, ptr); | ||
EXPECT_THAT(res, Fails(EFAULT, -1)); | ||
EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, EXEC_PAGESIZE), Succeeds()); | ||
EXPECT_THAT(LIBC_NAMESPACE::munmap(area, 2), Succeeds()); | ||
} | ||
|
||
TEST(LlvmLibcMincoreTest, UnalignedAddr) { | ||
void *addr = LIBC_NAMESPACE::mmap(nullptr, EXEC_PAGESIZE, PROT_READ, | ||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); | ||
EXPECT_NE(addr, MAP_FAILED); | ||
EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % EXEC_PAGESIZE, 0ul); | ||
libc_errno = 0; | ||
int res = LIBC_NAMESPACE::mincore(static_cast<char *>(addr) + 1, 1, nullptr); | ||
EXPECT_THAT(res, Fails(EINVAL, -1)); | ||
EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, EXEC_PAGESIZE), Succeeds()); | ||
} | ||
|
||
TEST(LlvmLibcMincoreTest, NoError) { | ||
void *addr = LIBC_NAMESPACE::mmap(nullptr, EXEC_PAGESIZE, PROT_READ, | ||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); | ||
EXPECT_NE(addr, MAP_FAILED); | ||
EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % EXEC_PAGESIZE, 0ul); | ||
unsigned char vec; | ||
libc_errno = 0; | ||
int res = LIBC_NAMESPACE::mincore(addr, 1, &vec); | ||
EXPECT_THAT(res, Succeeds()); | ||
EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, EXEC_PAGESIZE), Succeeds()); | ||
} | ||
|
||
TEST(LlvmLibcMincoreTest, NegativeLength) { | ||
void *addr = LIBC_NAMESPACE::mmap(nullptr, EXEC_PAGESIZE, PROT_READ, | ||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); | ||
EXPECT_NE(addr, MAP_FAILED); | ||
EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % EXEC_PAGESIZE, 0ul); | ||
unsigned char vec; | ||
libc_errno = 0; | ||
int res = LIBC_NAMESPACE::mincore(addr, -1, &vec); | ||
EXPECT_THAT(res, Fails(ENOMEM, -1)); | ||
EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, EXEC_PAGESIZE), Succeeds()); | ||
} | ||
|
||
TEST(LlvmLibcMincoreTest, PageOut) { | ||
unsigned char vec; | ||
void *addr = | ||
LIBC_NAMESPACE::mmap(nullptr, EXEC_PAGESIZE, PROT_READ | PROT_WRITE, | ||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); | ||
EXPECT_NE(addr, MAP_FAILED); | ||
EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % EXEC_PAGESIZE, 0ul); | ||
|
||
// touch the page | ||
{ | ||
static_cast<char *>(addr)[0] = 0; | ||
libc_errno = 0; | ||
int res = LIBC_NAMESPACE::mincore(addr, 1, &vec); | ||
EXPECT_EQ(vec & 1u, 1u); | ||
EXPECT_THAT(res, Succeeds()); | ||
} | ||
|
||
// page out the memory | ||
{ | ||
libc_errno = 0; | ||
EXPECT_THAT(LIBC_NAMESPACE::madvise(addr, EXEC_PAGESIZE, MADV_DONTNEED), | ||
Succeeds()); | ||
|
||
libc_errno = 0; | ||
int res = LIBC_NAMESPACE::mincore(addr, EXEC_PAGESIZE, &vec); | ||
EXPECT_EQ(vec & 1u, 0u); | ||
EXPECT_THAT(res, Succeeds()); | ||
} | ||
|
||
EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, EXEC_PAGESIZE), Succeeds()); | ||
} |