Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to obtain blocks with large alignment?

To avoid maintaining complex data structures, I want to allocate blocks with quite large alignment (say some kilobytes, possibly megabytes, always by power of two). This allows me to mask the lower bits of a pointer to easily retrieve the address of the beginning of the block it points in.

I'd like a method to guarantee the allocation of such a block with specified alignment, eg. to allocate 4096 byte blocks with 4096 byte alignment. For the method to work, the alignment will always be the size of the blocks, so memory waste is expected to be a concern in the long run.

I'm using C++ (so C and C++ techniques are fine), and any solution should be portable across common desktop environments. Should there be no portable solution, Linux has highest priority.

I'm aware of Win32 memory allocation with large alignment, but if there is a common C library which does this with one function call, I'd happily use it.

Background: I'm experimenting with the Vlist structures described there (ultimate goal is a sort of Scheme interpreter), and I'm currently implementing garbage collection for those lists. I need the quite large memory blocks as arenas for the garbage collector. Should I change the GC technique, I still need the VList blocks to have 32 byte alignment (I'm performing my experiments on 64bit machines).

like image 332
Alexandre C. Avatar asked Jan 14 '12 14:01

Alexandre C.


1 Answers

I'm not aware of a fully portable solution. But _mm_malloc() and _mm_free() seem to be supported by ICC, GCC, and MSVC.

This was added as part of the aligned memory support for SSE intrinsics.


Otherwise, you could implement your own fairly easily:

void* my_malloc(size_t bytes,size_t align){

    void *ptr = malloc(bytes + align + sizeof(intptr_t));

    if (ptr == NULL)
        return NULL;

    //  Get aligned return address
    intptr_t *ret = (intptr_t*)((((intptr_t)ptr + sizeof(intptr_t)) & ~(intptr_t)(align - 1)) + align);

    //  Save the free pointer
    ret[-1] = (intptr_t)ptr;

    return ret;
}

void my_free(void *ptr){
    if (ptr == NULL)
        return;

    //  Get the free pointer
    ptr = (void*)(((intptr_t*)ptr)[-1]);

    free(ptr); 
}
like image 165
Mysticial Avatar answered Sep 29 '22 04:09

Mysticial