@@ -2191,6 +2191,7 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
2191
2191
{
2192
2192
TCB_t * pxTCB ;
2193
2193
BaseType_t xDeleteTCBInIdleTask = pdFALSE ;
2194
+ BaseType_t xTaskIsRunningOrYielding ;
2194
2195
2195
2196
traceENTER_vTaskDelete ( xTaskToDelete );
2196
2197
@@ -2226,10 +2227,15 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
2226
2227
* not return. */
2227
2228
uxTaskNumber ++ ;
2228
2229
2230
+ /* Use temp variable as distinct sequence points for reading volatile
2231
+ * variables prior to a logical operator to ensure compliance with
2232
+ * MISRA C 2012 Rule 13.5. */
2233
+ xTaskIsRunningOrYielding = taskTASK_IS_RUNNING_OR_SCHEDULED_TO_YIELD ( pxTCB );
2234
+
2229
2235
/* If the task is running (or yielding), we must add it to the
2230
2236
* termination list so that an idle task can delete it when it is
2231
2237
* no longer running. */
2232
- if ( ( xSchedulerRunning != pdFALSE ) && ( taskTASK_IS_RUNNING_OR_SCHEDULED_TO_YIELD ( pxTCB ) != pdFALSE ) )
2238
+ if ( ( xSchedulerRunning != pdFALSE ) && ( xTaskIsRunningOrYielding != pdFALSE ) )
2233
2239
{
2234
2240
/* A running task or a task which is scheduled to yield is being
2235
2241
* deleted. This cannot complete when the task is still running
@@ -2261,6 +2267,30 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
2261
2267
#else
2262
2268
portPRE_TASK_DELETE_HOOK ( pxTCB , & ( xYieldPendings [ pxTCB -> xTaskRunState ] ) );
2263
2269
#endif
2270
+
2271
+ /* In the case of SMP, it is possible that the task being deleted
2272
+ * is running on another core. We must evict the task before
2273
+ * exiting the critical section to ensure that the task cannot
2274
+ * take an action which puts it back on ready/state/event list,
2275
+ * thereby nullifying the delete operation. Once evicted, the
2276
+ * task won't be scheduled ever as it will no longer be on the
2277
+ * ready list. */
2278
+ #if ( configNUMBER_OF_CORES > 1 )
2279
+ {
2280
+ if ( taskTASK_IS_RUNNING ( pxTCB ) == pdTRUE )
2281
+ {
2282
+ if ( pxTCB -> xTaskRunState == ( BaseType_t ) portGET_CORE_ID () )
2283
+ {
2284
+ configASSERT ( uxSchedulerSuspended == 0 );
2285
+ taskYIELD_WITHIN_API ();
2286
+ }
2287
+ else
2288
+ {
2289
+ prvYieldCore ( pxTCB -> xTaskRunState );
2290
+ }
2291
+ }
2292
+ }
2293
+ #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
2264
2294
}
2265
2295
else
2266
2296
{
@@ -2284,9 +2314,9 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
2284
2314
2285
2315
/* Force a reschedule if it is the currently running task that has just
2286
2316
* been deleted. */
2287
- if ( xSchedulerRunning != pdFALSE )
2317
+ #if ( configNUMBER_OF_CORES == 1 )
2288
2318
{
2289
- #if ( configNUMBER_OF_CORES == 1 )
2319
+ if ( xSchedulerRunning != pdFALSE )
2290
2320
{
2291
2321
if ( pxTCB == pxCurrentTCB )
2292
2322
{
@@ -2298,30 +2328,8 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
2298
2328
mtCOVERAGE_TEST_MARKER ();
2299
2329
}
2300
2330
}
2301
- #else /* #if ( configNUMBER_OF_CORES == 1 ) */
2302
- {
2303
- /* It is important to use critical section here because
2304
- * checking run state of a task must be done inside a
2305
- * critical section. */
2306
- taskENTER_CRITICAL ();
2307
- {
2308
- if ( taskTASK_IS_RUNNING ( pxTCB ) == pdTRUE )
2309
- {
2310
- if ( pxTCB -> xTaskRunState == ( BaseType_t ) portGET_CORE_ID () )
2311
- {
2312
- configASSERT ( uxSchedulerSuspended == 0 );
2313
- taskYIELD_WITHIN_API ();
2314
- }
2315
- else
2316
- {
2317
- prvYieldCore ( pxTCB -> xTaskRunState );
2318
- }
2319
- }
2320
- }
2321
- taskEXIT_CRITICAL ();
2322
- }
2323
- #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
2324
2331
}
2332
+ #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
2325
2333
2326
2334
traceRETURN_vTaskDelete ();
2327
2335
}
@@ -3155,26 +3163,66 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
3155
3163
}
3156
3164
}
3157
3165
#endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
3158
- }
3159
- taskEXIT_CRITICAL ();
3160
3166
3161
- if ( xSchedulerRunning != pdFALSE )
3162
- {
3163
- /* Reset the next expected unblock time in case it referred to the
3164
- * task that is now in the Suspended state. */
3165
- taskENTER_CRITICAL ();
3167
+ /* In the case of SMP, it is possible that the task being suspended
3168
+ * is running on another core. We must evict the task before
3169
+ * exiting the critical section to ensure that the task cannot
3170
+ * take an action which puts it back on ready/state/event list,
3171
+ * thereby nullifying the suspend operation. Once evicted, the
3172
+ * task won't be scheduled before it is resumed as it will no longer
3173
+ * be on the ready list. */
3174
+ #if ( configNUMBER_OF_CORES > 1 )
3166
3175
{
3167
- prvResetNextTaskUnblockTime ();
3176
+ if ( xSchedulerRunning != pdFALSE )
3177
+ {
3178
+ /* Reset the next expected unblock time in case it referred to the
3179
+ * task that is now in the Suspended state. */
3180
+ prvResetNextTaskUnblockTime ();
3181
+
3182
+ if ( taskTASK_IS_RUNNING ( pxTCB ) == pdTRUE )
3183
+ {
3184
+ if ( pxTCB -> xTaskRunState == ( BaseType_t ) portGET_CORE_ID () )
3185
+ {
3186
+ /* The current task has just been suspended. */
3187
+ configASSERT ( uxSchedulerSuspended == 0 );
3188
+ vTaskYieldWithinAPI ();
3189
+ }
3190
+ else
3191
+ {
3192
+ prvYieldCore ( pxTCB -> xTaskRunState );
3193
+ }
3194
+ }
3195
+ else
3196
+ {
3197
+ mtCOVERAGE_TEST_MARKER ();
3198
+ }
3199
+ }
3200
+ else
3201
+ {
3202
+ mtCOVERAGE_TEST_MARKER ();
3203
+ }
3168
3204
}
3169
- taskEXIT_CRITICAL ();
3170
- }
3171
- else
3172
- {
3173
- mtCOVERAGE_TEST_MARKER ();
3205
+ #endif /* #if ( configNUMBER_OF_CORES > 1 ) */
3174
3206
}
3207
+ taskEXIT_CRITICAL ();
3175
3208
3176
3209
#if ( configNUMBER_OF_CORES == 1 )
3177
3210
{
3211
+ if ( xSchedulerRunning != pdFALSE )
3212
+ {
3213
+ /* Reset the next expected unblock time in case it referred to the
3214
+ * task that is now in the Suspended state. */
3215
+ taskENTER_CRITICAL ();
3216
+ {
3217
+ prvResetNextTaskUnblockTime ();
3218
+ }
3219
+ taskEXIT_CRITICAL ();
3220
+ }
3221
+ else
3222
+ {
3223
+ mtCOVERAGE_TEST_MARKER ();
3224
+ }
3225
+
3178
3226
if ( pxTCB == pxCurrentTCB )
3179
3227
{
3180
3228
if ( xSchedulerRunning != pdFALSE )
@@ -3207,43 +3255,6 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
3207
3255
mtCOVERAGE_TEST_MARKER ();
3208
3256
}
3209
3257
}
3210
- #else /* #if ( configNUMBER_OF_CORES == 1 ) */
3211
- {
3212
- /* Enter critical section here to check run state of a task. */
3213
- taskENTER_CRITICAL ();
3214
- {
3215
- if ( taskTASK_IS_RUNNING ( pxTCB ) == pdTRUE )
3216
- {
3217
- if ( xSchedulerRunning != pdFALSE )
3218
- {
3219
- if ( pxTCB -> xTaskRunState == ( BaseType_t ) portGET_CORE_ID () )
3220
- {
3221
- /* The current task has just been suspended. */
3222
- configASSERT ( uxSchedulerSuspended == 0 );
3223
- vTaskYieldWithinAPI ();
3224
- }
3225
- else
3226
- {
3227
- prvYieldCore ( pxTCB -> xTaskRunState );
3228
- }
3229
- }
3230
- else
3231
- {
3232
- /* This code path is not possible because only Idle tasks are
3233
- * assigned a core before the scheduler is started ( i.e.
3234
- * taskTASK_IS_RUNNING is only true for idle tasks before
3235
- * the scheduler is started ) and idle tasks cannot be
3236
- * suspended. */
3237
- mtCOVERAGE_TEST_MARKER ();
3238
- }
3239
- }
3240
- else
3241
- {
3242
- mtCOVERAGE_TEST_MARKER ();
3243
- }
3244
- }
3245
- taskEXIT_CRITICAL ();
3246
- }
3247
3258
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */
3248
3259
3249
3260
traceRETURN_vTaskSuspend ();
0 commit comments