taskVarLib.c
上传用户:baixin
上传日期:2008-03-13
资源大小:4795k
文件大小:15k
开发平台:

MultiPlatform

  1. /* taskVarLib.c - task variables support library */
  2. /* Copyright 1984-1993 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01z,21jan93,jdi  documentation cleanup for 5.1.
  8. 01y,02oct92,jcf  added task validity check to switch hook.
  9. 01x,18jul92,smb  changed errno.h to errnoLib.h.
  10. 01w,07jul92,ajm  removed unnecesary cacheClear calls for 040
  11. 01v,04jul92,jcf  scalable/ANSI/cleanup effort.
  12. 01u,03jul92,jwt  converted cacheClearEntry() calls to cacheClear() for 5.1.
  13. 01t,26may92,rrr  the tree shuffle
  14. 01s,21dec91,gae  added includes for ANSI.
  15. 01r,19nov91,rrr  shut up some ansi warnings.
  16. 01q,04oct91,rrr  passed through the ansification filter
  17.                   -changed functions to ansi style
  18.   -fixed #else and #endif
  19.   -changed VOID to void
  20.   -changed copyright notice
  21. 01p,27aug91,shl  added cache coherency calls for MC68040 support.
  22. 01o,220may1,jdi  documentation tweak.
  23. 01n,05apr91,jdi  documentation -- removed header parens and x-ref numbers;
  24.  doc review by dnw.
  25. 01m,24mar91,jdi  documentation cleanup.
  26. 01l,01oct90,jcf  added taskVarInfo().
  27. 01k,01aug90,jcf  changed tcb taskVar to pTaskVar.
  28.  added include of taskVarLib.h.
  29. 01j,19jul90,dnw  mangen fix
  30. 01i,14apr90,jcf  removed tcb extension dependencies.
  31. 01h,14mar90,jdi  documentation cleanup.
  32. 01g,08apr89,dnw  added taskVarInit().
  33. 01f,17aug88,gae  documentation.
  34. 01d,22jun88,dnw  name tweaks.
  35. 01c,30may88,dnw  changed to v4 names.
  36. 01b,08apr88,gae  added taskId parm. to taskVar{Add,Del}();
  37.  made taskVar{Get,Set}() work with active task.
  38.  Fixed fatal bug in taskVarDel() of not replacing bg value.
  39.  Added taskVarDeleteHook() to cleanup after tasks.
  40.  Lint. Documentation.
  41. 01a,25jan88,jcf  written by extracting from vxLib.c.
  42. */
  43. /*
  44. DESCRIPTION
  45. VxWorks provides a facility called "task variables," which allows
  46. 4-byte variables to be added to a task's context, and the
  47. variables' values to be switched each time a task switch occurs to or
  48. from the calling task.  Typically, several tasks declare the same
  49. variable (4-byte memory location) as a task variable and treat that
  50. memory location as their own private variable.  For example, this
  51. facility can be used when a routine must be spawned more than once as
  52. several simultaneous tasks.
  53. The routines taskVarAdd() and taskVarDelete() are used to add or delete
  54. a task variable.  The routines taskVarGet() and taskVarSet() are used to get
  55. or set the value of a task variable.
  56. NOTE
  57. If you are using task variables in a task delete hook
  58. (see taskHookLib), refer to the manual entry for taskVarInit()
  59. for warnings on proper usage.
  60. INCLUDE FILES: taskVarLib.h
  61. SEE ALSO: taskHookLib,
  62. .pG "Basic OS"
  63. */
  64. /* LINTLIBRARY */
  65. #include "vxWorks.h"
  66. #include "stdlib.h"
  67. #include "taskHookLib.h"
  68. #include "taskVarLib.h"
  69. #include "taskLib.h"
  70. #include "errnoLib.h"
  71. /* forward static functions */
  72. static void taskVarDeleteHook (WIND_TCB *pTcb);
  73. static void taskVarSwitchHook (WIND_TCB *pOldTcb, WIND_TCB *pNewTcb);
  74. /*******************************************************************************
  75. *
  76. * taskVarInit - initialize the task variables facility
  77. *
  78. * This routine initializes the task variables facility.  It installs task
  79. * switch and delete hooks used for implementing task variables.
  80. * If taskVarInit() is not called explicitly, taskVarAdd() will call it
  81. * automatically when the first task variable is added.
  82. *
  83. * After the first invocation of this routine, subsequent invocations
  84. * have no effect.
  85. *
  86. * WARNING
  87. * Order dependencies in task delete hooks often involve
  88. * task variables.  If a facility uses task variables and has a
  89. * task delete hook that expects to use those task variables,
  90. * the facility's delete hook must run before the task
  91. * variables' delete hook.  Otherwise, the task variables
  92. * will be deleted by the time the facility's delete hook runs.
  93. *
  94. * VxWorks is careful to run the delete hooks in reverse of the order in
  95. * which they were installed.  Any facility that has a delete hook that will
  96. * use task variables can guarantee proper ordering by calling taskVarInit()
  97. * before adding its own delete hook.
  98. *
  99. * Note that this is not an issue in normal use of task variables.  The issue
  100. * only arises when adding another task delete hook that uses task variables.
  101. *
  102. * Caution should also be taken when adding task variables from within
  103. * create hooks.  If the task variable package has not been installed via
  104. * taskVarInit(), the create hook attempts to create a create hook, and that
  105. * may cause system failure.  To avoid this situation, taskVarInit() should
  106. * be called during system initialization from the root task, usrRoot(), in
  107. * usrConfig.c.
  108. *
  109. * RETURNS: OK, or ERROR if the task switch/delete hooks could not be installed.
  110. */
  111. STATUS taskVarInit (void)
  112.     {
  113.     static BOOL taskVarInstalled = FALSE; /* TRUE = facility installed */
  114.     /* if task variables facility is not already installed, then install it
  115.      * by adding the switch and delete hooks
  116.      */
  117.     if (!taskVarInstalled)
  118. {
  119. if ((taskSwitchHookAdd ((FUNCPTR)taskVarSwitchHook) != OK) ||
  120.     (taskDeleteHookAdd ((FUNCPTR)taskVarDeleteHook) != OK))
  121.     {
  122.     return (ERROR);
  123.     }
  124. taskVarInstalled = TRUE;
  125. }
  126.     return (OK);
  127.     }
  128. /*******************************************************************************
  129. *
  130. * taskVarDeleteHook - delete task variables of exiting tasks
  131. *
  132. * This routine is the task delete routine that deletes all task
  133. * variables of an exiting task.
  134. */
  135. LOCAL void taskVarDeleteHook
  136.     (
  137.     WIND_TCB *pTcb
  138.     )
  139.     {
  140.     FAST TASK_VAR *pTaskVar;
  141.     FAST TASK_VAR *pTaskVarNext;
  142.     for (pTaskVar = pTcb->pTaskVar;
  143.  pTaskVar != NULL;
  144.  pTaskVar = pTaskVarNext)
  145. {
  146. pTaskVarNext = pTaskVar->next;
  147. free ((char *)pTaskVar); /* free storage of deleted cell */
  148. }
  149.     }
  150. /*******************************************************************************
  151. *
  152. * taskVarSwitchHook - switch task variables of switching tasks
  153. *
  154. * This routine is the task switch routine that implements the task variable
  155. * facility.  It swaps the current and saved values of all the task variables
  156. * of the out-going and in-coming tasks.
  157. */
  158. LOCAL void taskVarSwitchHook
  159.     (
  160.     WIND_TCB *pOldTcb,
  161.     WIND_TCB *pNewTcb
  162.     )
  163.     {
  164.     FAST TASK_VAR *pTaskVar;
  165.     FAST int temp;
  166.     /* swap task variables of old task */
  167.     if (TASK_ID_VERIFY(pOldTcb) == OK) /* suicide runs delete hook 1st */
  168. {
  169. for (pTaskVar = pOldTcb->pTaskVar;
  170.      pTaskVar != NULL;
  171.      pTaskVar = pTaskVar->next)
  172.     {
  173.     /* swap current and save value of task variable */
  174.     temp = pTaskVar->value;
  175.     pTaskVar->value = *(pTaskVar->address);
  176.     *(pTaskVar->address) = temp;
  177.     }
  178. }
  179.     /* swap task variables of new task */
  180.     for (pTaskVar = pNewTcb->pTaskVar;
  181.  pTaskVar != NULL;
  182.  pTaskVar = pTaskVar->next)
  183. {
  184. /* swap current and save value of task variable */
  185. temp = pTaskVar->value;
  186. pTaskVar->value = *(pTaskVar->address);
  187. *(pTaskVar->address) = temp;
  188. }
  189.     }
  190. /*******************************************************************************
  191. *
  192. * taskVarAdd - add a task variable to a task
  193. *
  194. * This routine adds a specified variable <pVar> (4-byte memory location) to a
  195. * specified task's context.  After calling this routine, the variable will
  196. * be private to the task.  The task can access and modify the variable, but
  197. * the modifications will not appear to other tasks, and other tasks'
  198. * modifications to that variable will not affect the value seen by the
  199. * task.  This is accomplished by saving and restoring the variable's initial
  200. * value each time a task switch occurs to or from the calling task.
  201. *
  202. * This facility can be used when a routine is to be spawned repeatedly as
  203. * several independent tasks.  Although each task will have its own stack,
  204. * and thus separate stack variables, they will all share the same static and
  205. * global variables.  To make a variable f2notfP shareable, the routine can
  206. * call taskVarAdd() to make a separate copy of the variable for each task, but
  207. * all at the same physical address.
  208. *
  209. * Note that task variables increase the task switch time to and from the
  210. * tasks that own them.  Therefore, it is desirable to limit the number of
  211. * task variables that a task uses.  One efficient way to use task variables 
  212. * is to have a single task variable that is a pointer to a dynamically 
  213. * allocated structure containing the task's private data.
  214. *
  215. * EXAMPLE:
  216. * Assume that three identical tasks were spawned with a routine called
  217. * f2operator()f1.  All three use the structure OP_GLOBAL for all variables
  218. * that are specific to a particular incarnation of the task.  The following
  219. * code fragment shows how this is set up:
  220. *
  221. * .CS
  222. * OP_GLOBAL *opGlobal;  /@ ptr to operator task's global variables @/
  223. *
  224. * void operator
  225. *     (
  226. *     int opNum         /@ number of this operator task @/
  227. *     )
  228. *     {
  229. *     if (taskVarAdd (0, (int *)&opGlobal) != OK)
  230. *         {
  231. *         printErr ("operator%d: can't taskVarAdd opGlobalen", opNum);
  232. *         taskSuspend (0);
  233. *         }
  234. *
  235. *     if ((opGlobal = (OP_GLOBAL *) malloc (sizeof (OP_GLOBAL))) == NULL)
  236. *         {
  237. *         printErr ("operator%d: can't malloc opGlobalen", opNum);
  238. *         taskSuspend (0);
  239. *         }
  240. *     ...
  241. *     }
  242. * .CE
  243. *
  244. * RETURNS:
  245. * OK, or ERROR if memory is insufficient for the task variable descriptor.
  246. *
  247. * INTERNAL
  248. * The first time this routine is called the task switch and delete
  249. * routines, taskVarSwitchHook() and taskVarDeleteHook(), are installed.
  250. *
  251. * SEE ALSO: taskVarDelete(), taskVarGet(), taskVarSet()
  252. */
  253. STATUS taskVarAdd
  254.     (
  255.     int tid,    /* ID of task to have new variable */
  256.     int *pVar   /* pointer to variable to be switched for task */
  257.     )
  258.     {
  259.     FAST WIND_TCB *pTcb = taskTcb (tid);
  260.     FAST TASK_VAR *pTaskVar;
  261.     /* make sure task variable facility is installed */
  262.     if (taskVarInit () != OK)
  263. return (ERROR);
  264.     /* allocate descriptor for new task variable */
  265.     pTaskVar = (TASK_VAR *) malloc (sizeof (TASK_VAR));
  266.     if (pTaskVar == NULL)
  267. return (ERROR);
  268.     pTaskVar->address = pVar;
  269.     pTaskVar->value   = *pVar;
  270.     /* link new task variable into list in stack header */
  271.     pTaskVar->next = pTcb->pTaskVar;
  272.     pTcb->pTaskVar = pTaskVar;
  273.     return (OK);
  274.     }
  275. /*******************************************************************************
  276. *
  277. * taskVarDelete - remove a task variable from a task
  278. *
  279. * This routine removes a specified task variable, <pVar>, from the specified
  280. * task's context.  The private value of that variable is lost.
  281. *
  282. * RETURNS
  283. * OK, or
  284. * ERROR if the task variable does not exist for the specified task.
  285. *
  286. * SEE ALSO: taskVarAdd(), taskVarGet(), taskVarSet()
  287. */
  288. STATUS taskVarDelete
  289.     (
  290.     int tid,    /* ID of task whose variable is to be removed */
  291.     int *pVar   /* pointer to task variable to be removed */
  292.     )
  293.     {
  294.     FAST TASK_VAR **ppTaskVar; /* ptr to ptr to next node */
  295.     FAST TASK_VAR *pTaskVar;
  296.     WIND_TCB *pTcb = taskTcb (tid);
  297.     if (pTcb == NULL) /* check that task is valid */
  298. return (ERROR);
  299.     /* find descriptor for specified task variable */
  300.     for (ppTaskVar = &pTcb->pTaskVar;
  301.  *ppTaskVar != NULL;
  302.  ppTaskVar = &((*ppTaskVar)->next))
  303. {
  304. pTaskVar = *ppTaskVar;
  305. if (pTaskVar->address == pVar)
  306.     {
  307.     /* if active task, replace background value */
  308.     if (taskIdCurrent == pTcb)
  309. *pVar = pTaskVar->value;
  310.     *ppTaskVar = pTaskVar->next;/* delete variable from list */
  311.     free ((char *)pTaskVar); /* free storage of deleted cell */
  312.     return (OK);
  313.     }
  314. }
  315.     /* specified address is not a task variable for specified task */
  316.     errnoSet (S_taskLib_TASK_VAR_NOT_FOUND);
  317.     return (ERROR);
  318.     }
  319. /*******************************************************************************
  320. *
  321. * taskVarGet - get the value of a task variable
  322. *
  323. * This routine returns the private value of a task variable for a
  324. * specified task.  The specified task is usually not the calling task,
  325. * which can get its private value by directly accessing the variable.
  326. * This routine is provided primarily for debugging purposes.
  327. *
  328. * RETURNS:
  329. * The private value of the task variable, or
  330. * ERROR if the task is not found or it
  331. * does not own the task variable.
  332. *
  333. * SEE ALSO: taskVarAdd(), taskVarDelete(), taskVarSet()
  334. */
  335. int taskVarGet
  336.     (
  337.     int tid,            /* ID of task whose task variable is to be retrieved */
  338.     int *pVar           /* pointer to task variable */
  339.     )
  340.     {
  341.     FAST TASK_VAR *pTaskVar; /* ptr to next node */
  342.     WIND_TCB *pTcb = taskTcb (tid);
  343.     if (pTcb == NULL)
  344. return (ERROR);
  345.     /* find descriptor for specified task variable */
  346.     for (pTaskVar = pTcb->pTaskVar;
  347.  pTaskVar != NULL;
  348.  pTaskVar = pTaskVar->next)
  349. {
  350. if (pTaskVar->address == pVar)
  351.     return (taskIdCurrent == pTcb ? *pVar : pTaskVar->value);
  352. }
  353.     /* specified address is not a task variable for specified task */
  354.     errnoSet (S_taskLib_TASK_VAR_NOT_FOUND);
  355.     return (ERROR);
  356.     }
  357. /*******************************************************************************
  358. *
  359. * taskVarSet - set the value of a task variable
  360. *
  361. * This routine sets the private value of the task variable for a specified
  362. * task.  The specified task is usually not the calling task, which can set
  363. * its private value by directly modifying the variable.  This routine is
  364. * provided primarily for debugging purposes.
  365. *
  366. * RETURNS:
  367. * OK, or
  368. * ERROR if the task is not found or it
  369. * does not own the task variable.
  370. *
  371. * SEE ALSO: taskVarAdd(), taskVarDelete(), taskVarGet()
  372. */
  373. STATUS taskVarSet
  374.     (
  375.     int tid,    /* ID of task whose task variable is to be set */
  376.     int *pVar,  /* pointer to task variable to be set for this task */
  377.     int value   /* new value of task variable */
  378.     )
  379.     {
  380.     FAST TASK_VAR *pTaskVar; /* ptr to next node */
  381.     WIND_TCB *pTcb = taskTcb (tid);
  382.     if (pTcb == NULL)
  383. return (ERROR);
  384.     /* find descriptor for specified task variable */
  385.     for (pTaskVar = pTcb->pTaskVar;
  386.  pTaskVar != NULL;
  387.  pTaskVar = pTaskVar->next)
  388. {
  389. if (pTaskVar->address == pVar)
  390.     {
  391.     if (taskIdCurrent == pTcb)
  392. {
  393. *pVar = value;
  394. }
  395.     else
  396. pTaskVar->value = value;
  397.     return (OK);
  398.     }
  399. }
  400.     /* specified address is not a task variable for specified task */
  401.     errnoSet (S_taskLib_TASK_VAR_NOT_FOUND);
  402.     return (ERROR);
  403.     }
  404. /********************************************************************************
  405. * taskVarInfo - get a list of task variables of a task
  406. *
  407. * This routine provides the calling task with a list of all of the task
  408. * variables of a specified task.  The unsorted array of task variables is
  409. * copied to <varList>.
  410. *
  411. * CAVEATS
  412. * Kernel rescheduling is disabled with taskLock() while task variables are
  413. * looked up.  There is no guarantee that all the task variables are still
  414. * valid or that new task variables have not been created by the time this
  415. * routine returns.
  416. *
  417. * RETURNS: The number of task variables in the list.
  418. */
  419. int taskVarInfo
  420.     (
  421.     int tid,            /* ID of task whose task variable is to be set */
  422.     TASK_VAR varList[], /* array to hold task variable addresses */
  423.     int maxVars         /* maximum variables varList can accommodate */
  424.     )
  425.     {
  426.     FAST TASK_VAR *pTaskVar; /* ptr to next node */
  427.     WIND_TCB *    pTcb   = taskTcb (tid);
  428.     int    active = 0;
  429.     if (pTcb == NULL)
  430. return (ERROR);
  431.     taskLock (); /* LOCK PREEMPTION */
  432.     for (pTaskVar = pTcb->pTaskVar;
  433.  (pTaskVar != NULL) && (active < maxVars);
  434.  pTaskVar = pTaskVar->next, active ++)
  435. {
  436. varList[active] = *pTaskVar;
  437. }
  438.     taskUnlock (); /* UNLOCK PREEMPTION */
  439.     return (active);
  440.     }