The Embedded New Testament

The "Holy Bible" for embedded engineers


Project maintained by theEmbeddedGeorge Hosted on GitHub Pages — Theme by mattgraham

Heap (Binary Implementation)

Usage

make
./memalign

Code

#include <stdio.h>
#include <stdlib.h>

void *aligned_memory(size_t required, size_t alignment){
	void *p1;
	void **p2;

	p1 = malloc(alignment - 1 + sizeof(void *) + required);
	p2 = (void **)(((size_t)p1 + alignment - 1 + sizeof(void *)) & ~(alignment - 1));

	p2[-1] = p1;
	return p2;
}

void free_aligned(void *p) {
	free(((void **)p)[-1]);
}

int main (int argc, char *argv[]) {
	if(argc < 3) {
		printf("Wrong input\n");
		exit(1);
	}

	int required = atoi(argv[1]);
	int alignment = atoi(argv[2]);

	void *aligned_p = aligned_memory(required, alignment);

	printf("%p\n", aligned_p);

	return 0;
}

Analysis

Alligned malloc

Since malloc is not guaranteed to align our memory for us, we’ll need to perform two extra steps:

  1. Request extra bytes so we can returned an aligned address
  2. Request extra bytes and store the offset between our original pointer and our aligned pointer

Consider the following:

Example:

Example #2 (let’s try to prove we don’t need 8):

So our worst case padding for malloc is:

sizeof(offset_t) + (alignment - 1)

Which translates to our allocation as:

uint32_t hdr_size = PTR_OFFSET_SZ + (align - 1);
void * p = malloc(size + hdr_size);

Reference

https://embeddedartistry.com/blog/2017/02/22/generating-aligned-memory/

https://codeyarns.com/tech/2017-02-28-aligned-memory-allocation.html