1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32 33 34 35
36
37 package ti.sysbios.knl;
38
39 import xdc.rov.ViewInfo;
40
41 import xdc.runtime.Error;
42 import xdc.runtime.Assert;
43 import xdc.runtime.Diags;
44 import xdc.runtime.Log;
45 import xdc.runtime.IHeap;
46
47 import ti.sysbios.knl.Queue;
48
49 /*!
50 * ======== Task ========
51 * Task Manager.
52 *
53 * The Task module makes available a set of functions that manipulate task
54 * objects accessed through pointers of type {@link #Handle}. Tasks represent
55 * independent threads of control that conceptually execute functions in
56 * parallel within a single C program; in reality, concurrency is achieved
57 * by switching the processor from one task to another.
58 *
59 * All tasks executing within a single program share a common set of
60 * global variables, accessed according to the standard rules of scope
61 * defined for C functions.
62 *
63 * Each task is in one of five modes of execution at any point in time:
64 * running, ready, blocked, terminated, or inactive. By design, there is
65 * always one
66 * (and only one) task currently running, even if it is only the idle task
67 * managed internally by Task. The current task can be suspended from
68 * execution by calling certain Task functions, as well as functions
69 * provided by other modules like the Semaphore or Event Modules.
70 * The current task
71 * can also terminate its own execution. In either case, the processor
72 * is switched to the highest priority task that is ready to run.
73 *
74 * You can assign numeric priorities to tasks. Tasks are
75 * readied for execution in strict priority order; tasks of the same
76 * priority are scheduled on a first-come, first-served basis.
77 * The priority of the currently running task is never lower
78 * than the priority of any ready task. Conversely, the running task
79 * is preempted and re-scheduled for execution whenever there exists
80 * some ready task of higher priority.
81 *
82 * @a(Task Stacks)
83 *
84 * When you create a task, it is provided with its own run-time stack,
85 * used for storing local variables as well as for further nesting of
86 * function calls. Each stack must be large enough to handle normal
87 * subroutine calls and one task preemption context.
88 * A task preemption context is the context that gets saved when one task
89 * preempts another as a result of an interrupt thread readying
90 * a higher-priority task.
91 *
92 * See sections 3.5.3 and 7.5 of the BIOS User's Guide for further
93 * discussions regarding task stack sizing.
94 *
95 * Certain system configuration settings will result in
96 * task stacks needing to be large enough to absorb two interrupt
97 * contexts rather than just one.
98 * Setting {@link ti.sysbios.BIOS#logsEnabled BIOS.logsEnabled} to 'true'
99 * or installing any Task hooks will have the side effect of allowing
100 * up to two interrupt contexts to be placed on a task stack. Also
101 * see {@link #minimizeLatency Task.minimizeLatency}.
102 *
103 * @a(Task Deletion)
104 *
105 * Any dynamically created task that is not in the Task_Mode_RUNNING
106 * state (ie not the currently running task) can be deleted using the
107 * {@link #delete} API.
108 *
109 * Task_delete() removes the task from all internal queues and calls
110 * Memory_free() is used to free the task object and its stack.
111 * Memory_free() must acquire a lock to the memory before proceeding.
112 * If another task already holds a lock to the memory, then the thread
113 * performing the delete will be blocked until the memory is unlocked.
114 *
115 * Note:
116 * Task_delete() should be called with extreme care.
117 * As mentioned above, the scope of Task_delete() is limited to
118 * freeing the Task object itself, freeing the task's stack memory
119 * if it was allocated at create time, and removing the task from
120 * any SYS/BIOS-internal state structures.
121 *
122 * SYS/BIOS does not keep track of any resources the task may have
123 * acquired or used during its lifetime.
124 *
125 * It is the application's responsibility to guarantee the integrity
126 * of a task's partnerships prior to deleting that task.
127 *
128 * For example, if a task has obtained exclusive access to a resource,
129 * deleting that task will make the resource forever unavailable.
130 *
131 * Task_delete() sets the referenced task handle to NULL. Any subsequent
132 * call to a Task instance API using that null task handle will behave
133 * unpredictably and will usually result in an application crash.
134 *
135 * Assuming a task completely cleans up after itself prior to calling
136 * Task_exit() (or falling through the the bottom of the task
137 * function), it is then safest to use Task_delete() only when a task
138 * is in the 'Task_Mode_TERMINATED' state.
139 *
140 * Delete hooks:
141 * You can specify application-wide Delete hook functions that
142 * run whenever a task is deleted. See the discussion of Hook Functions
143 * below for details.
144 *
145 * Task_delete() constraints:
146 * @p(blist)
147 * -The task cannot be the currently executing task (Task_self()).
148 * -Task_delete cannot be called from a Swi or Hwi.
149 * -No check is performed to prevent Task_delete from being used on a
150 * statically-created object. If a program attempts to delete a task object
151 * that was created statically, the Memory_free() call will result in an
152 * assertion failure in its corresponding Heap manager, causing the
153 * application to exit.
154 * @p
155 *
156 * @a(Stack Alignment)
157 *
158 * Stack size parameters for both static and dynamic tasks are rounded
159 * up to the nearest integer multiple of a target-specific alignment
160 * requirement.
161 *
162 * In the case of Task's which are created with a user-provided stack,
163 * both the base address and the stackSize are aligned. The base address
164 * is increased to the nearest aligned address. The stack size is decreased
165 * accordingly and then rounded down to the nearest integer multiple of the
166 * target-specific required alignment.
167 *
168 * @p(html)
169 * <a name="hookfunc"></a>
170 * @p
171 *
172 * @a(Hook Functions)
173 *
174 * Sets of hook functions can be specified for the Task module. Each
175 * set can contains these hook functions:
176 * @p(blist)
177 * -Register: A function called before any statically created tasks
178 * are initialized at runtime. The register hook is called at boot time
179 * before main() and before interrupts are enabled.
180 * -Create: A function that is called when a task is created.
181 * This includes tasks that are created statically and those
182 * created dynamically using {@link #create} or {@link #construct}.
183 * The create hook is called outside of a Task_disable/enable block and
184 * before the task has been added to the ready list.
185 * -Ready: A function that is called when a task becomes ready to run.
186 * The ready hook is called from within a Task_disable/enable block with
187 * interrupts enabled.
188 * -Switch: A function that is called just before a task switch
189 * occurs. The 'prev' and 'next' task handles are passed to the Switch
190 * hook. 'prev' is set to NULL for the initial task switch that occurs
191 * during SYS/BIOS startup. The Switch hook is called from within a
192 * Task_disable/enable block with interrupts enabled.
193 * -Exit: A function that is called when a task exits using
194 * {@link #exit}. The exit hook is passed the handle of the exiting
195 * task. The exit hook is called outside of a Task_disable/enable block
196 * and before the task has been removed from the kernel lists.
197 * -Delete: A function that is called when any task is deleted at
198 * run-time with {@link #delete}. The delete hook is called outside
199 * of a Task_disable/enable block.
200 * @p
201 * Hook functions can only be configured statically.
202 *
203 * If you define more than one set of hook functions, all the functions
204 * of a particular type will be run when a Task triggers that type of
205 * hook.
206 *
207 * @a(Warning)
208 * Configuring ANY Task hook function will have the side effect of allowing
209 * up to two interrupt contexts beings saved on a task stack. Be careful
210 * to size your task stacks accordingly.
211 *
212 * @p(html)
213 * <B>Register Function</B>
214 * @p
215 *
216 * The Register function is provided to allow a hook set to store its
217 * hookset ID. This id can be passed to {@link #setHookContext} and
218 * {@link #getHookContext} to set or get hookset-specific context. The
219 * Register function must be specified if the hook implementation
220 * needs to use {@link #setHookContext} or {@link #getHookContext}.
221 * The registerFxn hook function is called during system initialization
222 * before interrupts have been enabled.
223 *
224 * @p(code)
225 * Void myRegisterFxn(Int id);
226 * @p
227 *
228 * @p(html)
229 * <B>Create and Delete Functions</B>
230 * @p
231 *
232 * The create and delete functions are called whenever a Task is created
233 * or deleted. They are called with interrupts enabled (unless called
234 * at boot time or from main()).
235 *
236 * @p(code)
237 * Void myCreateFxn(Task_Handle task, Error_Block *eb);
238 * @p
239 *
240 * @p(code)
241 * Void myDeleteFxn(Task_Handle task);
242 * @p
243 *
244 * @p(html)
245 * <B>Switch Function</B>
246 * @p
247 *
248 * If a switch function is specified, it is invoked just before the new task
249 * is switched to. The switch function is called with interrupts enabled.
250 *
251 * This function can be used to save/restore additional task context (for
252 * example, external hardware registers), to check for task stack overflow,
253 * to monitor the time used by each task, etc.
254 *
255 * @p(code)
256 * Void mySwitchFxn(Task_Handle prev, Task_Handle next);
257 * @p
258 *
259 * To properly handle the switch to the first task your switchFxn should
260 * check for "prev == NULL" before using prev:
261 *
262 * @p(code)
263 * Void mySwitchFxn(Task_Handle prev, Task_Handle next)
264 * {
265 * if (prev != NULL) {
266 * ...
267 * }
268 * ...
269 * }
270 * @p
271 *
272 * @p(html)
273 * <B>Ready Function</B>
274 * @p
275 *
276 * If a ready function is specified, it is invoked whenever a task is made
277 * ready to run. The ready function is called with interrupts enabled
278 * (unless called at boot time or from main()).
279 *
280 * @p(code)
281 * Void myReadyFxn(Task_Handle task);
282 * @p
283 *
284 * @p(html)
285 * <B>Exit Function</B>
286 * @p
287 *
288 * If an exit function is specified, it is invoked when a task exits (via
289 * call to Task_exit() or when a task returns from its' main function).
290 * The Exit Function is called with interrupts enabled.
291 *
292 * @p(code)
293 * Void myExitFxn(Task_Handle task);
294 * @p
295 *
296 * @p(html)
297 * <h3> Calling Context </h3>
298 * <table border="1" cellpadding="3">
299 * <colgroup span="1"></colgroup> <colgroup span="5" align="center">
300 * </colgroup>
301 *
302 * <tr><th> Function </th><th> Hwi </th><th> Swi </th>
303 * <th> Task </th><th> Main </th><th> Startup </th></tr>
304 * <!-- -->
305 * <tr><td> {@link #create} </td><td> N </td><td> N </td>
306 * <td> Y </td><td> Y </td><td> N </td></tr>
307 * <tr><td> {@link #disable} </td><td> Y </td><td> Y </td>
308 * <td> Y </td><td> Y </td><td> N </td></tr>
309 * <tr><td> {@link #exit} </td><td> N </td><td> N </td>
310 * <td> Y </td><td> N </td><td> N </td></tr>
311 * <tr><td> {@link #getIdleTask} </td><td> Y </td><td> Y </td>
312 * <td> Y </td><td> Y </td><td> N </td></tr>
313 * <tr><td> {@link #Params_init} </td><td> Y </td><td> Y </td>
314 * <td> Y </td><td> Y </td><td> Y </td></tr>
315 * <tr><td> {@link #restore} </td><td> Y </td><td> Y </td>
316 * <td> Y </td><td> Y </td><td> N </td></tr>
317 * <tr><td> {@link #self} </td><td> Y </td><td> Y </td>
318 * <td> Y </td><td> Y </td><td> N </td></tr>
319 * <tr><td> {@link #sleep} </td><td> N </td><td> N </td>
320 * <td> Y </td><td> N </td><td> N </td></tr>
321 * <tr><td> {@link #yield} </td><td> Y </td><td> Y </td>
322 * <td> Y </td><td> N </td><td> N </td></tr>
323 * <tr><td> {@link #construct} </td><td> N </td><td> N </td>
324 * <td> Y </td><td> Y </td><td> N </td></tr>
325 * <tr><td> {@link #delete} </td><td> N </td><td> N </td>
326 * <td> Y </td><td> Y </td><td> N </td></tr>
327 * <tr><td> {@link #destruct} </td><td> N </td><td> N </td>
328 * <td> Y </td><td> Y </td><td> N </td></tr>
329 * <tr><td> {@link #getEnv} </td><td> Y </td><td> Y </td>
330 * <td> Y </td><td> Y </td><td> N </td></tr>
331 * <tr><td> {@link #getHookContext} </td><td> Y </td><td> Y </td>
332 * <td> Y </td><td> Y </td><td> N </td></tr>
333 * <tr><td> {@link #getMode} </td><td> Y </td><td> Y </td>
334 * <td> Y </td><td> Y </td><td> N </td></tr>
335 * <tr><td> {@link #getPri} </td><td> Y </td><td> Y </td>
336 * <td> Y </td><td> Y </td><td> N </td></tr>
337 * <tr><td> {@link #getFunc} </td><td> Y </td><td> Y </td>
338 * <td> Y </td><td> Y </td><td> N </td></tr>
339 * <tr><td> {@link #setEnv} </td><td> Y </td><td> Y </td>
340 * <td> Y </td><td> Y </td><td> N </td></tr>
341 * <tr><td> {@link #setHookContext} </td><td> Y </td><td> Y </td>
342 * <td> Y </td><td> Y </td><td> N </td></tr>
343 * <tr><td> {@link #setPri} </td><td> Y </td><td> Y </td>
344 * <td> Y </td><td> N </td><td> N </td></tr>
345 * <tr><td> {@link #stat} </td><td> Y </td><td> Y </td>
346 * <td> Y </td><td> Y </td><td> N </td></tr>
347 * <tr><td colspan="6"> Definitions: <br />
348 * <ul>
349 * <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
350 * <li> <b>Swi</b>: API is callable from a Swi thread. </li>
351 * <li> <b>Task</b>: API is callable from a Task thread. </li>
352 * <li> <b>Main</b>: API is callable during any of these phases: </li>
353 * <ul>
354 * <li> In your module startup after this module is started
355 * (e.g. Task_Module_startupDone() returns TRUE). </li>
356 * <li> During xdc.runtime.Startup.lastFxns. </li>
357 * <li> During main().</li>
358 * <li> During BIOS.startupFxns.</li>
359 * </ul>
360 * <li> <b>Startup</b>: API is callable during any of these phases:</li>
361 * <ul>
362 * <li> During xdc.runtime.Startup.firstFxns.</li>
363 * <li> In your module startup before this module is started
364 * (e.g. Task_Module_startupDone() returns FALSE).</li>
365 * </ul>
366 * </ul>
367 * </td></tr>
368 *
369 * </table>
370 * @p
371 */
372
373 @DirectCall
374 @ModuleStartup
375 @InstanceInitStatic
376 @InstanceFinalize
377 @InstanceInitError
378 @Template ("./Task.xdt") 379
380
381 module Task
382 {
383
384
385
386
387
388 /*! Task function type definition. */
389 typedef Void (*FuncPtr)(UArg, UArg);
390
391 /*! "All Task Blocked" function type definition. */
392 typedef Void (*AllBlockedFuncPtr)(Void);
393
394 /*!
395 * Task execution modes.
396 *
397 * These enumerations are the range of modes or states that
398 * a task can be in. A task's current mode can be gotten using
399 * {@link #stat}.
400 */
401 enum Mode {
402 Mode_RUNNING, /*! Task is currently executing. */
403 Mode_READY, /*! Task is scheduled for execution. */
404 Mode_BLOCKED, /*! Task is suspended from execution. */
405 Mode_TERMINATED, /*! Task is terminated from execution. */
406 Mode_INACTIVE /*! Task is on inactive task list */
407 };
408
409 /*!
410 * Task Status Buffer.
411 *
412 * Passed to and filled in by {@link #stat};
413 */
414 struct Stat {
415 Int priority; /*! Task priority. */
416 Ptr stack; /*! Task stack. */
417 SizeT stackSize; /*! Task stack size. */
418 IHeap.Handle stackHeap; /*! Heap used to alloc stack. */
419 Ptr env; /*! Global environment struct. */
420 Mode mode; /*! Task's current mode. */
421 Ptr sp; /*! Task's current stack pointer. */
422 SizeT used; /*! max # of words used on stack. */
423 };
424
425 /*!
426 * Task hook set type definition.
427 *
428 * Sets of hook functions can be specified for the Task module.
429 * See {@link #hookfunc Hook Functions} for details.
430 */
431 struct HookSet {
432 Void (*registerFxn)(Int);
433 Void (*createFxn)(Handle, Error.Block *);
434 Void (*readyFxn)(Handle);
435 Void (*switchFxn)(Handle, Handle);
436 Void (*exitFxn)(Handle);
437 Void (*deleteFxn)(Handle);
438 };
439
440 /*! "Don't care" task affinity */
441 const UInt AFFINITY_NONE = ~(0);
442
443 /*! @_nodoc */
444 metaonly struct BasicView {
445 String label;
446 Int priority;
447 String mode;
448 String fxn[];
449 UArg arg0;
450 UArg arg1;
451 SizeT stackSize;
452 Ptr stackBase;
453 String curCoreId;
454 String affinity;
455 }
456
457 /*! @_nodoc */
458 metaonly struct DetailedView {
459 String label;
460 Int priority;
461 String mode;
462 String fxn[];
463 UArg arg0;
464 UArg arg1;
465 String stackPeak;
466 SizeT stackSize;
467 Ptr stackBase;
468 String curCoreId;
469 String affinity;
470 String blockedOn;
471 }
472
473 /*! @_nodoc */
474 metaonly struct ModuleView {
475 String schedulerState;
476 String readyQMask[];
477 Bool workPending;
478 UInt numVitalTasks;
479 Ptr currentTask[];
480 String hwiStackPeak;
481 SizeT hwiStackSize;
482 Ptr hwiStackBase;
483 }
484
485 /*! @_nodoc (not used by view) */
486 metaonly struct CallStackView {
487 Int depth;
488 String decode;
489 }
490
491 /*! @_nodoc */
492 metaonly struct ReadyQView {
493 Ptr task;
494 Ptr next;
495 Ptr prev;
496 Ptr readyQ;
497 String label;
498 Int priority;
499 String mode;
500 String fxn[];
501 String curCoreId;
502 String affinity;
503 }
504
505 /*! @_nodoc */
506 @Facet
507 metaonly config ViewInfo.Instance rovViewInfo =
508 ViewInfo.create({
509 viewMap: [
510 ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitBasic', structName: 'BasicView'}],
511 ['Detailed', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitDetailed', structName: 'DetailedView'}],
512 ['CallStacks', {type: ViewInfo.TREE, viewInitFxn: 'viewInitCallStack', structName: 'CallStackView'}],
513 ['ReadyQs', {type: ViewInfo.TREE_TABLE, viewInitFxn: 'viewInitReadyQs', structName: 'ReadyQView'}],
514 ['Module', {type: ViewInfo.MODULE, viewInitFxn: 'viewInitModule', structName: 'ModuleView'}],
515 ]
516 });
517
518
519
520
521
522 /*! Logged on every task switch */
523 config Log.Event LM_switch = {
524 mask: Diags.USER1 | Diags.USER2,
525 msg: "LM_switch: oldtsk: 0x%x, oldfunc: 0x%x, newtsk: 0x%x, newfunc: 0x%x"
526 };
527
528 /*! Logged on calls to Task_sleep */
529 config Log.Event LM_sleep = {
530 mask: Diags.USER1 | Diags.USER2,
531 msg: "LM_sleep: tsk: 0x%x, func: 0x%x, timeout: %d"
532 };
533
534 /*! Logged when a task is made ready to run (ie Semaphore_post()) */
535 config Log.Event LD_ready = {
536 mask: Diags.USER2,
537 msg: "LD_ready: tsk: 0x%x, func: 0x%x, pri: %d"
538 };
539
540 /*! Logged when a task is blocked (ie Semaphore_pend()) */
541 config Log.Event LD_block = {
542 mask: Diags.USER2,
543 msg: "LD_block: tsk: 0x%x, func: 0x%x"
544 };
545
546 /*! Logged on calls to Task_yield */
547 config Log.Event LM_yield = {
548 mask: Diags.USER1 | Diags.USER2,
549 msg: "LM_yield: tsk: 0x%x, func: 0x%x, currThread: %d"
550 };
551
552 /*! Logged on calls to Task_setPri */
553 config Log.Event LM_setPri = {
554 mask: Diags.USER1 | Diags.USER2,
555 msg: "LM_setPri: tsk: 0x%x, func: 0x%x, oldPri: %d, newPri %d"
556 };
557
558 /*!
559 * Logged when Task functions fall thru the bottom
560 * or when Task_exit() is explicitly called.
561 */
562 config Log.Event LD_exit = {
563 mask: Diags.USER2,
564 msg: "LD_exit: tsk: 0x%x, func: 0x%x"
565 };
566
567 /*! Logged on calls to Task_setAffinity */
568 config Log.Event LM_setAffinity = {
569 mask: Diags.USER1 | Diags.USER2,
570 msg: "LM_setAffinity: tsk: 0x%x, func: 0x%x, oldCore: %d, oldAffinity %d, newAffinity %d"
571 };
572
573 /*! Logged on every task schedule entry */
574 config Log.Event LM_schedule = {
575 mask: Diags.USER3,
576 msg: "LD_schedule: coreId: %d, workFlag: %d, curSetLocal: %d, curSetX: %d, curMaskLocal: %d"
577 };
578
579 /*! Logged when no scheduling work was found */
580 config Log.Event LM_noWork = {
581 mask: Diags.USER3,
582 msg: "LD_noWork: coreId: %d, curSetLocal: %d, curSetX: %d, curMaskLocal: %d"
583 };
584
585
586
587 /*!
588 * Error raised when a stack overflow (or corruption) is detected.
589 *
590 * This error is raised by kernel's stack checking function. This
591 * function checks the stacks before every task switch to make sure
592 * that reserved word at top of stack has not been modified.
593 *
594 * The stack checking logic is enabled by the {@link #initStackFlag} and
595 * {@link #checkStackFlag} configuration parameters. If both of these
596 * flags are set to true, the kernel will validate the stacks.
597 */
598 config Error.Id E_stackOverflow = {
599 msg: "E_stackOverflow: Task 0x%x stack overflow."
600 };
601
602 /*!
603 * Error raised when a task's stack pointer (SP) does not point
604 * somewhere within the task's stack.
605 *
606 * This error is raised by kernel's stack checking function. This
607 * function checks the SPs before every task switch to make sure
608 * they point within the task's stack.
609 *
610 * The stack checking logic is enabled by the {@link #initStackFlag} and
611 * {@link #checkStackFlag} configuration parameters. If both of these
612 * flags are set to true, the kernel will validate the stack pointers.
613 */
614 config Error.Id E_spOutOfBounds = {
615 msg: "E_spOutOfBounds: Task 0x%x stack error, SP = 0x%x."
616 };
617
618 config Error.Id E_deleteNotAllowed = {
619 msg: "E_deleteNotAllowed: Task 0x%x."
620 };
621
622
623
624 /*! Asserted in Task_create and Task_delete */
625 config Assert.Id A_badThreadType = {
626 msg: "A_badThreadType: Cannot create/delete a task from Hwi or Swi thread."
627 };
628
629 /*! Asserted in Task_delete */
630 config Assert.Id A_badTaskState = {
631 msg: "A_badTaskState: Can't delete a task in RUNNING state."
632 };
633
634 /*! Asserted in Task_delete */
635 config Assert.Id A_noPendElem = {
636 msg: "A_noPendElem: Not enough info to delete BLOCKED task."
637 };
638
639 /*! Asserted in Task_create */
640 config Assert.Id A_taskDisabled = {
641 msg: "A_taskDisabled: Cannot create a task when tasking is disabled."
642 };
643
644 /*! Asserted in Task_create */
645 config Assert.Id A_badPriority = {
646 msg: "A_badPriority: An invalid task priority was used."
647 };
648
649 /*! Asserted in Task_sleep */
650 config Assert.Id A_badTimeout = {
651 msg: "A_badTimeout: Can't sleep FOREVER."
652 };
653
654 /*! Asserted in Task_setAffinity */
655 config Assert.Id A_badAffinity = {
656 msg: "A_badAffinity: Invalid affinity."
657 };
658
659 /*! Asserted in Task_sleep */
660 config Assert.Id A_sleepTaskDisabled = {
661 msg: "A_sleepTaskDisabled: Cannot call Task_sleep() while the Task scheduler is disabled."
662 };
663
664 /*! Asserted in Task_getIdleTaskHandle */
665 config Assert.Id A_invalidCoreId = {
666 msg: "A_invalidCoreId: Cannot pass a non-zero CoreId in a non-SMP application."
667 };
668
669 /*!
670 * Number of Task priorities supported. Default is 16.
671 *
672 * The maximum number of priorities supported is
673 * target specific and depends on the number of
674 * bits in a UInt data type. For 6x and ARM devices
675 * the maximum number of priorities is therefore 32.
676 * For 28x, 55x, and MSP430 devices, the maximum number of
677 * priorities is 16.
678 */
679 config UInt numPriorities = 16;
680
681 /*!
682 * Default stack size (in MAUs) used for all tasks.
683 *
684 * Default is obtained from the family-specific TaskSupport module
685 * (e.g. {@link ti.sysbios.family.arm.m3.TaskSupport},
686 * {@link ti.sysbios.family.c62.TaskSupport}).
687 */
688 config SizeT defaultStackSize;
689
690 /*!
691 * Default memory section used for all statically created task stacks.
692 *
693 * The default stack section name is target/device specific.
694 * For C6x targets it is ".far:taskStackSection".
695 * For C28x targets it is ".taskStackSection".
696 * For GNU targets it is ".bss".
697 * For all other targets it is ".bss:taskStackSection".
698 *
699 * By default, all statically created task stacks are grouped together
700 * into the defaultStackSection and placed where ever
701 * the target specific defaultStackSection base section name
702 * (ie .bss, .far, .ebss) is placed.
703 *
704 * To place all task stacks into a different memory segment,
705 * add the following to your config script:
706 *
707 * @p(code)
708 * Program.sectMap[Task.defaultStackSection] = new Program.SectionSpec();
709 * Program.sectMap[Task.defaultStackSection].loadSegment =
710 * "yourMemorySegment";
711 * @p
712 *
713 * To group all task stacks into a different section AND place that
714 * section into a specific memory segment, add the following to your
715 * config script:
716 *
717 * @p(code)
718 * Task.defaultStackSection = ".yourSectionName";
719 * Program.sectMap[Task.defaultStackSection] = new Program.SectionSpec();
720 * Program.sectMap[Task.defaultStackSection].loadSegment =
721 * "yourMemorySegment";
722 * @p
723 *
724 * Where "yourSectionName" can be just about anything, and
725 * "yourMemorySegment"
726 * must be a memory segment defined for your board.
727 */
728 metaonly config String defaultStackSection;
729
730 /*!
731 * Default Mem heap used for all dynamically created task stacks.
732 *
733 * Default is null.
734 */
735 config IHeap.Handle defaultStackHeap;
736
737 /*!
738 * Default core affinity for newly created tasks.
739 *
740 * Default is Task_AFFINITY_NONE, meaning don't care.
741 */
742 metaonly config UInt defaultAffinity = AFFINITY_NONE;
743
744 /*!
745 * Create a task (of priority 0) to run the Idle functions in.
746 *
747 * When set to true, a task is created that continuously calls the
748 * {@link Idle#run Idle_run()} function, which, in turn calls each of
749 * the configured Idle functions.
750 *
751 * When set to false, no Idle Task is created and it is up to the
752 * user to call the Idle_run() function if the configured Idle
753 * functions need to be run. Or, by adding the following lines to
754 * the config script, the Idle functions will run whenever all
755 * tasks are blocked ({@link #allBlockedFunc Task.allBlockedFunc}):
756 *
757 * @p(code)
758 * Task.enableIdleTask = false;
759 * Task.allBlockedFunc = Idle.run;
760 * @p
761 *
762 * Default is true.
763 *
764 * @see #idleTaskStackSize
765 * @see #idleTaskStackSection
766 * @see #idleTaskVitalTaskFlag
767 * @see #allBlockedFunc
768 */
769 metaonly config Bool enableIdleTask = true;
770
771 /*!
772 * Reduce interrupt latency by enabling interrupts
773 * within the Task scheduler.
774 *
775 * By default, interrupts are disabled within certain critical
776 * sections of the task scheduler when switching to a different
777 * task thread. This default behavior guarantees that a task stack
778 * will only ever absorb ONE ISR context. Nested interrupts all run
779 * on the shared Hwi stack.
780 *
781 * While most users find this behavior desirable, the resulting
782 * impact on interrupt latency is too great for certain applications.
783 *
784 * By setting this parameter to 'true', the worst case interrupt latency
785 * imposed by the kernel will be reduced but will result in task stacks
786 * needing to be sized to accommodate one additional interrupt context.
787 *
788 * See sections 3.5.3 and 7.5 of the BIOS User's Guide for further
789 * discussions regarding task stack sizing.
790 *
791 * Also see {@link ti.sysbios.BIOS#logsEnabled BIOS.logsEnabled}
792 * and the discussion on Task hooks.
793 */
794 metaonly config Bool minimizeLatency = false;
795
796 /*!
797 * Idle task stack size in MAUs.
798 *
799 * Default is inherited from module config defaultStackSize.
800 */
801 metaonly config SizeT idleTaskStackSize;
802
803 /*!
804 * Idle task stack section
805 *
806 * Default is inherited from module config defaultStackSection;
807 */
808 metaonly config String idleTaskStackSection;
809
810 /*!
811 * Idle task's vitalTaskFlag.
812 * (see {@link #vitalTaskFlag}).
813 *
814 * Default is true.
815 */
816 metaonly config Bool idleTaskVitalTaskFlag = true;
817
818 /*!
819 * Function to call while all tasks are blocked.
820 *
821 * This function will be called repeatedly while no tasks are
822 * ready to run.
823 *
824 * Ordinarily (in applications that have tasks ready to run at startup),
825 * the function will run in the context of the last task to block.
826 *
827 * In an application where there are no tasks ready to run
828 * when BIOS_start() is called, the allBlockedFunc function is
829 * called within the BIOS_start() thread which runs on the system/ISR
830 * stack.
831 *
832 * By default, allBlockedFunc is initialized to point to an internal
833 * function that simply returns.
834 *
835 * By adding the following lines to the config script, the Idle
836 * functions will run whenever all tasks are blocked:
837 *
838 * @p(code)
839 * Task.enableIdleTask = false;
840 * Task.allBlockedFunc = Idle.run;
841 * @p
842 *
843 * @see #enableIdleTask
844 *
845 * @a(constraints)
846 * The configured allBlockedFunc is designed to be called repeatedly.
847 * It must return in order for the task scheduler to check if all
848 * tasks are STILL blocked and if not, run the highest priority task
849 * currently ready to run.
850 *
851 * The configured allBlockedFunc function is called with interrupts
852 * disabled. If your function must run with interrupts enabled,
853 * surround the body of your code with Hwi_enable()/Hwi_restore()
854 * function calls per the following example:
855 *
856 * @p(code)
857 * Void yourFunc() {
858 * UInt hwiKey;
859 *
860 * hwiKey = Hwi_enable();
861 *
862 * ... // your code here
863 *
864 * Hwi_restore(hwiKey);
865 * }
866 * @p
867 */
868 config AllBlockedFuncPtr allBlockedFunc = null;
869
870 /*!
871 * Initialize stack with known value for stack checking at runtime
872 * (see {@link #checkStackFlag}).
873 *
874 * This is also useful for inspection of stack in debugger or core
875 * dump utilities.
876 * Default is true.
877 */
878 config Bool initStackFlag = true;
879
880 /*!
881 * Check 'from' and 'to' task stacks before task context switch.
882 *
883 * The check consists of testing the top of stack value against
884 * its initial value (see {@link #initStackFlag}). If it is no
885 * longer at this value, the assumption is that the task has
886 * overrun its stack. If the test fails, then the
887 * {@link #E_stackOverflow} error is raised.
888 *
889 * Runtime stack checking is only performed if {@link #initStackFlag} is
890 * also true.
891 *
892 * Default is true.
893 *
894 * To enable or disable full stack checking, you should set both this
895 * flag and the {@link ti.sysbios.hal.Hwi#checkStackFlag}.
896 *
897 * @a(Note)
898 * Enabling stack checking will add some interrupt latency because the
899 * checks are made within the Task scheduler while interrupts are
900 * disabled.
901 */
902 config Bool checkStackFlag = true;
903
904 /*!
905 * Automatically delete terminated tasks.
906 *
907 * If this feature is enabled, an Idle function is installed that
908 * deletes dynamically created Tasks that have terminated either
909 * by falling through their task function or by explicitly calling
910 * Task_exit().
911 *
912 * A list of terminated Tasks that were created dynmically is
913 * maintained internally. Each invocation of the installed Idle function
914 * deletes the first Task on this list. This one-at-a-time process
915 * continues until the list is empty.
916 *
917 * @a(Note)
918 * This feature is disabled by default.
919 *
920 * @a(WARNING)
921 * When this feature is enabled, an error will be raised if the user's
922 * application attempts to delete a terminated task. If a terminated task
923 * has already been automatically deleted and THEN the user's application
924 * attempts to delete it (ie: using a stale Task handle), the results are
925 * undefined and probably catastrophic!
926 *
927 */
928 config Bool deleteTerminatedTasks = false;
929
930 /*!
931 * Const array that holds the HookSet objects.
932 *
933 * See {@link #hookfunc Hook Functions} for details about HookSets.
934 */
935 config HookSet hooks[length] = [];
936
937
938
939 /*!
940 * ======== addHookSet ========
941 * addHookSet is used in a config file to add a hook set.
942 *
943 * Configures a set of hook functions for the
944 * Task module. Each set contains these hook functions:
945 *
946 * @p(blist)
947 * -Register: A function called before any statically created tasks
948 * are initialized at runtime. The register hook is called at boot time
949 * before main() and before interrupts are enabled.
950 * -Create: A function that is called when a task is created.
951 * This includes tasks that are created statically and those
952 * created dynamically using {@link #create} or {@link #construct}.
953 * The create hook is called outside of a Task_disable/enable block and
954 * before the task has been added to the ready list.
955 * -Ready: A function that is called when a task becomes ready to run.
956 * The ready hook is called from within a Task_disable/enable block with
957 * interrupts enabled.
958 * -Switch: A function that is called just before a task switch
959 * occurs. The 'prev' and 'next' task handles are passed to the Switch
960 * hook. 'prev' is set to NULL for the initial task switch that occurs
961 * during SYS/BIOS startup. The Switch hook is called from within a
962 * Task_disable/enable block with interrupts enabled.
963 * -Exit: A function that is called when a task exits using
964 * {@link #exit}. The exit hook is passed the handle of the exiting
965 * task. The exit hook is called outside of a Task_disable/enable block
966 * and before the task has been removed from the kernel lists.
967 * -Delete: A function that is called when any task is deleted at
968 * run-time with {@link #delete}. The delete hook is called outside
969 * of a Task_disable/enable block.
970 * @p
971 * Hook functions can only be configured statically.
972 *
973 * See {@link #hookfunc Hook Functions} for more details.
974 *
975 * HookSet structure elements may be omitted, in which case those
976 * elements will not exist.
977 *
978 * For example, the following configuration code defines a HookSet:
979 *
980 * @p(code)
981 * // Hook Set 1
982 * Task.addHookSet({
983 * registerFxn: '&myRegister1',
984 * createFxn: '&myCreate1',
985 * readyFxn: '&myReady1',
986 * switchFxn: '&mySwitch1',
987 * exitFxn: '&myExit1',
988 * deleteFxn: '&myDelete1'
989 * });
990 * @p
991 *
992 * @param(hook) structure of type HookSet
993 */
994 metaonly Void addHookSet(HookSet hook);
995
996 /*!
997 * @_nodoc
998 * ======== Task_startup ========
999 * Start the task scheduler.
1000 *
1001 * Task_startup signals the end of boot operations, enables
1002 * the Task scheduler and schedules the highest priority ready
1003 * task for execution.
1004 *
1005 * Task_startup is called by BIOS_start() after Hwi_enable()
1006 * and Swi_enable(). There is no return from this function as the
1007 * execution thread is handed to the highest priority ready task.
1008 */
1009 Void startup();
1010
1011 /*!
1012 * ======== Task_enabled ========
1013 * Returns TRUE if the Task scheduler is enabled
1014 *
1015 * @_nodoc
1016 */
1017 Bool enabled();
1018
1019 /*!
1020 * @_nodoc
1021 * ======== unlockSched ========
1022 * Force a Task scheduler unlock. Used by Core_atExit() & Core_hwiFunc()
1023 * to unlock Task scheduler before exiting.
1024 *
1025 * This function should only be called after a Hwi_disable() has entered
1026 * the Inter-core gate and disabled interrupts locally.
1027 */
1028 Void unlockSched();
1029
1030 /*!
1031 * ======== Task_disable ========
1032 * Disable the task scheduler.
1033 *
1034 * {@link #disable} and {@link #restore} control Task scheduling.
1035 * {@link #disable} disables all other Tasks from running until
1036 * {@link #restore} is called. Hardware and Software interrupts
1037 * can still run.
1038 *
1039 * {@link #disable} and {@link #restore} allow you to ensure that
1040 * statements
1041 * that must be performed together during critical processing are not
1042 * preempted by other Tasks.
1043 *
1044 * The value of the key returned is opaque to applications and is meant
1045 * to be passed to Task_restore().
1046 *
1047 * In the following example, the critical section is
1048 * not preempted by any Tasks.
1049 *
1050 * @p(code)
1051 * key = Task_disable();
1052 * `critical section`
1053 * Task_restore(key);
1054 * @p
1055 *
1056 * You can also use {@link #disable} and {@link #restore} to
1057 * create several Tasks and allow them to be invoked in
1058 * priority order.
1059 *
1060 * {@link #disable} calls can be nested.
1061 *
1062 * @b(returns) key for use with {@link #restore}
1063 *
1064 * @a(constraints)
1065 * Do not call any function that can cause the current task to block
1066 * within a {@link #disable}/{@link #restore} block. For example,
1067 * {@link ti.sysbios.knl.Semaphore#pend Semaphore_pend}
1068 * (if timeout is non-zero),
1069 * {@link #sleep}, {@link #yield}, and Memory_alloc can all
1070 * cause blocking.
1071 */
1072 UInt disable();
1073
1074 /*!
1075 * @_nodoc
1076 * ======== enable ========
1077 * Enable the task scheduler.
1078 *
1079 * {@link #enable} unconditionally enables the Task scheduler and
1080 * schedules the highest priority ready task for execution.
1081 *
1082 * This function is called by {@link #startup} (which is called by
1083 * {@link ti.sysbios.BIOS#start BIOS_start}) to begin multi-tasking
1084 * operations.
1085 */
1086 Void enable();
1087
1088 /*!
1089 * ======== restore ========
1090 * Restore Task scheduling state.
1091 *
1092 * {@link #disable} and {@link #restore} control Task scheduling
1093 * {@link #disable} disables all other Tasks from running until
1094 * {@link #restore} is called. Hardware and Software interrupts
1095 * can still run.
1096 *
1097 * {@link #disable} and {@link #restore} allow you to ensure that
1098 * statements
1099 * that must be performed together during critical processing are not
1100 * preempted.
1101
1102 * In the following example, the critical section is not preempted
1103 * by any Tasks.
1104 *
1105 * @p(code)
1106 * key = Task_disable();
1107 * `critical section`
1108 * Task_restore(key);
1109 * @p
1110 *
1111 * You can also use {@link #disable} and {@link #restore} to create
1112 * several Tasks and allow them to be performed in priority order.
1113 *
1114 * {@link #disable} calls can be nested.
1115 *
1116 * {@link #restore} returns with interrupts enabled if the key unlocks
1117 * the scheduler
1118 *
1119 * @param(key) key to restore previous Task scheduler state
1120 *
1121 * @a(constraints)
1122 * Do not call any function that can cause the current task to block
1123 * within a {@link #disable}/{@link #restore} block. For example,
1124 * {@link ti.sysbios.knl.Semaphore#pend Semaphore_pend()}
1125 * (if timeout is non-zero),
1126 * {@link #sleep}, {@link #yield}, and Memory_alloc can all
1127 * cause blocking.
1128 *
1129 * {@link #restore} internally calls Hwi_enable() if the key passed
1130 * to it results in the unlocking of the Task scheduler (ie if this
1131 * is root Task_disable/Task_restore pair).
1132 */
1133 Void restore(UInt key);
1134
1135 /*!
1136 * @_nodoc
1137 * ======== restoreHwi ========
1138 * Restore Task scheduling state.
1139 * Used by dispatcher. Does not re-enable Ints.
1140 */
1141 Void restoreHwi(UInt key);
1142
1143 /*!
1144 * ======== self ========
1145 * Returns a handle to the currently executing Task object.
1146 *
1147 * Task_self returns the object handle for the currently executing task.
1148 * This function is useful when inspecting the object or when the current
1149 * task changes its own priority through {@link #setPri}.
1150 *
1151 * No task switch occurs when calling Task_self.
1152 *
1153 * Task_self will return NULL until Tasking is initiated at the end of
1154 * BIOS_start().
1155 *
1156 * @b(returns) address of currently executing task object
1157 */
1158 Handle self();
1159
1160 /*!
1161 * ======== selfMacro ========
1162 * Returns a handle to the currently executing Task object.
1163 *
1164 * Task_selfMacro is identical to {@link #self} but is implemented as
1165 * and inline macro.
1166 *
1167 * @b(returns) address of currently executing task object
1168 */
1169 @Macro
1170 Handle selfMacro();
1171
1172 /*!
1173 * @_nodoc
1174 * ======== checkStacks ========
1175 * Check for stack overflow.
1176 *
1177 * This function is usually called by the {@link #HookSet} switchFxn to
1178 * make sure task stacks are valid before performing the context
1179 * switch.
1180 *
1181 * If a stack overflow is detected on either the oldTask or the
1182 * newTask, a {@link #E_stackOverflow} Error is raised and the system
1183 * exited.
1184 *
1185 * In order to work properly, {@link #checkStacks} requires that the
1186 * {@link #initStackFlag} set to true, which it is by default.
1187 *
1188 * You can call {@link #checkStacks} directly from your application.
1189 * For example, you can check the current task's stack integrity
1190 * at any time with a call like the following:
1191 *
1192 * @p(code)
1193 * Task_checkStacks(Task_self(), Task_self());
1194 * @p
1195 *
1196 * @param(oldTask) leaving Task Object Ptr
1197 * @param(newTask) entering Task Object Ptr
1198 */
1199 Void checkStacks(Handle oldTask, Handle newTask);
1200
1201 /*!
1202 * ======== exit ========
1203 * Terminate execution of the current task.
1204 *
1205 * Task_exit terminates execution of the current task, changing its mode
1206 * from {@link #Mode_RUNNING} to {@link #Mode_TERMINATED}. If all tasks
1207 * have been terminated, or if all remaining tasks have their
1208 * vitalTaskFlag attribute set to FALSE, then SYS/BIOS terminates the
1209 * program as a whole by calling the function System_exit with a status
1210 * code of 0.
1211 *
1212 * Task_exit is automatically called whenever a task returns from its
1213 * top-level function.
1214 *
1215 * Exit Hooks (see exitFxn in {@link #HookSet}) can be used to provide
1216 * functions that run whenever a task is terminated. The exitFxn Hooks
1217 * are called before the task has been blocked and marked
1218 * {@link #Mode_TERMINATED}.
1219 * See {@link #hookfunc Hook Functions} for more information.
1220 *
1221 * Any SYS/BIOS function can be called from an Exit Hook function.
1222 *
1223 * Calling {@link #self} within an Exit function returns the task
1224 * being exited. Your Exit function declaration should be similar to
1225 * the following:
1226 * @p(code)
1227 * Void myExitFxn(Void);
1228 * @p
1229 *
1230 * A task switch occurs when calling Task_exit unless the program as a
1231 * whole is terminated
1232 *
1233 * @a(constraints)
1234 * Task_exit cannot be called from a Swi or Hwi.
1235 *
1236 * Task_exit cannot be called from the program's main() function.
1237 */
1238 Void exit();
1239
1240 /*!
1241 * ======== sleep ========
1242 * Delay execution of the current task.
1243 *
1244 * Task_sleep changes the current task's mode from {@link #Mode_RUNNING}
1245 * to {@link #Mode_BLOCKED}, and delays its execution for nticks
1246 * increments of the {@link Clock system clock}. The actual time
1247 * delayed can be up to 1 system clock tick less than nticks due to
1248 * granularity in system timekeeping and the time elapsed per
1249 * tick is determined by {@link Clock#tickPeriod Clock_tickPeriod}.
1250 *
1251 * After the specified period of time has elapsed, the task reverts to
1252 * the {@link #Mode_READY} mode and is scheduled for execution.
1253 *
1254 * A task switch always occurs when calling Task_sleep if nticks > 0.
1255 *
1256 * @param(nticks) number of system clock ticks to sleep
1257 *
1258 * @a(constraints)
1259 * Task_sleep cannot be called from a Swi or Hwi, or within a
1260 * {@link #disable} / {@link #restore} block.
1261 *
1262 * Task_sleep cannot be called from the program's main() function.
1263 *
1264 * Task_sleep should not be called from within an Idle function. Doing
1265 * so prevents analysis tools from gathering run-time information.
1266 *
1267 * nticks cannot be {@link ti.sysbios.BIOS#WAIT_FOREVER BIOS_WAIT_FOREVER}.
1268 */
1269 Void sleep(UInt32 nticks);
1270
1271 /*!
1272 * ======== yield ========
1273 * Yield processor to equal priority task.
1274 *
1275 * Task_yield yields the processor to another task of equal priority.
1276 *
1277 * A task switch occurs when you call Task_yield if there is an equal
1278 * priority task ready to run.
1279 *
1280 * Tasks of higher priority preempt the currently running task without
1281 * the need for a call to Task_yield. If only lower-priority tasks are
1282 * ready to run when you call Task_yield, the current task continues to
1283 * run. Control does not pass to a lower-priority task.
1284 *
1285 * @a(constraints)
1286 * When called within an Hwi, the code sequence calling Task_yield
1287 * must be invoked by the Hwi dispatcher.
1288 *
1289 * Task_yield cannot be called from the program's main() function.
1290 */
1291 Void yield();
1292
1293 /*!
1294 * ======== getIdleTask ========
1295 * returns a handle to the idle task object (for core 0)
1296 */
1297 Handle getIdleTask();
1298
1299 /*!
1300 * ======== getIdleTaskHandle ========
1301 * returns a handle to the idle task object for the specified coreId
1302 * (should be used only in applications built with
1303 * {@link ti.sysbios.BIOS#smpEnabled} set to true)
1304 *
1305 * @a(Note)
1306 * If this function is called in a non-SMP application, coreId should
1307 * always be 0.
1308 */
1309 Handle getIdleTaskHandle(UInt coreId);
1310
1311 /*!
1312 * @_nodoc
1313 * ======== startCore ========
1314 * begin tasking on a core
1315 */
1316 Void startCore(UInt coreId);
1317
1318 /*!
1319 * ======== getNickName ========
1320 *
1321 */
1322 metaonly String getNickName(Any tskView);
1323
1324 instance:
1325
1326 /*!
1327 * ======== create ========
1328 * Create a Task.
1329 *
1330 * Task_create creates a new task object. If successful, Task_create
1331 * returns the handle of the new task object. If unsuccessful,
1332 * Task_create returns NULL unless it aborts.
1333 *
1334 * The fxn parameter uses the {@link #FuncPtr} type to pass a pointer to
1335 * the function the Task object should run. For example, if myFxn is a
1336 * function in your program, your C code can create a Task object
1337 * to call that
1338 * function as follows:
1339 *
1340 * @p(code)
1341 * Task_Params taskParams;
1342 *
1343 * // Create task with priority 15
1344 * Task_Params_init(&taskParams);
1345 * taskParams.stackSize = 512;
1346 * taskParams.priority = 15;
1347 * Task_create((Task_FuncPtr)myFxn, &taskParams, &eb);
1348 * @p
1349 *
1350 * The following statements statically create a task in the
1351 * configuration file:
1352 *
1353 * @p(code)
1354 * var params = new Task.Params;
1355 * params.instance.name = "tsk0";
1356 * params.arg0 = 1;
1357 * params.arg1 = 2;
1358 * params.priority = 1;
1359 * Task.create('&tsk0_func', params);
1360 * @p
1361 *
1362 * If NULL is passed instead of a pointer to an actual Task_Params
1363 * struct, a
1364 * default set of parameters is used. The "eb" is an error block that
1365 * you can use
1366 * to handle errors that may occur during Task object creation.
1367 *
1368 * The newly created task is placed in {@link #Mode_READY} mode, and is
1369 * scheduled to begin concurrent execution of the following function
1370 * call:
1371 *
1372 * @p(code)
1373 * (*fxn)(arg1, arg2);
1374 * @p
1375 *
1376 * As a result of being made ready to run, the task runs any
1377 * application-wide Ready functions that have been specified.
1378 *
1379 * Task_exit is automatically called if and when the task returns
1380 * from fxn.
1381 *
1382 * @p(html)
1383 * <B>Create Hook Functions</B>
1384 * @p
1385 *
1386 * You can specify application-wide Create hook functions in your config
1387 * file that run whenever a task is created. This includes tasks that
1388 * are created statically and those created dynamically using
1389 * Task_create.
1390 *
1391 * For Task objects created statically, Create functions are called
1392 * during the Task module initialization phase of the program startup
1393 * process prior to main().
1394 *
1395 * For Task objects created dynamically, Create functions
1396 * are called after the task handle has been initialized but before the
1397 * task has been placed on its ready queue.
1398 *
1399 * Any SYS/BIOS function can be called from Create functions.
1400 * SYS/BIOS passes the task handle of the task being created to each of
1401 * the Create functions.
1402 *
1403 * All Create function declarations should be similar to this:
1404 * @p(code)
1405 * Void myCreateFxn(Task_Handle task);
1406 * @p
1407 *
1408 * @param(fxn) Task Function
1409 *
1410 * @a(constraints)
1411 * @p(blist)
1412 * - The fxn parameter and the name attribute cannot be NULL.
1413 * - The priority attribute must be less than or equal to
1414 * ({@link #numPriorities} - 1) and greater than or equal to one (1)
1415 * (priority 0 is owned by the Idle task).
1416 * - The priority can be set to -1 for tasks that will not execute
1417 * until another task changes the priority to a positive value.
1418 * - The stackHeap attribute must identify a valid memory Heap.
1419 * @p
1420 */
1421 create(FuncPtr fxn);
1422
1423
1424
1425 /*! Task function argument. Default is 0 */
1426 config UArg arg0 = 0;
1427
1428 /*! Task function argument. Default is 0 */
1429 config UArg arg1 = 0;
1430
1431 /*!
1432 * Task priority (0 to Task.numPriorities-1, or -1).
1433 * Default is 1.
1434 */
1435 config Int priority = 1;
1436
1437 /*!
1438 * Task stack pointer. Default = null.
1439 *
1440 * Null indicates that the stack is to be allocated by create().
1441 *
1442 * Example: To statically initialize "tsk0"'s stack to a literal
1443 * address, use the following syntax:
1444 *
1445 * @p(code)
1446 * Program.global.tsk0.stack = $addr(literal);
1447 * @p
1448 *
1449 */
1450 config Ptr stack = null;
1451
1452 /*!
1453 * Task stack size in MAUs.
1454 *
1455 * The default value of 0 means that the module config
1456 * {@link #defaultStackSize} is used.
1457 */
1458 config SizeT stackSize = 0;
1459
1460 /*!
1461 * Mem section used for statically created task stacks.
1462 *
1463 * Default is inherited from module config defaultStackSection.
1464 */
1465 metaonly config String stackSection;
1466
1467 /*!
1468 * Mem heap used for dynamically created task stack.
1469 *
1470 * The default value of NULL means that the module config
1471 * {@link #defaultStackHeap} is used.
1472 */
1473 config IHeap.Handle stackHeap = null;
1474
1475 /*! Environment data struct. */
1476 config Ptr env = null;
1477
1478 /*!
1479 * Exit system immediately when the last task with this
1480 * flag set to TRUE has terminated.
1481 *
1482 * Default is true.
1483 */
1484 config Bool vitalTaskFlag = true;
1485
1486 /*!
1487 * The core which this task is to run on. Default is Task_AFFINITY_NONE
1488 *
1489 * If there is a compelling reason for a task to be pinned to a
1490 * particular core, then setting 'affinity' to the corresponding core
1491 * id will force the task to only be run on that core.
1492 *
1493 * The default affinity is inherited from {@link #defaultAffinity
1494 * Task.defaultAffinity}
1495 * which in turn defaults to {@link #AFFINITY_NONE Task_AFFINITY_NONE},
1496 * which means the task can be run on either core.
1497 *
1498 * Furthermore, Task_AFFINITY_NONE implies that the task can be moved
1499 * from core to core as deemed necessary by the Task scheduler in order
1500 * to keep the two highest priority ready tasks running simultaneously.
1501 */
1502 config UInt affinity;
1503
1504
1505
1506 /*!
1507 * @_nodoc
1508 * ======== getArg0 ========
1509 * Returns arg0 passed via params to create.
1510 *
1511 * @b(returns) task's arg0
1512 */
1513 UArg getArg0();
1514
1515 /*!
1516 * @_nodoc
1517 * ======== getArg1 ========
1518 * Returns arg1 passed via params to create.
1519 *
1520 * @b(returns) task's arg1
1521 */
1522 UArg getArg1();
1523
1524 /*!
1525 * ======== getEnv ========
1526 * Get task environment pointer.
1527 *
1528 * Task_getEnv returns the environment pointer of the specified task. The
1529 * environment pointer references an arbitrary application-defined data
1530 * structure.
1531 *
1532 * If your program uses multiple hook sets, {@link #getHookContext}
1533 * allows you to get environment pointers you have set for a particular
1534 * hook set and Task object combination.
1535 *
1536 * @b(returns) task environment pointer
1537 */
1538 Ptr getEnv();
1539
1540 /*!
1541 * ======== getFunc ========
1542 * Get Task function and arguments
1543 *
1544 * If either arg0 or arg1 is NULL, then the corresponding argument is not
1545 * returned.
1546 *
1547 * @param(arg0) pointer for returning Task's first function argument
1548 * @param(arg1) pointer for returning Task's second function argument
1549 *
1550 * @b(returns) Task function
1551 */
1552 FuncPtr getFunc(UArg *arg0, UArg *arg1);
1553
1554 /*!
1555 * ======== getHookContext ========
1556 * Get hook set's context for a task.
1557 *
1558 * For example, this C code gets the HookContext, prints it,
1559 * and sets a new value for the HookContext.
1560 *
1561 * @p(code)
1562 * Ptr pEnv;
1563 * Task_Handle myTask;
1564 * Int myHookSetId1;
1565 *
1566 * pEnv = Task_getHookContext(task, myHookSetId1);
1567 *
1568 * System_printf("myEnd1: pEnv = 0x%lx, time = %ld\n",
1569 * (ULong)pEnv, (ULong)Timestamp_get32());
1570 *
1571 * Task_setHookContext(task, myHookSetId1, (Ptr)0xc0de1);
1572 * @p
1573 *
1574 * See {@link #hookfunc Hook Functions} for more details.
1575 *
1576 * @param(id) hook set ID
1577 * @b(returns) hook set context for task
1578 */
1579 Ptr getHookContext(Int id);
1580
1581 /*!
1582 * ======== getPri ========
1583 * Get task priority.
1584 *
1585 * Task_getPri returns the priority of the referenced task.
1586 *
1587 * @b(returns) task priority
1588 */
1589 Int getPri();
1590
1591 /*!
1592 * @_nodoc
1593 * ======== setArg0 ========
1594 * Set arg0 (used primarily for legacy support)
1595 */
1596 Void setArg0(UArg arg);
1597
1598 /*!
1599 * @_nodoc
1600 * ======== setArg1 ========
1601 * Set arg1 (used primarily for legacy support)
1602 */
1603 Void setArg1(UArg arg);
1604
1605 /*!
1606 * ======== setEnv ========
1607 * Set task environment.
1608 *
1609 * Task_setEnv sets the task environment pointer to env. The
1610 * environment pointer references an arbitrary application-defined
1611 * data structure.
1612 *
1613 * If your program uses multiple hook sets, {@link #setHookContext}
1614 * allows you to set environment pointers for any
1615 * hook set and Task object combination.
1616 *
1617 * @param(env) task environment pointer
1618 */
1619 Void setEnv(Ptr env);
1620
1621 /*!
1622 * ======== setHookContext ========
1623 * Set hook instance's context for a task.
1624 *
1625 * For example, this C code gets the HookContext, prints it,
1626 * and sets a new value for the HookContext.
1627 *
1628 * @p(code)
1629 * Ptr pEnv;
1630 * Task_Handle myTask;
1631 * Int myHookSetId1;
1632 *
1633 * pEnv = Task_getHookContext(task, myHookSetId1);
1634 *
1635 * System_printf("myEnd1: pEnv = 0x%lx, time = %ld\n",
1636 * (ULong)pEnv, (ULong)Timestamp_get32());
1637 *
1638 * Task_setHookContext(task, myHookSetId1, (Ptr)0xc0de1);
1639 * @p
1640 *
1641 * See {@link #hookfunc Hook Functions} for more details.
1642 *
1643 * @param(id) hook set ID
1644 * @param(hookContext) value to write to context
1645 */
1646 Void setHookContext(Int id, Ptr hookContext);
1647
1648 /*!
1649 * ======== setPri ========
1650 * Set a task's priority
1651 *
1652 * Task_setpri sets the execution priority of task to newpri, and returns
1653 * that task's old priority value. Raising or lowering a task's priority
1654 * does not necessarily force preemption and re-scheduling of the caller:
1655 * tasks in the {@link #Mode_BLOCKED} mode remain suspended despite a
1656 * change in priority; and tasks in the {@link #Mode_READY} mode gain
1657 * control only if their new priority is greater than that of the
1658 * currently executing task.
1659 *
1660 * newpri should be set to a value greater than or equal to 1 and
1661 * less than or equal to ({@link #numPriorities} - 1). newpri can also
1662 * be set to -1 which puts the the task into the INACTIVE state and the
1663 * task will not run until its priority is raised at a later time by
1664 * another task. Priority 0 is reserved for the idle task.
1665 * If newpri equals ({@link #numPriorities} - 1), execution of the task
1666 * effectively locks out all other program activity, except for the
1667 * handling of interrupts.
1668 *
1669 * The current task can change its own priority (and possibly preempt its
1670 * execution) by passing the output of {@link #self} as the value of the
1671 * task parameter.
1672 *
1673 * A context switch occurs when calling Task_setpri if a currently
1674 * running task priority is set lower than the priority of another
1675 * currently ready task, or if another ready task is made to have a
1676 * higher priority than the currently running task.
1677 *
1678 * Task_setpri can be used for mutual exclusion.
1679 *
1680 * If a task's new priority is different than its previous priority,
1681 * then its relative placement in its new ready task priority
1682 * queue can be different than the one it was removed from. This can
1683 * effect the relative order in which it becomes the running task.
1684 *
1685 * The effected task is placed at the head of its new priority queue
1686 * if it is the currently running task. Otherwise it is placed at
1687 * at the end of its new task priority queue.
1688 *
1689 * @param(newpri) task's new priority
1690 * @b(returns) task's old priority
1691 *
1692 * @a(constraints)
1693 * newpri must be a value between 1 and ({@link #numPriorities} - 1) or -1.
1694 *
1695 * The task cannot be in the {@link #Mode_TERMINATED} mode.
1696 *
1697 * The new priority should not be zero (0). This priority level is
1698 * reserved for the Idle task.
1699 */
1700 UInt setPri(Int newpri);
1701
1702 /*!
1703 * ======== stat ========
1704 * Retrieve the status of a task.
1705 *
1706 * Task_stat retrieves attribute values and status information about a
1707 * task.
1708 *
1709 * Status information is returned through statbuf, which references a
1710 * structure of type {@link #Stat}.
1711 *
1712 * When a task is preempted by a software or hardware interrupt, the task
1713 * execution mode returned for that task by Task_stat is still
1714 * {@link #Mode_RUNNING} because the task runs when the preemption ends.
1715 *
1716 * The current task can inquire about itself by passing the output of
1717 * {@link #self} as the first argument to Task_stat. However, the task
1718 * stack pointer (sp) in the {@link #Stat} structure is the value from
1719 * the previous context switch.
1720 *
1721 * Task_stat has a non-deterministic execution time. As such, it is not
1722 * recommended to call this API from Swis or Hwis.
1723 *
1724 * @param(statbuf) pointer to task status structure
1725 *
1726 * @a(constraints)
1727 * statbuf cannot be NULL;
1728 */
1729 Void stat(Stat *statbuf);
1730
1731 /*!
1732 * ======== getMode ========
1733 * Retrieve the {@link #Mode} of a task.
1734 */
1735 Mode getMode();
1736
1737 /*!
1738 * ======== setAffinity ========
1739 * Set task's core affinity (should be used only in applications built
1740 * with {@link ti.sysbios.BIOS#smpEnabled} set to true)
1741 *
1742 * If the new core ID is different than the current core affinity
1743 * a reschedule will be performed immediately.
1744 *
1745 * @a(constraints)
1746 * Must NOT be called with interrupts disabled
1747 * (ie within a Hwi_disable()/Hwi_restore() block).
1748 *
1749 * Must NOT be called with tasking disabled
1750 * (ie within a Task_disable()/Task_restore() block).
1751 *
1752 * @b(returns) task's previous core affinity
1753 */
1754 UInt setAffinity(UInt coreId);
1755
1756 /*!
1757 * ======== getAffinity ========
1758 * Return task's core affinity (should be used only in applications built
1759 * with {@link ti.sysbios.BIOS#smpEnabled} set to true)
1760 *
1761 * @b(returns) task's current core affinity
1762 */
1763 UInt getAffinity();
1764
1765 /*!
1766 * @_nodoc
1767 * ======== block ========
1768 * Block a task.
1769 *
1770 * Remove a task from its ready list.
1771 * The effect of this API is manifest the next time the internal
1772 * Task scheduler is invoked.
1773 * This can be done directly by embedding the call within a
1774 * {@link #disable}/{@link #restore} block.
1775 * Otherwise, the effect will be manifest as a result of processing
1776 * the next dispatched interrupt, or by posting a Swi, or by falling
1777 * through the task function.
1778 *
1779 * @a(constraints)
1780 * If called from within a Hwi or a Swi, or main(), there is no need
1781 * to embed the call within a {@link #disable}/{@link #restore} block.
1782 */
1783 Void block();
1784
1785 /*!
1786 * @_nodoc
1787 * ======== unblock ========
1788 * Unblock a task.
1789 *
1790 * Place task in its ready list.
1791 * The effect of this API is manifest the next time the internal
1792 * Task scheduler is invoked.
1793 * This can be done directly by embedding the call within a
1794 * {@link #disable}/{@link #restore} block.
1795 * Otherwise, the effect will be manifest as a result of processing
1796 * the next dispatched interrupt, or by posting a Swi, or by falling
1797 * through the task function.
1798 *
1799 * @a(constraints)
1800 * If called from within a Hwi or a Swi, or main(), there is no need
1801 * to embed the call within a {@link #disable}/{@link #restore} block.
1802 */
1803 Void unblock();
1804
1805 /*!
1806 * @_nodoc
1807 * ======== blockI ========
1808 * Block a task.
1809 *
1810 * Remove a task from its ready list.
1811 * Must be called within Task_disable/Task_restore block
1812 * with interrupts disabled.
1813 * This API is meant to be used internally.
1814 */
1815 Void blockI();
1816
1817 /*!
1818 * @_nodoc
1819 * ======== unblockI ========
1820 * Unblock a task.
1821 *
1822 * Place task in its ready list.
1823 * Must be called within Task_disable/Task_restore block
1824 * with interrupts disabled.
1825 * This API is meant to be used internally.
1826 *
1827 * @param(hwiKey) key returned from Hwi_disable()
1828 */
1829 Void unblockI(UInt hwiKey);
1830
1831 internal:
1832
1833 /*! Target-specific support functions. */
1834 proxy SupportProxy inherits ti.sysbios.interfaces.ITaskSupport;
1835
1836 1837 1838 1839 1840 1841
1842 Void schedule();
1843
1844 1845 1846 1847
1848 Void enter();
1849
1850 1851 1852 1853
1854 Void sleepTimeout(UArg arg);
1855
1856 1857 1858 1859
1860 Int postInit(Object *task, Error.Block *eb);
1861
1862 1863 1864 1865 1866
1867 config UInt numConstructedTasks = 0;
1868
1869 1870 1871 1872
1873 Void allBlockedFunction();
1874
1875 1876 1877 1878 1879
1880 Void deleteTerminatedTasksFunc();
1881
1882 1883 1884 1885 1886
1887 Void processVitalTaskFlag(Object *task);
1888
1889 1890 1891 1892
1893 config Void (*startupHookFunc)(Void) = null;
1894
1895 1896 1897 1898
1899 struct PendElem {
1900 Queue.Elem qElem;
1901 Task.Handle task;
1902 Clock.Handle clock;
1903 };
1904
1905 struct Instance_State {
1906 Queue.Elem qElem;
1907 volatile Int priority;
1908 UInt mask;
1909 Ptr context;
1910
1911 Mode mode;
1912 PendElem *pendElem;
1913
1914 SizeT stackSize;
1915 Char stack[];
1916 IHeap.Handle stackHeap;
1917 FuncPtr fxn;
1918 UArg arg0;
1919 UArg arg1;
1920 Ptr env;
1921 Ptr hookEnv[];
1922 Bool vitalTaskFlag;
1923
1924 Queue.Handle readyQ;
1925 UInt curCoreId;
1926 UInt affinity;
1927
1928 };
1929
1930 struct Module_State {
1931 volatile Bool locked;
1932 volatile UInt curSet;
1933 Bool workFlag;
1934
1935
1936 UInt vitalTasks;
1937
1938 Handle curTask;
1939 Queue.Handle curQ;
1940 Queue.Object readyQ[];
1941
1942 volatile UInt smpCurSet[];
1943
1944
1945 volatile UInt smpCurMask[];
1946 Handle smpCurTask[];
1947 Queue.Handle smpReadyQ[];
1948
1949
1950
1951 Queue.Object inactiveQ;
1952 Queue.Object terminatedQ;
1953
1954 Handle idleTask[];
1955 Handle constructedTasks[];
1956
1957 };
1958
1959 struct RunQEntry {
1960 Queue.Elem elem;
1961 UInt coreId;
1962 Int priority;
1963 };
1964
1965 struct Module_StateSmp {
1966 Queue.Object *sortedRunQ;
1967
1968 volatile RunQEntry smpRunQ[];
1969
1970 };
1971 }