3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 * http://www.FreeRTOS.org
23 * http://aws.amazon.com/freertos
29 * Create a single persistent task which periodically dynamically creates another
30 * two tasks. The original task is called the creator task, the two tasks it
31 * creates are called suicidal tasks.
33 * One of the created suicidal tasks kill one other suicidal task before killing
34 * itself - leaving just the original task remaining.
36 * The creator task must be spawned after all of the other demo application tasks
37 * as it keeps a check on the number of tasks under the scheduler control. The
38 * number of tasks it expects to see running should never be greater than the
39 * number of tasks that were in existence when the creator task was spawned, plus
40 * one set of four suicidal tasks. If this number is exceeded an error is flagged.
42 * \page DeathC death.c
50 /* Scheduler include files. */
54 /* Demo program include files. */
57 #define deathSTACK_SIZE ( configMINIMAL_STACK_SIZE + 60 )
59 /* The task originally created which is responsible for periodically dynamically
60 * creating another four tasks. */
61 static portTASK_FUNCTION_PROTO( vCreateTasks, pvParameters );
63 /* The task function of the dynamically created tasks. */
64 static portTASK_FUNCTION_PROTO( vSuicidalTask, pvParameters );
66 /* A variable which is incremented every time the dynamic tasks are created. This
67 * is used to check that the task is still running. */
68 static volatile uint16_t usCreationCount = 0;
70 /* Used to store the number of tasks that were originally running so the creator
71 * task can tell if any of the suicidal tasks have failed to die.
73 static volatile UBaseType_t uxTasksRunningAtStart = 0;
75 /* When a task deletes itself, it stack and TCB are cleaned up by the Idle task.
76 * Under heavy load the idle task might not get much processing time, so it would
77 * be legitimate for several tasks to remain undeleted for a short period. There
78 * may also be a few other unexpected tasks if, for example, the tasks that test
79 * static allocation are also being used. */
80 static const UBaseType_t uxMaxNumberOfExtraTasksRunning = 3;
82 /* Used to store a handle to the task that should be killed by a suicidal task,
83 * before it kills itself. */
84 TaskHandle_t xCreatedTask;
86 /*-----------------------------------------------------------*/
88 void vCreateSuicidalTasks( UBaseType_t uxPriority )
90 xTaskCreate( vCreateTasks, "CREATOR", deathSTACK_SIZE, ( void * ) NULL, uxPriority, NULL );
92 /*-----------------------------------------------------------*/
94 static portTASK_FUNCTION( vSuicidalTask, pvParameters )
97 TaskHandle_t xTaskToKill;
98 const TickType_t xDelay = pdMS_TO_TICKS( ( TickType_t ) 200 );
100 /* Test deletion of a task's secure context, if any. */
101 portALLOCATE_SECURE_CONTEXT( configMINIMAL_SECURE_STACK_SIZE );
103 if( pvParameters != NULL )
105 /* This task is periodically created four times. Two created tasks are
106 * passed a handle to the other task so it can kill it before killing itself.
107 * The other task is passed in null. */
108 xTaskToKill = *( TaskHandle_t * ) pvParameters;
117 /* Do something random just to use some stack and registers. */
121 vTaskDelay( xDelay );
123 if( xTaskToKill != NULL )
125 /* Make sure the other task has a go before we delete it. */
126 vTaskDelay( ( TickType_t ) 0 );
128 /* Kill the other task that was created by vCreateTasks(). */
129 vTaskDelete( xTaskToKill );
131 /* Kill ourselves. */
135 } /*lint !e818 !e550 Function prototype must be as per standard for task functions. */
136 /*-----------------------------------------------------------*/
138 static portTASK_FUNCTION( vCreateTasks, pvParameters )
140 const TickType_t xDelay = pdMS_TO_TICKS( ( TickType_t ) 1000 );
141 UBaseType_t uxPriority;
143 /* Remove compiler warning about unused parameter. */
144 ( void ) pvParameters;
146 /* Delay at the start to ensure tasks created by other demos have been
147 * created before storing the current number of tasks. */
148 vTaskDelay( xDelay );
149 uxTasksRunningAtStart = ( UBaseType_t ) uxTaskGetNumberOfTasks();
151 uxPriority = uxTaskPriorityGet( NULL );
155 /* Just loop round, delaying then creating the four suicidal tasks. */
156 vTaskDelay( xDelay );
160 xTaskCreate( vSuicidalTask, "SUICID1", configMINIMAL_STACK_SIZE, NULL, uxPriority, &xCreatedTask );
161 xTaskCreate( vSuicidalTask, "SUICID2", configMINIMAL_STACK_SIZE, &xCreatedTask, uxPriority, NULL );
166 /*-----------------------------------------------------------*/
168 /* This is called to check that the creator task is still running and that there
169 * are not any more than four extra tasks. */
170 BaseType_t xIsCreateTaskStillRunning( void )
172 static uint16_t usLastCreationCount = 0xfff;
173 BaseType_t xReturn = pdTRUE;
174 static UBaseType_t uxTasksRunningNow;
176 if( usLastCreationCount == usCreationCount )
182 usLastCreationCount = usCreationCount;
185 uxTasksRunningNow = ( UBaseType_t ) uxTaskGetNumberOfTasks();
187 if( uxTasksRunningNow < uxTasksRunningAtStart )
191 else if( ( uxTasksRunningNow - uxTasksRunningAtStart ) > uxMaxNumberOfExtraTasksRunning )
197 /* Everything is okay. */