| #include <stdio.h> |
| #include "tests/sys_mman.h" |
| #include <stdlib.h> |
| #include <unistd.h> |
| |
| /* The code testing MAP_HUGETLB huge pages is disabled by default, |
| as many distros do not have huge pages configured |
| by default. |
| To have e.g. 20 huge pages configured, do (as root) |
| echo 20 > /proc/sys/vm/nr_hugepages |
| Once this is done, uncomment the below, and recompile. |
| */ |
| //#define TEST_MAP_HUGETLB 1 |
| |
| /* Similarly, testing SHM_HUGETLB huge pages is disabled by default. |
| To have shmget/shmat big pages working, do (as root) |
| echo 500 > /proc/sys/vm/hugetlb_shm_group |
| where 500 is the groupid of the user that runs this test |
| Once this is done, uncomment the below, and recompile. |
| */ |
| //#define TEST_SHM_HUGETLB 1 |
| |
| // Size to use for huge pages |
| #define HUGESZ (4 * 1024 * 1024) |
| |
| #ifdef TEST_MAP_HUGETLB |
| /* Ensure this compiles on pre 2.6 systems, or on glibc missing MAP_HUGETLB */ |
| #ifndef MAP_HUGETLB |
| /* The below works for me on an f12/x86 linux */ |
| #define MAP_HUGETLB 0x40000 |
| #endif |
| |
| #endif /* TEST_MAP_HUGETLB */ |
| |
| #ifdef TEST_SHM_HUGETLB |
| #include <sys/ipc.h> |
| #include <sys/shm.h> |
| #include <sys/stat.h> |
| #ifndef SHM_HUGETLB |
| #define SHM_HUGETLB 04000 |
| #endif |
| #endif /* TEST_SHM_HUGETLB */ |
| |
| static unsigned int pagesize; |
| |
| #define PAGES 1024u |
| #define LEN (PAGES*pagesize) |
| |
| static void *domap(size_t len, int addflags) |
| { |
| void *ret = mmap(0, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|addflags, -1, 0); |
| |
| if (ret == (void *)-1) { |
| perror("mmap"); |
| exit(1); |
| } |
| |
| return ret; |
| } |
| |
| /* unmap in pieces to exercise munmap more */ |
| static void nibblemap(void *p) |
| { |
| int off; |
| int i; |
| |
| off = (random() % LEN) & ~(pagesize-1); |
| |
| for(i = 0; i < PAGES; i++) { |
| /* printf("unmapping off=%d\n", off/pagesize); */ |
| munmap((char *)p + off, pagesize); |
| off += 619*pagesize; |
| off %= LEN; |
| } |
| } |
| |
| static void prmaps() |
| { |
| char buf[100]; |
| sprintf(buf, "/bin/cat /proc/%ld/maps", (long) getpid()); |
| system(buf); |
| exit(1); |
| } |
| |
| int main() |
| { |
| int i; |
| void *expect1, *expect2; |
| |
| pagesize = getpagesize(); |
| |
| expect1 = domap(LEN, 0); |
| expect2 = domap(LEN, 0); |
| munmap(expect1, LEN); |
| munmap(expect2, LEN); |
| |
| for(i = 0; i < 5; i++) { |
| void *m1, *m2; |
| |
| m1 = domap(LEN, 0); |
| if (m1 != expect1) { |
| printf("FAIL i=%d: m1=%p expect1=%p\n", |
| i, m1, expect1); |
| prmaps(); |
| return 1; |
| } |
| m2 = domap(LEN, 0); |
| if (m2 != expect2) { |
| printf("FAIL i=%d: m2=%p expect2=%p\n", |
| i, m2, expect2); |
| prmaps(); |
| return 1; |
| } |
| nibblemap(m2); |
| munmap(m1, LEN); |
| } |
| |
| #ifdef TEST_MAP_HUGETLB |
| { |
| void *expect3; |
| expect3 = domap(HUGESZ, MAP_HUGETLB); |
| munmap(expect3, HUGESZ); |
| } |
| #endif |
| |
| #ifdef TEST_SHM_HUGETLB |
| { |
| int shmid; |
| void *expect4; |
| |
| |
| shmid = shmget(IPC_PRIVATE, HUGESZ, |
| IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | SHM_HUGETLB); |
| if (shmid == -1) { |
| perror("shmget"); |
| exit(1); |
| } |
| expect4 = shmat(shmid, NULL, 0); |
| if (expect4 == (void*) -1){ |
| perror("shmat"); |
| exit(1); |
| } |
| if (shmdt(expect4) != 0) { |
| perror("shmdt"); |
| exit(1); |
| } |
| if (shmctl(shmid, IPC_RMID, 0) != 0) { |
| perror("shmctl IPC_RMID"); |
| exit(1); |
| } |
| } |
| #endif |
| |
| printf("PASS\n"); |
| return 0; |
| } |