Rob Norris
twisty passages, all aligned
I just finished implementing posix_memalign()
. It will help with JavaScriptCore porting, as its allocator/garbage collector wants to do lots of memory tricks, including unusual alignments. I’ll write more about my WebKit porting progress later.
I love doing pointer arithmetic. It spices up C so that I feel like I’m writing Perl one-liners:
int posix_memalign (void **memptr, size_t alignment, size_t size) {
UBYTE *mem = NULL, *orig;
/* check the alignment is valid */
if (alignment % sizeof(void *) != 0 || !powerof2(alignment))
return EINVAL;
/* allocate enough space to satisfy the alignment and save some info */
mem = AllocPooled(__startup_mempool, size + alignment + AROS_ALIGN(sizeof(size_t)) + AROS_ALIGN(sizeof(void *)));
if (mem == NULL)
return ENOMEM;
/* store the size for free(). it will add sizeof(size_t) itself */
*((size_t *) mem) = size + alignment + AROS_ALIGN(sizeof(void *));
mem += AROS_ALIGN(sizeof(size_t));
/* if its already aligned correctly, then we just use it as-is */
if (((IPTR) mem & (alignment-1)) == 0) {
*memptr = mem;
return 0;
}
orig = mem;
/* move forward to an even alignment boundary */
mem = (UBYTE *) (((IPTR) mem + alignment - 1) & -alignment);
/* store a magic number in the place that free() will look for the
* allocation size, so it can handle this specially */
((size_t *) mem)[-1] = MEMALIGN_MAGIC;
/* then store the original pointer before it, for free() to find */
((void **) &(((size_t *) mem)[-1]))[-1] = orig;
*memptr = mem;
return 0;
}