]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/Full/death.c
7bc65f519195a755fef132df4a497ba6eb13a46a
[freertos] / FreeRTOS / Demo / Common / Full / death.c
1 /*\r
2  * FreeRTOS Kernel V10.2.1\r
3  * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://www.FreeRTOS.org\r
23  * http://aws.amazon.com/freertos\r
24  *\r
25  * 1 tab == 4 spaces!\r
26  */\r
27 \r
28 /**\r
29  * Create a single persistent task which periodically dynamically creates another \r
30  * four tasks.  The original task is called the creator task, the four tasks it \r
31  * creates are called suicidal tasks.\r
32  *\r
33  * Two of the created suicidal tasks kill one other suicidal task before killing \r
34  * themselves - leaving just the original task remaining.  \r
35  *\r
36  * The creator task must be spawned after all of the other demo application tasks \r
37  * as it keeps a check on the number of tasks under the scheduler control.  The \r
38  * number of tasks it expects to see running should never be greater than the \r
39  * number of tasks that were in existence when the creator task was spawned, plus \r
40  * one set of four suicidal tasks.  If this number is exceeded an error is flagged.\r
41  *\r
42  * \page DeathC death.c\r
43  * \ingroup DemoFiles\r
44  * <HR>\r
45  */\r
46 \r
47 /*\r
48 Changes from V2.0.0\r
49 \r
50         + Delay periods are now specified using variables and constants of\r
51           TickType_t rather than unsigned long.\r
52 */\r
53 \r
54 #include <stdlib.h>\r
55 \r
56 /* Scheduler include files. */\r
57 #include "FreeRTOS.h"\r
58 #include "task.h"\r
59 \r
60 /* Demo program include files. */\r
61 #include "death.h"\r
62 #include "print.h"\r
63 \r
64 #define deathSTACK_SIZE         ( ( unsigned short ) 512 )\r
65 \r
66 /* The task originally created which is responsible for periodically dynamically \r
67 creating another four tasks. */\r
68 static void vCreateTasks( void *pvParameters );\r
69 \r
70 /* The task function of the dynamically created tasks. */\r
71 static void vSuicidalTask( void *pvParameters );\r
72 \r
73 /* A variable which is incremented every time the dynamic tasks are created.  This \r
74 is used to check that the task is still running. */\r
75 static volatile short sCreationCount = 0;\r
76 \r
77 /* Used to store the number of tasks that were originally running so the creator \r
78 task can tell if any of the suicidal tasks have failed to die. */\r
79 static volatile unsigned portBASE_TYPE uxTasksRunningAtStart = 0;\r
80 static const unsigned portBASE_TYPE uxMaxNumberOfExtraTasksRunning = 5;\r
81 \r
82 /* Used to store a handle to the tasks that should be killed by a suicidal task, \r
83 before it kills itself. */\r
84 TaskHandle_t xCreatedTask1, xCreatedTask2;\r
85 \r
86 /*-----------------------------------------------------------*/\r
87 \r
88 void vCreateSuicidalTasks( unsigned portBASE_TYPE uxPriority )\r
89 {\r
90 unsigned portBASE_TYPE *puxPriority;\r
91 \r
92         /* Create the Creator tasks - passing in as a parameter the priority at which \r
93         the suicidal tasks should be created. */\r
94         puxPriority = ( unsigned portBASE_TYPE * ) pvPortMalloc( sizeof( unsigned portBASE_TYPE ) );\r
95         *puxPriority = uxPriority;\r
96 \r
97         xTaskCreate( vCreateTasks, "CREATOR", deathSTACK_SIZE, ( void * ) puxPriority, uxPriority, NULL );\r
98 \r
99         /* Record the number of tasks that are running now so we know if any of the \r
100         suicidal tasks have failed to be killed. */\r
101         uxTasksRunningAtStart = uxTaskGetNumberOfTasks();\r
102 }\r
103 /*-----------------------------------------------------------*/\r
104 \r
105 static void vSuicidalTask( void *pvParameters )\r
106 {\r
107 portDOUBLE d1, d2;\r
108 TaskHandle_t xTaskToKill;\r
109 const TickType_t xDelay = ( TickType_t ) 500 / portTICK_PERIOD_MS;\r
110 \r
111         if( pvParameters != NULL )\r
112         {\r
113                 /* This task is periodically created four times.  Tow created tasks are \r
114                 passed a handle to the other task so it can kill it before killing itself.  \r
115                 The other task is passed in null. */\r
116                 xTaskToKill = *( TaskHandle_t* )pvParameters;\r
117         }\r
118         else\r
119         {\r
120                 xTaskToKill = NULL;\r
121         }\r
122 \r
123         for( ;; )\r
124         {\r
125                 /* Do something random just to use some stack and registers. */\r
126                 d1 = 2.4;\r
127                 d2 = 89.2;\r
128                 d2 *= d1;\r
129                 vTaskDelay( xDelay );\r
130 \r
131                 if( xTaskToKill != NULL )\r
132                 {\r
133                         /* Make sure the other task has a go before we delete it. */\r
134                         vTaskDelay( ( TickType_t ) 0 );\r
135                         /* Kill the other task that was created by vCreateTasks(). */\r
136                         vTaskDelete( xTaskToKill );\r
137                         /* Kill ourselves. */\r
138                         vTaskDelete( NULL );\r
139                 }\r
140         }\r
141 }/*lint !e818 !e550 Function prototype must be as per standard for task functions. */\r
142 /*-----------------------------------------------------------*/\r
143 \r
144 static void vCreateTasks( void *pvParameters )\r
145 {\r
146 const TickType_t xDelay = ( TickType_t ) 1000 / portTICK_PERIOD_MS;\r
147 unsigned portBASE_TYPE uxPriority;\r
148 const char * const pcTaskStartMsg = "Create task started.\r\n";\r
149 \r
150         /* Queue a message for printing to say the task has started. */\r
151         vPrintDisplayMessage( &pcTaskStartMsg );\r
152 \r
153         uxPriority = *( unsigned portBASE_TYPE * ) pvParameters;\r
154         vPortFree( pvParameters );\r
155 \r
156         for( ;; )\r
157         {\r
158                 /* Just loop round, delaying then creating the four suicidal tasks. */\r
159                 vTaskDelay( xDelay );\r
160 \r
161                 xTaskCreate( vSuicidalTask, "SUICIDE1", deathSTACK_SIZE, NULL, uxPriority, &xCreatedTask1 );\r
162                 xTaskCreate( vSuicidalTask, "SUICIDE2", deathSTACK_SIZE, &xCreatedTask1, uxPriority, NULL );\r
163 \r
164                 xTaskCreate( vSuicidalTask, "SUICIDE1", deathSTACK_SIZE, NULL, uxPriority, &xCreatedTask2 );\r
165                 xTaskCreate( vSuicidalTask, "SUICIDE2", deathSTACK_SIZE, &xCreatedTask2, uxPriority, NULL );\r
166 \r
167                 ++sCreationCount;\r
168         }\r
169 }\r
170 /*-----------------------------------------------------------*/\r
171 \r
172 /* This is called to check that the creator task is still running and that there \r
173 are not any more than four extra tasks. */\r
174 portBASE_TYPE xIsCreateTaskStillRunning( void )\r
175 {\r
176 static short sLastCreationCount = 0;\r
177 short sReturn = pdTRUE;\r
178 unsigned portBASE_TYPE uxTasksRunningNow;\r
179 \r
180         if( sLastCreationCount == sCreationCount )\r
181         {\r
182                 sReturn = pdFALSE;\r
183         }\r
184         \r
185         uxTasksRunningNow = uxTaskGetNumberOfTasks();\r
186 \r
187         if( uxTasksRunningNow < uxTasksRunningAtStart )\r
188         {\r
189                 sReturn = pdFALSE;\r
190         }\r
191         else if( ( uxTasksRunningNow - uxTasksRunningAtStart ) > uxMaxNumberOfExtraTasksRunning )\r
192         {\r
193                 sReturn = pdFALSE;\r
194         }\r
195         else\r
196         {\r
197                 /* Everything is okay. */\r
198         }\r
199 \r
200         return sReturn;\r
201 }\r
202 \r
203 \r