X-Git-Url: https://git.lttng.org/?p=urcu.git;a=blobdiff_plain;f=src%2Frculfhash-mm-mmap.c;h=72333a866da098a7107cde22a666ac6c36b84d41;hp=3cc3fa01c9d5ed5c16888ae8f02fb85ae65cf1de;hb=cafe8ce139ea02d497582c4abb27d065e6e46d79;hpb=6893800a4d1cc14dff0395ddcd660a5138db183d diff --git a/src/rculfhash-mm-mmap.c b/src/rculfhash-mm-mmap.c index 3cc3fa0..72333a8 100644 --- a/src/rculfhash-mm-mmap.c +++ b/src/rculfhash-mm-mmap.c @@ -21,6 +21,9 @@ */ #include +#include +#include +#include #include #include "rculfhash-internal.h" @@ -28,48 +31,99 @@ #define MAP_ANONYMOUS MAP_ANON #endif -/* reserve inaccessible memory space without allocation any memory */ -static void *memory_map(size_t length) +/* + * The allocation scheme used by the mmap based RCU hash table is to make a + * large unaccessible mapping to reserve memory without allocating it. + * Then smaller chunks are allocated by overlapping read/write mappings which + * do allocate memory. Deallocation is done by an overlapping unaccessible + * mapping. + * + * This scheme was tested on Linux, macOS and Solaris. However, on Cygwin the + * mmap wrapper is based on the Windows NtMapViewOfSection API which doesn't + * support overlapping mappings. + * + * An alternative to the overlapping mappings is to use mprotect to change the + * protection on chunks of the large mapping, read/write to allocate and none + * to deallocate. This works perfecty on Cygwin and Solaris but on Linux a + * call to madvise is also required to deallocate and it just doesn't work on + * macOS. + * + * For this reason, we keep to original scheme on all platforms except Cygwin. + */ + + +/* Reserve inaccessible memory space without allocating it */ +static +void *memory_map(size_t length) { - void *ret = mmap(NULL, length, PROT_NONE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + void *ret; - assert(ret != MAP_FAILED); + ret = mmap(NULL, length, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (ret == MAP_FAILED) { + perror("mmap"); + abort(); + } return ret; } -static void memory_unmap(void *ptr, size_t length) +static +void memory_unmap(void *ptr, size_t length) { - int ret __attribute__((unused)); - - ret = munmap(ptr, length); + if (munmap(ptr, length)) { + perror("munmap"); + abort(); + } +} - assert(ret == 0); +#ifdef __CYGWIN__ +/* Set protection to read/write to allocate a memory chunk */ +static +void memory_populate(void *ptr, size_t length) +{ + if (mprotect(ptr, length, PROT_READ | PROT_WRITE)) { + perror("mprotect"); + abort(); + } } -static void memory_populate(void *ptr, size_t length) +/* Set protection to none to deallocate a memory chunk */ +static +void memory_discard(void *ptr, size_t length) { - void *ret __attribute__((unused)); + if (mprotect(ptr, length, PROT_NONE)) { + perror("mprotect"); + abort(); + } +} - ret = mmap(ptr, length, PROT_READ | PROT_WRITE, - MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +#else /* __CYGWIN__ */ - assert(ret == ptr); +static +void memory_populate(void *ptr, size_t length) +{ + if (mmap(ptr, length, PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0) != ptr) { + perror("mmap"); + abort(); + } } /* * Discard garbage memory and avoid system save it when try to swap it out. * Make it still reserved, inaccessible. */ -static void memory_discard(void *ptr, size_t length) +static +void memory_discard(void *ptr, size_t length) { - void *ret __attribute__((unused)); - - ret = mmap(ptr, length, PROT_NONE, - MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - - assert(ret == ptr); + if (mmap(ptr, length, PROT_NONE, + MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0) != ptr) { + perror("mmap"); + abort(); + } } +#endif /* __CYGWIN__ */ static void cds_lfht_alloc_bucket_table(struct cds_lfht *ht, unsigned long order)