Embedded Artistry libmemory
Memory library for embedded systems (malloc and friends)
aligned_malloc.c
Go to the documentation of this file.
1 /*
2  * Copyright © 2017 Embedded Artistry LLC.
3  * License: MIT. See LICENSE file for details.
4  */
5 
6 #include <assert.h>
7 #include <stdbool.h>
8 #include <stdint.h>
9 #include <stdlib.h>
10 
11 #include "aligned_malloc.h"
12 #include "malloc.h"
13 
14 #pragma mark - Definitions -
15 
20 #ifndef align_up
21 #define align_up(num, align) (((num) + ((align)-1)) & ~((align)-1))
22 #endif
23 
25 typedef uint16_t offset_t;
26 
28 #define PTR_OFFSET_SZ sizeof(offset_t)
29 
30 #pragma mark - APIs -
31 
36 void* aligned_malloc(size_t align, size_t size)
37 {
38  void* ptr = NULL;
39 
40  // We want it to be a power of two since align_up operates on powers of two
41  assert((align & (align - 1)) == 0);
42 
43  if(align && size)
44  {
45  /*
46  * We know we have to fit an offset value
47  * We also allocate extra bytes to ensure we can meet the alignment
48  */
49  size_t hdr_size = PTR_OFFSET_SZ + (align - 1);
50  void* p = malloc(size + hdr_size);
51 
52  if(p)
53  {
54  /*
55  * Add the offset size to malloc's pointer (we will always store that)
56  * Then align the resulting value to the arget alignment
57  */
58  ptr = (void*)align_up(((uintptr_t)p + PTR_OFFSET_SZ), align);
59 
60  // Calculate the offset and store it behind our aligned pointer
61  *((offset_t*)ptr - 1) = (offset_t)((uintptr_t)ptr - (uintptr_t)p);
62 
63  } // else NULL, could not malloc
64  } // else NULL, invalid arguments
65 
66  return ptr;
67 }
68 
74 void aligned_free(void* ptr)
75 {
76  assert(ptr);
77 
78  /*
79  * Walk backwards from the passed-in pointer to get the pointer offset
80  * We convert to an offset_t pointer and rely on pointer math to get the data
81  */
82  offset_t offset = *((offset_t*)ptr - 1);
83 
84  /*
85  * Once we have the offset, we can get our original pointer and call free
86  */
87  void* p = (void*)((uint8_t*)ptr - offset);
88  free(p);
89 }
void * aligned_malloc(size_t align, size_t size)
Allocated aligned memory.
void aligned_free(void *ptr)
Free aligned memory.
void * malloc(size_t __attribute__((unused)) size)
Definition: malloc_assert.c:17
uint16_t offset_t
Number of bytes we're using for storing the aligned pointer offset.
#define PTR_OFFSET_SZ
Macro for accessing the size of our current pointer offset.
void free(void *__attribute__((unused)) ptr)
Definition: malloc_assert.c:23
#define align_up(num, align)