timerLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:25k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* timerLib.c - timer library (POSIX) */
  2. /* Copyright 1991-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02w,09may02,wsl  add definition of timespec to nanosleep comments; SPR 26086
  8. 02v,08aug00,jgn  move alarm from sigLib to timerLib
  9. 02u,17jul00,jgn  merge DOT-4 pthreads code
  10. 02t,19oct01,dcb  Fix the routine title line to match the coding conventions.
  11. 02s,21sep99,cno  check return from wdDelete (SPR20611)
  12. 02r,15sep99,pfl  fixed compile error
  13. 02q,09jul99,cno  timer_settime returns timer_gettime remaining time (SPR27189)
  14. 02p,21feb99,jdi  doc: listed errnos.
  15. 02o,05feb96,dbt  added a test in timer_settime to detect if the time has
  16.  already passed (SPR #7463).
  17. 02n,30oct96,dgp  doc: change INTERNAL comment to external for timer_settime
  18.   per SPR #6525
  19. 02m,09oct06,dgp  doc: correct timer_settime() reference per SPR 7323 & 3612
  20. 02l,28mar95,kdl  return timer reload value during timer_gettime() (SPR #3299).
  21. 02k,20jan95,jdi  doc cleanup, including new number for POSIX standard.
  22. 02j,08apr94,dvs  added check for disarmed timer in timer_gettime() (SPR #3100).
  23. 02i,08dec93,dvs  added fix of timer_gettime() for interval timer as well.
  24. 02h,06dec93,dvs  timer_gettime() now returns amt of time remaining on the timer
  25.  (SPR #2673)
  26. 02g,29nov93,dvs  brought up to POSIX draft 14 specification
  27. 02f,14mar93,jdi  fixed typo in code example for timer_connect().
  28. 02e,11feb93,gae  clockLibInit() installed before using timers (#1834).
  29.  made sure wdStart() not invoked with 0 delay when
  30.  interval less than clock resolution (#2006).
  31. 02d,02oct92,jdi  documentation cleanup.
  32. 02c,23sep92,kdl  changed include to private/timerLibP.h; deleted signal
  33.  function prototypes, now in sigLibP.h.
  34. 02b,19aug92,gae  fixed nanosleep() to return correct amount of underrun.
  35. 02a,22jul92,gae  Draft 12 revision.  fixed timer_getoverrun(), nanosleep().
  36.  Removed timerLibInit() and timer_object_create().
  37.  Got rid of objects.
  38. 01d,25jul92,smb  changed time.h to timers.h
  39. 01d,26may92,rrr  the tree shuffle
  40. 01c,30apr92,rrr  some preparation for posix signals.
  41. 01b,04feb92,gae  fixed copyright include; revised according to DEC review.
  42.      added ability to delete timers from exiting tasks;
  43.      timer_create() tests for valid signal number;
  44.      timer_getoverrun() always returns -1 as no support;
  45.      timer_settime() no longer arms timer with 0 delay.
  46.      nanosleep() no longer returns +1 on "success";
  47.      documentation touchup.
  48. 01a,16oct91,gae  written.
  49. */
  50. /*
  51. DESCRIPTION
  52. This library provides a timer interface, as defined in the IEEE standard,
  53. POSIX 1003.1b.
  54. Timers are mechanisms by which tasks signal themselves after a designated
  55. interval.  Timers are built on top of the clock and signal facilities.  The
  56. clock facility provides an absolute time-base.  Standard timer functions
  57. simply consist of creation, deletion and setting of a timer.  When a timer
  58. expires, sigaction() (see sigLib) must be in place in order for the user
  59. to handle the event.  The "high resolution sleep" facility, nanosleep(),
  60. allows sub-second sleeping to the resolution of the clock.
  61. The clockLib library should be installed and clock_settime() set
  62. before the use of any timer routines.
  63. ADDITIONS
  64. Two non-POSIX functions are provided for user convenience:
  65.    
  66.     timer_cancel() quickly disables a timer by calling timer_settime().
  67.     timer_connect() easily hooks up a user routine by calling sigaction().
  68. CLARIFICATIONS
  69. The task creating a timer with timer_create() will receive the
  70. signal no matter which task actually arms the timer.
  71. When a timer expires and the task has previously exited, logMsg()
  72. indicates the expected task is not present.  Similarly, logMsg() indicates
  73. when a task arms a timer without installing a signal handler.  Timers may
  74. be armed but not created or deleted at interrupt level.
  75. IMPLEMENTATION
  76. The actual clock resolution is hardware-specific and in many cases is
  77. 1/60th of a second.  This is less than _POSIX_CLOCKRES_MIN, which is
  78. defined as 20 milliseconds (1/50th of a second).
  79. INTERNAL
  80. 1. The <timespec> key calculation is limited by the amount of time
  81. represented (years?) and the resolution of the clock (1/1000's?).
  82. 2. Request for option of timer deletion when task is deleted.
  83. However, the task that created the timer is not necessarily the
  84. task that is going to receive it (set in timer_settime()).
  85. This could be cleared up, if the task calling timer_create()
  86. was the task to receive the signal.
  87. INCLUDE FILES: timers.h
  88. SEE ALSO: clockLib, sigaction(), POSIX 1003.1b documentation,
  89. .pG "Basic OS"
  90. */
  91. #include "vxWorks.h"
  92. #include "errno.h"
  93. #include "memLib.h"
  94. #include "logLib.h"
  95. #include "stdio.h"
  96. #include "stdlib.h"
  97. #include "string.h"
  98. #include "taskLib.h"
  99. #include "wdLib.h"
  100. #include "intLib.h"
  101. #include "time.h"
  102. #include "tickLib.h"
  103. #include "private/sigLibP.h"
  104. #include "private/timerLibP.h"
  105. #define __PTHREAD_SRC
  106. #include "pthread.h"
  107. extern int clockLibInit ();
  108. int timerLibLog = TRUE; /* log warning messages from wd handler */
  109. #define TIMER_RELTIME (~TIMER_ABSTIME) /* relative time */
  110. /*******************************************************************************
  111. *
  112. * timer_cancel - cancel a timer
  113. *
  114. * This routine is a shorthand method of invoking timer_settime(), which stops
  115. * a timer.
  116. *
  117. * NOTE
  118. * Non-POSIX.
  119. *
  120. * RETURNS: 0 (OK), or -1 (ERROR) if <timerid> is invalid.
  121. *
  122. * ERRNO: EINVAL
  123. */
  124. int timer_cancel
  125.     (
  126.     timer_t timerid /* timer ID */
  127.     )
  128.     {
  129.     struct itimerspec value;
  130.     bzero ((char*)&value, sizeof (value));
  131.     return (timer_settime (timerid, TIMER_RELTIME, &value, NULL));
  132.     }
  133. /*******************************************************************************
  134. *
  135. * timerConHandler - default 'connect' timer handler
  136. *
  137. * User routine wrapper called from timerWdHandler().
  138. *
  139. * RETURNS: N/A
  140. */
  141. LOCAL void timerConHandler
  142.     (
  143.     int     sig, /* caught signal */
  144.     timer_t timerid, /* "int code" */
  145.     struct sigcontext *pContext /* unused */
  146.     )
  147.     {
  148.     if (timerid == NULL)
  149. {
  150. /* sometimes caused by a pended signal ('code' lost when unblocked) */
  151. if (timerLibLog)
  152.     {
  153.     logMsg ("timerConHandler: bad timer %#x, signal %dn",
  154.     (int)timerid, sig, 0, 0, 0, 0);
  155.     }
  156. }
  157.     else if (timerid->routine == NULL)
  158. {
  159. if (timerLibLog)
  160.     {
  161.     logMsg ("timerConHandler: expired %#x, signal %dn",
  162.     (int)timerid, sig, 0, 0, 0, 0);
  163.     }
  164. }
  165.     else
  166. {
  167. (*timerid->routine) (timerid, timerid->arg);
  168. }
  169.     }
  170. /*******************************************************************************
  171. *
  172. * timer_connect - connect a user routine to the timer signal
  173. *
  174. * This routine sets the specified <routine> to be invoked with <arg> when
  175. * fielding a signal indicated by the timer's <evp> signal number, or
  176. * if <evp> is NULL, when fielding the default signal (SIGALRM).
  177. *
  178. * The signal handling routine should be declared as:
  179. * .ne 5
  180. * .CS
  181. *     void my_handler
  182. *         (
  183. *         timer_t timerid, /@ expired timer ID @/
  184. *         int arg               /@ user argument    @/
  185. *         )
  186. * .CE
  187. *
  188. * NOTE
  189. * Non-POSIX.
  190. *
  191. * RETURNS: 0 (OK), or -1 (ERROR) if the timer is invalid or cannot bind the 
  192. * signal handler.
  193. *
  194. * ERRNO: EINVAL
  195. */
  196. int timer_connect
  197.     (
  198.     timer_t     timerid, /* timer ID      */
  199.     VOIDFUNCPTR routine, /* user routine  */
  200.     int         arg /* user argument */
  201.     )
  202.     {
  203.     static struct sigaction timerSig;
  204.     if (timerSig.sa_handler == 0)
  205. {
  206. /* just the first time */
  207. timerSig.sa_handler = (void (*)(int))timerConHandler;
  208. (void) sigemptyset (&timerSig.sa_mask);
  209. timerSig.sa_flags = 0; /* !SA_SIGINFO: cause timerid to be passed */
  210. }
  211.     if (intContext ())
  212. return (ERROR);
  213.     if (timerid == NULL)
  214. {
  215. errno = EINVAL;
  216. return (ERROR);
  217. }
  218.     timerid->routine = routine;
  219.     timerid->arg     = arg;
  220.     timerid->sevent.sigev_signo = SIGALRM;
  221.     timerid->sevent.sigev_value.sival_ptr = timerid; /* !SA_SIGINFO */
  222.     if (sigaction (SIGALRM, &timerSig, NULL) == ERROR)
  223. return (ERROR);
  224.     else
  225. return (OK);
  226.     }
  227. /*******************************************************************************
  228. *
  229. * timer_create - allocate a timer using the specified clock for a timing base (POSIX)
  230. *
  231. * This routine returns a value in <pTimer> that identifies the timer 
  232. * in subsequent timer requests.  The <evp> argument, if non-NULL, points to 
  233. * a `sigevent' structure, which is allocated by the application and defines 
  234. * the signal number and application-specific data to be sent to the task when 
  235. * the timer expires.  If <evp> is NULL, a default signal (SIGALRM) is queued 
  236. * to the task, and the signal data is set to the timer ID.  Initially, the 
  237. * timer is disarmed.
  238. *
  239. * RETURNS:
  240. * 0 (OK), or -1 (ERROR) if too many timers already are allocated or the signal 
  241. * number is invalid.
  242. *
  243. * ERRNO: EMTIMERS, EINVAL, ENOSYS, EAGAIN, S_memLib_NOT_ENOUGH_MEMORY
  244. *
  245. * SEE ALSO: timer_delete()
  246. */
  247. int timer_create
  248.     (
  249.     clockid_t clock_id, /* clock ID (always CLOCK_REALTIME) */
  250.     struct sigevent *evp, /* user event handler               */
  251.     timer_t * pTimer /* ptr to return value      */
  252.     )
  253.     {
  254.     timer_t timerid;
  255.     struct sigevent sevp;
  256.     if (intContext ())
  257. return (ERROR);
  258.     (void)clockLibInit (); /* make sure clock "running" */
  259.     timerid = (timer_t) calloc (1, sizeof(*timerid));
  260.     if (timerid == NULL)
  261. {
  262. /* errno = EMTIMERS;  * S_memLib_NOT_ENOUGH_MEMORY will be lost */
  263. return (ERROR);
  264. }
  265.     if ((timerid->wdog = wdCreate ()) == NULL)
  266.         {
  267. free ((char *) timerid);
  268. return (ERROR);
  269.         }
  270.     timerid->active = FALSE;
  271.     timerid->taskId = taskIdSelf ();
  272.     timerid->clock_id = clock_id; /* should check for known clock_id? */
  273.     if (evp == NULL)
  274. {
  275. sevp.sigev_signo = SIGALRM;
  276. /* remember value possibly set in timer_connect() */
  277. /* XXX
  278. sevp.sigev_value.sival_int = timerid->sevent.sigev_value.sival_int;
  279. */
  280. sevp.sigev_value.sival_ptr = timerid;
  281. }
  282.     else
  283. {
  284. if (evp->sigev_signo < 1 || evp->sigev_signo > _NSIGS)
  285.     {
  286.     errno = EINVAL;
  287.     return (ERROR);
  288.     }
  289. sevp = *evp;
  290. }
  291.     timerid->sevent = sevp;
  292.     timerid->sigpend.sigp_info.si_signo = sevp.sigev_signo;
  293.     timerid->sigpend.sigp_info.si_code  = SI_TIMER;
  294.     timerid->sigpend.sigp_info.si_value = sevp.sigev_value;
  295.     sigPendInit (&timerid->sigpend);
  296.     TV_ZERO(timerid->exp.it_interval);
  297.     TV_ZERO(timerid->exp.it_value);
  298.     *pTimer = timerid;
  299.     return (OK);
  300.     }
  301. /*******************************************************************************
  302. *
  303. * timer_delete - remove a previously created timer (POSIX)
  304. *
  305. * This routine removes a timer.
  306. *
  307. * RETURNS: 0 (OK), or -1 (ERROR) if <timerid> is invalid.
  308. *
  309. * ERRNO: EINVAL
  310. *
  311. * SEE ALSO: timer_create()
  312. */
  313. int timer_delete
  314.     (
  315.     timer_t timerid /* timer ID */
  316.     )
  317.     {
  318.     if (intContext ())
  319. return (ERROR);
  320.     if (timerid == NULL)
  321. {
  322. errno = EINVAL;
  323. return (ERROR);
  324. }
  325.     if (timer_cancel (timerid) != 0)
  326. return (ERROR);
  327.     if (wdDelete (timerid->wdog) != OK)
  328.     return (ERROR);
  329.     (void)sigPendDestroy (&timerid->sigpend);
  330.     free ((char *) timerid);
  331.     return (OK);
  332.     }
  333. /*******************************************************************************
  334. *
  335. * timer_gettime - get the remaining time before expiration and the reload value (POSIX)
  336. *
  337. * This routine gets the remaining time and reload value of a specified timer.
  338. * Both values are copied to the <value> structure.
  339. *
  340. * RETURNS: 0 (OK), or -1 (ERROR) if <timerid> is invalid.
  341. *
  342. * ERRNO: EINVAL
  343. */
  344. int timer_gettime
  345.     (
  346.     timer_t           timerid,  /* timer ID                       */
  347.     struct itimerspec *value  /* where to return remaining time */
  348.     )
  349.     {
  350.     struct timespec now;   /* current time */ 
  351.     struct timespec timerExpire; /* absolute time that timer will go off */
  352.     if (timerid == NULL || value == NULL)
  353. {
  354. errno = EINVAL;
  355. return (ERROR);
  356. }
  357.     if (timerid->clock_id != CLOCK_REALTIME)
  358. {
  359. errno = EINVAL;
  360. return (ERROR);
  361. }
  362.     /* if timer is disarmed simply set value to 0 */
  363.     if (timerid->active == FALSE)
  364.         {
  365.         value->it_value.tv_sec = 0;
  366.         value->it_value.tv_nsec = 0;
  367.         value->it_interval.tv_sec = 0;
  368.         value->it_interval.tv_nsec = 0;
  369.         return (OK);
  370.         }
  371.     /* get current time */
  372.     if (clock_gettime (CLOCK_REALTIME, &now) == ERROR)
  373. return (ERROR);;
  374.     /* use time stamp and get absolute time that timer will go off */
  375.     timerExpire.tv_sec = timerid->timeStamp.tv_sec + timerid->exp.it_value.tv_sec;
  376.     timerExpire.tv_nsec = timerid->timeStamp.tv_nsec + timerid->exp.it_value.tv_nsec;
  377.     TV_NORMALIZE (timerExpire);
  378.     /* compute difference using current time */
  379.     value->it_value.tv_sec = timerExpire.tv_sec - now.tv_sec;
  380.     value->it_value.tv_nsec = timerExpire.tv_nsec - now.tv_nsec;
  381.     TV_NORMALIZE (value->it_value);
  382.     /* get reload value */
  383.     value->it_interval.tv_sec = timerid->exp.it_interval.tv_sec;
  384.     value->it_interval.tv_nsec = timerid->exp.it_interval.tv_nsec;
  385.     TV_NORMALIZE (value->it_interval);
  386.     return (OK);
  387.     }
  388. /*******************************************************************************
  389. *
  390. * timer_getoverrun - return the timer expiration overrun (POSIX)
  391. *
  392. * This routine returns the timer expiration overrun count for <timerid>,
  393. * when called from a timer expiration signal catcher.  The overrun count is
  394. * the number of extra timer expirations that have occurred, up to the
  395. * implementation-defined maximum _POSIX_DELAYTIMER_MAX.  If the count is
  396. * greater than the maximum, it returns the maximum.
  397. *
  398. * RETURNS:
  399. * The number of overruns, or _POSIX_DELAYTIMER_MAX if the count equals or is
  400. * greater than _POSIX_DELAYTIMER_MAX, or -1 (ERROR) if <timerid> is invalid.
  401. *
  402. * ERRNO: EINVAL, ENOSYS
  403. */
  404. int timer_getoverrun
  405.     (
  406.     timer_t timerid /* timer ID */
  407.     )
  408.     {
  409.     if (timerid == NULL)
  410. {
  411. errno = EINVAL;
  412. return (ERROR);
  413. }
  414.     return (timerid->sigpend.sigp_overruns);
  415.     }
  416. /*******************************************************************************
  417. *
  418. * timerWdHandler - wd handler used by timer_settime
  419. *
  420. * RETURNS: 
  421. */
  422. LOCAL void timerWdHandler
  423.     (
  424.     timer_t timerid
  425.     )
  426.     {
  427.     ULONG delayTicks;
  428.     int status;
  429.     if (timerid == NULL)
  430. {
  431. if (timerLibLog)
  432.     logMsg ("timerWdHandler: NULL timerid!n", 0, 0, 0, 0, 0, 0);
  433. return;
  434. }
  435.     status = sigPendKill (timerid->taskId, &timerid->sigpend);
  436.     if (status != OK && timerLibLog)
  437. {
  438. logMsg ("timerWdHandler: kill failed (timer=%#x, tid=%#x, errno=%#x)n",
  439. (int)timerid, timerid->taskId, errno, 0, 0, 0);
  440. }
  441.     if (TV_ISZERO(timerid->exp.it_interval))
  442. {
  443. timerid->active = FALSE;
  444. }
  445.     else
  446. {
  447. /* interval timer needs reloading */
  448. TV_CONVERT_TO_TICK (delayTicks, timerid->exp.it_interval);
  449. if (delayTicks < 1)
  450.     delayTicks = 1; /* delay of 0 will cause recursion! */
  451. /* time stamp when we arm interval timer */
  452. (void) clock_gettime (CLOCK_REALTIME, &(timerid->timeStamp));
  453. wdStart (timerid->wdog, (int)delayTicks, (FUNCPTR)timerWdHandler,
  454. (int)timerid);
  455. }
  456.     }
  457. /*******************************************************************************
  458. *
  459. * timer_settime - set the time until the next expiration and arm timer (POSIX)
  460. *
  461. * This routine sets the next expiration of the timer, using the `.it_value'
  462. * of <value>, thus arming the timer.  If the timer is already armed, this
  463. * call resets the time until the next expiration.  If `.it_value' is zero,
  464. * the timer is disarmed.
  465. *
  466. * If <flags> is not equal to TIMER_ABSTIME, the interval is relative to the
  467. * current time, the interval being the `.it_value' of the <value> parameter.
  468. * If <flags> is equal to TIMER_ABSTIME, the expiration is set to
  469. * the difference between the absolute time of `.it_value' and the current
  470. * value of the clock associated with <timerid>.  If the time has already
  471. * passed, then the timer expiration notification is made immediately.
  472. * The task that sets the timer receives the signal; in other words, the taskId
  473. * is noted.  If a timer is set by an ISR, the signal is delivered to the
  474. * task that created the timer.
  475. *
  476. * The reload value of the timer is set to the value specified by
  477. * the `.it_interval' field of <value>.  When a timer is
  478. * armed with a nonzero `.it_interval' a periodic timer is set up.
  479. *
  480. * Time values that are between two consecutive non-negative integer
  481. * multiples of the resolution of the specified timer are rounded up to
  482. * the larger multiple of the resolution.
  483. *
  484. * If <ovalue> is non-NULL, the routine stores a value representing the
  485. * previous amount of time before the timer would have expired.  Or if the
  486. * timer is disarmed, the routine stores zero, together with the previous
  487. * timer reload value.  The <ovalue> parameter is the same value as that 
  488. * returned by timer_gettime() and is subject to the timer resolution.
  489. *
  490. * WARNING
  491. * If clock_settime() is called to reset the absolute clock time after a timer
  492. * has been set with timer_settime(), and if <flags> is equal to TIMER_ABSTIME, 
  493. * then the timer will behave unpredictably.  If you must reset the absolute
  494. * clock time after setting a timer, do not use <flags> equal to TIMER_ABSTIME.
  495. *
  496. * RETURNS:
  497. * 0 (OK), or -1 (ERROR) if <timerid> is invalid, the number of nanoseconds 
  498. * specified by <value> is less than 0 or greater than or equal to 
  499. * 1,000,000,000, or the time specified by <value> exceeds the maximum 
  500. * allowed by the timer.
  501. *
  502. * ERRNO: EINVAL
  503. */
  504. int timer_settime
  505.     (
  506.     timer_t                 timerid, /* timer ID                           */
  507.     int                     flags, /* absolute or relative               */
  508.     const struct itimerspec *value, /* time to be set                     */
  509.     struct itimerspec       *ovalue /* previous time set (NULL=no result) */
  510.     )
  511.     {
  512.     struct timespec now;
  513.     struct timespec timerExpire; /* absolute time that timer will go off */
  514.     ULONG delayTicks;
  515.     if (timerid == NULL)
  516. {
  517. errno = EINVAL;
  518. return (ERROR);
  519. }
  520.     if (timerid->clock_id != CLOCK_REALTIME || !TV_VALID(value->it_value))
  521. {
  522. errno = EINVAL;
  523. return (ERROR);
  524. }
  525.     if (ovalue != NULL)
  526. {
  527.     /* if timer is disarmed, simply set value to 0 */
  528.         if (timerid->active == FALSE)
  529.         {
  530.             ovalue->it_value.tv_sec = 0;
  531.             ovalue->it_value.tv_nsec = 0;
  532.         }
  533.         else
  534.         {
  535.     /* get current time */
  536.             if (clock_gettime (CLOCK_REALTIME, &now) == ERROR)
  537.                 return (ERROR);;
  538.     /* use time stamp and get absolute time that timer will go off */
  539.             timerExpire.tv_sec = timerid->timeStamp.tv_sec + timerid->exp.it_value.tv_sec;
  540.             timerExpire.tv_nsec = timerid->timeStamp.tv_nsec + timerid->exp.it_value.tv_nsec;
  541.             TV_NORMALIZE (timerExpire);
  542.     /* compute difference using current time */
  543.             ovalue->it_value.tv_sec = timerExpire.tv_sec - now.tv_sec;
  544.             ovalue->it_value.tv_nsec = timerExpire.tv_nsec - now.tv_nsec;
  545.             TV_NORMALIZE (ovalue->it_value);
  546.         }
  547.     /* get reload value */
  548.         ovalue->it_interval.tv_sec = timerid->exp.it_interval.tv_sec;
  549.         ovalue->it_interval.tv_nsec = timerid->exp.it_interval.tv_nsec;
  550.         TV_NORMALIZE (ovalue->it_interval);
  551.     }
  552.     if (TV_ISZERO(value->it_value))
  553. {
  554. if (timerid->active)
  555.     {
  556.     timerid->active = FALSE;
  557.     wdCancel (timerid->wdog);
  558.     }
  559. return (OK);
  560. }
  561.     TV_SET(timerid->exp.it_interval, value->it_interval);
  562.     TV_SET(timerid->exp.it_value, value->it_value);
  563.     if (flags == TIMER_ABSTIME)
  564. {
  565. /* convert current to relative time */
  566. (void) clock_gettime (CLOCK_REALTIME, &now);
  567. /* could be in the past */
  568. if (TV_GT(now, timerid->exp.it_value))
  569.     {
  570.     TV_ZERO(timerid->exp.it_value);
  571.     }
  572. else
  573.     {
  574.          TV_SUB(timerid->exp.it_value, now);
  575.     }
  576. /* time stamp when timer is armed */
  577. TV_SET (timerid->timeStamp, now);
  578. }
  579.     else
  580. /* time stamp when timer is armed */
  581. (void) clock_gettime (CLOCK_REALTIME, &(timerid->timeStamp));
  582.     TV_CONVERT_TO_TICK (delayTicks, timerid->exp.it_value);
  583.     if (timerid->active)
  584. wdCancel (timerid->wdog);
  585.     else
  586. timerid->active = TRUE;
  587.     wdStart (timerid->wdog, delayTicks, (FUNCPTR)timerWdHandler, (int)timerid);
  588.     return (OK);
  589.     }
  590. /*******************************************************************************
  591. *
  592. * timer_show - show information on a specified timer
  593. *
  594. * WARNING
  595. * Non-POSIX.
  596. *
  597. * RETURNS: 0 (OK), or -1 (ERROR) if <timerid> is invalid, or the context is 
  598. * invalid.
  599. *
  600. * ERRNO: EINVAL
  601. *
  602. * NOMANUAL
  603. */
  604. int timer_show
  605.     (
  606.     timer_t timerid /* timer ID */
  607.     )
  608.     {
  609.     static char *title1 = "task       timerid    evp        routinen";
  610.     static char *title2 = "---------- ---------- ---------- ----------n";
  611.     if (intContext ())
  612. return (ERROR);
  613.     if (timerid == NULL)
  614. return (OK);
  615.     printf (title1);
  616.     printf (title2);
  617.     printf ("%#10x %#10x %#10x %#10xn", timerid->taskId, (unsigned int)timerid,
  618. (unsigned int)&timerid->sevent, (unsigned int)timerid->routine);
  619.     return (OK);
  620.     }
  621. /*******************************************************************************
  622. *
  623. * nanosleep - suspend the current task until the time interval elapses (POSIX)
  624. *
  625. * This routine suspends the current task for a specified time <rqtp>
  626. * or until a signal or event notification is made.
  627. *
  628. * The suspension may be longer than requested due to the rounding up of the
  629. * request to the timer's resolution or to other scheduling activities (e.g.,
  630. * a higher priority task intervenes).
  631. *
  632. * The `timespec' structure is defined as follows:
  633. *
  634. * cs
  635. * struct timespec
  636. *     {
  637. *                                /@ interval = tv_sec*10**9 + tv_nsec @/
  638. *      time_t tv_sec;            /@ seconds @/
  639. *      long tv_nsec;             /@ nanoseconds (0 - 1,000,000,000) @/
  640. *      };
  641. * ce
  642. *
  643. * If <rmtp> is non-NULL, the `timespec' structure is updated to contain the
  644. * amount of time remaining.  If <rmtp> is NULL, the remaining time is not
  645. * returned.  The <rqtp> parameter is greater than 0 or less than or equal to
  646. * 1,000,000,000.
  647. *
  648. * RETURNS:
  649. * 0 (OK), or -1 (ERROR) if the routine is interrupted by a signal or an 
  650. * asynchronous event notification, or <rqtp> is invalid.
  651. *
  652. * ERRNO: EINVAL, EINTR
  653. *
  654. * SEE ALSO: sleep(), taskDelay()
  655. */
  656. int nanosleep
  657.     (
  658.     const struct timespec *rqtp, /* time to delay                     */
  659.     struct timespec       *rmtp /* premature wakeup (NULL=no result) */
  660.     )
  661.     {
  662.     int status;
  663.     /* int oldErrno; */
  664.     ULONG delayTicks;
  665.     struct timespec then;
  666.     struct timespec now;
  667.     int returnStatus;
  668.     int savtype;
  669.     if (rqtp == NULL || !TV_VALID(*rqtp))
  670. {
  671. errno = EINVAL;
  672. return (ERROR);
  673. }
  674.     if (TV_ISZERO(*rqtp))
  675. return (OK);
  676.     if (_func_pthread_setcanceltype != NULL)
  677.         {
  678.         _func_pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &savtype);
  679.         }
  680.     (void)clockLibInit (); /* make sure clock "running" */
  681.     (void)clock_gettime (CLOCK_REALTIME, &then);
  682.     TV_CONVERT_TO_TICK (delayTicks, *rqtp);
  683.     /* return's 1 (RESTART) if interrupted sleep */
  684.     status = taskDelay (delayTicks);
  685.     if (status == 0)
  686. returnStatus = 0;
  687.     else
  688. returnStatus = -1;
  689.     if (rmtp != NULL)
  690. {
  691. (void)clock_gettime (CLOCK_REALTIME, &now);
  692. TV_SUB (now, then); /* make time relative to start */
  693. if (TV_LT(now, *rqtp))
  694.     {
  695.     TV_SET(*rmtp, *rqtp);
  696.     TV_SUB(*rmtp, now);
  697.     }
  698. else
  699.     TV_ZERO((*rmtp));
  700. }
  701.     if (_func_pthread_setcanceltype != NULL)
  702.         {
  703.         _func_pthread_setcanceltype(savtype, NULL);
  704.         }
  705.     return (returnStatus);
  706.     }
  707. /*******************************************************************************
  708. *
  709. * sleep - delay for a specified amount of time
  710. *
  711. * This routine causes the calling task to be blocked for <secs> seconds.
  712. *
  713. * The time the task is blocked for may be longer than requested due to the
  714. * rounding up of the request to the timer's resolution or to other scheduling
  715. * activities (e.g., a higher priority task intervenes).
  716. *
  717. * RETURNS: Zero if the requested time has elapsed, or the number of seconds
  718. * remaining if it was interrupted.
  719. *
  720. * ERRNO: EINVAL, EINTR
  721. *
  722. * SEE ALSO: nanosleep(), taskDelay()
  723. */
  724.  
  725. unsigned int sleep
  726.     (
  727.     unsigned int secs
  728.     )
  729.     {
  730.     struct timespec ntp, otp;
  731.  
  732.     ntp.tv_sec = secs;
  733.     ntp.tv_nsec = 0;
  734.  
  735.     nanosleep(&ntp, &otp);
  736.  
  737.     return(otp.tv_sec);
  738.     }
  739. /*******************************************************************************
  740. *
  741. * alarm - set an alarm clock for delivery of a signal
  742. *
  743. * This routine arranges for a 'SIGALRM' signal to be delivered to the
  744. * calling task after <secs> seconds.
  745. *
  746. * If <secs> is zero, no new alarm is scheduled. In all cases, any previously
  747. * set alarm is cancelled.
  748. *
  749. * RETURNS: Time remaining until a previously scheduled alarm was due to be
  750. * delivered, zero if there was no previous alarm, or ERROR in case of an
  751. * error.
  752. */
  753.  
  754. unsigned int alarm
  755.     (
  756.     unsigned int secs
  757.     )
  758.     {
  759.     static timer_t timer_id = NULL;
  760.     struct itimerspec tspec, tremain;
  761.  
  762.     /* if first time, create a timer */
  763.  
  764.     if (!timer_id)
  765.         {
  766.         if (timer_create(CLOCK_REALTIME, NULL, &timer_id) == ERROR)
  767.             return(ERROR);
  768.         }
  769.  
  770.     /* set new time*/
  771.  
  772.     tspec.it_interval.tv_sec = 0;
  773.     tspec.it_interval.tv_nsec = 0;
  774.     tspec.it_value.tv_sec = secs;
  775.     tspec.it_value.tv_nsec = 0;
  776.  
  777.     /* save off timer remaining from previous for return */
  778.  
  779.     timer_gettime(timer_id, &tremain);
  780.     timer_settime(timer_id, CLOCK_REALTIME, &tspec, NULL);
  781.  
  782.     return((unsigned int)tremain.it_value.tv_sec);
  783.     }