gonzui


Format: Advanced Search

mtkernel_3/kernel/tkernel/mutex.cbare sourcepermlink (0.03 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    micro T-Kernel 3.00.00
    4:  *
    5:  *    Copyright (C) 2006-2019 by Ken Sakamura.
    6:  *    This software is distributed under the T-License 2.1.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by TRON Forum(http://www.tron.org) at 2019/12/11.
   10:  *
   11:  *----------------------------------------------------------------------
   12:  */
   13: 
   14: /*
   15:  *      mutex.c
   16:  *      Mutex
   17:  */
   18: 
   19: #include "kernel.h"
   20: #include "wait.h"
   21: #include "check.h"
   22: #include "mutex.h"
   23: 
   24: #if USE_MUTEX == 1
   25: 
   26: Noinit(EXPORT MTXCB     knl_mtxcb_table[NUM_MTXID]);        /* Mutex control block */
   27: Noinit(EXPORT QUEUE     knl_free_mtxcb);    /* FreeQue */
   28: 
   29: 
   30: /*
   31:  * Initialization of mutex control block 
   32:  */
   33: EXPORT ER knl_mutex_initialize(void)
   34: {
   35:         MTXCB  *mtxcb, *end;
   36: 
   37:         /* Get system information */
   38:         if ( NUM_MTXID < 1 ) {
   39:                 return E_SYS;
   40:         }
   41: 
   42:         /* Register all control blocks onto FreeQue */
   43:         QueInit(&knl_free_mtxcb);
   44:         end = knl_mtxcb_table + NUM_MTXID;
   45:         for( mtxcb = knl_mtxcb_table; mtxcb < end; mtxcb++ ) {
   46:                 mtxcb->mtxid = 0;
   47:                 QueInsert(&mtxcb->wait_queue, &knl_free_mtxcb);
   48:         }
   49: 
   50:         return E_OK;
   51: }
   52: 
   53: 
   54: /*
   55:  * Release the lock and delete it from list, and then adjust the
   56:  * priority of task.
   57:  * Set the highest priority between listed below:
   58:  *      (A) The highest priority in all mutexes in which 'tcb' task locks. 
   59:  *      (B) The base priority of 'tcb' task.
   60:  */
   61: EXPORT void knl_release_mutex( TCB *tcb, MTXCB *relmtxcb )
   62: {
   63:         MTXCB  *mtxcb, **prev;
   64:         INT    newpri, pri;
   65: 
   66:         /* (B) The base priority of task */
   67:         newpri = tcb->bpriority;
   68: 
   69:         /* (A) The highest priority in mutex which is locked */
   70:         pri = newpri;
   71:         prev = &tcb->mtxlist;
   72:         while ( (mtxcb = *prev) != NULL ) {
   73:                 if ( mtxcb == relmtxcb ) {
   74:                         /* Delete from list */
   75:                         *prev = mtxcb->mtxlist;
   76:                         continue;
   77:                 }
   78: 
   79:                 switch ( mtxcb->mtxatr & TA_CEILING ) {
   80:                   case TA_CEILING:
   81:                         pri = mtxcb->ceilpri;
   82:                         break;
   83:                   case TA_INHERIT:
   84:                         if ( mtx_waited(mtxcb) ) {
   85:                                 pri = mtx_head_pri(mtxcb);
   86:                         }
   87:                         break;
   88:                   default: /* TA_TFIFO, TA_TPRI */
   89:                         /* nothing to do */
   90:                         break;
   91:                 }
   92:                 if ( newpri > pri ) {
   93:                         newpri = pri;
   94:                 }
   95: 
   96:                 prev = &mtxcb->mtxlist;
   97:         }
   98: 
   99:         if ( newpri != tcb->priority ) {
  100:                 /* Change priority of lock get task */
  101:                 knl_change_task_priority(tcb, newpri);
  102:         }
  103: }
  104: 
  105: /*
  106:  * Free mutex when task is terminated
  107:  *      Free all mutexes which the task holds.
  108:  *      Do not need to handle mutex list and priority of terminated task.
  109:  *      
  110:  */
  111: EXPORT void knl_signal_all_mutex( TCB *tcb )
  112: {
  113:         MTXCB  *mtxcb, *next_mtxcb;
  114:         TCB    *next_tcb;
  115: 
  116:         next_mtxcb = tcb->mtxlist;
  117:         while ( (mtxcb = next_mtxcb) != NULL ) {
  118:                 next_mtxcb = mtxcb->mtxlist;
  119: 
  120:                 if ( mtx_waited(mtxcb) ) {
  121:                         next_tcb = (TCB*)mtxcb->wait_queue.next;
  122: 
  123:                         /* Wake wait task */
  124:                         knl_wait_release_ok(next_tcb);
  125: 
  126:                         /* Change mutex get task */
  127:                         mtxcb->mtxtsk = next_tcb;
  128:                         mtxcb->mtxlist = next_tcb->mtxlist;
  129:                         next_tcb->mtxlist = mtxcb;
  130: 
  131:                         if ( (mtxcb->mtxatr & TA_CEILING) == TA_CEILING ) {
  132:                                 if ( next_tcb->priority > mtxcb->ceilpri ) {
  133:                                         /* Raise the priority for the task
  134:                                            that got lock to the highest
  135:                                            priority limit */
  136:                                         knl_change_task_priority(next_tcb,
  137:                                                         mtxcb->ceilpri);
  138:                                 }
  139:                         }
  140:                 } else {
  141:                         /* No wait task */
  142:                         mtxcb->mtxtsk = NULL;
  143:                 }
  144:         }
  145: }
  146: 
  147: /*
  148:  * Limit the priority change by mutex at task priority change
  149:  *    1.If the 'tcb' task locks mutex, cannot set lower priority than the 
  150:  *      highest priority in all mutexes which hold lock. In such case, 
  151:  *      return the highest priority of locked mutex. 
  152:  *    2.If mutex with TA_CEILING attribute is locked or waiting to be locked, 
  153:  *      cannot set higher priority than the lowest within the highest 
  154:  *      priority limit of mutex with TA_CEILING attribute.
  155:  *      In this case, return E_ILUSE.
  156:  *    3.Other than above, return the 'priority'.
  157:  */
  158: EXPORT INT knl_chg_pri_mutex( TCB *tcb, INT priority )
  159: {
  160:         MTXCB  *mtxcb;
  161:         INT    hi_pri, low_pri, pri;
  162: 
  163:         hi_pri  = priority;
  164:         low_pri = int_priority(MIN_TSKPRI);
  165: 
  166:         /* Mutex lock wait */
  167:         if ( (tcb->state & TS_WAIT) != 0 && (tcb->wspec->tskwait & TTW_MTX) != 0 ) {
  168:                 mtxcb = get_mtxcb(tcb->wid);
  169:                 if ( (mtxcb->mtxatr & TA_CEILING) == TA_CEILING ) {
  170:                         pri = mtxcb->ceilpri;
  171:                         if ( pri > low_pri ) {
  172:                                 low_pri = pri;
  173:                         }
  174:                 }
  175:         }
  176: 
  177:         /* Locked Mutex */
  178:         pri = hi_pri;
  179:         for ( mtxcb = tcb->mtxlist; mtxcb != NULL; mtxcb = mtxcb->mtxlist ) {
  180:                 switch ( mtxcb->mtxatr & TA_CEILING ) {
  181:                   case TA_CEILING:
  182:                         pri = mtxcb->ceilpri;
  183:                         if ( pri > low_pri ) {
  184:                                 low_pri = pri;
  185:                         }
  186:                         break;
  187:                   case TA_INHERIT:
  188:                         if ( mtx_waited(mtxcb) ) {
  189:                                 pri = mtx_head_pri(mtxcb);
  190:                         }
  191:                         break;
  192:                   default: /* TA_TFIFO, TA_TPRI */
  193:                         /* nothing to do */
  194:                         break;
  195:                 }
  196:                 if ( pri < hi_pri ) {
  197:                         hi_pri = pri;
  198:                 }
  199:         }
  200: 
  201:         if ( priority < low_pri ) {
  202:                 return E_ILUSE;
  203:         }
  204:         return hi_pri;
  205: }
  206: 
  207: 
  208: /*
  209:  * Create mutex
  210:  */
  211: SYSCALL ID tk_cre_mtx( CONST T_CMTX *pk_cmtx )
  212: {
  213: #if CHK_RSATR
  214:         const ATR VALID_MTXATR = {
  215:                  TA_CEILING
  216: #if USE_OBJECT_NAME
  217:                 |TA_DSNAME
  218: #endif
  219:         };
  220: #endif
  221:         MTXCB  *mtxcb;
  222:         ID     mtxid;
  223:         INT    ceilpri;
  224:         ER     ercd;
  225: 
  226:         CHECK_RSATR(pk_cmtx->mtxatr, VALID_MTXATR);
  227: 
  228:         if ( (pk_cmtx->mtxatr & TA_CEILING) == TA_CEILING ) {
  229:                 CHECK_PRI(pk_cmtx->ceilpri);
  230:                 ceilpri = int_priority(pk_cmtx->ceilpri);
  231:         } else {
  232:                 ceilpri = 0;
  233:         }
  234: 
  235:         BEGIN_CRITICAL_SECTION;
  236:         /* Get control block from FreeQue */
  237:         mtxcb = (MTXCB*)QueRemoveNext(&knl_free_mtxcb);
  238:         if ( mtxcb == NULL ) {
  239:                 ercd = E_LIMIT;
  240:         } else {
  241:                 mtxid = ID_MTX(mtxcb - knl_mtxcb_table);
  242: 
  243:                 /* Initialize control block */
  244:                 QueInit(&mtxcb->wait_queue);
  245:                 mtxcb->mtxid   = mtxid;
  246:                 mtxcb->exinf   = pk_cmtx->exinf;
  247:                 mtxcb->mtxatr  = pk_cmtx->mtxatr;
  248:                 mtxcb->ceilpri = ceilpri;
  249:                 mtxcb->mtxtsk  = NULL;
  250:                 mtxcb->mtxlist = NULL;
  251: #if USE_OBJECT_NAME
  252:                 if ( (pk_cmtx->mtxatr & TA_DSNAME) != 0 ) {
  253:                         knl_strncpy((char*)mtxcb->name, (char*)pk_cmtx->dsname,
  254:                                 (UINT)OBJECT_NAME_LENGTH);
  255:                 }
  256: #endif
  257:                 ercd = mtxid;
  258:         }
  259:         END_CRITICAL_SECTION;
  260: 
  261:         return ercd;
  262: }
  263: 
  264: #ifdef USE_FUNC_TK_DEL_MTX
  265: /*
  266:  * Delete mutex
  267:  */
  268: SYSCALL ER tk_del_mtx( ID mtxid )
  269: {
  270:         MTXCB  *mtxcb;
  271:         ER     ercd = E_OK;
  272: 
  273:         CHECK_MTXID(mtxid);
  274: 
  275:         mtxcb = get_mtxcb(mtxid);
  276: 
  277:         BEGIN_CRITICAL_SECTION;
  278:         if ( mtxcb->mtxid == 0 ) {
  279:                 ercd = E_NOEXS;
  280:         } else {
  281:                 /* If there is a task that holds mutex to delete,
  282:                  * delete the mutex from the list
  283:                  * and adjust the task priority if necessary.
  284:                  */
  285:                 if ( mtxcb->mtxtsk != NULL ) {
  286:                         knl_release_mutex(mtxcb->mtxtsk, mtxcb);
  287:                 }
  288: 
  289:                 /* Free wait state of task (E_DLT) */
  290:                 knl_wait_delete(&mtxcb->wait_queue);
  291: 
  292:                 /* Return to FreeQue */
  293:                 QueInsert(&mtxcb->wait_queue, &knl_free_mtxcb);
  294:                 mtxcb->mtxid = 0;
  295:         }
  296:         END_CRITICAL_SECTION;
  297: 
  298:         return ercd;
  299: }
  300: #endif /* USE_FUNC_TK_DEL_MTX */
  301: 
  302: 
  303: /*
  304:  * Processing if the priority of wait task changes
  305:  */
  306: LOCAL void mtx_chg_pri( TCB *tcb, INT oldpri )
  307: {
  308:         MTXCB  *mtxcb;
  309:         TCB    *mtxtsk;
  310: 
  311:         mtxcb = get_mtxcb(tcb->wid);
  312:         knl_gcb_change_priority((GCB*)mtxcb, tcb);
  313: 
  314:         if ( (mtxcb->mtxatr & TA_CEILING) == TA_INHERIT ) {
  315:                 mtxtsk = mtxcb->mtxtsk;
  316:                 if ( mtxtsk->priority > tcb->priority ) {
  317:                         /* Since the highest priority of the lock wait task
  318:                            became higher, raise the lock get task priority
  319:                            higher */
  320:                         knl_change_task_priority(mtxtsk, tcb->priority);
  321: 
  322:                 } else if ( mtxtsk->priority == oldpri ) {
  323:                         /* Since the highest priority of the lock wait task
  324:                            might become lower, adjust this priority */
  325:                         reset_priority(mtxtsk);
  326:                 }
  327:         }
  328: }
  329: 
  330: /*
  331:  * Processing if the wait task is released (For TA_INHERIT only)
  332:  */
  333: LOCAL void mtx_rel_wai( TCB *tcb )
  334: {
  335:         MTXCB  *mtxcb;
  336:         TCB    *mtxtsk;
  337: 
  338:         mtxcb = get_mtxcb(tcb->wid);
  339:         mtxtsk = mtxcb->mtxtsk;
  340: 
  341:         if ( mtxtsk->priority == tcb->priority ) {
  342:                 /* Since the highest priority of the lock wait task might 
  343:                    become lower, adjust this priority */
  344:                 reset_priority(mtxtsk);
  345:         }
  346: }
  347: 
  348: /*
  349:  * Definition of mutex wait specification
  350:  */
  351: LOCAL CONST WSPEC knl_wspec_mtx_tfifo   = { TTW_MTX, NULL, NULL };
  352: LOCAL CONST WSPEC knl_wspec_mtx_tpri    = { TTW_MTX, mtx_chg_pri, NULL };
  353: LOCAL CONST WSPEC knl_wspec_mtx_inherit = { TTW_MTX, mtx_chg_pri, mtx_rel_wai };
  354: 
  355: /*
  356:  * Lock mutex
  357:  */
  358: SYSCALL ER tk_loc_mtx( ID mtxid, TMO tmout )
  359: {
  360:         MTXCB  *mtxcb;
  361:         TCB    *mtxtsk;
  362:         ATR    mtxatr;
  363:         ER     ercd = E_OK;
  364: 
  365:         CHECK_MTXID(mtxid);
  366:         CHECK_TMOUT(tmout);
  367:         CHECK_DISPATCH();
  368: 
  369:         mtxcb = get_mtxcb(mtxid);
  370: 
  371:         BEGIN_CRITICAL_SECTION;
  372:         if ( mtxcb->mtxid == 0 ) {
  373:                 ercd = E_NOEXS;
  374:                 goto error_exit;
  375:         }
  376:         if ( mtxcb->mtxtsk == knl_ctxtsk ) {
  377:                 ercd = E_ILUSE;  /* Multiplexed lock */
  378:                 goto error_exit;
  379:         }
  380: 
  381:         mtxatr = mtxcb->mtxatr & TA_CEILING;
  382:         if ( mtxatr == TA_CEILING ) {
  383:                 if ( knl_ctxtsk->bpriority < mtxcb->ceilpri ) {
  384:                         /* Violation of highest priority limit */
  385:                         ercd = E_ILUSE;
  386:                         goto error_exit;
  387:                 }
  388:         }
  389: 
  390:         mtxtsk = mtxcb->mtxtsk;
  391:         if ( mtxtsk == NULL ) {
  392:                 /* Get lock */
  393:                 mtxcb->mtxtsk = knl_ctxtsk;
  394:                 mtxcb->mtxlist = knl_ctxtsk->mtxlist;
  395:                 knl_ctxtsk->mtxlist = mtxcb;
  396: 
  397:                 if ( mtxatr == TA_CEILING ) {
  398:                         if ( knl_ctxtsk->priority > mtxcb->ceilpri ) {
  399:                                 /* Raise its own task to the highest
  400:                                    priority limit */
  401:                                 knl_change_task_priority(knl_ctxtsk, mtxcb->ceilpri);
  402:                         }
  403:                 }
  404:         } else {
  405:                 ercd = E_TMOUT;
  406:                 if ( tmout == TMO_POL ) {
  407:                         goto error_exit;
  408:                 }
  409: 
  410:                 if ( mtxatr == TA_INHERIT ) {
  411:                         if ( mtxtsk->priority > knl_ctxtsk->priority ) {
  412:                                 /* Raise the priority of task during
  413:                                    locking to the same priority as its
  414:                                    own task */
  415:                                 knl_change_task_priority(mtxtsk, knl_ctxtsk->priority);
  416:                         }
  417:                 }
  418: 
  419:                 /* Ready for wait */
  420:                 knl_ctxtsk->wspec = ( mtxatr == TA_TFIFO   )? &knl_wspec_mtx_tfifo:
  421:                                 ( mtxatr == TA_INHERIT )? &knl_wspec_mtx_inherit:
  422:                                                           &knl_wspec_mtx_tpri;
  423:                 knl_ctxtsk->wercd = &ercd;
  424:                 knl_ctxtsk->wid = mtxcb->mtxid;
  425:                 knl_make_wait(tmout, mtxcb->mtxatr);
  426:                 if ( mtxatr == TA_TFIFO ) {
  427:                         QueInsert(&knl_ctxtsk->tskque, &mtxcb->wait_queue);
  428:                 } else {
  429:                         knl_queue_insert_tpri(knl_ctxtsk, &mtxcb->wait_queue);
  430:                 }
  431:         }
  432: 
  433:     error_exit:
  434:         END_CRITICAL_SECTION;
  435: 
  436:         return ercd;
  437: }
  438: 
  439: /*
  440:  * Unlock mutex
  441:  */
  442: SYSCALL ER tk_unl_mtx( ID mtxid )
  443: {
  444:         MTXCB  *mtxcb;  
  445:         TCB    *tcb;
  446:         ER     ercd = E_OK;
  447: 
  448:         CHECK_MTXID(mtxid);
  449:         CHECK_INTSK();
  450: 
  451:         mtxcb = get_mtxcb(mtxid);
  452: 
  453:         BEGIN_CRITICAL_SECTION;
  454:         if ( mtxcb->mtxid == 0 ) {
  455:                 ercd = E_NOEXS;
  456:                 goto error_exit;
  457:         }
  458:         if ( mtxcb->mtxtsk != knl_ctxtsk ) {
  459:                 ercd = E_ILUSE;  /* This is not locked by its own task */
  460:                 goto error_exit;
  461:         }
  462: 
  463:         /* Delete the mutex from the list,
  464:            and adjust its own task priority if necessary. */
  465:         knl_release_mutex(knl_ctxtsk, mtxcb);
  466: 
  467:         if ( mtx_waited(mtxcb) ) {
  468:                 tcb = (TCB*)mtxcb->wait_queue.next;
  469: 
  470:                 /* Release wait */
  471:                 knl_wait_release_ok(tcb);
  472: 
  473:                 /* Change mutex get task */
  474:                 mtxcb->mtxtsk = tcb;
  475:                 mtxcb->mtxlist = tcb->mtxlist;
  476:                 tcb->mtxlist = mtxcb;
  477: 
  478:                 if ( (mtxcb->mtxatr & TA_CEILING) == TA_CEILING ) {
  479:                         if ( tcb->priority > mtxcb->ceilpri ) {
  480:                                 /* Raise the priority of the task that
  481:                                    got lock to the highest priority limit */
  482:                                 knl_change_task_priority(tcb, mtxcb->ceilpri);
  483:                         }
  484:                 }
  485:         } else {
  486:                 /* No wait task */
  487:                 mtxcb->mtxtsk = NULL;
  488:         }
  489: 
  490:     error_exit:
  491:         END_CRITICAL_SECTION;
  492: 
  493:         return ercd;
  494: }
  495: 
  496: 
  497: #ifdef USE_FUNC_TK_REF_MTX
  498: /*
  499:  * Refer mutex state
  500:  */
  501: SYSCALL ER tk_ref_mtx( ID mtxid, T_RMTX *pk_rmtx )
  502: {
  503:         MTXCB  *mtxcb;
  504:         ER     ercd = E_OK;
  505: 
  506:         CHECK_MTXID(mtxid);
  507: 
  508:         mtxcb = get_mtxcb(mtxid);
  509: 
  510:         BEGIN_CRITICAL_SECTION;
  511:         if ( mtxcb->mtxid == 0 ) {
  512:                 ercd = E_NOEXS;
  513:         } else {
  514:                 pk_rmtx->exinf = mtxcb->exinf;
  515:                 pk_rmtx->htsk = ( mtxcb->mtxtsk != NULL )?
  516:                                         mtxcb->mtxtsk->tskid: 0;
  517:                 pk_rmtx->wtsk = knl_wait_tskid(&mtxcb->wait_queue);
  518:         }
  519:         END_CRITICAL_SECTION;
  520: 
  521:         return ercd;
  522: }
  523: #endif /* USE_FUNC_TK_REF_MTX */
  524: 
  525: /* ------------------------------------------------------------------------ */
  526: /*
  527:  *      Debugger support function
  528:  */
  529: #if USE_DBGSPT
  530: 
  531: #if USE_OBJECT_NAME
  532: /*
  533:  * Get object name from control block
  534:  */
  535: EXPORT ER knl_mutex_getname(ID id, UB **name)
  536: {
  537:         MTXCB  *mtxcb;
  538:         ER     ercd = E_OK;
  539: 
  540:         CHECK_MTXID(id);
  541: 
  542:         BEGIN_DISABLE_INTERRUPT;
  543:         mtxcb = get_mtxcb(id);
  544:         if ( mtxcb->mtxid == 0 ) {
  545:                 ercd = E_NOEXS;
  546:                 goto error_exit;
  547:         }
  548:         if ( (mtxcb->mtxatr & TA_DSNAME) == 0 ) {
  549:                 ercd = E_OBJ;
  550:                 goto error_exit;
  551:         }
  552:         *name = mtxcb->name;
  553: 
  554:     error_exit:
  555:         END_DISABLE_INTERRUPT;
  556: 
  557:         return ercd;
  558: }
  559: #endif /* USE_OBJECT_NAME */
  560: 
  561: #ifdef USE_FUNC_TD_LST_MTX
  562: /*
  563:  * Refer mutex usage state
  564:  */
  565: SYSCALL INT td_lst_mtx( ID list[], INT nent )
  566: {
  567:         MTXCB  *mtxcb, *end;
  568:         INT    n = 0;
  569: 
  570:         BEGIN_DISABLE_INTERRUPT;
  571:         end = knl_mtxcb_table + NUM_MTXID;
  572:         for ( mtxcb = knl_mtxcb_table; mtxcb < end; mtxcb++ ) {
  573:                 if ( mtxcb->mtxid == 0 ) {
  574:                         continue;
  575:                 }
  576: 
  577:                 if ( n++ < nent ) {
  578:                         *list++ = mtxcb->mtxid;
  579:                 }
  580:         }
  581:         END_DISABLE_INTERRUPT;
  582: 
  583:         return n;
  584: }
  585: #endif /* USE_FUNC_TD_LST_MTX */
  586: 
  587: #ifdef USE_FUNC_TD_REF_MTX
  588: /*
  589:  * Refer mutex state
  590:  */
  591: SYSCALL ER td_ref_mtx( ID mtxid, TD_RMTX *pk_rmtx )
  592: {
  593:         MTXCB  *mtxcb;
  594:         ER     ercd = E_OK;
  595: 
  596:         CHECK_MTXID(mtxid);
  597: 
  598:         mtxcb = get_mtxcb(mtxid);
  599: 
  600:         BEGIN_DISABLE_INTERRUPT;
  601:         if ( mtxcb->mtxid == 0 ) {
  602:                 ercd = E_NOEXS;
  603:         } else {
  604:                 pk_rmtx->exinf = mtxcb->exinf;
  605:                 pk_rmtx->htsk = ( mtxcb->mtxtsk != NULL )?
  606:                                         mtxcb->mtxtsk->tskid: 0;
  607:                 pk_rmtx->wtsk = knl_wait_tskid(&mtxcb->wait_queue);
  608:         }
  609:         END_DISABLE_INTERRUPT;
  610: 
  611:         return ercd;
  612: }
  613: #endif /* USE_FUNC_TD_REF_MTX */
  614: 
  615: #ifdef USE_FUNC_TD_MTX_QUE
  616: /*
  617:  * Refer mutex wait queue
  618:  */
  619: SYSCALL INT td_mtx_que( ID mtxid, ID list[], INT nent )
  620: {
  621:         MTXCB  *mtxcb;
  622:         QUEUE  *q;
  623:         ER     ercd = E_OK;
  624: 
  625:         CHECK_MTXID(mtxid);
  626: 
  627:         mtxcb = get_mtxcb(mtxid);
  628: 
  629:         BEGIN_DISABLE_INTERRUPT;
  630:         if ( mtxcb->mtxid == 0 ) {
  631:                 ercd = E_NOEXS;
  632:         } else {
  633:                 INT n = 0;
  634:                 for ( q = mtxcb->wait_queue.next; q != &mtxcb->wait_queue; q = q->next ) {
  635:                         if ( n++ < nent ) {
  636:                                 *list++ = ((TCB*)q)->tskid;
  637:                         }
  638:                 }
  639:                 ercd = n;
  640:         }
  641:         END_DISABLE_INTERRUPT;
  642: 
  643:         return ercd;
  644: }
  645: #endif /* USE_FUNC_TD_MTX_QUE */
  646: 
  647: #endif /* USE_DBGSPT */
  648: #endif /* USE_MUTEX */