memalign.c 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. #include <stdlib.h>
  2. #include <stdint.h>
  3. #include <errno.h>
  4. #include "libc.h"
  5. /* This function should work with most dlmalloc-like chunk bookkeeping
  6. * systems, but it's only guaranteed to work with the native implementation
  7. * used in this library. */
  8. void *__memalign(size_t align, size_t len)
  9. {
  10. unsigned char *mem, *new, *end;
  11. size_t header, footer;
  12. if ((align & -align) != align) {
  13. errno = EINVAL;
  14. return NULL;
  15. }
  16. if (len > SIZE_MAX - align) {
  17. errno = ENOMEM;
  18. return NULL;
  19. }
  20. if (align <= 4*sizeof(size_t)) {
  21. if (!(mem = malloc(len)))
  22. return NULL;
  23. return mem;
  24. }
  25. if (!(mem = malloc(len + align-1)))
  26. return NULL;
  27. new = (void *)((uintptr_t)mem + align-1 & -align);
  28. if (new == mem) return mem;
  29. header = ((size_t *)mem)[-1];
  30. if (!(header & 7)) {
  31. ((size_t *)new)[-2] = ((size_t *)mem)[-2] + (new-mem);
  32. ((size_t *)new)[-1] = ((size_t *)mem)[-1] - (new-mem);
  33. return new;
  34. }
  35. end = mem + (header & -8);
  36. footer = ((size_t *)end)[-2];
  37. ((size_t *)mem)[-1] = header&7 | new-mem;
  38. ((size_t *)new)[-2] = footer&7 | new-mem;
  39. ((size_t *)new)[-1] = header&7 | end-new;
  40. ((size_t *)end)[-2] = footer&7 | end-new;
  41. free(mem);
  42. return new;
  43. }
  44. weak_alias(__memalign, memalign);