PageRenderTime 38ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/tests/lib/libc/sys/t_mincore.c

https://gitlab.com/storedmirrors/minix
C | 318 lines | 174 code | 70 blank | 74 comment | 56 complexity | 173d9cd8d92d6ccecf42043ca6250e66 MD5 | raw file
  1. /* $NetBSD: t_mincore.c,v 1.8 2012/06/08 07:18:58 martin Exp $ */
  2. /*-
  3. * Copyright (c) 2011 The NetBSD Foundation, Inc.
  4. * All rights reserved.
  5. *
  6. * This code is derived from software contributed to The NetBSD Foundation
  7. * by Jukka Ruohonen.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  19. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  20. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  21. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  22. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  23. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  24. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  25. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  26. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  27. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. * POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. /*-
  31. * Copyright (c) 1999 The NetBSD Foundation, Inc.
  32. * All rights reserved.
  33. *
  34. * This code is derived from software contributed to The NetBSD Foundation
  35. * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
  36. * NASA Ames Research Center.
  37. *
  38. * Redistribution and use in source and binary forms, with or without
  39. * modification, are permitted provided that the following conditions
  40. * are met:
  41. * 1. Redistributions of source code must retain the above copyright
  42. * notice, this list of conditions and the following disclaimer.
  43. * 2. Redistributions in binary form must reproduce the above copyright
  44. * notice, this list of conditions and the following disclaimer in the
  45. * documentation and/or other materials provided with the distribution.
  46. *
  47. * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  48. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  49. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  50. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  51. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  52. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  53. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  54. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  55. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  56. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  57. * POSSIBILITY OF SUCH DAMAGE.
  58. */
  59. #include <sys/cdefs.h>
  60. __RCSID("$NetBSD: t_mincore.c,v 1.8 2012/06/08 07:18:58 martin Exp $");
  61. #include <sys/mman.h>
  62. #include <sys/shm.h>
  63. #include <atf-c.h>
  64. #include <errno.h>
  65. #include <fcntl.h>
  66. #include <kvm.h>
  67. #include <stdio.h>
  68. #include <stdlib.h>
  69. #include <string.h>
  70. #include <unistd.h>
  71. #include <sys/resource.h>
  72. static long page = 0;
  73. static const char path[] = "mincore";
  74. static size_t check_residency(void *, size_t);
  75. static size_t
  76. check_residency(void *addr, size_t npgs)
  77. {
  78. size_t i, resident;
  79. char *vec;
  80. vec = malloc(npgs);
  81. ATF_REQUIRE(vec != NULL);
  82. ATF_REQUIRE(mincore(addr, npgs * page, vec) == 0);
  83. for (i = resident = 0; i < npgs; i++) {
  84. if (vec[i] != 0)
  85. resident++;
  86. #if 0
  87. (void)fprintf(stderr, "page 0x%p is %sresident\n",
  88. (char *)addr + (i * page), vec[i] ? "" : "not ");
  89. #endif
  90. }
  91. free(vec);
  92. return resident;
  93. }
  94. ATF_TC(mincore_err);
  95. ATF_TC_HEAD(mincore_err, tc)
  96. {
  97. atf_tc_set_md_var(tc, "descr", "Test errors from mincore(2)");
  98. }
  99. ATF_TC_BODY(mincore_err, tc)
  100. {
  101. char *map, *vec;
  102. map = mmap(NULL, page, PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
  103. vec = malloc(page);
  104. ATF_REQUIRE(vec != NULL);
  105. ATF_REQUIRE(map != MAP_FAILED);
  106. errno = 0;
  107. ATF_REQUIRE_ERRNO(EINVAL, mincore(map, 0, vec) == -1);
  108. errno = 0;
  109. ATF_REQUIRE_ERRNO(ENOMEM, mincore(0, page, vec) == -1);
  110. errno = 0;
  111. ATF_REQUIRE_ERRNO(EFAULT, mincore(map, page, (void *)-1) == -1);
  112. free(vec);
  113. ATF_REQUIRE(munmap(map, page) == 0);
  114. }
  115. ATF_TC_WITH_CLEANUP(mincore_resid);
  116. ATF_TC_HEAD(mincore_resid, tc)
  117. {
  118. atf_tc_set_md_var(tc, "descr", "Test page residency with mincore(2)");
  119. }
  120. ATF_TC_BODY(mincore_resid, tc)
  121. {
  122. void *addr, *addr2, *addr3, *buf;
  123. size_t npgs = 0, resident;
  124. struct stat st;
  125. int fd, rv;
  126. struct rlimit rlim;
  127. ATF_REQUIRE(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
  128. rlim.rlim_cur = rlim.rlim_max;
  129. ATF_REQUIRE(setrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
  130. (void)memset(&st, 0, sizeof(struct stat));
  131. fd = open(path, O_RDWR | O_CREAT, 0700);
  132. buf = malloc(page * 5);
  133. ATF_REQUIRE(fd >= 0);
  134. ATF_REQUIRE(buf != NULL);
  135. rv = write(fd, buf, page * 5);
  136. ATF_REQUIRE(rv >= 0);
  137. ATF_REQUIRE(fd >= 0);
  138. ATF_REQUIRE(fstat(fd, &st) == 0);
  139. addr = mmap(NULL, (size_t)st.st_size, PROT_READ,
  140. MAP_FILE | MAP_SHARED, fd, (off_t) 0);
  141. ATF_REQUIRE(addr != MAP_FAILED);
  142. (void)close(fd);
  143. npgs = st.st_size / page;
  144. if (st.st_size % page != 0)
  145. npgs++;
  146. (void)check_residency(addr, npgs);
  147. rv = mlock(addr, npgs * page);
  148. if (rv == -1 && errno == EAGAIN)
  149. atf_tc_skip("hit process resource limits");
  150. ATF_REQUIRE(munmap(addr, st.st_size) == 0);
  151. npgs = 128;
  152. addr = mmap(NULL, npgs * page, PROT_READ | PROT_WRITE,
  153. MAP_ANON | MAP_PRIVATE | MAP_WIRED, -1, (off_t)0);
  154. if (addr == MAP_FAILED)
  155. atf_tc_skip("could not mmap wired anonymous test area, system "
  156. "might be low on memory");
  157. ATF_REQUIRE(check_residency(addr, npgs) == npgs);
  158. ATF_REQUIRE(munmap(addr, npgs * page) == 0);
  159. npgs = 128;
  160. addr = mmap(NULL, npgs * page, PROT_READ | PROT_WRITE,
  161. MAP_ANON | MAP_PRIVATE, -1, (off_t)0);
  162. ATF_REQUIRE(addr != MAP_FAILED);
  163. /*
  164. * Check that the in-core pages match the locked pages.
  165. */
  166. ATF_REQUIRE(check_residency(addr, npgs) == 0);
  167. errno = 0;
  168. if (mlockall(MCL_CURRENT|MCL_FUTURE) != 0 && errno != ENOMEM)
  169. atf_tc_fail("mlockall(2) failed");
  170. if (errno == ENOMEM)
  171. atf_tc_skip("mlockall() exceeded process resource limits");
  172. resident = check_residency(addr, npgs);
  173. if (resident < npgs)
  174. atf_tc_fail("mlockall(MCL_FUTURE) succeeded, still only "
  175. "%zu pages of the newly mapped %zu pages are resident",
  176. resident, npgs);
  177. addr2 = mmap(NULL, npgs * page, PROT_READ, MAP_ANON, -1, (off_t)0);
  178. addr3 = mmap(NULL, npgs * page, PROT_NONE, MAP_ANON, -1, (off_t)0);
  179. if (addr2 == MAP_FAILED || addr3 == MAP_FAILED)
  180. atf_tc_skip("could not mmap more anonymous test pages with "
  181. "mlockall(MCL_FUTURE) in effect, system "
  182. "might be low on memory");
  183. ATF_REQUIRE(check_residency(addr2, npgs) == npgs);
  184. ATF_REQUIRE(check_residency(addr3, npgs) == 0);
  185. ATF_REQUIRE(mprotect(addr3, npgs * page, PROT_READ) == 0);
  186. ATF_REQUIRE(check_residency(addr, npgs) == npgs);
  187. ATF_REQUIRE(check_residency(addr2, npgs) == npgs);
  188. (void)munlockall();
  189. ATF_REQUIRE(madvise(addr2, npgs * page, MADV_FREE) == 0);
  190. ATF_REQUIRE(check_residency(addr2, npgs) == 0);
  191. (void)memset(addr, 0, npgs * page);
  192. ATF_REQUIRE(madvise(addr, npgs * page, MADV_FREE) == 0);
  193. ATF_REQUIRE(check_residency(addr, npgs) == 0);
  194. (void)munmap(addr, npgs * page);
  195. (void)munmap(addr2, npgs * page);
  196. (void)munmap(addr3, npgs * page);
  197. (void)unlink(path);
  198. }
  199. ATF_TC_CLEANUP(mincore_resid, tc)
  200. {
  201. (void)unlink(path);
  202. }
  203. ATF_TC(mincore_shmseg);
  204. ATF_TC_HEAD(mincore_shmseg, tc)
  205. {
  206. atf_tc_set_md_var(tc, "descr", "residency of shared memory");
  207. }
  208. ATF_TC_BODY(mincore_shmseg, tc)
  209. {
  210. size_t npgs = 128;
  211. void *addr = NULL;
  212. int shmid;
  213. shmid = shmget(IPC_PRIVATE, npgs * page,
  214. IPC_CREAT | S_IRUSR | S_IWUSR);
  215. ATF_REQUIRE(shmid != -1);
  216. addr = shmat(shmid, NULL, 0);
  217. ATF_REQUIRE(addr != NULL);
  218. ATF_REQUIRE(check_residency(addr, npgs) == 0);
  219. (void)memset(addr, 0xff, npgs * page);
  220. ATF_REQUIRE(check_residency(addr, npgs) == npgs);
  221. ATF_REQUIRE(madvise(addr, npgs * page, MADV_FREE) == 0);
  222. /*
  223. * NOTE! Even though we have MADV_FREE'd the range,
  224. * there is another reference (the kernel's) to the
  225. * object which owns the pages. In this case, the
  226. * kernel does not simply free the pages, as haphazardly
  227. * freeing pages when there are still references to
  228. * an object can cause data corruption (say, the other
  229. * referencer doesn't expect the pages to be freed,
  230. * and is surprised by the subsequent ZFOD).
  231. *
  232. * Because of this, we simply report the number of
  233. * pages still resident, for information only.
  234. */
  235. npgs = check_residency(addr, npgs);
  236. (void)fprintf(stderr, "%zu pages still resident\n", npgs);
  237. ATF_REQUIRE(shmdt(addr) == 0);
  238. ATF_REQUIRE(shmctl(shmid, IPC_RMID, NULL) == 0);
  239. }
  240. ATF_TP_ADD_TCS(tp)
  241. {
  242. page = sysconf(_SC_PAGESIZE);
  243. ATF_REQUIRE(page >= 0);
  244. ATF_TP_ADD_TC(tp, mincore_err);
  245. ATF_TP_ADD_TC(tp, mincore_resid);
  246. ATF_TP_ADD_TC(tp, mincore_shmseg);
  247. return atf_no_error();
  248. }