1 /* Test that munmap() and thread creation do not race. */ 2 #include <assert.h> 3 #include <pthread.h> 4 #include <stdbool.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <sys/mman.h> 8 #include <unistd.h> 9 10 static const char nop_func[] = { 11 #if defined(__aarch64__) 12 0xc0, 0x03, 0x5f, 0xd6, /* ret */ 13 #elif defined(__alpha__) 14 0x01, 0x80, 0xFA, 0x6B, /* ret */ 15 #elif defined(__arm__) 16 0x1e, 0xff, 0x2f, 0xe1, /* bx lr */ 17 #elif defined(__riscv) 18 0x67, 0x80, 0x00, 0x00, /* ret */ 19 #elif defined(__s390__) 20 0x07, 0xfe, /* br %r14 */ 21 #elif defined(__i386__) || defined(__x86_64__) 22 0xc3, /* ret */ 23 #endif 24 }; 25 26 static void *thread_mmap_munmap(void *arg) 27 { 28 volatile bool *run = arg; 29 char *p; 30 int ret; 31 32 while (*run) { 33 p = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC, 34 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 35 assert(p != MAP_FAILED); 36 37 /* Create a small translation block. */ 38 memcpy(p, nop_func, sizeof(nop_func)); 39 ((void(*)(void))p)(); 40 41 ret = munmap(p, getpagesize()); 42 assert(ret == 0); 43 } 44 45 return NULL; 46 } 47 48 static void *thread_dummy(void *arg) 49 { 50 return NULL; 51 } 52 53 int main(void) 54 { 55 pthread_t mmap_munmap, dummy; 56 volatile bool run = true; 57 int i, ret; 58 59 /* Without a template, nothing to test. */ 60 if (sizeof(nop_func) == 0) { 61 return EXIT_SUCCESS; 62 } 63 64 ret = pthread_create(&mmap_munmap, NULL, thread_mmap_munmap, (void *)&run); 65 assert(ret == 0); 66 67 for (i = 0; i < 1000; i++) { 68 ret = pthread_create(&dummy, NULL, thread_dummy, NULL); 69 assert(ret == 0); 70 ret = pthread_join(dummy, NULL); 71 assert(ret == 0); 72 } 73 74 run = false; 75 ret = pthread_join(mmap_munmap, NULL); 76 assert(ret == 0); 77 78 return EXIT_SUCCESS; 79 } 80