align_ptr.h 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. #ifndef ALIGN_PTR_H_
  2. #define ALIGN_PTR_H_
  3. #include <stddef.h>
  4. #include <stdint.h>
  5. /**
  6. * ALIGN_PTR_DECL(type, name, num, alignsize):
  7. * Declare a pointer called ${name}, which points to an array large enough to
  8. * contain ${num} values of ${type} and is aligned to ${alignsize} bytes. The
  9. * pointer must not be used until ALIGN_PTR_INIT(${name}, ${alignsize}) has
  10. * been called. This macro may also create an additional variable called
  11. * "${name}_buf".
  12. */
  13. #define ALIGN_PTR_DECL(type, name, num, alignsize) \
  14. uint8_t name##_buf[num * sizeof(type) + (alignsize - 1)]; \
  15. type * name
  16. /**
  17. * ALIGN_PTR_INIT(name, alignsize):
  18. * Initialize the variable called ${name} to point to an array which is
  19. * aligned to ${alignsize} bytes. They must have previously been declared
  20. * with ALIGN_PTR_DECL(${name}, ${alignsize}). This macro assumes that
  21. * casting a pointer to uintptr_t behaves naturally, i.e. yields a byte offset
  22. * relative to aligned memory.
  23. */
  24. #define ALIGN_PTR_INIT(name, alignsize) \
  25. name = align_ptr(name##_buf, alignsize)
  26. /**
  27. * align_ptr(arr, alignment):
  28. * Return a pointer to the first memory location within ${arr} which is
  29. * aligned to ${alignsize} bytes. (It is expected that this function will
  30. * only be called via the ALIGN_PTR_INIT macro).
  31. */
  32. static inline void *
  33. align_ptr(uint8_t * arr, size_t alignment)
  34. {
  35. size_t offset;
  36. /*
  37. * This assumes that casting a pointer to uintptr_t behaves naturally,
  38. * i.e. yields a byte offset relative to aligned memory.
  39. */
  40. offset = (uintptr_t)(&arr[0]) % alignment;
  41. offset = (alignment - offset) % alignment;
  42. /* Return the aligned pointer. */
  43. return ((void *)&arr[offset]);
  44. }
  45. #endif /* !ALIGN_PTR_H_ */