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
44 static unsigned int pagesize;
45
46 #define PAGES 1024u
47 #define LEN (PAGES*pagesize)
48
domap(size_t len,int addflags)49 static 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 */
nibblemap(void * p)62 static 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
prmaps()77 static void prmaps()
78 {
79 char buf[100];
80 sprintf(buf, "/bin/cat /proc/%d/maps", getpid());
81 system(buf);
82 exit(1);
83 }
84
main()85 int 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