gonzui


Format: Advanced Search

mtkernel_3/kernel/tkernel/time_calls.cbare sourcepermlink (0.07 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:  *      time_calls.c
   16:  *      Time Management Function
   17:  */
   18: 
   19: #include "kernel.h"
   20: #include "timer.h"
   21: #include "wait.h"
   22: #include "check.h"
   23: #include "time_calls.h"
   24: #include "../sysdepend/sys_timer.h"
   25: 
   26: /* ------------------------------------------------------------------------ */
   27: /*
   28:  *      Time Management
   29:  */
   30: #if USE_TIMEMANAGEMENT
   31: 
   32: #ifdef USE_FUNC_TK_SET_UTC
   33: /*
   34:  * Set system clock
   35:  */
   36: SYSCALL ER tk_set_utc( CONST SYSTIM *pk_tim )
   37: {
   38:         CHECK_PAR(pk_tim->hi >= 0);
   39: 
   40:         BEGIN_CRITICAL_SECTION;
   41:         knl_real_time_ofs = ll_sub(knl_toLSYSTIM(pk_tim), knl_current_time);
   42:         END_CRITICAL_SECTION;
   43: 
   44:         return E_OK;
   45: }
   46: #endif /* USE_FUNC_TK_SET_UTC */
   47: 
   48: #ifdef USE_FUNC_TK_GET_UTC
   49: /*
   50:  * Refer system clock
   51:  */
   52: SYSCALL ER tk_get_utc( SYSTIM *pk_tim )
   53: {
   54:         BEGIN_CRITICAL_SECTION;
   55:         *pk_tim = knl_toSYSTIM(ll_add(knl_current_time, knl_real_time_ofs));
   56:         END_CRITICAL_SECTION;
   57: 
   58:         return E_OK;
   59: }
   60: #endif /* USE_FUNC_TK_GET_UTC */
   61: 
   62: #ifdef USE_FUNC_TK_SET_TIM
   63: /*
   64:  * Set system clock (TRON Time)
   65:  */
   66: SYSCALL ER tk_set_tim( CONST SYSTIM *pk_tim )
   67: {
   68:         LSYSTIM                utc_time;
   69: 
   70:         CHECK_PAR(pk_tim->hi >= 0);
   71:         utc_time = ll_add(knl_toLSYSTIM(pk_tim), DIFF_TRON_UTC);
   72: 
   73:         BEGIN_CRITICAL_SECTION;
   74:         knl_real_time_ofs = ll_sub(utc_time, knl_current_time);
   75:         END_CRITICAL_SECTION;
   76: 
   77:         return E_OK;
   78: }
   79: #endif /* USE_FUNC_TK_SET_TIM */
   80: 
   81: #ifdef USE_FUNC_TK_GET_TIM
   82: /*
   83:  * Refer system clock (TRON Time)
   84:  */
   85: SYSCALL ER tk_get_tim( SYSTIM *pk_tim )
   86: {
   87:         LSYSTIM                utc_time;
   88: 
   89:         BEGIN_CRITICAL_SECTION;
   90:         utc_time = ll_add(knl_current_time, knl_real_time_ofs);
   91:         END_CRITICAL_SECTION;
   92: 
   93:         *pk_tim = knl_toSYSTIM(ll_sub(utc_time, DIFF_TRON_UTC));
   94: 
   95:         return E_OK;
   96: }
   97: #endif /* USE_FUNC_TK_GET_TIM */
   98: 
   99: #ifdef USE_FUNC_TK_GET_OTM
  100: /*
  101:  * Refer system operating time
  102:  */
  103: SYSCALL ER tk_get_otm( SYSTIM *pk_tim )
  104: {
  105:         BEGIN_CRITICAL_SECTION;
  106:         *pk_tim = knl_toSYSTIM(knl_current_time);
  107:         END_CRITICAL_SECTION;
  108: 
  109:         return E_OK;
  110: }
  111: #endif /* USE_FUNC_TK_GET_OTM */
  112: 
  113: #if USE_DBGSPT
  114: #ifdef USE_FUNC_TD_GET_TIM
  115: /*
  116:  * Refer system clock
  117:  */
  118: SYSCALL ER td_get_tim( SYSTIM *tim, UW *ofs )
  119: {
  120:         BEGIN_DISABLE_INTERRUPT;
  121:         *ofs = knl_get_hw_timer_nsec();
  122:         *tim = knl_toSYSTIM(ll_add(knl_current_time, knl_real_time_ofs));
  123:         END_DISABLE_INTERRUPT;
  124: 
  125:         return E_OK;
  126: }
  127: #endif /* USE_FUNC_TD_GET_TIM */
  128: 
  129: #ifdef USE_FUNC_TD_GET_OTM
  130: /*
  131:  * Refer system operating time
  132:  */
  133: SYSCALL ER td_get_otm( SYSTIM *tim, UW *ofs )
  134: {
  135:         BEGIN_DISABLE_INTERRUPT;
  136:         *ofs = knl_get_hw_timer_nsec();
  137:         *tim = knl_toSYSTIM(knl_current_time);
  138:         END_DISABLE_INTERRUPT;
  139: 
  140:         return E_OK;
  141: }
  142: #endif /* USE_FUNC_TD_GET_OTM */
  143: #endif /* USE_DBGSPT */
  144: #endif /* USE_TIMEMANAGEMENT */
  145: 
  146: 
  147: /* ------------------------------------------------------------------------ */
  148: /*
  149:  *      Cyclic handler
  150:  */
  151: 
  152: #if USE_CYCLICHANDLER
  153: 
  154: Noinit(EXPORT CYCCB knl_cyccb_table[NUM_CYCID]);        /* Cyclic handler control block */
  155: Noinit(EXPORT QUEUE     knl_free_cyccb);    /* FreeQue */
  156: 
  157: 
  158: /*
  159:  * Initialization of cyclic handler control block
  160:  */
  161: EXPORT ER knl_cyclichandler_initialize( void )
  162: {
  163:         CYCCB  *cyccb, *end;
  164: 
  165:         /* Get system information */
  166:         if ( NUM_CYCID < 1 ) {
  167:                 return E_SYS;
  168:         }
  169: 
  170:         /* Register all control blocks onto FreeQue */
  171:         QueInit(&knl_free_cyccb);
  172:         end = knl_cyccb_table + NUM_CYCID;
  173:         for ( cyccb = knl_cyccb_table; cyccb < end; cyccb++ ) {
  174:                 cyccb->cychdr = NULL; /* Unregistered handler */
  175:                 QueInsert((QUEUE*)cyccb, &knl_free_cyccb);
  176:         }
  177: 
  178:         return E_OK;
  179: }
  180: 
  181: 
  182: /*
  183:  * Cyclic handler routine
  184:  */
  185: EXPORT void knl_call_cychdr( CYCCB *cyccb )
  186: {
  187:         /* Set next startup time */
  188:         knl_cyc_timer_insert(cyccb, knl_cyc_next_time(cyccb));
  189: 
  190:         /* Execute cyclic handler / Enable interrupt nest */
  191:         ENABLE_INTERRUPT_UPTO(TIMER_INTLEVEL);
  192:         CallUserHandlerP1(cyccb->exinf, cyccb->cychdr, cyccb);
  193:         DISABLE_INTERRUPT;
  194: }
  195: 
  196: /*
  197:  * Immediate call of cyclic handler 
  198:  */
  199: LOCAL void knl_immediate_call_cychdr( CYCCB *cyccb )
  200: {
  201:         /* Set next startup time */
  202:         knl_cyc_timer_insert(cyccb, knl_cyc_next_time(cyccb));
  203: 
  204:         /* Execute cyclic handler in task-independent part
  205:            (Keep interrupt disabled) */
  206:         ENTER_TASK_INDEPENDENT;
  207:         CallUserHandlerP1(cyccb->exinf, cyccb->cychdr, cyccb);
  208:         LEAVE_TASK_INDEPENDENT;
  209: }
  210: 
  211: /*
  212:  * Create cyclic handler 
  213:  */
  214: SYSCALL ID tk_cre_cyc( CONST T_CCYC *pk_ccyc )
  215: {
  216: #if CHK_RSATR
  217:         const ATR VALID_CYCATR = {
  218:                  TA_HLNG
  219:                 |TA_STA
  220:                 |TA_PHS
  221: #if USE_OBJECT_NAME
  222:                 |TA_DSNAME
  223: #endif
  224:         };
  225: #endif
  226:         CYCCB  *cyccb;
  227:         ABSTIM tm;
  228:         ER     ercd = E_OK;
  229: 
  230:         CHECK_RSATR(pk_ccyc->cycatr, VALID_CYCATR);
  231:         CHECK_PAR(pk_ccyc->cychdr != NULL);
  232:         CHECK_PAR(pk_ccyc->cyctim > 0);
  233:         CHECK_RELTIM(pk_ccyc->cyctim);
  234: 
  235:         BEGIN_CRITICAL_SECTION;
  236:         /* Get control block from FreeQue */
  237:         cyccb = (CYCCB*)QueRemoveNext(&knl_free_cyccb);
  238:         if ( cyccb == NULL ) {
  239:                 ercd = E_LIMIT;
  240:                 goto error_exit;
  241:         }
  242: 
  243:         /* Initialize control block */
  244:         cyccb->exinf   = pk_ccyc->exinf;
  245:         cyccb->cycatr  = pk_ccyc->cycatr;
  246:         cyccb->cychdr  = pk_ccyc->cychdr;
  247:         cyccb->cyctim  = pk_ccyc->cyctim;
  248: #if USE_OBJECT_NAME
  249:         if ( (pk_ccyc->cycatr & TA_DSNAME) != 0 ) {
  250:                 knl_strncpy((char*)cyccb->name, (char*)pk_ccyc->dsname, OBJECT_NAME_LENGTH);
  251:         }
  252: #endif
  253: 
  254:         /* First startup time
  255:          *     To guarantee the start of handler after the specified time,
  256:          *     add TIMER_PERIOD. 
  257:          */
  258:         tm = lltoul(knl_current_time) + pk_ccyc->cycphs + TIMER_PERIOD;
  259: 
  260:         if ( (pk_ccyc->cycatr & TA_STA) != 0 ) {
  261:                 /* Start cyclic handler */
  262:                 cyccb->cycstat = TCYC_STA;
  263: 
  264:                 if ( pk_ccyc->cycphs == 0 ) {
  265:                         /* Immediate execution */
  266:                         cyccb->cyctmeb.time = tm;
  267:                         knl_immediate_call_cychdr(cyccb);
  268:                 } else {
  269:                         /* Register onto timer event queue */
  270:                         knl_cyc_timer_insert(cyccb, tm);
  271:                 }
  272:         } else {
  273:                 /* Initialize only counter */
  274:                 cyccb->cycstat = TCYC_STP;
  275:                 cyccb->cyctmeb.time = tm;
  276:         }
  277: 
  278:         ercd = ID_CYC(cyccb - knl_cyccb_table);
  279: 
  280:     error_exit:
  281:         END_CRITICAL_SECTION;
  282: 
  283:         return ercd;
  284: }
  285: 
  286: #ifdef USE_FUNC_TK_DEL_CYC
  287: /*
  288:  * Delete cyclic handler 
  289:  */
  290: SYSCALL ER tk_del_cyc( ID cycid )
  291: {
  292:         CYCCB  *cyccb;
  293:         ER     ercd = E_OK;
  294: 
  295:         CHECK_CYCID(cycid);
  296: 
  297:         cyccb = get_cyccb(cycid);
  298: 
  299:         BEGIN_CRITICAL_SECTION;
  300:         if ( cyccb->cychdr == NULL ) { /* Unregistered handler */
  301:                 ercd = E_NOEXS;
  302:         } else {
  303:                 if ( (cyccb->cycstat & TCYC_STA) != 0 ) {
  304:                         /* Delete timer event queue */
  305:                         knl_timer_delete(&cyccb->cyctmeb);
  306:                 }
  307: 
  308:                 /* Return to FreeQue */
  309:                 QueInsert((QUEUE*)cyccb, &knl_free_cyccb);
  310:                 cyccb->cychdr = NULL; /* Unregistered handler */
  311:         }
  312:         END_CRITICAL_SECTION;
  313: 
  314:         return ercd;
  315: }
  316: #endif /* USE_FUNC_TK_DEL_CYC */
  317: 
  318: #ifdef USE_FUNC_TK_STA_CYC
  319: /*
  320:  * Start cyclic handler 
  321:  */
  322: SYSCALL ER tk_sta_cyc( ID cycid )
  323: {
  324:         CYCCB  *cyccb;
  325:         ABSTIM tm, cur;
  326:         ER     ercd = E_OK;
  327: 
  328:         CHECK_CYCID(cycid);
  329: 
  330:         cyccb = get_cyccb(cycid);
  331: 
  332:         BEGIN_CRITICAL_SECTION;
  333:         if ( cyccb->cychdr == NULL ) { /* Unregistered handler */
  334:                 ercd = E_NOEXS;
  335:                 goto error_exit;
  336:         }
  337: 
  338:         cur = lltoul(knl_current_time);
  339: 
  340:         if ( (cyccb->cycatr & TA_PHS) != 0 ) {
  341:                 /* Continue cyclic phase */
  342:                 if ( (cyccb->cycstat & TCYC_STA) == 0 ) {
  343:                         /* Start cyclic handler */
  344:                         tm = cyccb->cyctmeb.time;
  345:                         if ( knl_abstim_reached(cur, tm) ) {
  346:                                 tm = knl_cyc_next_time(cyccb);
  347:                         }
  348:                         knl_cyc_timer_insert(cyccb, tm);
  349:                 }
  350:         } else {
  351:                 /* Reset cyclic interval */
  352:                 if ( (cyccb->cycstat & TCYC_STA) != 0 ) {
  353:                         /* Stop once */
  354:                         knl_timer_delete(&cyccb->cyctmeb);
  355:                 }
  356: 
  357:                 /* FIRST ACTIVATION TIME
  358:                  *    Adjust the first activation time with TIMER_PERIOD.
  359:                  *    TIMER_PERIOD is Timer interrupt interval (millisecond).
  360:                  */
  361:                 tm = cur + cyccb->cyctim + TIMER_PERIOD;
  362: 
  363:                 /* Start cyclic handler */
  364:                 knl_cyc_timer_insert(cyccb, tm);
  365:         }
  366:         cyccb->cycstat |= TCYC_STA;
  367: 
  368:     error_exit:
  369:         END_CRITICAL_SECTION;
  370: 
  371:         return ercd;
  372: }
  373: #endif /* USE_FUNC_TK_STA_CYC */
  374: 
  375: #ifdef USE_FUNC_TK_STP_CYC
  376: /*
  377:  * Stop cyclic handler 
  378:  */
  379: SYSCALL ER tk_stp_cyc( ID cycid )
  380: {
  381:         CYCCB  *cyccb;
  382:         ER     ercd = E_OK;
  383: 
  384:         CHECK_CYCID(cycid);
  385: 
  386:         cyccb = get_cyccb(cycid);
  387: 
  388:         BEGIN_CRITICAL_SECTION;
  389:         if ( cyccb->cychdr == NULL ) { /* Unregistered handler */
  390:                 ercd = E_NOEXS;
  391:         } else {
  392:                 if ( (cyccb->cycstat & TCYC_STA) != 0 ) {
  393:                         /* Stop cyclic handler */
  394:                         knl_timer_delete(&cyccb->cyctmeb);
  395:                 }
  396:                 cyccb->cycstat &= ~TCYC_STA;
  397:         }
  398:         END_CRITICAL_SECTION;
  399: 
  400:         return ercd;
  401: }
  402: #endif /* USE_FUNC_TK_STP_CYC */
  403: 
  404: #ifdef USE_FUNC_TK_REF_CYC
  405: /*
  406:  * Refer cyclic handler state
  407:  */
  408: SYSCALL ER tk_ref_cyc( ID cycid, T_RCYC* pk_rcyc )
  409: {
  410:         CYCCB  *cyccb;
  411:         ABSTIM tm, cur;
  412:         ER     ercd = E_OK;
  413: 
  414:         CHECK_CYCID(cycid);
  415: 
  416:         cyccb = get_cyccb(cycid);
  417: 
  418:         BEGIN_CRITICAL_SECTION;
  419:         if ( cyccb->cychdr == NULL ) { /* Unregistered handler */
  420:                 ercd = E_NOEXS;
  421:         } else {
  422:                 tm = cyccb->cyctmeb.time;
  423:                 cur = lltoul(knl_current_time);
  424:                 if ( (cyccb->cycstat & TCYC_STA) == 0 ) {
  425:                         if ( knl_abstim_reached(cur, tm) ) {
  426:                                 tm = knl_cyc_next_time(cyccb);
  427:                         }
  428:                 }
  429:                 if ( knl_abstim_reached(cur + TIMER_PERIOD, tm) ) {
  430:                         tm = 0;
  431:                 }
  432:                 else {
  433:                         tm -= (cur + TIMER_PERIOD);
  434:                 }
  435: 
  436:                 pk_rcyc->exinf   = cyccb->exinf;
  437:                 pk_rcyc->lfttim  = tm;
  438:                 pk_rcyc->cycstat = cyccb->cycstat;
  439:         }
  440:         END_CRITICAL_SECTION;
  441: 
  442:         return ercd;
  443: }
  444: #endif /* USE_FUNC_TK_REF_CYC */
  445: 
  446: #if USE_DBGSPT
  447: 
  448: #if USE_OBJECT_NAME
  449: /*
  450:  * Get object name from control block
  451:  */
  452: EXPORT ER knl_cyclichandler_getname(ID id, UB **name)
  453: {
  454:         CYCCB  *cyccb;
  455:         ER     ercd = E_OK;
  456: 
  457:         CHECK_CYCID(id);
  458: 
  459:         BEGIN_DISABLE_INTERRUPT;
  460:         cyccb = get_cyccb(id);
  461:         if ( cyccb->cychdr == NULL ) {
  462:                 ercd = E_NOEXS;
  463:                 goto error_exit;
  464:         }
  465:         if ( (cyccb->cycatr & TA_DSNAME) == 0 ) {
  466:                 ercd = E_OBJ;
  467:                 goto error_exit;
  468:         }
  469:         *name = cyccb->name;
  470: 
  471:     error_exit:
  472:         END_DISABLE_INTERRUPT;
  473: 
  474:         return ercd;
  475: }
  476: #endif /* USE_OBJECT_NAME */
  477: 
  478: #ifdef USE_FUNC_TD_LST_CYC
  479: /*
  480:  * Refer cyclic handler usage state
  481:  */
  482: SYSCALL INT td_lst_cyc( ID list[], INT nent )
  483: {
  484:         CYCCB  *cyccb, *end;
  485:         INT    n = 0;
  486: 
  487:         BEGIN_DISABLE_INTERRUPT;
  488:         end = knl_cyccb_table + NUM_CYCID;
  489:         for ( cyccb = knl_cyccb_table; cyccb < end; cyccb++ ) {
  490:                 /* Unregistered handler */
  491:                 if ( cyccb->cychdr == NULL ) {
  492:                         continue;
  493:                 }
  494: 
  495:                 if ( n++ < nent ) {
  496:                         *list++ = ID_CYC(cyccb - knl_cyccb_table);
  497:                 }
  498:         }
  499:         END_DISABLE_INTERRUPT;
  500: 
  501:         return n;
  502: }
  503: #endif /* USE_FUNC_TD_LST_CYC */
  504: 
  505: #ifdef USE_FUNC_TD_REF_CYC
  506: /*
  507:  * Refer cyclic handler state
  508:  */
  509: SYSCALL ER td_ref_cyc( ID cycid, TD_RCYC* pk_rcyc )
  510: {
  511:         CYCCB  *cyccb;
  512:         ABSTIM tm, cur;
  513:         ER     ercd = E_OK;
  514: 
  515:         CHECK_CYCID(cycid);
  516: 
  517:         cyccb = get_cyccb(cycid);
  518: 
  519:         BEGIN_DISABLE_INTERRUPT;
  520:         if ( cyccb->cychdr == NULL ) { /* Unregistered handler */
  521:                 ercd = E_NOEXS;
  522:         } else {
  523:                 tm = cyccb->cyctmeb.time;
  524:                 cur = lltoul(knl_current_time);
  525:                 if ( (cyccb->cycstat & TCYC_STA) == 0 ) {
  526:                         if ( knl_abstim_reached(cur, tm) ) {
  527:                                 tm = knl_cyc_next_time(cyccb);
  528:                         }
  529:                 }
  530:                 if ( knl_abstim_reached(cur + TIMER_PERIOD, tm) ) {
  531:                         tm = 0;
  532:                 }
  533:                 else {
  534:                         tm -= (cur + TIMER_PERIOD);
  535:                 }
  536: 
  537:                 pk_rcyc->exinf   = cyccb->exinf;
  538:                 pk_rcyc->lfttim  = lltoul(tm);
  539:                 pk_rcyc->cycstat = cyccb->cycstat;
  540:         }
  541:         END_DISABLE_INTERRUPT;
  542: 
  543:         return ercd;
  544: }
  545: #endif /* USE_FUNC_TD_REF_CYC */
  546: 
  547: #endif /* USE_DBGSPT */
  548: #endif /* USE_CYCLICHANDLER */
  549: 
  550: /* ------------------------------------------------------------------------ */
  551: /*
  552:  *      Alarm handler
  553:  */
  554: 
  555: #if USE_ALARMHANDLER
  556: 
  557: Noinit(EXPORT ALMCB knl_almcb_table[NUM_ALMID]);        /* Alarm handler control block */
  558: Noinit(EXPORT QUEUE     knl_free_almcb);    /* FreeQue */
  559: 
  560: 
  561: /*
  562:  * Initialization of alarm handler control block 
  563:  */
  564: EXPORT ER knl_alarmhandler_initialize( void )
  565: {
  566:         ALMCB  *almcb, *end;
  567: 
  568:         /* Get system information */
  569:         if ( NUM_ALMID < 1 ) {
  570:                 return E_SYS;
  571:         }
  572: 
  573:         /* Register all control blocks onto FreeQue */
  574:         QueInit(&knl_free_almcb);
  575:         end = knl_almcb_table + NUM_ALMID;
  576:         for ( almcb = knl_almcb_table; almcb < end; almcb++ ) {
  577:                 almcb->almhdr = NULL; /* Unregistered handler */
  578:                 QueInsert((QUEUE*)almcb, &knl_free_almcb);
  579:         }
  580: 
  581:         return E_OK;
  582: }
  583: 
  584: 
  585: /*
  586:  * Alarm handler start routine
  587:  */
  588: EXPORT void knl_call_almhdr( ALMCB *almcb )
  589: {
  590:         almcb->almstat &= ~TALM_STA;
  591: 
  592:         /* Execute alarm handler/ Enable interrupt nesting */
  593:         ENABLE_INTERRUPT_UPTO(TIMER_INTLEVEL);
  594:         CallUserHandlerP1(almcb->exinf, almcb->almhdr, almcb);
  595:         DISABLE_INTERRUPT;
  596: }
  597: 
  598: 
  599: /*
  600:  * Create alarm handler
  601:  */
  602: SYSCALL ID tk_cre_alm( CONST T_CALM *pk_calm )
  603: {
  604: #if CHK_RSATR
  605:         const ATR VALID_ALMATR = {
  606:                  TA_HLNG
  607: #if USE_OBJECT_NAME
  608:                 |TA_DSNAME
  609: #endif
  610:         };
  611: #endif
  612:         ALMCB  *almcb;
  613:         ER     ercd = E_OK;
  614: 
  615:         CHECK_RSATR(pk_calm->almatr, VALID_ALMATR);
  616:         CHECK_PAR(pk_calm->almhdr != NULL);
  617: 
  618:         BEGIN_CRITICAL_SECTION;
  619:         /* Get control block from free queue */
  620:         almcb = (ALMCB*)QueRemoveNext(&knl_free_almcb);
  621:         if ( almcb == NULL ) {
  622:                 ercd = E_LIMIT;
  623:                 goto error_exit;
  624:         }
  625: 
  626:         /* Initialize control block */
  627:         almcb->exinf   = pk_calm->exinf;
  628:         almcb->almatr  = pk_calm->almatr;
  629:         almcb->almhdr  = pk_calm->almhdr;
  630:         almcb->almstat = TALM_STP;
  631: #if USE_OBJECT_NAME
  632:         if ( (pk_calm->almatr & TA_DSNAME) != 0 ) {
  633:                 knl_strncpy((char*)almcb->name, (char*)pk_calm->dsname, OBJECT_NAME_LENGTH);
  634:         }
  635: #endif
  636: 
  637:         ercd = ID_ALM(almcb - knl_almcb_table);
  638: 
  639:     error_exit:
  640:         END_CRITICAL_SECTION;
  641: 
  642:         return ercd;
  643: }
  644: 
  645: #ifdef USE_FUNC_TK_DEL_ALM
  646: /*
  647:  * Delete alarm handler
  648:  */
  649: SYSCALL ER tk_del_alm( ID almid )
  650: {
  651:         ALMCB  *almcb;
  652:         ER     ercd = E_OK;
  653: 
  654:         CHECK_ALMID(almid);
  655: 
  656:         almcb = get_almcb(almid);
  657: 
  658:         BEGIN_CRITICAL_SECTION;
  659:         if ( almcb->almhdr == NULL ) { /* Unregistered handler */
  660:                 ercd = E_NOEXS;
  661:         } else {
  662:                 if ( (almcb->almstat & TALM_STA) != 0 ) {
  663:                         /* Delete from timer event queue */
  664:                         knl_timer_delete(&almcb->almtmeb);
  665:                 }
  666: 
  667:                 /* Return to FreeQue */
  668:                 QueInsert((QUEUE*)almcb, &knl_free_almcb);
  669:                 almcb->almhdr = NULL; /* Unregistered handler */
  670:         }
  671:         END_CRITICAL_SECTION;
  672: 
  673:         return ercd;
  674: }
  675: #endif /* USE_FUNC_TK_DEL_ALM */
  676: 
  677: /*
  678:  * Alarm handler immediate call
  679:  */
  680: LOCAL void knl_immediate_call_almhdr( ALMCB *almcb )
  681: {
  682:         almcb->almstat &= ~TALM_STA;
  683: 
  684:         /* Execute alarm handler in task-independent part
  685:            (Keep interrupt disabled) */
  686:         ENTER_TASK_INDEPENDENT;
  687:         CallUserHandlerP1(almcb->exinf, almcb->almhdr, almcb);
  688:         LEAVE_TASK_INDEPENDENT;
  689: }
  690: 
  691: /*
  692:  * Start alarm handler
  693:  */
  694: SYSCALL ER tk_sta_alm( ID almid, RELTIM almtim )
  695: {
  696:         ALMCB  *almcb;
  697:         ER     ercd = E_OK;
  698: 
  699:         CHECK_ALMID(almid);
  700:         CHECK_RELTIM(almtim);
  701: 
  702:         almcb = get_almcb(almid);
  703: 
  704:         BEGIN_CRITICAL_SECTION;
  705:         if ( almcb->almhdr == NULL ) { /* Unregistered handler */
  706:                 ercd = E_NOEXS;
  707:                 goto error_exit;
  708:         }
  709: 
  710:         if ( (almcb->almstat & TALM_STA) != 0 ) {
  711:                 /* Cancel current settings */
  712:                 knl_timer_delete(&almcb->almtmeb);
  713:         }
  714: 
  715:         if ( almtim > 0 ) {
  716:                 /* Register onto timer event queue */
  717:                 knl_alm_timer_insert(almcb, almtim);
  718:                 almcb->almstat |= TALM_STA;
  719:         } else {
  720:                 /* Immediate execution */
  721:                 knl_immediate_call_almhdr(almcb);
  722:         }
  723: 
  724:     error_exit:
  725:         END_CRITICAL_SECTION;
  726: 
  727:         return ercd;
  728: }
  729: 
  730: #ifdef USE_FUNC_TK_STP_ALM
  731: /*
  732:  * Stop alarm handler
  733:  */
  734: SYSCALL ER tk_stp_alm( ID almid )
  735: {
  736:         ALMCB  *almcb;
  737:         ER     ercd = E_OK;
  738: 
  739:         CHECK_ALMID(almid);
  740: 
  741:         almcb = get_almcb(almid);
  742: 
  743:         BEGIN_CRITICAL_SECTION;
  744:         if ( almcb->almhdr == NULL ) { /* Unregistered handler */
  745:                 ercd = E_NOEXS;
  746:         } else {
  747:                 if ( (almcb->almstat & TALM_STA) != 0 ) {
  748:                         /* Stop alarm handler address */
  749:                         knl_timer_delete(&almcb->almtmeb);
  750:                         almcb->almstat &= ~TALM_STA;
  751:                 }
  752:         }
  753:         END_CRITICAL_SECTION;
  754: 
  755:         return ercd;
  756: }
  757: #endif /* USE_FUNC_TK_STP_ALM */
  758: 
  759: #ifdef USE_FUNC_TK_REF_ALM
  760: /*
  761:  * Refer alarm handler state
  762:  */
  763: SYSCALL ER tk_ref_alm( ID almid, T_RALM *pk_ralm )
  764: {
  765:         ALMCB  *almcb;
  766:         ABSTIM tm, cur;
  767:         ER     ercd = E_OK;
  768: 
  769:         CHECK_ALMID(almid);
  770: 
  771:         almcb = get_almcb(almid);
  772: 
  773:         BEGIN_CRITICAL_SECTION;
  774:         if ( almcb->almhdr == NULL ) { /* Unregistered handler */
  775:                 ercd = E_NOEXS;
  776:         } else {
  777:                 cur = lltoul(knl_current_time);
  778:                 if ( (almcb->almstat & TALM_STA) != 0 ) {
  779:                         tm = almcb->almtmeb.time;
  780:                         if ( knl_abstim_reached(cur + TIMER_PERIOD, tm) ) {
  781:                                 tm = 0;
  782:                         }
  783:                         else {
  784:                                 tm -= (cur + TIMER_PERIOD);
  785:                         }
  786:                 } else {
  787:                         tm = 0;
  788:                 }
  789: 
  790:                 pk_ralm->exinf   = almcb->exinf;
  791:                 pk_ralm->lfttim  = tm;
  792:                 pk_ralm->almstat = almcb->almstat;
  793:         }
  794:         END_CRITICAL_SECTION;
  795: 
  796:         return ercd;
  797: }
  798: #endif /* USE_FUNC_TK_REF_ALM */
  799: 
  800: #if USE_DBGSPT
  801: 
  802: #if USE_OBJECT_NAME
  803: /*
  804:  * Get object name from control block
  805:  */
  806: EXPORT ER knl_alarmhandler_getname(ID id, UB **name)
  807: {
  808:         ALMCB  *almcb;
  809:         ER     ercd = E_OK;
  810: 
  811:         CHECK_ALMID(id);
  812: 
  813:         BEGIN_DISABLE_INTERRUPT;
  814:         almcb = get_almcb(id);
  815:         if ( almcb->almhdr == NULL ) {
  816:                 ercd = E_NOEXS;
  817:                 goto error_exit;
  818:         }
  819:         if ( (almcb->almatr & TA_DSNAME) == 0 ) {
  820:                 ercd = E_OBJ;
  821:                 goto error_exit;
  822:         }
  823:         *name = almcb->name;
  824: 
  825:     error_exit:
  826:         END_DISABLE_INTERRUPT;
  827: 
  828:         return ercd;
  829: }
  830: #endif /* USE_OBJECT_NAME */
  831: 
  832: #ifdef USE_FUNC_TD_LST_ALM
  833: /*
  834:  * Refer alarm handler usage state
  835:  */
  836: SYSCALL INT td_lst_alm( ID list[], INT nent )
  837: {
  838:         ALMCB  *almcb, *end;
  839:         INT    n = 0;
  840: 
  841:         BEGIN_DISABLE_INTERRUPT;
  842:         end = knl_almcb_table + NUM_ALMID;
  843:         for ( almcb = knl_almcb_table; almcb < end; almcb++ ) {
  844:                 /* Unregistered handler */
  845:                 if ( almcb->almhdr == NULL ) {
  846:                         continue;
  847:                 }
  848: 
  849:                 if ( n++ < nent ) {
  850:                         *list++ = ID_ALM(almcb - knl_almcb_table);
  851:                 }
  852:         }
  853:         END_DISABLE_INTERRUPT;
  854: 
  855:         return n;
  856: }
  857: #endif /* USE_FUNC_TD_LST_ALM */
  858: 
  859: #ifdef USE_FUNC_TD_REF_ALM
  860: /*
  861:  * Refer alarm handler state
  862:  */
  863: SYSCALL ER td_ref_alm( ID almid, TD_RALM *pk_ralm )
  864: {
  865:         ALMCB  *almcb;
  866:         ABSTIM tm, cur;
  867:         ER     ercd = E_OK;
  868: 
  869:         CHECK_ALMID(almid);
  870: 
  871:         almcb = get_almcb(almid);
  872: 
  873:         BEGIN_DISABLE_INTERRUPT;
  874:         if ( almcb->almhdr == NULL ) { /* Unregistered handler */
  875:                 ercd = E_NOEXS;
  876:         } else {
  877:                 cur = lltoul(knl_current_time);
  878:                 if ( (almcb->almstat & TALM_STA) != 0 ) {
  879:                         tm = almcb->almtmeb.time;
  880:                         if ( knl_abstim_reached(cur + TIMER_PERIOD, tm) ) {
  881:                                 tm = 0;
  882:                         }
  883:                         else {
  884:                                 tm -= (cur + TIMER_PERIOD);
  885:                         }
  886:                 } else {
  887:                         tm = 0;
  888:                 }
  889: 
  890:                 pk_ralm->exinf   = almcb->exinf;
  891:                 pk_ralm->lfttim  = tm;
  892:                 pk_ralm->almstat = almcb->almstat;
  893:         }
  894:         END_DISABLE_INTERRUPT;
  895: 
  896:         return ercd;
  897: }
  898: #endif /* USE_FUNC_TD_REF_ALM */
  899: 
  900: #endif /* USE_DBGSPT */
  901: #endif /* USE_ALARMHANDLER */