📄 timerlib.c
字号:
** This routine returns the timer expiration overrun count for <timerid>,* when called from a timer expiration signal catcher. The overrun count is* the number of extra timer expirations that have occurred, up to the* implementation-defined maximum _POSIX_DELAYTIMER_MAX. If the count is* greater than the maximum, it returns the maximum.** RETURNS:* The number of overruns, or _POSIX_DELAYTIMER_MAX if the count equals or is* greater than _POSIX_DELAYTIMER_MAX, or -1 (ERROR) if <timerid> is invalid.** ERRNO: EINVAL, ENOSYS*/int timer_getoverrun ( timer_t timerid /* timer ID */ ) { if (timerid == NULL) { errno = EINVAL; return (ERROR); } return (timerid->sigpend.sigp_overruns); }/********************************************************************************* timerWdHandler - wd handler used by timer_settime** RETURNS: */LOCAL void timerWdHandler ( timer_t timerid ) { ULONG delayTicks; int status; if (timerid == NULL) { if (timerLibLog) logMsg ("timerWdHandler: NULL timerid!\n", 0, 0, 0, 0, 0, 0); return; } status = sigPendKill (timerid->taskId, &timerid->sigpend); if (status != OK && timerLibLog) { logMsg ("timerWdHandler: kill failed (timer=%#x, tid=%#x, errno=%#x)\n", (int)timerid, timerid->taskId, errno, 0, 0, 0); } if (TV_ISZERO(timerid->exp.it_interval)) { timerid->active = FALSE; } else { /* interval timer needs reloading */ TV_CONVERT_TO_TICK (delayTicks, timerid->exp.it_interval); if (delayTicks < 1) delayTicks = 1; /* delay of 0 will cause recursion! */ /* time stamp when we arm interval timer */ (void) clock_gettime (CLOCK_REALTIME, &(timerid->timeStamp)); wdStart (timerid->wdog, (int)delayTicks, (FUNCPTR)timerWdHandler, (int)timerid); } }/********************************************************************************* timer_settime - set the time until the next expiration and arm timer (POSIX)** This routine sets the next expiration of the timer, using the `.it_value'* of <value>, thus arming the timer. If the timer is already armed, this* call resets the time until the next expiration. If `.it_value' is zero,* the timer is disarmed.** If <flags> is not equal to TIMER_ABSTIME, the interval is relative to the* current time, the interval being the `.it_value' of the <value> parameter.* If <flags> is equal to TIMER_ABSTIME, the expiration is set to* the difference between the absolute time of `.it_value' and the current* value of the clock associated with <timerid>. If the time has already* passed, then the timer expiration notification is made immediately.* The task that sets the timer receives the signal; in other words, the taskId* is noted. If a timer is set by an ISR, the signal is delivered to the* task that created the timer.** The reload value of the timer is set to the value specified by* the `.it_interval' field of <value>. When a timer is* armed with a nonzero `.it_interval' a periodic timer is set up.** Time values that are between two consecutive non-negative integer* multiples of the resolution of the specified timer are rounded up to* the larger multiple of the resolution.** If <ovalue> is non-NULL, the routine stores a value representing the* previous amount of time before the timer would have expired. Or if the* timer is disarmed, the routine stores zero, together with the previous* timer reload value. The <ovalue> parameter is the same value as that * returned by timer_gettime() and is subject to the timer resolution.** WARNING* If clock_settime() is called to reset the absolute clock time after a timer* has been set with timer_settime(), and if <flags> is equal to TIMER_ABSTIME, * then the timer will behave unpredictably. If you must reset the absolute* clock time after setting a timer, do not use <flags> equal to TIMER_ABSTIME.** RETURNS:* 0 (OK), or -1 (ERROR) if <timerid> is invalid, the number of nanoseconds * specified by <value> is less than 0 or greater than or equal to * 1,000,000,000, or the time specified by <value> exceeds the maximum * allowed by the timer.** ERRNO: EINVAL*/int timer_settime ( timer_t timerid, /* timer ID */ int flags, /* absolute or relative */ const struct itimerspec *value, /* time to be set */ struct itimerspec *ovalue /* previous time set (NULL=no result) */ ) { struct timespec now; struct timespec timerExpire; /* absolute time that timer will go off */ ULONG delayTicks; if (timerid == NULL) { errno = EINVAL; return (ERROR); } if (timerid->clock_id != CLOCK_REALTIME || !TV_VALID(value->it_value)) { errno = EINVAL; return (ERROR); } if (ovalue != NULL) { /* if timer is disarmed, simply set value to 0 */ if (timerid->active == FALSE) { ovalue->it_value.tv_sec = 0; ovalue->it_value.tv_nsec = 0; } else { /* get current time */ if (clock_gettime (CLOCK_REALTIME, &now) == ERROR) return (ERROR);; /* use time stamp and get absolute time that timer will go off */ timerExpire.tv_sec = timerid->timeStamp.tv_sec + timerid->exp.it_value.tv_sec; timerExpire.tv_nsec = timerid->timeStamp.tv_nsec + timerid->exp.it_value.tv_nsec; TV_NORMALIZE (timerExpire); /* compute difference using current time */ ovalue->it_value.tv_sec = timerExpire.tv_sec - now.tv_sec; ovalue->it_value.tv_nsec = timerExpire.tv_nsec - now.tv_nsec; TV_NORMALIZE (ovalue->it_value); } /* get reload value */ ovalue->it_interval.tv_sec = timerid->exp.it_interval.tv_sec; ovalue->it_interval.tv_nsec = timerid->exp.it_interval.tv_nsec; TV_NORMALIZE (ovalue->it_interval); } if (TV_ISZERO(value->it_value)) { if (timerid->active) { timerid->active = FALSE; wdCancel (timerid->wdog); } return (OK); } TV_SET(timerid->exp.it_interval, value->it_interval); TV_SET(timerid->exp.it_value, value->it_value); if (flags == TIMER_ABSTIME) { /* convert current to relative time */ (void) clock_gettime (CLOCK_REALTIME, &now); /* could be in the past */ if (TV_GT(now, timerid->exp.it_value)) { TV_ZERO(timerid->exp.it_value); } else { TV_SUB(timerid->exp.it_value, now); } /* time stamp when timer is armed */ TV_SET (timerid->timeStamp, now); } else /* time stamp when timer is armed */ (void) clock_gettime (CLOCK_REALTIME, &(timerid->timeStamp)); TV_CONVERT_TO_TICK (delayTicks, timerid->exp.it_value); if (timerid->active) wdCancel (timerid->wdog); else timerid->active = TRUE; wdStart (timerid->wdog, delayTicks, (FUNCPTR)timerWdHandler, (int)timerid); return (OK); }/********************************************************************************* timer_show - show information on a specified timer** WARNING* Non-POSIX.** RETURNS: 0 (OK), or -1 (ERROR) if <timerid> is invalid, or the context is * invalid.** ERRNO: EINVAL** NOMANUAL*/int timer_show ( timer_t timerid /* timer ID */ ) { static char *title1 = "task timerid evp routine\n"; static char *title2 = "---------- ---------- ---------- ----------\n"; if (intContext ()) return (ERROR); if (timerid == NULL) return (OK); printf (title1); printf (title2); printf ("%#10x %#10x %#10x %#10x\n", timerid->taskId, (unsigned int)timerid, (unsigned int)&timerid->sevent, (unsigned int)timerid->routine); return (OK); }/********************************************************************************* nanosleep - suspend the current task until the time interval elapses (POSIX)** This routine suspends the current task for a specified time <rqtp>* or until a signal or event notification is made.** The suspension may be longer than requested due to the rounding up of the* request to the timer's resolution or to other scheduling activities (e.g.,* a higher priority task intervenes).** The `timespec' structure is defined as follows:** \cs* struct timespec* {* /@ interval = tv_sec*10**9 + tv_nsec @/* time_t tv_sec; /@ seconds @/* long tv_nsec; /@ nanoseconds (0 - 1,000,000,000) @/* };* \ce** If <rmtp> is non-NULL, the `timespec' structure is updated to contain the* amount of time remaining. If <rmtp> is NULL, the remaining time is not* returned. The <rqtp> parameter is greater than 0 or less than or equal to* 1,000,000,000.** RETURNS:* 0 (OK), or -1 (ERROR) if the routine is interrupted by a signal or an * asynchronous event notification, or <rqtp> is invalid.** ERRNO: EINVAL, EINTR** SEE ALSO: sleep(), taskDelay()*/int nanosleep ( const struct timespec *rqtp, /* time to delay */ struct timespec *rmtp /* premature wakeup (NULL=no result) */ ) { int status; /* int oldErrno; */ ULONG delayTicks; struct timespec then; struct timespec now; int returnStatus; int savtype; if (rqtp == NULL || !TV_VALID(*rqtp)) { errno = EINVAL; return (ERROR); } if (TV_ISZERO(*rqtp)) return (OK); if (_func_pthread_setcanceltype != NULL) { _func_pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &savtype); } (void)clockLibInit (); /* make sure clock "running" */ (void)clock_gettime (CLOCK_REALTIME, &then); TV_CONVERT_TO_TICK (delayTicks, *rqtp); /* return's 1 (RESTART) if interrupted sleep */ status = taskDelay (delayTicks); if (status == 0) returnStatus = 0; else returnStatus = -1; if (rmtp != NULL) { (void)clock_gettime (CLOCK_REALTIME, &now); TV_SUB (now, then); /* make time relative to start */ if (TV_LT(now, *rqtp)) { TV_SET(*rmtp, *rqtp); TV_SUB(*rmtp, now); } else TV_ZERO((*rmtp)); } if (_func_pthread_setcanceltype != NULL) { _func_pthread_setcanceltype(savtype, NULL); } return (returnStatus); }/********************************************************************************* sleep - delay for a specified amount of time** This routine causes the calling task to be blocked for <secs> seconds.** The time the task is blocked for may be longer than requested due to the* rounding up of the request to the timer's resolution or to other scheduling* activities (e.g., a higher priority task intervenes).** RETURNS: Zero if the requested time has elapsed, or the number of seconds* remaining if it was interrupted.** ERRNO: EINVAL, EINTR** SEE ALSO: nanosleep(), taskDelay()*/ unsigned int sleep ( unsigned int secs ) { struct timespec ntp, otp; ntp.tv_sec = secs; ntp.tv_nsec = 0; nanosleep(&ntp, &otp); return(otp.tv_sec); }/********************************************************************************* alarm - set an alarm clock for delivery of a signal** This routine arranges for a 'SIGALRM' signal to be delivered to the* calling task after <secs> seconds.** If <secs> is zero, no new alarm is scheduled. In all cases, any previously* set alarm is cancelled.** RETURNS: Time remaining until a previously scheduled alarm was due to be* delivered, zero if there was no previous alarm, or ERROR in case of an* error.*/ unsigned int alarm ( unsigned int secs ) { static timer_t timer_id = NULL; struct itimerspec tspec, tremain; /* if first time, create a timer */ if (!timer_id) { if (timer_create(CLOCK_REALTIME, NULL, &timer_id) == ERROR) return(ERROR); } /* set new time*/ tspec.it_interval.tv_sec = 0; tspec.it_interval.tv_nsec = 0; tspec.it_value.tv_sec = secs; tspec.it_value.tv_nsec = 0; /* save off timer remaining from previous for return */ timer_gettime(timer_id, &tremain); timer_settime(timer_id, CLOCK_REALTIME, &tspec, NULL); return((unsigned int)tremain.it_value.tv_sec); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -