1 #include <stdlib.h>
2 #include <stdint.h>
3 #include <errno.h>
4 #include "libc.h"
5 #include "pthread_impl.h"
6 #include "oldmalloc/malloc_impl.h"
7
lock(volatile int * lk)8 static inline void lock(volatile int *lk)
9 {
10 if (libc.threads_minus_1)
11 while(a_swap(lk, 1)) __wait(lk, lk+1, 1, 1);
12 }
13
unlock(volatile int * lk)14 static inline void unlock(volatile int *lk)
15 {
16 if (lk[0]) {
17 a_store(lk, 0);
18 if (lk[1]) __wake(lk, 1, 1);
19 }
20 }
21
__memalign(size_t align,size_t len)22 void *__memalign(size_t align, size_t len)
23 {
24 unsigned char *mem, *new;
25
26 if ((align & -align) != align) {
27 errno = EINVAL;
28 return 0;
29 }
30
31 if (len > SIZE_MAX - align || __malloc_replaced) {
32 errno = ENOMEM;
33 return 0;
34 }
35
36 if (align <= SIZE_ALIGN)
37 return malloc(len);
38
39 if (!(mem = malloc(len + align-1)))
40 return 0;
41
42 new = (void *)((uintptr_t)mem + align-1 & -align);
43 if (new == mem) return mem;
44
45 struct chunk *c = MEM_TO_CHUNK(mem);
46 struct chunk *n = MEM_TO_CHUNK(new);
47
48 if (g_enable_check) {
49 int status = delete_node(mem);
50 if (status != 0) {
51 get_free_trace(mem);
52 a_crash();
53 }
54 }
55
56 if (IS_MMAPPED(c)) {
57 /* Apply difference between aligned and original
58 * address to the "extra" field of mmapped chunk. */
59 n->psize = c->psize + (new-mem);
60 n->csize = c->csize - (new-mem);
61 if (g_enable_check) {
62 insert_node(CHUNK_TO_MEM(n), CHUNK_SIZE(n));
63 }
64 return new;
65 }
66
67 struct chunk *t = NEXT_CHUNK(c);
68
69 /* Split the allocated chunk into two chunks. The aligned part
70 * that will be used has the size in its footer reduced by the
71 * difference between the aligned and original addresses, and
72 * the resulting size copied to its header. A new header and
73 * footer are written for the split-off part to be freed. */
74 lock(g_mem_lock);
75 n->psize = c->csize = C_INUSE | (new-mem);
76 n->csize = t->psize -= new-mem;
77 calculate_checksum(c, n);
78 calculate_checksum(NULL, t);
79 unlock(g_mem_lock);
80 if (g_enable_check) {
81 insert_node(CHUNK_TO_MEM(n), CHUNK_SIZE(n));
82 }
83
84 __bin_chunk(c);
85 return new;
86 }
87
88 weak_alias(__memalign, memalign);
89