# New Ticket Created by Jeff Clites # Please include the string: [perl #31966] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org:80/rt3/Ticket/Display.html?id=31966 >
This patch implements Parrot_memalign for Mac OS X (to allow ARENA_DOD_FLAGS usage). It's a patch, plus a new file (config/gen/platform/darwin/memalign.c). Notes: 1) In src/interpreter.c, there was a note about Parrot_memalign_if_possible on OpenBSD having the wrong behavior. I believe that may have been due to a bad #define in config/gen/platform/platform_interface.h, which this patch fixes. It would be good to see if OpenBSD behaves correctly now, after the patch is applied. 2) You need to enable ARENA_DOD_FLAGS in include/parrot/settings.h for the patch to make much of a difference. (At one point it defaulted to "on" if you had memalign, but that appears not to be the case currently.) config/gen/platform/darwin/memalign.c:
/* * memalign related stuff */ #include <mach/vm_map.h> #include <mach/mach_init.h> static unsigned log2int(unsigned x) { return (x<2) ? 0 : log2int (x>>1)+1; }; static unsigned roundDownPowerOf2(unsigned x) { return (1 << log2int(x)); }; static unsigned roundUpPowerOf2(unsigned x) { static unsigned one = 1; unsigned log2Int = log2int(x); return ((one << log2Int) == x) ? x : (one << (log2Int + 1)); }; static unsigned roundUpToPageBoundary(unsigned x) { unsigned roundedDown = trunc_page(x); return (roundedDown == x) ? x : (roundedDown + vm_page_size); }; typedef struct _memalign_marker_t { vm_address_t start; vm_size_t size; } memalign_marker_t; void * Parrot_memalign(size_t align, size_t size) { size_t effectiveAlign = align; size_t padding = 0; size_t amountToAllocate = 0; if( effectiveAlign < sizeof(void *) ) { effectiveAlign = roundUpPowerOf2(sizeof(void *)); } else { effectiveAlign = roundUpPowerOf2(effectiveAlign); } if( effectiveAlign < sizeof(memalign_marker_t) ) { padding = sizeof(memalign_marker_t); } else { padding = effectiveAlign; } amountToAllocate = roundUpToPageBoundary(size + padding); { vm_address_t p = NULL; kern_return_t status = vm_allocate(mach_task_self(), &p, amountToAllocate, 1); if( status != KERN_SUCCESS ) { return NULL; } else { vm_size_t logEffectiveAlign = log2int(effectiveAlign); vm_address_t lowestAvaliableAddress = p + sizeof(memalign_marker_t); vm_address_t roundedDownAddress = ((lowestAvaliableAddress >> logEffectiveAlign) << logEffectiveAlign); vm_address_t returnAddress = (roundedDownAddress == lowestAvaliableAddress) ? lowestAvaliableAddress : (roundedDownAddress + effectiveAlign); vm_address_t firstUnneededPage = 0; memalign_marker_t *marker = (memalign_marker_t *)returnAddress - 1; /* lowest address used, then round down to vm_page boundary */ vm_address_t usedPageBase = trunc_page((vm_address_t)marker); marker->start = usedPageBase; marker->size = returnAddress + size - usedPageBase; if( usedPageBase > p ) { status = vm_deallocate(mach_task_self(), p, usedPageBase - p); if( status != KERN_SUCCESS ) { fprintf(stderr, "Parrot_memalign(%zx, %zx) failed to deallocate extra header space.\n", align, size); } } firstUnneededPage = roundUpToPageBoundary(returnAddress + size); if( firstUnneededPage < p + amountToAllocate ) { status = vm_deallocate(mach_task_self(), firstUnneededPage, p + amountToAllocate - firstUnneededPage); if( status != KERN_SUCCESS ) { fprintf(stderr, "Parrot_memalign(%zx, %zx) failed to deallocate extra footer space.\n", align, size); } } return (void *)returnAddress; } } } void Parrot_free_memalign(void *p) { memalign_marker_t *marker = (memalign_marker_t *)p - 1; kern_return_t status = vm_deallocate(mach_task_self(), marker->start, marker->size); if( status != KERN_SUCCESS ) { fprintf(stderr, "Parrot_free_memalign(%p) failed!\n", p); } }
patch:
memalign.patch
Description: application/text
JEff