Home | History | Annotate | Download | only in tests
      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 
     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 */
     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 
     77 static 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 
     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