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