📄 timerlib.c
字号:
* RETURNS: 0 (OK), or -1 (ERROR) if <timerid> is invalid.** ERRNO: EINVAL*/int timer_gettime ( timer_t timerid, /* timer ID */ struct itimerspec *value /* where to return remaining time */ ) { struct timespec now; /* current time */ struct timespec timerExpire; /* absolute time that timer will go off */ if (timerid == NULL || value == NULL) { errno = EINVAL; return (ERROR); } if (timerid->clock_id != CLOCK_REALTIME) { errno = EINVAL; return (ERROR); } /* if timer is disarmed simply set value to 0 */ if (timerid->active == FALSE) { value->it_value.tv_sec = 0; value->it_value.tv_nsec = 0; value->it_interval.tv_sec = 0; value->it_interval.tv_nsec = 0; return (OK); } /* 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 */ value->it_value.tv_sec = timerExpire.tv_sec - now.tv_sec; value->it_value.tv_nsec = timerExpire.tv_nsec - now.tv_nsec; TV_NORMALIZE (value->it_value); /* get reload value */ value->it_interval.tv_sec = timerid->exp.it_interval.tv_sec; value->it_interval.tv_nsec = timerid->exp.it_interval.tv_nsec; TV_NORMALIZE (value->it_interval); return (OK); }/********************************************************************************* timer_getoverrun - return the timer expiration overrun (POSIX)** 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 -*/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; 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) { /* remainder (should already be zero if disarmed) */ TV_SET(ovalue->it_value, timerid->exp.it_value); TV_SET(ovalue->it_interval, timerid->exp.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).** 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: 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; if (rqtp == NULL || !TV_VALID(*rqtp)) { errno = EINVAL; return (ERROR); } if (TV_ISZERO(*rqtp)) return (OK); (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)); } return (returnStatus); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -