1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
13:
14: 15: 16: 17:
18:
19: #include "kernel.h"
20: #include "memory.h"
21:
22: 23: 24: 25: 26: 27: 28:
29: EXPORT QUEUE* knl_searchFreeArea( IMACB *imacb, W blksz )
30: {
31: QUEUE *q = &imacb->freeque;
32:
33: 34: 35:
36: if ( blksz > imacb->memsz / 4 ) {
37:
38: W fsz = 0;
39: while ( (q = q->prev) != &imacb->freeque ) {
40: fsz = FreeSize(q);
41: if ( fsz <= blksz ) {
42: return ( fsz < blksz )? q->next: q;
43: }
44: }
45: return ( fsz >= blksz )? q->next: q;
46: } else {
47:
48: while ( (q = q->next) != &imacb->freeque ) {
49: if ( FreeSize(q) >= blksz ) {
50: break;
51: }
52: }
53: return q;
54: }
55: }
56:
57:
58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76:
77: EXPORT void knl_appendFreeArea( IMACB *imacb, QUEUE *aq )
78: {
79: QUEUE *fq;
80: W size = AreaSize(aq);
81:
82:
83: 84: 85: 86:
87: fq = knl_searchFreeArea(imacb, size);
88:
89:
90: clrAreaFlag(aq, AREA_USE);
91: if ( fq != &imacb->freeque && FreeSize(fq) == size ) {
92:
93: (aq + 2)->next = (fq + 1)->next;
94: (fq + 1)->next = aq + 2;
95: (aq + 2)->prev = fq + 1;
96: if( (aq + 2)->next != NULL ) {
97: (aq + 2)->next->prev = aq + 2;
98: }
99: (aq + 1)->next = NULL;
100: } else {
101:
102: QueInsert(aq + 1, fq);
103: (aq + 2)->next = NULL;
104: (aq + 2)->prev = (QUEUE*)size;
105: }
106: }
107:
108: 109: 110:
111: EXPORT void knl_removeFreeQue( QUEUE *fq )
112: {
113: if ( fq->next == NULL ) {
114: (fq + 1)->prev->next = (fq + 1)->next;
115: if ( (fq + 1)->next != NULL ) {
116: (fq + 1)->next->prev = (fq + 1)->prev;
117: }
118: } else {
119: if ( (fq + 1)->next != NULL ) {
120: QueInsert((fq + 1)->next - 1, fq);
121: (fq + 1)->next->prev = (fq + 1)->prev;
122: }
123: QueRemove(fq);
124: }
125: }
126:
127: 128: 129: 130:
131: EXPORT void knl_insertAreaQue( QUEUE *que, QUEUE *ent )
132: {
133: ent->prev = que;
134: ent->next = que->next;
135: Assign(que->next->prev, ent);
136: que->next = ent;
137: }
138:
139: 140: 141:
142: EXPORT void knl_removeAreaQue( QUEUE *aq )
143: {
144: Mask(aq->prev)->next = aq->next;
145: Assign(aq->next->prev, Mask(aq->prev));
146: }
147:
148:
149:
150: #if USE_IMALLOC
151:
152:
153: Noinit(EXPORT IMACB *knl_imacb);
154:
155:
156:
157: 158: 159:
160: EXPORT void* knl_Imalloc( SZ size )
161: {
162: QUEUE *q, *aq, *aq2;
163: UINT imask;
164:
165: 166:
167: if( size <= 0 ) {
168: return (void *)NULL;
169: } else if ( size < MIN_FRAGMENT ) {
170: size = MIN_FRAGMENT;
171: } else {
172: size = ROUND(size);
173: }
174:
175: DI(imask);
176:
177:
178: q = knl_searchFreeArea(knl_imacb, size);
179: if ( q == &(knl_imacb->freeque) ) {
180: q = NULL;
181: goto err_ret;
182: }
183:
184:
185: knl_removeFreeQue(q);
186:
187: aq = q - 1;
188:
189: 190:
191: if ( FreeSize(q) - size >= MIN_FRAGMENT + sizeof(QUEUE) ) {
192:
193:
194: aq2 = (QUEUE*)((VB*)(aq + 1) + size);
195: knl_insertAreaQue(aq, aq2);
196:
197:
198: knl_appendFreeArea(knl_imacb, aq2);
199: }
200: setAreaFlag(aq, AREA_USE);
201:
202: err_ret:
203: EI(imask);
204:
205: return (void *)q;
206: }
207:
208: 209: 210:
211: EXPORT void* knl_Icalloc( SZ nmemb, SZ size )
212: {
213: SZ sz = nmemb * size;
214: void *mem;
215:
216: mem = knl_Imalloc(sz);
217: if ( mem == NULL ) {
218: return NULL;
219: }
220:
221: knl_memset(mem, 0, sz);
222:
223: return mem;
224: }
225:
226:
227: 228: 229:
230: EXPORT void* knl_Irealloc( void *ptr, SZ size )
231: {
232: void *newptr;
233: QUEUE *aq;
234: SZ oldsz;
235:
236: if(size != 0) {
237: newptr = knl_Imalloc(size);
238: if(newptr == NULL) {
239: return NULL;
240: }
241: } else {
242: newptr = NULL;
243: }
244:
245: if(ptr != NULL) {
246: if(newptr != NULL) {
247: aq = (QUEUE*)ptr - 1;
248: oldsz = (SZ)AreaSize(aq);
249: knl_memcpy(newptr, ptr, (size > oldsz)?oldsz:size);
250: }
251: knl_Ifree(ptr);
252: }
253:
254: return newptr;
255: }
256:
257:
258: 259: 260:
261: EXPORT void knl_Ifree( void *ptr )
262: {
263: QUEUE *aq;
264: UINT imask;
265:
266: DI(imask);
267:
268: aq = (QUEUE*)ptr - 1;
269: clrAreaFlag(aq, AREA_USE);
270:
271: if ( !chkAreaFlag(aq->next, AREA_USE) ) {
272:
273: knl_removeFreeQue(aq->next + 1);
274: knl_removeAreaQue(aq->next);
275: }
276:
277: if ( !chkAreaFlag(aq->prev, AREA_USE) ) {
278:
279: aq = aq->prev;
280: knl_removeFreeQue(aq + 1);
281: knl_removeAreaQue(aq->next);
282: }
283:
284: knl_appendFreeArea(knl_imacb, aq);
285:
286: EI(imask);
287: }
288:
289:
290:
291:
292: 293: 294:
295: LOCAL void initIMACB( void )
296: {
297: QueInit(&(knl_imacb->areaque));
298: QueInit(&(knl_imacb->freeque));
299: }
300:
301: 302: 303:
304: EXPORT ER knl_init_Imalloc( void )
305: {
306: QUEUE *top, *end;
307:
308:
309: knl_lowmem_top = (void *)(((UW)knl_lowmem_top + 3) & ~0x00000003UL);
310: knl_imacb = (IMACB*)knl_lowmem_top;
311: knl_lowmem_top = (void *)((UW)knl_lowmem_top + sizeof(IMACB));
312:
313:
314: knl_lowmem_top = (void *)(((UW)knl_lowmem_top + 7) & ~0x00000007UL);
315: top = (QUEUE*)knl_lowmem_top;
316: knl_imacb->memsz = (W)((UW)knl_lowmem_limit - (UW)knl_lowmem_top - sizeof(QUEUE)*2);
317:
318: knl_lowmem_top = knl_lowmem_limit;
319:
320: initIMACB();
321:
322:
323: end = (QUEUE*)((VB*)top + knl_imacb->memsz) + 1;
324: knl_insertAreaQue(&knl_imacb->areaque, end);
325: knl_insertAreaQue(&knl_imacb->areaque, top);
326: setAreaFlag(end, AREA_USE);
327: setAreaFlag(&knl_imacb->areaque, AREA_USE);
328:
329: knl_appendFreeArea(knl_imacb, top);
330:
331: return E_OK;
332: }
333:
334: #endif