1 //===-- Unittests for mincore ---------------------------------------------===// 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/__support/OSUtil/syscall.h" // For internal syscall function. 10 #include "src/errno/libc_errno.h" 11 #include "src/sys/mman/madvise.h" 12 #include "src/sys/mman/mincore.h" 13 #include "src/sys/mman/mlock.h" 14 #include "src/sys/mman/mmap.h" 15 #include "src/sys/mman/munlock.h" 16 #include "src/sys/mman/munmap.h" 17 #include "src/unistd/sysconf.h" 18 #include "test/UnitTest/ErrnoSetterMatcher.h" 19 #include "test/UnitTest/Test.h" 20 21 #include <sys/mman.h> 22 #include <sys/syscall.h> 23 #include <unistd.h> 24 25 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; 26 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; 27 28 TEST(LlvmLibcMincoreTest, UnMappedMemory) { 29 LIBC_NAMESPACE::libc_errno = 0; 30 unsigned char vec; 31 int res = LIBC_NAMESPACE::mincore(nullptr, 1, &vec); 32 EXPECT_THAT(res, Fails(ENOMEM, -1)); 33 } 34 35 TEST(LlvmLibcMincoreTest, UnalignedAddr) { 36 unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE); 37 void *addr = LIBC_NAMESPACE::mmap(nullptr, page_size, PROT_READ, 38 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 39 EXPECT_NE(addr, MAP_FAILED); 40 EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul); 41 LIBC_NAMESPACE::libc_errno = 0; 42 int res = LIBC_NAMESPACE::mincore(static_cast<char *>(addr) + 1, 1, nullptr); 43 EXPECT_THAT(res, Fails(EINVAL, -1)); 44 EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds()); 45 } 46 47 TEST(LlvmLibcMincoreTest, InvalidVec) { 48 unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE); 49 void *addr = LIBC_NAMESPACE::mmap(nullptr, 4 * page_size, PROT_READ, 50 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 51 EXPECT_NE(addr, MAP_FAILED); 52 EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul); 53 LIBC_NAMESPACE::libc_errno = 0; 54 int res = LIBC_NAMESPACE::mincore(addr, 1, nullptr); 55 EXPECT_THAT(res, Fails(EFAULT, -1)); 56 } 57 58 TEST(LlvmLibcMincoreTest, NoError) { 59 unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE); 60 void *addr = LIBC_NAMESPACE::mmap(nullptr, page_size, PROT_READ, 61 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 62 EXPECT_NE(addr, MAP_FAILED); 63 EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul); 64 unsigned char vec; 65 LIBC_NAMESPACE::libc_errno = 0; 66 int res = LIBC_NAMESPACE::mincore(addr, 1, &vec); 67 EXPECT_THAT(res, Succeeds()); 68 EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds()); 69 } 70 71 TEST(LlvmLibcMincoreTest, NegativeLength) { 72 unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE); 73 void *addr = LIBC_NAMESPACE::mmap(nullptr, page_size, PROT_READ, 74 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 75 EXPECT_NE(addr, MAP_FAILED); 76 EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul); 77 unsigned char vec; 78 LIBC_NAMESPACE::libc_errno = 0; 79 int res = LIBC_NAMESPACE::mincore(addr, -1, &vec); 80 EXPECT_THAT(res, Fails(ENOMEM, -1)); 81 EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds()); 82 } 83 84 TEST(LlvmLibcMincoreTest, PageOut) { 85 unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE); 86 unsigned char vec; 87 void *addr = LIBC_NAMESPACE::mmap(nullptr, page_size, PROT_READ | PROT_WRITE, 88 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 89 EXPECT_NE(addr, MAP_FAILED); 90 EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul); 91 92 // touch the page 93 { 94 static_cast<char *>(addr)[0] = 0; 95 EXPECT_THAT(LIBC_NAMESPACE::mlock(addr, page_size), Succeeds()); 96 int res = LIBC_NAMESPACE::mincore(addr, 1, &vec); 97 EXPECT_EQ(vec & 1u, 1u); 98 EXPECT_THAT(res, Succeeds()); 99 EXPECT_THAT(LIBC_NAMESPACE::munlock(addr, page_size), Succeeds()); 100 } 101 102 // page out the memory 103 { 104 LIBC_NAMESPACE::libc_errno = 0; 105 EXPECT_THAT(LIBC_NAMESPACE::madvise(addr, page_size, MADV_DONTNEED), 106 Succeeds()); 107 108 LIBC_NAMESPACE::libc_errno = 0; 109 int res = LIBC_NAMESPACE::mincore(addr, page_size, &vec); 110 EXPECT_EQ(vec & 1u, 0u); 111 EXPECT_THAT(res, Succeeds()); 112 } 113 114 EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds()); 115 } 116