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