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