1#include <stdio.h> 2#include "tests/sys_mman.h" 3#include <stdlib.h> 4#include <unistd.h> 5 6/* The code testing MAP_HUGETLB huge pages is disabled by default, 7 as many distros do not have huge pages configured 8 by default. 9 To have e.g. 20 huge pages configured, do (as root) 10 echo 20 > /proc/sys/vm/nr_hugepages 11 Once this is done, uncomment the below, and recompile. 12*/ 13//#define TEST_MAP_HUGETLB 1 14 15/* Similarly, testing SHM_HUGETLB huge pages is disabled by default. 16 To have shmget/shmat big pages working, do (as root) 17 echo 500 > /proc/sys/vm/hugetlb_shm_group 18 where 500 is the groupid of the user that runs this test 19 Once this is done, uncomment the below, and recompile. 20*/ 21//#define TEST_SHM_HUGETLB 1 22 23// Size to use for huge pages 24#define HUGESZ (4 * 1024 * 1024) 25 26#ifdef TEST_MAP_HUGETLB 27/* Ensure this compiles on pre 2.6 systems, or on glibc missing MAP_HUGETLB */ 28#ifndef MAP_HUGETLB 29/* The below works for me on an f12/x86 linux */ 30#define MAP_HUGETLB 0x40000 31#endif 32 33#endif /* TEST_MAP_HUGETLB */ 34 35#ifdef TEST_SHM_HUGETLB 36#include <sys/ipc.h> 37#include <sys/shm.h> 38#include <sys/stat.h> 39#ifndef SHM_HUGETLB 40#define SHM_HUGETLB 04000 41#endif 42#endif /* TEST_SHM_HUGETLB */ 43 44static unsigned int pagesize; 45 46#define PAGES 1024u 47#define LEN (PAGES*pagesize) 48 49static void *domap(size_t len, int addflags) 50{ 51 void *ret = mmap(0, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|addflags, -1, 0); 52 53 if (ret == (void *)-1) { 54 perror("mmap"); 55 exit(1); 56 } 57 58 return ret; 59} 60 61/* unmap in pieces to exercise munmap more */ 62static void nibblemap(void *p) 63{ 64 int off; 65 int i; 66 67 off = (random() % LEN) & ~(pagesize-1); 68 69 for(i = 0; i < PAGES; i++) { 70 /* printf("unmapping off=%d\n", off/pagesize); */ 71 munmap((char *)p + off, pagesize); 72 off += 619*pagesize; 73 off %= LEN; 74 } 75} 76 77static void prmaps() 78{ 79 char buf[100]; 80 sprintf(buf, "/bin/cat /proc/%ld/maps", (long) getpid()); 81 system(buf); 82 exit(1); 83} 84 85int main() 86{ 87 int i; 88 void *expect1, *expect2; 89 90 pagesize = getpagesize(); 91 92 expect1 = domap(LEN, 0); 93 expect2 = domap(LEN, 0); 94 munmap(expect1, LEN); 95 munmap(expect2, LEN); 96 97 for(i = 0; i < 5; i++) { 98 void *m1, *m2; 99 100 m1 = domap(LEN, 0); 101 if (m1 != expect1) { 102 printf("FAIL i=%d: m1=%p expect1=%p\n", 103 i, m1, expect1); 104 prmaps(); 105 return 1; 106 } 107 m2 = domap(LEN, 0); 108 if (m2 != expect2) { 109 printf("FAIL i=%d: m2=%p expect2=%p\n", 110 i, m2, expect2); 111 prmaps(); 112 return 1; 113 } 114 nibblemap(m2); 115 munmap(m1, LEN); 116 } 117 118#ifdef TEST_MAP_HUGETLB 119 { 120 void *expect3; 121 expect3 = domap(HUGESZ, MAP_HUGETLB); 122 munmap(expect3, HUGESZ); 123 } 124#endif 125 126#ifdef TEST_SHM_HUGETLB 127 { 128 int shmid; 129 void *expect4; 130 131 132 shmid = shmget(IPC_PRIVATE, HUGESZ, 133 IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | SHM_HUGETLB); 134 if (shmid == -1) { 135 perror("shmget"); 136 exit(1); 137 } 138 expect4 = shmat(shmid, NULL, 0); 139 if (expect4 == (void*) -1){ 140 perror("shmat"); 141 exit(1); 142 } 143 if (shmdt(expect4) != 0) { 144 perror("shmdt"); 145 exit(1); 146 } 147 if (shmctl(shmid, IPC_RMID, 0) != 0) { 148 perror("shmctl IPC_RMID"); 149 exit(1); 150 } 151 } 152#endif 153 154 printf("PASS\n"); 155 return 0; 156} 157