1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
13:
14: 15: 16: 17:
18:
19: #include "kernel.h"
20: #include "wait.h"
21: #include "check.h"
22: #include "memory.h"
23: #include "mempool.h"
24:
25: #if USE_MEMORYPOOL
26:
27:
28: Noinit(EXPORT MPLCB knl_mplcb_table[NUM_MPLID]);
29: Noinit(EXPORT QUEUE knl_free_mplcb);
30:
31:
32: 33: 34:
35: EXPORT ER knl_memorypool_initialize( void )
36: {
37: MPLCB *mplcb, *end;
38:
39: if ( NUM_MPLID < 1 ) {
40: return E_SYS;
41: }
42:
43:
44: QueInit(&knl_free_mplcb);
45: end = knl_mplcb_table + NUM_MPLID;
46: for ( mplcb = knl_mplcb_table; mplcb < end; mplcb++ ) {
47: mplcb->mplid = 0;
48: QueInsert(&mplcb->wait_queue, &knl_free_mplcb);
49: }
50:
51: return E_OK;
52: }
53:
54:
55:
56: 57: 58: 59:
60: LOCAL void knl_appendFreeAreaBound( MPLCB *mplcb, QUEUE *aq )
61: {
62: IMACB *imacb = (IMACB*)&(mplcb->mplsz);
63: QUEUE *fq, *top, *end;
64: W size;
65:
66: if ( aq == &(mplcb->areaque) ) {
67: top = (QUEUE*)mplcb->mempool;
68: } else {
69: top = aq + 1;
70: }
71:
72: if ( aq->next == &(mplcb->areaque_end) ) {
73: end = (QUEUE*)((VB*)mplcb->mempool + mplcb->mplsz);
74: } else {
75: end = aq->next;
76: }
77:
78: size = (W)((VB*)end - (VB*)top);
79:
80:
81: 82: 83: 84:
85: fq = knl_searchFreeArea(imacb, size);
86:
87:
88: clrAreaFlag(aq, AREA_USE);
89: if ( fq != &imacb->freeque && FreeSize(fq) == size ) {
90:
91: (top + 1)->next = (fq + 1)->next;
92: (fq + 1)->next = top + 1;
93: (top + 1)->prev = fq + 1;
94: if( (top + 1)->next != NULL ) {
95: (top + 1)->next->prev = top + 1;
96: }
97: top->next = NULL;
98: } else {
99:
100: QueInsert(top, fq);
101: (top + 1)->next = NULL;
102: (top + 1)->prev = (QUEUE*)size;
103: }
104: }
105:
106: 107: 108: 109: 110:
111: LOCAL void *knl_get_blk( MPLCB *mplcb, W blksz )
112: {
113: QUEUE *q, *aq, *aq2;
114: IMACB* imacb = (IMACB*)&(mplcb->mplsz);
115:
116:
117: q = knl_searchFreeArea(imacb, blksz);
118: if ( q == &(imacb->freeque) ) {
119: return NULL;
120: }
121:
122:
123: knl_removeFreeQue(q);
124: aq = ((void *)q == mplcb->mempool) ? &(mplcb->areaque) : q - 1;
125:
126: 127:
128: if ( FreeSize(q) - (UW)blksz >= MIN_FRAGMENT + sizeof(QUEUE) ) {
129:
130:
131: aq2 = (QUEUE*)((VB*)q + blksz);
132: knl_insertAreaQue(aq, aq2);
133:
134:
135: if ( aq2->next == &(mplcb->areaque_end) ) {
136: knl_appendFreeAreaBound(mplcb, aq2);
137: } else {
138: knl_appendFreeArea(imacb, aq2);
139: }
140: }
141: setAreaFlag(aq, AREA_USE);
142:
143: return (void *)q;
144: }
145:
146: 147: 148:
149: LOCAL ER knl_rel_blk( MPLCB *mplcb, void *blk )
150: {
151: QUEUE *aq;
152: IMACB* imacb = (IMACB*)&(mplcb->mplsz);
153:
154: aq = (blk == mplcb->mempool) ? &(mplcb->areaque) : (QUEUE*)blk - 1;
155:
156: #if CHK_PAR
157: if ( !chkAreaFlag(aq, AREA_USE) ) {
158: return E_PAR;
159: }
160: #endif
161: clrAreaFlag(aq, AREA_USE);
162:
163: if ( !chkAreaFlag(aq->next, AREA_USE) ) {
164:
165: knl_removeFreeQue(aq->next + 1);
166: knl_removeAreaQue(aq->next);
167: }
168: if ( !chkAreaFlag(aq->prev, AREA_USE) ) {
169:
170: QUEUE *fq;
171: aq = aq->prev;
172: fq = (aq == &(mplcb->areaque)) ? (QUEUE*)(mplcb->mempool) : aq + 1;
173:
174: knl_removeFreeQue(fq);
175: knl_removeAreaQue(aq->next);
176: }
177:
178:
179: if ( aq == &(mplcb->areaque) || aq->next == &(mplcb->areaque_end) ) {
180: knl_appendFreeAreaBound(mplcb, aq);
181: } else {
182: knl_appendFreeArea(imacb, aq);
183: }
184:
185: return E_OK;
186: }
187:
188:
189:
190: 191: 192: 193:
194: EXPORT void knl_mpl_wakeup( MPLCB *mplcb )
195: {
196: TCB *top;
197: void *blk;
198: W blksz;
199:
200: while ( !isQueEmpty(&mplcb->wait_queue) ) {
201: top = (TCB*)mplcb->wait_queue.next;
202: blksz = top->winfo.mpl.blksz;
203:
204:
205: if ( blksz > knl_MaxFreeSize(mplcb) ) {
206: break;
207: }
208:
209:
210: blk = knl_get_blk(mplcb, blksz);
211: *top->winfo.mpl.p_blk = blk;
212:
213:
214: knl_wait_release_ok(top);
215: }
216: }
217:
218:
219: 220: 221:
222: LOCAL void init_mempool( MPLCB *mplcb )
223: {
224: QueInit(&mplcb->areaque);
225: QueInit(&mplcb->freeque);
226:
227:
228: knl_insertAreaQue(&mplcb->areaque, &mplcb->areaque_end);
229:
230:
231: setAreaFlag(&mplcb->areaque_end, AREA_USE);
232:
233:
234: knl_appendFreeAreaBound(mplcb, &mplcb->areaque);
235: }
236:
237: 238: 239:
240: SYSCALL ID tk_cre_mpl( CONST T_CMPL *pk_cmpl )
241: {
242: #if CHK_RSATR
243: const ATR VALID_MPLATR = {
244: TA_TPRI
245: |TA_RNG3
246: |TA_USERBUF
247: #if USE_OBJECT_NAME
248: |TA_DSNAME
249: #endif
250: };
251: #endif
252: MPLCB *mplcb;
253: ID mplid;
254: W mplsz;
255: void *mempool;
256: ER ercd;
257:
258: CHECK_RSATR(pk_cmpl->mplatr, VALID_MPLATR);
259: CHECK_PAR(pk_cmpl->mplsz > 0 && pk_cmpl->mplsz <= MAX_ALLOCATE);
260: #if !USE_IMALLOC
261:
262: CHECK_PAR((pk_cmpl->mplatr & TA_USERBUF) != 0);
263: #endif
264: CHECK_DISPATCH();
265:
266: mplsz = roundSize(pk_cmpl->mplsz);
267:
268: #if USE_IMALLOC
269: if ( (pk_cmpl->mplatr & TA_USERBUF) != 0 ) {
270: 271:
272: if ( mplsz != pk_cmpl->mplsz ) {
273: return E_PAR;
274: }
275:
276: mempool = pk_cmpl->bufptr;
277: } else {
278:
279: mempool = knl_Imalloc((UW)mplsz);
280: if ( mempool == NULL ) {
281: return E_NOMEM;
282: }
283: }
284: #else
285: 286:
287: if ( mplsz != pk_cmpl->mplsz ) {
288: return E_PAR;
289: }
290:
291: mempool = pk_cmpl->bufptr;
292: #endif
293:
294: BEGIN_CRITICAL_SECTION;
295:
296: mplcb = (MPLCB*)QueRemoveNext(&knl_free_mplcb);
297: if ( mplcb == NULL ) {
298: ercd = E_LIMIT;
299: } else {
300: mplid = ID_MPL(mplcb - knl_mplcb_table);
301:
302:
303: QueInit(&mplcb->wait_queue);
304: mplcb->mplid = mplid;
305: mplcb->exinf = pk_cmpl->exinf;
306: mplcb->mplatr = pk_cmpl->mplatr;
307: mplcb->mplsz = mplsz;
308: #if USE_OBJECT_NAME
309: if ( (pk_cmpl->mplatr & TA_DSNAME) != 0 ) {
310: knl_strncpy((char*)mplcb->name, (char*)pk_cmpl->dsname, OBJECT_NAME_LENGTH);
311: }
312: #endif
313:
314: mplcb->mempool = mempool;
315:
316:
317: init_mempool(mplcb);
318:
319: ercd = mplid;
320: }
321: END_CRITICAL_SECTION;
322:
323: #if USE_IMALLOC
324: if ( (ercd < E_OK) && ((pk_cmpl->mplatr & TA_USERBUF) == 0) ) {
325: knl_Ifree(mempool);
326: }
327: #endif
328:
329: return ercd;
330: }
331:
332: #ifdef USE_FUNC_TK_DEL_MPL
333: 334: 335:
336: SYSCALL ER tk_del_mpl( ID mplid )
337: {
338: MPLCB *mplcb;
339: void *mempool = NULL;
340: ATR memattr = 0;
341: ER ercd = E_OK;
342:
343: CHECK_MPLID(mplid);
344: CHECK_DISPATCH();
345:
346: mplcb = get_mplcb(mplid);
347:
348: BEGIN_CRITICAL_SECTION;
349: if ( mplcb->mplid == 0 ) {
350: ercd = E_NOEXS;
351: } else {
352: mempool = mplcb->mempool;
353: memattr = mplcb->mplatr;
354:
355:
356: knl_wait_delete(&mplcb->wait_queue);
357:
358:
359: QueInsert(&mplcb->wait_queue, &knl_free_mplcb);
360: mplcb->mplid = 0;
361: }
362: END_CRITICAL_SECTION;
363:
364: #if USE_IMALLOC
365: if ( (ercd == E_OK) && ((memattr & TA_USERBUF) == 0) ) {
366: knl_Ifree(mempool);
367: }
368: #endif
369:
370: return ercd;
371: }
372: #endif
373:
374: 375: 376: 377:
378: LOCAL void mpl_chg_pri( TCB *tcb, INT oldpri )
379: {
380: MPLCB *mplcb;
381:
382: mplcb = get_mplcb(tcb->wid);
383: if ( oldpri >= 0 ) {
384:
385: knl_gcb_change_priority((GCB*)mplcb, tcb);
386: }
387:
388: 389:
390: knl_mpl_wakeup(mplcb);
391: }
392:
393: 394: 395:
396: LOCAL void mpl_rel_wai( TCB *tcb )
397: {
398: mpl_chg_pri(tcb, -1);
399: }
400:
401: 402: 403:
404: LOCAL CONST WSPEC knl_wspec_mpl_tfifo = { TTW_MPL, NULL, mpl_rel_wai };
405: LOCAL CONST WSPEC knl_wspec_mpl_tpri = { TTW_MPL, mpl_chg_pri, mpl_rel_wai };
406:
407: 408: 409:
410: SYSCALL ER tk_get_mpl( ID mplid, SZ blksz, void **p_blk, TMO tmout )
411: {
412: MPLCB *mplcb;
413: void *blk = NULL;
414: ER ercd = E_OK;
415:
416: CHECK_MPLID(mplid);
417: CHECK_PAR(blksz > 0 && blksz <= MAX_ALLOCATE);
418: CHECK_TMOUT(tmout);
419: CHECK_DISPATCH();
420:
421: mplcb = get_mplcb(mplid);
422: blksz = roundSize(blksz);
423:
424: BEGIN_CRITICAL_SECTION;
425: if ( mplcb->mplid == 0 ) {
426: ercd = E_NOEXS;
427: goto error_exit;
428: }
429:
430: #if CHK_PAR
431: if ( blksz > mplcb->mplsz ) {
432: ercd = E_PAR;
433: goto error_exit;
434: }
435: #endif
436:
437: if ( knl_gcb_top_of_wait_queue((GCB*)mplcb, knl_ctxtsk) == knl_ctxtsk
438: && (blk = knl_get_blk(mplcb, blksz)) != NULL ) {
439:
440: *p_blk = blk;
441: } else {
442:
443: knl_ctxtsk->wspec = ( (mplcb->mplatr & TA_TPRI) != 0 )?
444: &knl_wspec_mpl_tpri: &knl_wspec_mpl_tfifo;
445: knl_ctxtsk->wercd = &ercd;
446: knl_ctxtsk->winfo.mpl.blksz = blksz;
447: knl_ctxtsk->winfo.mpl.p_blk = p_blk;
448: knl_gcb_make_wait((GCB*)mplcb, tmout);
449: }
450:
451: error_exit:
452: END_CRITICAL_SECTION;
453:
454: return ercd;
455: }
456:
457: 458: 459:
460: SYSCALL ER tk_rel_mpl( ID mplid, void *blk )
461: {
462: MPLCB *mplcb;
463: ER ercd = E_OK;
464:
465: CHECK_MPLID(mplid);
466: CHECK_DISPATCH();
467:
468: mplcb = get_mplcb(mplid);
469:
470: BEGIN_CRITICAL_SECTION;
471: if ( mplcb->mplid == 0 ) {
472: ercd = E_NOEXS;
473: goto error_exit;
474: }
475: #if CHK_PAR
476: if ( (B*)blk < (B*)mplcb->mempool || (B*)blk > (B*)mplcb->mempool + mplcb->mplsz ) {
477: ercd = E_PAR;
478: goto error_exit;
479: }
480: #endif
481:
482:
483: ercd = knl_rel_blk(mplcb, blk);
484: if ( ercd < E_OK ) {
485: goto error_exit;
486: }
487:
488:
489: knl_mpl_wakeup(mplcb);
490:
491: error_exit:
492: END_CRITICAL_SECTION;
493:
494: return ercd;
495: }
496:
497: #ifdef USE_FUNC_TK_REF_MPL
498: 499: 500:
501: SYSCALL ER tk_ref_mpl( ID mplid, T_RMPL *pk_rmpl )
502: {
503: MPLCB *mplcb;
504: QUEUE *fq, *q;
505: W frsz, blksz;
506: ER ercd = E_OK;
507:
508: CHECK_MPLID(mplid);
509: CHECK_DISPATCH();
510:
511: mplcb = get_mplcb(mplid);
512:
513: BEGIN_CRITICAL_SECTION;
514: if ( mplcb->mplid == 0 ) {
515: ercd = E_NOEXS;
516: } else {
517: pk_rmpl->exinf = mplcb->exinf;
518: pk_rmpl->wtsk = knl_wait_tskid(&mplcb->wait_queue);
519: frsz = 0;
520: for ( fq = mplcb->freeque.next; fq != &mplcb->freeque; fq = fq->next ) {
521: blksz = FreeSize(fq);
522: frsz += blksz;
523: for ( q = (fq+1)->next; q != NULL; q = q->next ) {
524: frsz += blksz;
525: }
526: }
527: pk_rmpl->frsz = frsz;
528: pk_rmpl->maxsz = knl_MaxFreeSize(mplcb);
529: }
530: END_CRITICAL_SECTION;
531:
532: return ercd;
533: }
534: #endif
535:
536:
537: 538: 539:
540: #if USE_DBGSPT
541:
542: #if USE_OBJECT_NAME
543: 544: 545:
546: EXPORT ER knl_memorypool_getname(ID id, UB **name)
547: {
548: MPLCB *mplcb;
549: ER ercd = E_OK;
550:
551: CHECK_MPLID(id);
552:
553: BEGIN_DISABLE_INTERRUPT;
554: mplcb = get_mplcb(id);
555: if ( mplcb->mplid == 0 ) {
556: ercd = E_NOEXS;
557: goto error_exit;
558: }
559: if ( (mplcb->mplatr & TA_DSNAME) == 0 ) {
560: ercd = E_OBJ;
561: goto error_exit;
562: }
563: *name = mplcb->name;
564:
565: error_exit:
566: END_DISABLE_INTERRUPT;
567:
568: return ercd;
569: }
570: #endif
571:
572: #ifdef USE_FUNC_TD_LST_MPL
573: 574: 575:
576: SYSCALL INT td_lst_mpl( ID list[], INT nent )
577: {
578: MPLCB *mplcb, *end;
579: INT n = 0;
580:
581: BEGIN_DISABLE_INTERRUPT;
582: end = knl_mplcb_table + NUM_MPLID;
583: for ( mplcb = knl_mplcb_table; mplcb < end; mplcb++ ) {
584: if ( mplcb->mplid == 0 ) {
585: continue;
586: }
587:
588: if ( n++ < nent ) {
589: *list++ = ID_MPL(mplcb - knl_mplcb_table);
590: }
591: }
592: END_DISABLE_INTERRUPT;
593:
594: return n;
595: }
596: #endif
597:
598: #ifdef USE_FUNC_TD_REF_MPL
599: 600: 601:
602: SYSCALL ER td_ref_mpl( ID mplid, TD_RMPL *pk_rmpl )
603: {
604: MPLCB *mplcb;
605: QUEUE *fq, *q;
606: W frsz, blksz;
607: ER ercd = E_OK;
608:
609: CHECK_MPLID(mplid);
610:
611: mplcb = get_mplcb(mplid);
612:
613: BEGIN_DISABLE_INTERRUPT;
614: if ( mplcb->mplid == 0 ) {
615: ercd = E_NOEXS;
616: } else {
617: pk_rmpl->exinf = mplcb->exinf;
618: pk_rmpl->wtsk = knl_wait_tskid(&mplcb->wait_queue);
619: frsz = 0;
620: for ( fq = mplcb->freeque.next; fq != &mplcb->freeque; fq = fq->next ) {
621: blksz = FreeSize(fq);
622: frsz += blksz;
623: for ( q = (fq+1)->next; q != NULL; q = q->next ) {
624: frsz += blksz;
625: }
626: }
627: pk_rmpl->frsz = frsz;
628: pk_rmpl->maxsz = knl_MaxFreeSize(mplcb);
629: }
630: END_DISABLE_INTERRUPT;
631:
632: return ercd;
633: }
634: #endif
635:
636: #ifdef USE_FUNC_TD_MPL_QUE
637: 638: 639:
640: SYSCALL INT td_mpl_que( ID mplid, ID list[], INT nent )
641: {
642: MPLCB *mplcb;
643: QUEUE *q;
644: ER ercd = E_OK;
645:
646: CHECK_MPLID(mplid);
647:
648: mplcb = get_mplcb(mplid);
649:
650: BEGIN_DISABLE_INTERRUPT;
651: if ( mplcb->mplid == 0 ) {
652: ercd = E_NOEXS;
653: } else {
654: INT n = 0;
655: for ( q = mplcb->wait_queue.next; q != &mplcb->wait_queue; q = q->next ) {
656: if ( n++ < nent ) {
657: *list++ = ((TCB*)q)->tskid;
658: }
659: }
660: ercd = n;
661: }
662: END_DISABLE_INTERRUPT;
663:
664: return ercd;
665: }
666: #endif
667:
668: #endif
669: #endif