1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15:
16: 17: 18: 19: 20: 21: 22: 23:
24:
25: #include "mem.h"
26:
27: 28: 29: 30:
31: EXPORT size_t _mem_minfragment = sizeof(QUEUE) * 2;
32:
33: 34: 35:
36: EXPORT BOOL (*_mem_chkalloc)( void *ptr, int mode, MACB *macb );
37:
38: #define chkalloc (*_mem_chkalloc)
39:
40: 41: 42:
43: Inline size_t toPageCount( size_t size, MACB *macb )
44: {
45: return (size + (macb->pagesz-1)) / macb->pagesz;
46: }
47:
48: 49: 50: 51: 52: 53:
54: LOCAL QUEUE* searchFreeArea( size_t size, MACB *macb )
55: {
56: QUEUE *q = &macb->freeque;
57:
58: 59: 60: 61: 62:
63: if ( size > macb->pagesz / 4 ) {
64:
65: size_t fsz = 0;
66: while ( (q = q->prev) != &macb->freeque ) {
67: fsz = (size_t)FreeSize(q);
68: if ( fsz <= size ) {
69: return ( fsz < size )? q->next: q;
70: }
71: }
72: return ( fsz >= size )? q->next: q;
73: } else {
74:
75: while ( (q = q->next) != &macb->freeque ) {
76: if ( (size_t)FreeSize(q) >= size ) {
77: break;
78: }
79: }
80: return q;
81: }
82: }
83:
84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102:
103: LOCAL void appendFreeArea( QUEUE *aq, MACB *macb )
104: {
105: QUEUE *fq;
106: size_t size = (size_t)AreaSize(aq);
107:
108:
109: 110: 111: 112:
113: fq = searchFreeArea(size, macb);
114:
115:
116: clrAreaFlag(aq, AREA_USE);
117: if ( fq != &macb->freeque && (size_t)FreeSize(fq) == size ) {
118: QueInsert(aq + 1, fq + 1);
119: } else {
120: QueInsert(aq + 1, fq);
121: }
122: QueInit(aq + 2);
123: }
124:
125: 126: 127:
128: LOCAL void removeFreeQue( QUEUE *fq )
129: {
130: if ( !isQueEmpty(fq + 1) ) {
131: QUEUE *nq = (fq + 1)->next;
132:
133: QueRemove(fq + 1);
134: QueInsert(nq + 1, nq);
135: QueRemove(nq);
136: QueInsert(nq, fq);
137: }
138:
139: QueRemove(fq);
140: }
141:
142: 143: 144: 145:
146: LOCAL void insertAreaQue( QUEUE *que, QUEUE *ent )
147: {
148: ent->prev = que;
149: ent->next = que->next;
150: Assign(que->next->prev, ent);
151: que->next = ent;
152: }
153:
154: 155: 156:
157: LOCAL void removeAreaQue( QUEUE *aq )
158: {
159: Mask(aq->prev)->next = aq->next;
160: Assign(aq->next->prev, Mask(aq->prev));
161: }
162:
163: 164: 165: 166:
167: Inline QUEUE* newPage( size_t size, MACB *macb )
168: {
169: QUEUE *top, *end;
170: size_t nblk;
171:
172: if ( macb->pagesz == 0 ) {
173: return NULL;
174: }
175:
176:
177: nblk = toPageCount(size + sizeof(QUEUE)*2, macb);
178: top = (QUEUE*)(*macb->getblk)(nblk, macb->mematr);
179: if ( top == NULL ) {
180: return NULL;
181: }
182:
183:
184: end = (QUEUE*)((VB*)top + nblk * macb->pagesz) - 1;
185: insertAreaQue(&macb->areaque, end);
186: insertAreaQue(&macb->areaque, top);
187: setAreaFlag(top, AREA_TOP);
188: setAreaFlag(end, AREA_END);
189:
190: return top;
191: }
192:
193: 194: 195:
196: Inline void* allocate( QUEUE *aq, size_t size, MACB *macb )
197: {
198: QUEUE *q;
199:
200: 201:
202: if ( (size_t)AreaSize(aq) - size >= MIN_FRAGMENT + sizeof(QUEUE) ) {
203:
204:
205: q = (QUEUE*)((VB*)(aq + 1) + size);
206: insertAreaQue(aq, q);
207:
208:
209: appendFreeArea(q, macb);
210: }
211: setAreaFlag(aq, AREA_USE);
212:
213: return (void*)(aq + 1);
214: }
215:
216:
217:
218: 219: 220:
221: EXPORT void* _mem_malloc( size_t size, MACB *_macb )
222: {
223: MACB *macb = AlignMACB(_macb);
224: QUEUE *q;
225:
226: if ( macb->testmode > 0 ) {
227: chkalloc(NULL, 0, macb);
228: }
229:
230: 231:
232: if ( size > 0 && size < MIN_FRAGMENT ) {
233: size = MIN_FRAGMENT;
234: }
235:
236: size = ROUND(size);
237: if ( size <= 0 ) {
238: return NULL;
239: }
240:
241:
242: q = searchFreeArea(size, macb);
243: if ( q != &macb->freeque ) {
244:
245: removeFreeQue(q);
246:
247: q = q - 1;
248: } else {
249:
250: q = newPage(size, macb);
251: if ( q == NULL ) {
252: return NULL;
253: }
254: }
255:
256:
257: return allocate(q, size, macb);
258: }
259:
260: 261: 262:
263: EXPORT void* _mem_calloc( size_t nmemb, size_t size, MACB *macb )
264: {
265: size_t sz = nmemb * size;
266: void *p;
267:
268:
269: p = _mem_malloc(sz, macb);
270: if ( p == NULL ) {
271: return NULL;
272: }
273:
274:
275: return MEMSET(p, 0, sz);
276: }
277:
278: 279: 280:
281: EXPORT void* _mem_realloc( void *ptr, size_t size, MACB *_macb )
282: {
283: MACB *macb = AlignMACB(_macb);
284: QUEUE *aq;
285: size_t oldsz, sz;
286:
287: if ( macb->testmode > 0 ) {
288: if ( !chkalloc(ptr, 0, macb) ) {
289: return NULL;
290: }
291: }
292:
293: 294:
295: if ( size > 0 && size < MIN_FRAGMENT ) {
296: size = MIN_FRAGMENT;
297: }
298:
299: size = ROUND(size);
300:
301: aq = (QUEUE*)ptr - 1;
302:
303: if ( ptr != NULL ) {
304:
305: oldsz = (size_t)AreaSize(aq);
306:
307:
308: if ( !chkAreaFlag(aq->next, AREA_END|AREA_USE) ) {
309: removeFreeQue(aq->next + 1);
310: removeAreaQue(aq->next);
311: }
312:
313: sz = (size_t)AreaSize(aq);
314: } else {
315: sz = oldsz = 0;
316: }
317:
318: if ( size <= sz ) {
319: if ( size > 0 ) {
320:
321: allocate(aq, size, macb);
322: } else {
323:
324: _mem_free(ptr, macb);
325: ptr = NULL;
326: }
327: } else {
328:
329: void *newptr = _mem_malloc(size, macb);
330: if ( newptr == NULL ) {
331:
332: if ( ptr != NULL ) {
333: allocate(aq, oldsz, macb);
334: }
335: return NULL;
336: }
337:
338: if ( ptr != NULL ) {
339:
340: MEMCPY(newptr, ptr, oldsz);
341:
342:
343: _mem_free(ptr, macb);
344: }
345: ptr = newptr;
346: }
347:
348: return ptr;
349: }
350:
351: 352: 353:
354: EXPORT void _mem_free( void *ptr, MACB *_macb )
355: {
356: MACB *macb = AlignMACB(_macb);
357: QUEUE *aq;
358:
359: if ( ptr == NULL ) {
360: return;
361: }
362:
363: if ( macb->testmode > 0 ) {
364: if ( !chkalloc(ptr, 0, macb) ) {
365: return;
366: }
367: }
368:
369: aq = (QUEUE*)ptr - 1;
370: clrAreaFlag(aq, AREA_USE);
371:
372: if ( !chkAreaFlag(aq->next, AREA_END|AREA_USE) ) {
373:
374: removeFreeQue(aq->next + 1);
375: removeAreaQue(aq->next);
376: }
377:
378: if ( !chkAreaFlag(aq, AREA_TOP) && !chkAreaFlag(aq->prev, AREA_USE) ) {
379:
380: aq = aq->prev;
381: removeFreeQue(aq + 1);
382: removeAreaQue(aq->next);
383: }
384:
385:
386: if ( chkAreaFlag(aq, AREA_TOP) && chkAreaFlag(aq->next, AREA_END) ) {
387:
388: removeAreaQue(aq->next);
389: removeAreaQue(aq);
390: (*macb->relblk)(aq);
391: } else {
392:
393: appendFreeArea(aq, macb);
394: }
395: }