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