]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/alloc.c
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / libc / stdlib / malloc-simple / alloc.c
1 /* 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
22 void *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
52 void * 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
76 void *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
98 extern int weak_function __libc_free_aligned(void *ptr);
99 void 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 */
120 struct 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 };
126 struct alignlist *_aligned_blocks;
127
128 /* Return memory to the heap. */
129 int __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 }
150 void * 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;
179 DONE:
180                 __MALLOC_UNLOCK;
181         }
182
183         return result;
184 }
185 #endif