blob: 914c89dc050fce8c4bebb9d38821d5fa5e79d17f [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* alloc.c
2 *
3 * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
4 *
5 * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
6 */
7/*
8 * Parts of the memalign code were stolen from malloc-930716.
9 */
10
11#include <features.h>
12#include <unistd.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <errno.h>
17#include <sys/mman.h>
18#include <malloc.h>
19
20
21#ifdef L_malloc
22void *malloc(size_t size)
23{
24 void *result;
25
26 if (unlikely(size == 0)) {
27#if defined(__MALLOC_GLIBC_COMPAT__)
28 size++;
29#else
30 /* Some programs will call malloc (0). Lets be strict and return NULL */
31 __set_errno(ENOMEM);
32 return NULL;
33#endif
34 }
35
36#ifdef __ARCH_USE_MMU__
37# define MMAP_FLAGS MAP_PRIVATE | MAP_ANONYMOUS
38#else
39# define MMAP_FLAGS MAP_SHARED | MAP_ANONYMOUS | MAP_UNINITIALIZE
40#endif
41
42 result = mmap((void *) 0, size + sizeof(size_t), PROT_READ | PROT_WRITE,
43 MMAP_FLAGS, 0, 0);
44 if (result == MAP_FAILED)
45 return 0;
46 * (size_t *) result = size;
47 return(result + sizeof(size_t));
48}
49#endif
50
51#ifdef L_calloc
52void * calloc(size_t nmemb, size_t lsize)
53{
54 void *result;
55 size_t size=lsize * nmemb;
56
57 /* guard vs integer overflow, but allow nmemb
58 * to fall through and call malloc(0) */
59 if (nmemb && lsize != (size / nmemb)) {
60 __set_errno(ENOMEM);
61 return NULL;
62 }
63 result = malloc(size);
64
65#ifndef __ARCH_USE_MMU__
66 /* mmap'd with MAP_UNINITIALIZE, we have to blank memory ourselves */
67 if (result != NULL) {
68 memset(result, 0, size);
69 }
70#endif
71 return result;
72}
73#endif
74
75#ifdef L_realloc
76void *realloc(void *ptr, size_t size)
77{
78 void *newptr = NULL;
79
80 if (!ptr)
81 return malloc(size);
82 if (!size) {
83 free(ptr);
84 return malloc(0);
85 }
86
87 newptr = malloc(size);
88 if (newptr) {
89 size_t old_size = *((size_t *) (ptr - sizeof(size_t)));
90 memcpy(newptr, ptr, (old_size < size ? old_size : size));
91 free(ptr);
92 }
93 return newptr;
94}
95#endif
96
97#ifdef L_free
98extern int weak_function __libc_free_aligned(void *ptr);
99void free(void *ptr)
100{
101 if (unlikely(ptr == NULL))
102 return;
103 if (unlikely(__libc_free_aligned != NULL)) {
104 if (__libc_free_aligned(ptr))
105 return;
106 }
107 ptr -= sizeof(size_t);
108 munmap(ptr, * (size_t *) ptr + sizeof(size_t));
109}
110#endif
111
112#ifdef L_memalign
113
114#include <bits/uClibc_mutex.h>
115__UCLIBC_MUTEX_INIT(__malloc_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
116#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock)
117#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock)
118
119/* List of blocks allocated with memalign or valloc */
120struct alignlist
121{
122 struct alignlist *next;
123 __ptr_t aligned; /* The address that memaligned returned. */
124 __ptr_t exact; /* The address that malloc returned. */
125};
126struct alignlist *_aligned_blocks;
127
128/* Return memory to the heap. */
129int __libc_free_aligned(void *ptr)
130{
131 struct alignlist *l;
132
133 if (ptr == NULL)
134 return 0;
135
136 __MALLOC_LOCK;
137 for (l = _aligned_blocks; l != NULL; l = l->next) {
138 if (l->aligned == ptr) {
139 /* Mark the block as free */
140 l->aligned = NULL;
141 ptr = l->exact;
142 ptr -= sizeof(size_t);
143 munmap(ptr, * (size_t *) ptr + sizeof(size_t));
144 return 1;
145 }
146 }
147 __MALLOC_UNLOCK;
148 return 0;
149}
150void * memalign (size_t alignment, size_t size)
151{
152 void * result;
153 unsigned long int adj;
154
155 result = malloc (size + alignment - 1);
156 if (result == NULL)
157 return NULL;
158
159 adj = (unsigned long int) ((unsigned long int) ((char *) result - (char *) NULL)) % alignment;
160 if (adj != 0) {
161 struct alignlist *l;
162 __MALLOC_LOCK;
163 for (l = _aligned_blocks; l != NULL; l = l->next)
164 if (l->aligned == NULL)
165 /* This slot is free. Use it. */
166 break;
167 if (l == NULL) {
168 l = (struct alignlist *) malloc (sizeof (struct alignlist));
169 if (l == NULL) {
170 free(result);
171 result = NULL;
172 goto DONE;
173 }
174 l->next = _aligned_blocks;
175 _aligned_blocks = l;
176 }
177 l->exact = result;
178 result = l->aligned = (char *) result + alignment - adj;
179DONE:
180 __MALLOC_UNLOCK;
181 }
182
183 return result;
184}
185#endif