ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/microscheme/malloc.c
(Generate patch)

Comparing microscheme/malloc.c (file contents):
Revision 1.1 by root, Sat Nov 28 05:57:08 2015 UTC vs.
Revision 1.2 by root, Wed Dec 2 07:43:46 2015 UTC

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
42typedef struct { 40typedef 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
60static void REGPARM(1) *do_mmap(size_t size) { 58static 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
66static __alloc_t* __small_mem[8]; 64static 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
77static inline int __ind_shift() { return (MEM_BLOCK_SIZE==4096)?4:5; } 75static inline int ind_shift() { return (MEM_BLOCK_SIZE==4096)?4:5; }
78 76
79static size_t REGPARM(1) get_index(size_t _size) { 77static 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 */
89static void __small_free(void*_ptr,size_t _size) REGPARM(2); 87static void small_free(void*_ptr,size_t _size) REGPARM(2);
90 88
91static void REGPARM(2) __small_free(void*_ptr,size_t _size) { 89static 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
108static void* REGPARM(1) __small_malloc(size_t _size) { 106static 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
142void free(void *ptr) { 140void 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
155void* malloc(size_t size) { 153void* 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);
172err_out: 170err_out:
173 //(*__errno_location())=ENOMEM; 171 //(*errno_location())=ENOMEM;
174 return 0; 172 return 0;
175} 173}
176 174
175#if 0
177void* calloc(size_t nmemb, size_t _size) { 176void* 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
193void* realloc(void* ptr, size_t _size) { 193void* 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) {
218retzero: 218retzero:
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);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines