replace stgMallocBytesRWX() with our own allocator
[ghc-hetmet.git] / rts / posix / OSMem.c
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The University of Glasgow 2006
4  *
5  * OS-specific memory management
6  *
7  * ---------------------------------------------------------------------------*/
8
9 #include "Rts.h"
10 #include "OSMem.h"
11
12 #include <unistd.h>
13 #include <sys/types.h>
14 #include <sys/mman.h>
15
16 /* no C99 header stdint.h on OpenBSD? */
17 #if defined(openbsd_HOST_OS)
18 typedef unsigned long my_uintptr_t;
19 #else
20 #include <stdint.h>
21 typedef uintptr_t my_uintptr_t;
22 #endif
23
24 lnat getPageSize (void)
25 {
26     static lnat pageSize = 0;
27     if (pageSize) {
28         return pageSize;
29     } else {
30         long ret;
31         ret = sysconf(_SC_PAGESIZE);
32         if (ret == -1) {
33             barf("getPageSize: cannot get page size");
34         }
35         return ret;
36     }
37 }
38
39 void setExecutable (void *p, lnat len, rtsBool exec)
40 {
41     my_uintptr_t pageSize = getPageSize();
42
43     /* malloced memory isn't executable by default on OpenBSD */
44     my_uintptr_t mask             = ~(pageSize - 1);
45     my_uintptr_t startOfFirstPage = ((my_uintptr_t)p          ) & mask;
46     my_uintptr_t startOfLastPage  = ((my_uintptr_t)p + len - 1) & mask;
47     my_uintptr_t size             = startOfLastPage - startOfFirstPage + pageSize;
48     if (mprotect((void*)startOfFirstPage, (size_t)size, 
49                  (exec ? PROT_EXEC : 0) | PROT_READ | PROT_WRITE) != 0) {
50         barf("makeExecutable: failed to protect 0x%p\n", p);
51     }
52 }