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: #include "sysmgr.h"
53: #include <sys/imalloc.h>
54: #include <sys/queue.h>
55: #include "cpu_conf.h"
56:
57: #if defined(USE_MMU) && defined(MMU_MIN_USER_LEVEL)
58: #define IMALLOC_MIN_USER_LEVEL MMU_MIN_USER_LEVEL
59: #else
60: #define IMALLOC_MIN_USER_LEVEL 3
61: #endif
62:
63: 64: 65:
66: typedef struct {
67: const QUEUE nouse;
68:
69: 70: 71:
72: QUEUE areaque;
73: 74:
75: QUEUE freeque;
76:
77: UINT mematr;
78: } IMACB;
79:
80: 81: 82:
83: #define AlignIMACB(imacb) ( (IMACB*)((UW)(imacb) & ~0x00000007U) )
84:
85: LOCAL UINT pagesz;
86:
87: 88: 89: 90: 91: 92:
93: #define ROUNDSZ ( sizeof(QUEUE) )
94: #define ROUND(sz) ( ((sz) + (ROUNDSZ-1)) & ~(ROUNDSZ-1) )
95:
96:
97: #define MIN_FRAGMENT ( sizeof(QUEUE) * 2 )
98:
99: 100: 101:
102: #define AREA_USE 0x00000001U
103: #define AREA_TOP 0x00000002U
104: #define AREA_END 0x00000004U
105: #define AREA_MASK 0x00000007U
106:
107: #define setAreaFlag(q, f) ( (q)->prev = (QUEUE*)((UW)(q)->prev | (f)) )
108: #define clrAreaFlag(q, f) ( (q)->prev = (QUEUE*)((UW)(q)->prev & ~(f)) )
109: #define chkAreaFlag(q, f) ( ((UW)(q)->prev & (f)) != 0 )
110:
111: #define Mask(x) ( (QUEUE*)((UW)(x) & ~AREA_MASK) )
112: #define Assign(x, y) ( (x) = (QUEUE*)(((UW)(x) & AREA_MASK) | (UW)(y)) )
113:
114: 115: 116:
117: #define AreaSize(aq) ((size_t)( (VB*)(aq)->next - (VB*)((aq) + 1) ))
118: #define FreeSize(fq) ((size_t)( (VB*)((fq) - 1)->next - (VB*)(fq) ))
119:
120: 121: 122:
123: Inline size_t PageCount( size_t size )
124: {
125: return (size + (pagesz-1)) / pagesz;
126: }
127:
128: 129: 130: 131: 132: 133:
134: LOCAL QUEUE* searchFreeArea( size_t blksz, IMACB *imacb )
135: {
136: QUEUE *q = &imacb->freeque;
137:
138: 139:
140: if ( blksz > pagesz / 4 ) {
141:
142: size_t fsz = 0;
143: while ( (q = q->prev) != &imacb->freeque ) {
144: fsz = FreeSize(q);
145: if ( fsz <= blksz ) {
146: return ( fsz < blksz )? q->next: q;
147: }
148: }
149: return ( fsz >= blksz )? q->next: q;
150: } else {
151:
152: while ( (q = q->next) != &imacb->freeque ) {
153: if ( FreeSize(q) >= blksz ) {
154: break;
155: }
156: }
157: return q;
158: }
159: }
160:
161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179:
180: LOCAL void appendFreeArea( QUEUE *aq, IMACB *imacb )
181: {
182: QUEUE *fq;
183: size_t size = AreaSize(aq);
184:
185:
186: 187: 188: 189:
190: fq = searchFreeArea(size, imacb);
191:
192:
193: clrAreaFlag(aq, AREA_USE);
194: if ( fq != &imacb->freeque && FreeSize(fq) == size ) {
195: QueInsert(aq + 1, fq + 1);
196: } else {
197: QueInsert(aq + 1, fq);
198: }
199: QueInit(aq + 2);
200: }
201:
202: 203: 204:
205: LOCAL void removeFreeQue( QUEUE *fq )
206: {
207: if ( !isQueEmpty(fq + 1) ) {
208: QUEUE *nq = (fq + 1)->next;
209:
210: QueRemove(fq + 1);
211: QueInsert(nq + 1, nq);
212: QueRemove(nq);
213: QueInsert(nq, fq);
214: }
215:
216: QueRemove(fq);
217: }
218:
219: 220: 221: 222:
223: LOCAL void insertAreaQue( QUEUE *que, QUEUE *ent )
224: {
225: ent->prev = que;
226: ent->next = que->next;
227: Assign(que->next->prev, ent);
228: que->next = ent;
229: }
230:
231: 232: 233:
234: LOCAL void removeAreaQue( QUEUE *aq )
235: {
236: Mask(aq->prev)->next = aq->next;
237: Assign(aq->next->prev, Mask(aq->prev));
238: }
239:
240: 241: 242:
243: Inline void* mem_alloc( QUEUE *aq, size_t blksz, IMACB *imacb )
244: {
245: QUEUE *q;
246:
247: 248:
249: if ( AreaSize(aq) - blksz >= MIN_FRAGMENT + sizeof(QUEUE) ) {
250:
251:
252: q = (QUEUE*)((VB*)(aq + 1) + blksz);
253: insertAreaQue(aq, q);
254:
255:
256: appendFreeArea(q, imacb);
257: }
258: setAreaFlag(aq, AREA_USE);
259:
260: return (void*)(aq + 1);
261: }
262:
263: 264: 265:
266: LOCAL void* imalloc( size_t size, IMACB *imacb )
267: {
268: QUEUE *q;
269: void *mem;
270: UW imask;
271:
272: 273:
274: if ( size < MIN_FRAGMENT ) {
275: size = MIN_FRAGMENT;
276: }
277: size = ROUND(size);
278:
279: DI(imask);
280:
281:
282: q = searchFreeArea(size, imacb);
283: if ( q != &imacb->freeque ) {
284:
285: removeFreeQue(q);
286:
287: q = q - 1;
288: } else {
289:
290: QUEUE *e;
291: size_t n;
292:
293:
294: EI(imask);
295: n = PageCount(size + sizeof(QUEUE) * 2);
296: q = GetSysMemBlk(n, imacb->mematr);
297: if ( q == NULL ) {
298: goto err_ret;
299: }
300: DI(imask);
301:
302:
303: e = (QUEUE*)((VB*)q + n * pagesz) - 1;
304: insertAreaQue(&imacb->areaque, e);
305: insertAreaQue(&imacb->areaque, q);
306: setAreaFlag(q, AREA_TOP);
307: setAreaFlag(e, AREA_END);
308: }
309:
310:
311: mem = mem_alloc(q, size, imacb);
312:
313: EI(imask);
314: return mem;
315:
316: err_ret:
317: TM_DEBUG_PRINT(("imalloc error\n"));
318: return NULL;
319: }
320:
321: 322: 323:
324: LOCAL void* icalloc( size_t nmemb, size_t size, IMACB *imacb )
325: {
326: size_t sz = nmemb * size;
327: void *mem;
328:
329: mem = imalloc(sz, imacb);
330: if ( mem == NULL ) {
331: return NULL;
332: }
333:
334: memset(mem, 0, sz);
335:
336: return mem;
337: }
338:
339: 340: 341: 342: 343:
344: LOCAL void ifree( void *ptr, IMACB *imacb )
345: {
346: QUEUE *aq;
347: UW imask;
348:
349: DI(imask);
350:
351: aq = (QUEUE*)ptr - 1;
352: clrAreaFlag(aq, AREA_USE);
353:
354: if ( !chkAreaFlag(aq->next, AREA_END|AREA_USE) ) {
355:
356: removeFreeQue(aq->next + 1);
357: removeAreaQue(aq->next);
358: }
359:
360: if ( !chkAreaFlag(aq, AREA_TOP) && !chkAreaFlag(aq->prev, AREA_USE) ) {
361:
362: aq = aq->prev;
363: removeFreeQue(aq + 1);
364: removeAreaQue(aq->next);
365: }
366:
367: 368: 369: 370:
371: if ( !isDI(imask) && chkAreaFlag(aq, AREA_TOP) && chkAreaFlag(aq->next, AREA_END) ) {
372:
373: removeAreaQue(aq->next);
374: removeAreaQue(aq);
375: EI(imask);
376: RelSysMemBlk(aq);
377: DI(imask);
378: } else {
379:
380: appendFreeArea(aq, imacb);
381: }
382:
383: EI(imask);
384: }
385:
386:
387: 388: 389: 390:
391:
392: LOCAL IMACB Imacb[2][2];
393:
394: #define RING(attr) ( ( (((attr) & TA_RNG3) >> 8) >= IMALLOC_MIN_USER_LEVEL )? 1: 0 )
395: #define RESIDENT(attr) ( ( ((attr) & TA_NORESIDENT) == 0 )? 1: 0 )
396:
397: #define SelIMACB(attr) ( AlignIMACB(&Imacb[RING(attr)][RESIDENT(attr)]) )
398:
399: EXPORT void* IAmalloc( size_t size, UINT attr )
400: {
401: return imalloc(size, SelIMACB(attr));
402: }
403:
404: EXPORT void* IAcalloc( size_t nmemb, size_t size, UINT attr )
405: {
406: return icalloc(nmemb, size, SelIMACB(attr));
407: }
408:
409: EXPORT void IAfree( void *ptr, UINT attr )
410: {
411: ifree(ptr, SelIMACB(attr));
412: }
413:
414:
415: 416: 417: 418:
419:
420:
421: IMPORT INT svc_call_limit;
422:
423: #define TA_RNG ( (UINT)svc_call_limit << 8 )
424:
425: EXPORT void* Imalloc( size_t size )
426: {
427: return IAmalloc(size, TA_RNG);
428: }
429:
430: EXPORT void* Icalloc( size_t nmemb, size_t size )
431: {
432: return IAcalloc(nmemb, size, TA_RNG);
433: }
434:
435: EXPORT void Ifree( void *ptr )
436: {
437: IAfree(ptr, TA_RNG);
438: }
439:
440:
441:
442: 443: 444:
445: LOCAL void initIMACB( UINT attr )
446: {
447: IMACB *imacb = SelIMACB(attr);
448:
449: QueInit(&imacb->areaque);
450: QueInit(&imacb->freeque);
451: imacb->mematr = attr;
452: }
453:
454: 455: 456:
457: EXPORT ER init_Imalloc( void )
458: {
459: T_RSMB rsmb;
460: ER ercd;
461:
462: ercd = RefSysMemInfo(&rsmb);
463: if ( ercd < E_OK ) {
464: goto err_ret;
465: }
466:
467: pagesz = (UINT)rsmb.blksz;
468:
469: initIMACB(TA_RNG0);
470: initIMACB(TA_RNG0|TA_NORESIDENT);
471: initIMACB(TA_RNG3);
472: initIMACB(TA_RNG3|TA_NORESIDENT);
473:
474: return E_OK;
475:
476: err_ret:
477: TM_DEBUG_PRINT(("init_Imalloc ercd = %d\n", ercd));
478: return ercd;
479: }