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

VxWorks

开发平台:

C/C++

  1. /* wdLib.c - watchdog timer library */
  2. /* Copyright 1984-1995 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01t,24jun96,sbs  made windview instrumentation conditionally compiled
  8. 02s,13oct95,jdi  doc: removed SEE ALSO to .pG Cross-Dev.
  9. 02r,18jan95,rhp  doc: say explicitly no need to cancel expired timers,
  10.                  and improve wdLib and wdSTart() man pages from bss comments.
  11. 02u,14apr94,smb  fixed class dereferencing for instrumentation macros
  12. 02t,15mar94,smb  modified instrumentation macros
  13. 02s,24jan94,smb  added instrumentation macros
  14. 02r,10dec93,smb  added instrumentation
  15. 02q,24feb93,jdi  doc tweaks from review by kdl.
  16. 02p,20jan93,jdi  documentation cleanup for 5.1.
  17. 02o,13nov92,jcf  package init called with with watchdog creation.
  18. 02n,29jul92,jcf  package init called with with object initialization.
  19. 02m,04jul92,jcf  private headers.
  20. 02l,26may92,rrr  the tree shuffle
  21. 02k,04oct91,rrr  passed through the ansification filter
  22.                   -changed functions to ansi style
  23.   -changed includes to have absolute path from h/
  24.   -changed VOID to void
  25.   -changed copyright notice
  26. 02j,30mar91,jdi  documentation cleanup; doc review by jcf.
  27. 02i,05oct90,dnw  made wdInit() and wdTerminate() be NOMANUAL.
  28. 02h,01oct90,jcf  fixed wdDestroy() to invalidate with ISR mutual exclusion.
  29. 02g,29aug90,jcf  documentation.
  30. 02f,10aug90,dnw  changed wdCancel() from void to STATUS.
  31. 02e,02aug90,jcf  documentation.
  32. 02d,17jul90,dnw  changed to new objAlloc() call.
  33. 02c,03jul90,jcf  documentation.
  34.  removed erroneous log message.
  35. 02b,26jun90,jcf  updated class structure, change over to objAlloc ()
  36. 02a,17apr90,jcf  integrated into wind 2.0.
  37. 01j,01sep88,gae  documentation.
  38. 01i,04nov87,ecs  documentation.
  39. 01h,25mar87,jlf  documentation
  40. 01g,21dec86,dnw  changed to not get include files from default directories.
  41. 01f,05sep86,jlf  minor documentation.
  42. 01e,14apr86,rdc  changed memAllocates to mallocs.
  43. 01d,07sep84,jlf  added copyright notice and comments.
  44. 01c,02aug84,dnw  changed calls to vxInt... to int...
  45. 01b,11jul84,ecs  changed calls to vxIntLock/vxIntUnlock to restore old level.
  46. 01a,22may84,dnw  written
  47. */
  48. /*
  49. DESCRIPTION
  50. This library provides a general watchdog timer facility.  Any task may
  51. create a watchdog timer and use it to run a specified routine in
  52. the context of the system-clock ISR, after a specified delay.
  53. Once a timer has been created with wdCreate(), it can be started with
  54. wdStart().  The wdStart() routine specifies what routine to run, a
  55. parameter for that routine, and the amount of time (in ticks) before
  56. the routine is to be called.  (The timeout value is in ticks as
  57. determined by the system clock; see sysClkRateSet() for more
  58. information.)  After the specified delay ticks have elapsed (unless
  59. wdCancel() is called first to cancel the timer) the timeout routine is
  60. invoked with the parameter specified in the wdStart() call.  The
  61. timeout routine is invoked whether the task which started the watchdog
  62. is running, suspended, or deleted.
  63. The timeout routine executes only once per wdStart() invocation; there
  64. is no need to cancel a timer with wdCancel() after it has expired, or
  65. in the expiration callback itself.
  66. Note that the timeout routine is invoked at interrupt level, rather than
  67. in the context of the task.  Thus, there are restrictions on what the
  68. routine may do.  Watchdog routines are constrained to the same rules
  69. as interrupt service routines.  For example, they may not take semaphores,
  70. issue other calls that may block, or use I/O system routines like printf().
  71. EXAMPLE
  72. In the fragment below, if maybeSlowRoutine() takes more than 60 ticks,
  73. logMsg() will be called with the string as a parameter, causing the message to
  74. be printed on the console.  Normally, of course, more significant corrective
  75. action would be taken.
  76. .CS
  77.     WDOG_ID wid = wdCreate ();
  78.     wdStart (wid, 60, logMsg, "Help, I've timed out!");
  79.     maybeSlowRoutine (); /@ user-supplied routine @/
  80.     wdCancel (wid);
  81. .CE
  82. INTERNAL:
  83. WINDVIEW INSTRUMENTATION
  84. Level 1:
  85. wdCreate() causes EVENT_WDCREATE
  86. wdDestroy() causes EVENT_WDDELETE
  87. wdStart() causes EVENT_WDSTART
  88. wdCancel() causes EVENT_WDCANCEL
  89. Level 2:
  90. N/A
  91. Level 3: N/A
  92. INCLUDE FILES: wdLib.h
  93. SEE ALSO: logLib,
  94. .pG "Basic OS"
  95. */
  96. #include "vxWorks.h"
  97. #include "taskLib.h"
  98. #include "errno.h"
  99. #include "intLib.h"
  100. #include "private/classLibP.h"
  101. #include "private/objLibP.h"
  102. #include "private/wdLibP.h"
  103. #include "private/windLibP.h"
  104. #include "private/workQLibP.h"
  105. #include "private/eventP.h"
  106. /* locals */
  107. LOCAL BOOL wdLibInstalled;
  108. LOCAL OBJ_CLASS wdClass; /* non-instrumented class */
  109. /* globals */
  110. CLASS_ID wdClassId = &wdClass;
  111. /* windview definitions */
  112. #ifdef WV_INSTRUMENTATION
  113. LOCAL OBJ_CLASS wdInstClass;
  114. CLASS_ID wdInstClassId = &wdInstClass;
  115. #endif
  116. /*******************************************************************************
  117. *
  118. * wdLibInit - initialize watchdog library
  119. *
  120. * This routine initializes the watchdog object class.  No watchdog operation
  121. * will work until this is called.  This routine is called during system
  122. * configuration within kernelInit().  This routine should only be called once.
  123. *
  124. * NOMANUAL
  125. */
  126. STATUS wdLibInit (void)
  127.     {
  128.     if ((!wdLibInstalled) &&
  129. (classInit (wdClassId, sizeof (WDOG), OFFSET (WDOG, objCore),
  130.  (FUNCPTR) wdCreate, (FUNCPTR) wdInit, (FUNCPTR) wdDestroy) == OK))
  131. {
  132. #ifdef WV_INSTRUMENTATION
  133. /* initialise the instrumented class for level 1 event logging */
  134. wdClassId -> initRtn = wdInstClassId;
  135.         classInstrument (wdClassId, wdInstClassId);
  136.         wdInstClassId->instRtn = (FUNCPTR) _func_evtLogO;
  137. #endif
  138. wdLibInstalled = TRUE;
  139. }
  140.     return ((wdLibInstalled) ? OK : ERROR);
  141.     }
  142. /*******************************************************************************
  143. *
  144. * wdCreate - create a watchdog timer
  145. *
  146. * This routine creates a watchdog timer by allocating a WDOG structure in
  147. * memory.
  148. *
  149. * RETURNS: The ID for the watchdog created, or NULL if memory is insufficient.
  150. *
  151. * SEE ALSO: wdDelete()
  152. */
  153. WDOG_ID wdCreate (void)
  154.     {
  155.     WDOG_ID wdId;
  156. #ifdef WV_INSTRUMENTATION
  157.     int level;
  158. #endif
  159.     if ((!wdLibInstalled) && (wdLibInit () != OK))
  160. return (NULL); /* package init problem */
  161.     wdId = (WDOG_ID) objAlloc (wdClassId);
  162.     /* initialize allocated watchdog */
  163.     if ((wdId != NULL) && (wdInit (wdId) != OK))
  164. {
  165. objFree (wdClassId, (char *) wdId);
  166. return (NULL);
  167. }
  168. #ifdef WV_INSTRUMENTATION
  169.     /* windview - level 1 event logging */
  170.     level = intLock ();
  171.     EVT_OBJ_1 (OBJ, wdId, wdClassId, EVENT_WDCREATE, wdId);
  172.     intUnlock (level);
  173. #endif
  174.     return (wdId);
  175.     }
  176. /*******************************************************************************
  177. *
  178. * wdInit - initialize a watchdog timer
  179. *
  180. * This routine initializes a static watchdog or a watchdog embedded in a
  181. * larger object.
  182. *
  183. * RETURNS: OK, or ERROR if the watchdog could not be initialized.
  184. *
  185. * NOMANUAL
  186. */
  187. STATUS wdInit
  188.     (
  189.     WDOG *pWdog         /* pointer to watchdog to initialize */
  190.     )
  191.     {
  192.     if ((!wdLibInstalled) && (wdLibInit () != OK))
  193. return (ERROR); /* package init problem */
  194.     pWdog->status        = WDOG_OUT_OF_Q; /* initially out of q */
  195.     pWdog->deferStartCnt = 0; /* no pending starts */
  196. #ifdef WV_INSTRUMENTATION
  197.     /* windview - connect instrumented class for level 1 event logging */
  198.     if (wvObjIsEnabled)
  199. objCoreInit (&pWdog->objCore, wdInstClassId); 
  200.     else
  201. #endif
  202.         objCoreInit (&pWdog->objCore, wdClassId); /* initialize core */
  203.     return (OK);
  204.     }
  205. /*******************************************************************************
  206. *
  207. * wdDelete - delete a watchdog timer
  208. *
  209. * This routine de-allocates a watchdog timer.  The watchdog will be removed
  210. * from the timer queue if it has been started.  This routine complements
  211. * wdCreate().
  212. *
  213. * RETURNS: OK, or ERROR if the watchdog timer cannot be de-allocated.
  214. *
  215. * SEE ALSO: wdCreate()
  216. */
  217. STATUS wdDelete
  218.     (
  219.     WDOG_ID wdId                /* ID of watchdog to delete */
  220.     )
  221.     {
  222.     return (wdDestroy (wdId, TRUE)); /* delete watchdog */
  223.     }
  224. /*******************************************************************************
  225. *
  226. * wdTerminate - terminate a watchdog timer
  227. *
  228. * This routine terminates a watchdog timer.  The watchdog will be removed
  229. * from the timer queue if it has been started.  This routine differs from
  230. * wdDelete() in that associated memory is not de-allocated.  This routine
  231. * complements wdInit().
  232. *
  233. * RETURNS: OK, or ERROR if the watchdog cannot be terminated.
  234. *
  235. * NOMANUAL
  236. */
  237. STATUS wdTerminate
  238.     (
  239.     WDOG_ID wdId                /* ID of watchdog to terminate */
  240.     )
  241.     {
  242.     return (wdDestroy (wdId, FALSE)); /* terminate watchdog */
  243.     }
  244. /*******************************************************************************
  245. *
  246. * wdDestroy - terminate a watchdog timer
  247. *
  248. * This routine terminates a watchdog timer and optionally de-allocates
  249. * associated memory.  If the watchdog has been started, it will be removed
  250. * from the timer queue.  This routine underlies wdDelete(), and
  251. * wdTerminate().
  252. *
  253. * RETURNS: OK, or ERROR if the watchdog cannot be destroyed.
  254. *
  255. * NOMANUAL
  256. */
  257. STATUS wdDestroy
  258.     (
  259.     WDOG_ID wdId,               /* ID of watchdog to terminate */
  260.     BOOL    dealloc             /* dealloc associated memory */
  261.     )
  262.     {
  263.     int level;
  264.     if (INT_RESTRICT () != OK) /* restrict isr use */
  265. return (ERROR);
  266.     level = intLock (); /* LOCK INTERRUPTS */
  267.     if (OBJ_VERIFY (wdId, wdClassId) != OK) /* validate watchdog ID */
  268. {
  269. intUnlock (level); /* UNLOCK INTERRUPTS */
  270. return (ERROR);
  271. }
  272. #ifdef WV_INSTRUMENTATION
  273.     /* windview - level 1 event logging */
  274.     EVT_OBJ_1 (OBJ, wdId, wdClassId, EVENT_WDDELETE, wdId);
  275. #endif
  276.     objCoreTerminate (&wdId->objCore); /* invalidate watchdog */
  277.     kernelState = TRUE; /* KERNEL ENTER */
  278.     intUnlock (level); /* UNLOCK INTERRUPTS */
  279.     windWdCancel (wdId); /* cancel watchdog */
  280.     wdId->status = WDOG_DEAD; /* dead dog */
  281.     TASK_SAFE (); /* TASK SAFE */
  282.     windExit (); /* EXIT KERNEL */
  283.     if (dealloc)
  284. objFree (wdClassId, (char *) wdId); /* deallocate watchdog */
  285.     TASK_UNSAFE (); /* TASK UNSAFE */
  286.     return (OK);
  287.     }
  288. /*******************************************************************************
  289. *
  290. * wdStart - start a watchdog timer
  291. * This routine adds a watchdog timer to the system tick queue.  The
  292. * specified watchdog routine will be called from interrupt level after
  293. * the specified number of ticks has elapsed.  Watchdog timers may be
  294. * started from interrupt level.  
  295. * To replace either the timeout <delay> or the routine to be executed,
  296. * call wdStart() again with the same <wdId>; only the most recent
  297. * wdStart() on a given watchdog ID has any effect.  (If your
  298. * application requires multiple watchdog routines, use wdCreate() to
  299. * generate separate a watchdog ID for each.)  To cancel a watchdog
  300. * timer before the specified tick count is reached, call wdCancel().
  301. * Watchdog timers execute only once, but some applications require
  302. * periodically executing timers.  To achieve this effect, the timer
  303. * routine itself must call wdStart() to restart the timer on each
  304. * invocation.
  305. * WARNING: The watchdog routine runs in the context of the
  306. * system-clock ISR; thus, it is subject to all ISR restrictions.
  307. * RETURNS: OK, or ERROR if the watchdog timer cannot be started.
  308. *
  309. * SEE ALSO: wdCancel()
  310. */
  311. STATUS wdStart
  312.     (
  313.     WDOG_ID wdId,               /* watchdog ID */
  314.     int delay,                  /* delay count, in ticks */
  315.     FUNCPTR pRoutine,           /* routine to call on time-out */
  316.     int parameter               /* parameter with which to call routine */
  317.     )
  318.     {
  319.     int level = intLock (); /* LOCK INTERRUPTS */
  320.     if (OBJ_VERIFY (wdId, wdClassId) != OK)
  321. {
  322. intUnlock (level); /* UNLOCK INTERRUPTS */
  323. return (ERROR);
  324. }
  325. #ifdef WV_INSTRUMENTATION
  326.     /* windview - level 1 event logging */
  327.     EVT_OBJ_2 (OBJ, wdId, wdClassId, EVENT_WDSTART, wdId, delay);
  328. #endif
  329.     if (kernelState) /* already in kernel? */
  330. {
  331. wdId->deferStartCnt ++; /* bump the start count */
  332. wdId->wdParameter = parameter; /* update w/ new parameter */
  333. wdId->wdRoutine   = pRoutine; /* update w/ new routine */
  334. intUnlock (level); /* UNLOCK INTERRUPTS */
  335. workQAdd2 (windWdStart, (int)wdId, delay); /* defer the wdStart */
  336. }
  337.     else
  338. {
  339. wdId->deferStartCnt  = 1; /* initialize start count */
  340. wdId->wdParameter    = parameter; /* update w/ new parameter */
  341. wdId->wdRoutine      = pRoutine; /* update w/ new routine */
  342. kernelState      = TRUE; /* KERNEL ENTER */
  343. intUnlock (level); /* UNLOCK INTERRUPTS */
  344. if (windWdStart (wdId, delay) != OK) /* start the watchdog */
  345.     {
  346.     windExit (); /* KERNEL EXIT */
  347.     return (ERROR);
  348.     }
  349. windExit (); /* KERNEL EXIT */
  350. }
  351.     return (OK);
  352.     }
  353. /*******************************************************************************
  354. *
  355. * wdCancel - cancel a currently counting watchdog
  356. *
  357. * This routine cancels a currently running watchdog timer by
  358. * zeroing its delay count.  Watchdog timers may be canceled from interrupt
  359. * level.
  360. *
  361. * RETURNS: OK, or ERROR if the watchdog timer cannot be canceled.
  362. *
  363. * SEE ALSO: wdStart()
  364. */
  365. STATUS wdCancel
  366.     (
  367.     WDOG_ID wdId        /* ID of watchdog to cancel */
  368.     )
  369.     {
  370.     int level = intLock (); /* LOCK INTERRUPTS */
  371.     if (OBJ_VERIFY (wdId, wdClassId) != OK)
  372. {
  373. intUnlock (level); /* UNLOCK INTERRUPTS */
  374. return (ERROR);
  375. }
  376. #ifdef WV_INSTRUMENTATION
  377.     /* windview - level 1 event logging */
  378.     EVT_OBJ_1 (OBJ, wdId, wdClassId, EVENT_WDCANCEL, wdId);
  379. #endif
  380.     if (kernelState)
  381. {
  382. intUnlock (level); /* UNLOCK INTERRUPTS */
  383. workQAdd1 ((FUNCPTR)windWdCancel, (int)wdId);
  384. }
  385.     else
  386. {
  387. kernelState = TRUE; /* KERNEL_ENT */
  388. intUnlock (level); /* UNLOCK INTERRUPTS */
  389. windWdCancel (wdId); /* cancel watchdog */
  390. windExit (); /* KERNEL EXIT */
  391. }
  392.     return (OK);
  393.     }
  394. /*******************************************************************************
  395. *
  396. * wdTick - obsolete routine
  397. *
  398. * This routine is provided for backward compatibility and is simply a NOP
  399. * if called.
  400. *
  401. * NOMANUAL
  402. */
  403. void wdTick (void)
  404.     {
  405.     /* obsolete */
  406.     }