Commit | Line | Data |
---|---|---|
3144ee8a AT |
1 | /* -*- mode: c; tab-width: 4; fill-column: 128 -*- */ |
2 | /* vi: set ts=4 tw=128: */ | |
3 | ||
4 | /* | |
5 | aligned_malloc.c, Copyright (c) 2014 Dave Odell <dmo2118@gmail.com> | |
6 | ||
7 | Permission to use, copy, modify, distribute, and sell this software and its | |
8 | documentation for any purpose is hereby granted without fee, provided that | |
9 | the above copyright notice appear in all copies and that both that | |
10 | copyright notice and this permission notice appear in supporting | |
11 | documentation. No representations are made about the suitability of this | |
12 | software for any purpose. It is provided "as is" without express or | |
13 | implied warranty. | |
14 | */ | |
15 | ||
16 | #include "aligned_malloc.h" | |
17 | ||
18 | #include <stddef.h> | |
19 | #include <stdlib.h> | |
20 | ||
21 | #include <assert.h> | |
22 | #include <errno.h> | |
23 | ||
24 | /* aligned_alloc() (C11) or posix_memalign() (POSIX) are other possibilities | |
25 | for aligned_malloc(). | |
26 | */ | |
27 | ||
28 | int aligned_malloc(void **ptr, unsigned alignment, size_t size) | |
29 | { | |
30 | void *block_start; | |
31 | ptrdiff_t align1 = alignment - 1; | |
32 | ||
33 | assert(alignment && !(alignment & (alignment - 1))); /* alignment must be a power of two. */ | |
34 | ||
35 | size += sizeof(void *) + align1; | |
36 | block_start = malloc(size); | |
37 | if(!block_start) | |
38 | return ENOMEM; | |
39 | *ptr = (void *)(((ptrdiff_t)block_start + sizeof(void *) + align1) & ~align1); | |
40 | ((void **)(*ptr))[-1] = block_start; | |
41 | return 0; | |
42 | } | |
43 | ||
44 | void aligned_free(void *ptr) | |
45 | { | |
46 | if(ptr) | |
47 | free(((void **)(ptr))[-1]); | |
48 | } |