ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/microscheme/malloc.c
Revision: 1.2
Committed: Wed Dec 2 07:43:46 2015 UTC (8 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +50 -50 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 * malloc/free by O.Dreesen
3 *
4 * first TRY:
5 * lists w/magics
6 * and now the second TRY
7 * let the kernel map all the stuff (if there is something to do)
8 */
9
10 #include <unistd.h>
11 #include <sys/mman.h>
12 #include <errno.h>
13
14 #include <sys/types.h>
15 #include <stddef.h>
16 #include <stdlib.h>
17 #include <string.h>
18
19 #include <limits.h>
20 //#include <sys/shm.h> /* for PAGE_SIZE */
21
22 #ifndef PAGE_SIZE
23 #define PAGE_SIZE sysconf (_SC_PAGESIZE)
24 #endif
25
26 #ifndef MREMAP_MAYMOVE
27 #define MREMAP_MAYMOVE 1
28 #endif
29
30 /* -- HELPER CODE --------------------------------------------------------- */
31
32 #ifndef MAP_FAILED
33 #define MAP_FAILED ((void*)-1)
34 #endif
35
36 #ifndef NULL
37 #define NULL ((void*)0)
38 #endif
39
40 typedef struct {
41 void* next;
42 size_t size;
43 } alloc_t;
44
45 #define BLOCK_START(b) (((void*)(b))-sizeof(alloc_t))
46 #define BLOCK_RET(b) (((void*)(b))+sizeof(alloc_t))
47
48 #define MEM_BLOCK_SIZE PAGE_SIZE
49 #define PAGE_ALIGN(s) (((s)+MEM_BLOCK_SIZE-1)&(unsigned long)(~(MEM_BLOCK_SIZE-1)))
50
51 /* a simple mmap :) */
52 #if defined(i386)
53 #define REGPARM(x) attribute((regparm(x)))
54 #else
55 #define REGPARM(x)
56 #endif
57
58 static void REGPARM(1) *do_mmap(size_t size) {
59 return mmap(0, size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, (size_t)0);
60 }
61
62 /* -- SMALL MEM ----------------------------------------------------------- */
63
64 static alloc_t* small_mem[8];
65
66 #define SMALL_NR(i) (MEM_BLOCK_SIZE/(i))
67
68 #define MIN_SMALL_SIZE SMALL_NR(256) /* 16 / 32 */
69 #define MAX_SMALL_SIZE SMALL_NR(2) /* 2048 / 4096 */
70
71 #define GET_SIZE(s) (MIN_SMALL_SIZE<<get_index((s)))
72
73 #define FIRST_SMALL(p) (((unsigned long)(p))&(~(MEM_BLOCK_SIZE-1)))
74
75 static inline int ind_shift() { return (MEM_BLOCK_SIZE==4096)?4:5; }
76
77 static size_t REGPARM(1) get_index(size_t _size) {
78 register size_t idx=0;
79 // if (_size) { /* we already check this in the callers */
80 register size_t size=((_size-1)&(MEM_BLOCK_SIZE-1))>>ind_shift();
81 while(size) { size>>=1; ++idx; }
82 // }
83 return idx;
84 }
85
86 /* small mem */
87 static void small_free(void*_ptr,size_t _size) REGPARM(2);
88
89 static void REGPARM(2) small_free(void*_ptr,size_t _size) {
90 alloc_t* ptr=BLOCK_START(_ptr);
91 size_t size=_size;
92 size_t idx=get_index(size);
93
94 #ifdef WANT_FREE_OVERWRITE
95 memset(ptr,0x55,size); /* allways zero out small mem */
96 #else
97 #if 0
98 memset(ptr,0,size); /* allways zero out small mem */
99 #endif
100 #endif
101
102 ptr->next=small_mem[idx];
103 small_mem[idx]=ptr;
104 }
105
106 static void* REGPARM(1) small_malloc(size_t _size) {
107 alloc_t *ptr;
108 size_t size=_size;
109 size_t idx;
110
111 idx=get_index(size);
112 ptr=small_mem[idx];
113
114 if (ptr==0) { /* no free blocks ? */
115 register int i,nr;
116 ptr=do_mmap(MEM_BLOCK_SIZE);
117 if (ptr==MAP_FAILED) return MAP_FAILED;
118
119 small_mem[idx]=ptr;
120
121 nr=SMALL_NR(size)-1;
122 for (i=0;i<nr;i++) {
123 ptr->next=(((void*)ptr)+size);
124 ptr=ptr->next;
125 }
126 ptr->next=0;
127
128 ptr=small_mem[idx];
129 }
130
131 /* get a free block */
132 small_mem[idx]=ptr->next;
133 ptr->next=0;
134
135 return ptr;
136 }
137
138 /* -- PUBLIC FUNCTIONS ---------------------------------------------------- */
139
140 void tiny_free(void *ptr) {
141 register size_t size;
142 if (ptr) {
143 size=((alloc_t*)BLOCK_START(ptr))->size;
144 if (size) {
145 if (size<=MAX_SMALL_SIZE)
146 small_free(ptr,size);
147 else
148 munmap(BLOCK_START(ptr),size);
149 }
150 }
151 }
152
153 void* tiny_malloc(size_t size) {
154 alloc_t* ptr;
155 size_t need;
156 if (!size) goto err_out;
157 size+=sizeof(alloc_t);
158 if (size<sizeof(alloc_t)) goto err_out;
159 if (size<=MAX_SMALL_SIZE) {
160 need=GET_SIZE(size);
161 ptr=small_malloc(need);
162 }
163 else {
164 need=PAGE_ALIGN(size);
165 if (!need) ptr=MAP_FAILED; else ptr=do_mmap(need);
166 }
167 if (ptr==MAP_FAILED) goto err_out;
168 ptr->size=need;
169 return BLOCK_RET(ptr);
170 err_out:
171 //(*errno_location())=ENOMEM;
172 return 0;
173 }
174
175 #if 0
176 void* tiny_calloc(size_t nmemb, size_t _size) {
177 register size_t size=_size*nmemb;
178 if (nmemb && size/nmemb!=_size) {
179 //(*errno_location())=ENOMEM;
180 return 0;
181 }
182 #ifdef WANT_FREE_OVERWRITE
183 if (size<MAX_SMALL_SIZE) {
184 void* x=malloc(size);
185 memset(x,0,size);
186 return x;
187 } else
188 #endif
189 return malloc(size);
190 }
191 #endif
192
193 void* tiny_realloc(void* ptr, size_t _size) {
194 register size_t size=_size;
195 if (ptr) {
196 if (size) {
197 alloc_t* tmp=BLOCK_START(ptr);
198 size+=sizeof(alloc_t);
199 if (size<sizeof(alloc_t)) goto retzero;
200 size=(size<=MAX_SMALL_SIZE)?GET_SIZE(size):PAGE_ALIGN(size);
201 if (tmp->size!=size) {
202 if ((tmp->size<=MAX_SMALL_SIZE)) {
203 void *new=malloc(_size);
204 if (new) {
205 register alloc_t* foo=BLOCK_START(new);
206 size=foo->size;
207 if (size>tmp->size) size=tmp->size;
208 if (size) memcpy(new,ptr,size-sizeof(alloc_t));
209 free(ptr);
210 }
211 ptr=new;
212 }
213 else {
214 register alloc_t* foo;
215 size=PAGE_ALIGN(size);
216 foo=mremap(tmp,tmp->size,size,MREMAP_MAYMOVE);
217 if (foo==MAP_FAILED) {
218 retzero:
219 //(*errno_location())=ENOMEM;
220 ptr=0;
221 }
222 else {
223 foo->size=size;
224 ptr=BLOCK_RET(foo);
225 }
226 }
227 }
228 }
229 else { /* size==0 */
230 free(ptr);
231 ptr = NULL;
232 }
233 }
234 else { /* ptr==0 */
235 if (size) {
236 ptr=malloc(size);
237 }
238 }
239 return ptr;
240 }
241