]> begriffs open source - freertos/blob - Demo/Common/Full/death.c
Update to V4.0.4. Add in STR912 port and demo.
[freertos] / Demo / Common / Full / death.c
1 /*\r
2         FreeRTOS.org V4.0.4 - Copyright (C) 2003-2006 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS.org distribution.\r
5 \r
6         FreeRTOS.org is free software; you can redistribute it and/or modify\r
7         it under the terms of the GNU General Public License as published by\r
8         the Free Software Foundation; either version 2 of the License, or\r
9         (at your option) any later version.\r
10 \r
11         FreeRTOS.org is distributed in the hope that it will be useful,\r
12         but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14         GNU General Public License for more details.\r
15 \r
16         You should have received a copy of the GNU General Public License\r
17         along with FreeRTOS.org; if not, write to the Free Software\r
18         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 \r
20         A special exception to the GPL can be applied should you wish to distribute\r
21         a combined work that includes FreeRTOS.org, without being obliged to provide\r
22         the source code for any proprietary components.  See the licensing section \r
23         of http://www.FreeRTOS.org for full details of how and when the exception\r
24         can be applied.\r
25 \r
26         ***************************************************************************\r
27         See http://www.FreeRTOS.org for documentation, latest information, license \r
28         and contact details.  Please ensure to read the configuration and relevant \r
29         port sections of the online documentation.\r
30         ***************************************************************************\r
31 */\r
32 \r
33 /**\r
34  * Create a single persistent task which periodically dynamically creates another \r
35  * four tasks.  The original task is called the creator task, the four tasks it \r
36  * creates are called suicidal tasks.\r
37  *\r
38  * Two of the created suicidal tasks kill one other suicidal task before killing \r
39  * themselves - leaving just the original task remaining.  \r
40  *\r
41  * The creator task must be spawned after all of the other demo application tasks \r
42  * as it keeps a check on the number of tasks under the scheduler control.  The \r
43  * number of tasks it expects to see running should never be greater than the \r
44  * number of tasks that were in existence when the creator task was spawned, plus \r
45  * one set of four suicidal tasks.  If this number is exceeded an error is flagged.\r
46  *\r
47  * \page DeathC death.c\r
48  * \ingroup DemoFiles\r
49  * <HR>\r
50  */\r
51 \r
52 /*\r
53 Changes from V2.0.0\r
54 \r
55         + Delay periods are now specified using variables and constants of\r
56           portTickType rather than unsigned portLONG.\r
57 */\r
58 \r
59 #include <stdlib.h>\r
60 \r
61 /* Scheduler include files. */\r
62 #include "FreeRTOS.h"\r
63 #include "task.h"\r
64 \r
65 /* Demo program include files. */\r
66 #include "death.h"\r
67 #include "print.h"\r
68 \r
69 #define deathSTACK_SIZE         ( ( unsigned portSHORT ) 512 )\r
70 \r
71 /* The task originally created which is responsible for periodically dynamically \r
72 creating another four tasks. */\r
73 static void vCreateTasks( void *pvParameters );\r
74 \r
75 /* The task function of the dynamically created tasks. */\r
76 static void vSuicidalTask( void *pvParameters );\r
77 \r
78 /* A variable which is incremented every time the dynamic tasks are created.  This \r
79 is used to check that the task is still running. */\r
80 static volatile portSHORT sCreationCount = 0;\r
81 \r
82 /* Used to store the number of tasks that were originally running so the creator \r
83 task can tell if any of the suicidal tasks have failed to die. */\r
84 static volatile unsigned portBASE_TYPE uxTasksRunningAtStart = 0;\r
85 static const unsigned portBASE_TYPE uxMaxNumberOfExtraTasksRunning = 5;\r
86 \r
87 /* Used to store a handle to the tasks that should be killed by a suicidal task, \r
88 before it kills itself. */\r
89 xTaskHandle xCreatedTask1, xCreatedTask2;\r
90 \r
91 /*-----------------------------------------------------------*/\r
92 \r
93 void vCreateSuicidalTasks( unsigned portBASE_TYPE uxPriority )\r
94 {\r
95 unsigned portBASE_TYPE *puxPriority;\r
96 \r
97         /* Create the Creator tasks - passing in as a parameter the priority at which \r
98         the suicidal tasks should be created. */\r
99         puxPriority = ( unsigned portBASE_TYPE * ) pvPortMalloc( sizeof( unsigned portBASE_TYPE ) );\r
100         *puxPriority = uxPriority;\r
101 \r
102         xTaskCreate( vCreateTasks, "CREATOR", deathSTACK_SIZE, ( void * ) puxPriority, uxPriority, NULL );\r
103 \r
104         /* Record the number of tasks that are running now so we know if any of the \r
105         suicidal tasks have failed to be killed. */\r
106         uxTasksRunningAtStart = uxTaskGetNumberOfTasks();\r
107 }\r
108 /*-----------------------------------------------------------*/\r
109 \r
110 static void vSuicidalTask( void *pvParameters )\r
111 {\r
112 portDOUBLE d1, d2;\r
113 xTaskHandle xTaskToKill;\r
114 const portTickType xDelay = ( portTickType ) 500 / portTICK_RATE_MS;\r
115 \r
116         if( pvParameters != NULL )\r
117         {\r
118                 /* This task is periodically created four times.  Tow created tasks are \r
119                 passed a handle to the other task so it can kill it before killing itself.  \r
120                 The other task is passed in null. */\r
121                 xTaskToKill = *( xTaskHandle* )pvParameters;\r
122         }\r
123         else\r
124         {\r
125                 xTaskToKill = NULL;\r
126         }\r
127 \r
128         for( ;; )\r
129         {\r
130                 /* Do something random just to use some stack and registers. */\r
131                 d1 = 2.4;\r
132                 d2 = 89.2;\r
133                 d2 *= d1;\r
134                 vTaskDelay( xDelay );\r
135 \r
136                 if( xTaskToKill != NULL )\r
137                 {\r
138                         /* Make sure the other task has a go before we delete it. */\r
139                         vTaskDelay( ( portTickType ) 0 );\r
140                         /* Kill the other task that was created by vCreateTasks(). */\r
141                         vTaskDelete( xTaskToKill );\r
142                         /* Kill ourselves. */\r
143                         vTaskDelete( NULL );\r
144                 }\r
145         }\r
146 }/*lint !e818 !e550 Function prototype must be as per standard for task functions. */\r
147 /*-----------------------------------------------------------*/\r
148 \r
149 static void vCreateTasks( void *pvParameters )\r
150 {\r
151 const portTickType xDelay = ( portTickType ) 1000 / portTICK_RATE_MS;\r
152 unsigned portBASE_TYPE uxPriority;\r
153 const portCHAR * const pcTaskStartMsg = "Create task started.\r\n";\r
154 \r
155         /* Queue a message for printing to say the task has started. */\r
156         vPrintDisplayMessage( &pcTaskStartMsg );\r
157 \r
158         uxPriority = *( unsigned portBASE_TYPE * ) pvParameters;\r
159         vPortFree( pvParameters );\r
160 \r
161         for( ;; )\r
162         {\r
163                 /* Just loop round, delaying then creating the four suicidal tasks. */\r
164                 vTaskDelay( xDelay );\r
165 \r
166                 xTaskCreate( vSuicidalTask, "SUICIDE1", deathSTACK_SIZE, NULL, uxPriority, &xCreatedTask1 );\r
167                 xTaskCreate( vSuicidalTask, "SUICIDE2", deathSTACK_SIZE, &xCreatedTask1, uxPriority, NULL );\r
168 \r
169                 xTaskCreate( vSuicidalTask, "SUICIDE1", deathSTACK_SIZE, NULL, uxPriority, &xCreatedTask2 );\r
170                 xTaskCreate( vSuicidalTask, "SUICIDE2", deathSTACK_SIZE, &xCreatedTask2, uxPriority, NULL );\r
171 \r
172                 ++sCreationCount;\r
173         }\r
174 }\r
175 /*-----------------------------------------------------------*/\r
176 \r
177 /* This is called to check that the creator task is still running and that there \r
178 are not any more than four extra tasks. */\r
179 portBASE_TYPE xIsCreateTaskStillRunning( void )\r
180 {\r
181 static portSHORT sLastCreationCount = 0;\r
182 portSHORT sReturn = pdTRUE;\r
183 unsigned portBASE_TYPE uxTasksRunningNow;\r
184 \r
185         if( sLastCreationCount == sCreationCount )\r
186         {\r
187                 sReturn = pdFALSE;\r
188         }\r
189         \r
190         uxTasksRunningNow = uxTaskGetNumberOfTasks();\r
191 \r
192         if( uxTasksRunningNow < uxTasksRunningAtStart )\r
193         {\r
194                 sReturn = pdFALSE;\r
195         }\r
196         else if( ( uxTasksRunningNow - uxTasksRunningAtStart ) > uxMaxNumberOfExtraTasksRunning )\r
197         {\r
198                 sReturn = pdFALSE;\r
199         }\r
200         else\r
201         {\r
202                 /* Everything is okay. */\r
203         }\r
204 \r
205         return sReturn;\r
206 }\r
207 \r
208 \r