gonzui


Format: Advanced Search

tkernel_2/kernel/tkernel/src/mutex.cbare sourcepermlink (0.09 seconds)

Search this content:

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