X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=rculfhash-mm-mmap.c;h=a8fadf0696de5e743fe56c4190cc0e4d8e1578b1;hb=refs%2Fheads%2Fstable-0.8;hp=4554ed6007f20df68bfac3f2fe74a5a9e39c55fc;hpb=f8fc437722856fefd5d415405d5ce8d79e8b6e96;p=userspace-rcu.git diff --git a/rculfhash-mm-mmap.c b/rculfhash-mm-mmap.c index 4554ed6..a8fadf0 100644 --- a/rculfhash-mm-mmap.c +++ b/rculfhash-mm-mmap.c @@ -24,8 +24,34 @@ #include #include "rculfhash-internal.h" -/* reserve inaccessible memory space without allocation any memory */ -static void *memory_map(size_t length) +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + +/* + * 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); @@ -34,7 +60,8 @@ static void *memory_map(size_t length) return ret; } -static void memory_unmap(void *ptr, size_t length) +static +void memory_unmap(void *ptr, size_t length) { int ret __attribute__((unused)); @@ -43,7 +70,33 @@ static void memory_unmap(void *ptr, size_t length) assert(ret == 0); } -static void memory_populate(void *ptr, size_t length) +#ifdef __CYGWIN__ +/* Set protection to read/write to allocate a memory chunk */ +static +void memory_populate(void *ptr, size_t length) +{ + int ret __attribute__((unused)); + + ret = mprotect(ptr, length, PROT_READ | PROT_WRITE); + + assert(!ret); +} + +/* Set protection to none to deallocate a memory chunk */ +static +void memory_discard(void *ptr, size_t length) +{ + int ret __attribute__((unused)); + + ret = mprotect(ptr, length, PROT_NONE); + + assert(!ret); +} + +#else /* __CYGWIN__ */ + +static +void memory_populate(void *ptr, size_t length) { void *ret __attribute__((unused)); @@ -57,7 +110,8 @@ static void memory_populate(void *ptr, size_t length) * 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)); @@ -66,6 +120,7 @@ static void memory_discard(void *ptr, size_t length) assert(ret == ptr); } +#endif /* __CYGWIN__ */ static void cds_lfht_alloc_bucket_table(struct cds_lfht *ht, unsigned long order)