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