#include "FreeRTOS.h"\r
#include "task.h"\r
\r
+/* Standard includes. */\r
+#include <stdio.h>\r
+\r
/* IoT SDK includes. */\r
#include "iot_taskpool.h"\r
\r
+/* The priority at which that tasks in the task pool (the worker tasks) get\r
+created. */\r
+#define tpTASK_POOL_WORKER_PRIORITY 1\r
+\r
/*\r
* Prototypes for the functions that demonstrate the task pool API.\r
*/\r
static void prvExample_BasicSingleJob( void );\r
+static void prvExample_DeferredSingleJob( void );\r
static void prvExample_BasicRecyclableJob( void );\r
+static void prvExample_ReuseRecyclableJobFromLowPriorityTask( void );\r
+static void prvExample_ReuseRecyclableJobFromHighPriorityTask( void );\r
\r
/* Prototypes of the callback functions used in the examples. */\r
static void prvSimpleTaskNotifyCallback( IotTaskPool_t pTaskPool, IotTaskPoolJob_t pJob, void *pUserContext );\r
/* Stack size for every task pool thread - in words, not bytes. */\r
configMINIMAL_STACK_SIZE,\r
/* Priority for every task pool thread. */\r
- tskIDLE_PRIORITY,\r
+ tpTASK_POOL_WORKER_PRIORITY,\r
};\r
\r
/*-----------------------------------------------------------*/\r
{\r
/* This example uses a single application task, which in turn is used to\r
create and send jobs to task pool tasks. */\r
- xTaskCreate( prvTaskPoolDemoTask,\r
- "PoolDemo",\r
- configMINIMAL_STACK_SIZE,\r
- NULL,\r
- tskIDLE_PRIORITY,\r
- NULL );\r
+ xTaskCreate( prvTaskPoolDemoTask, /* Function that implements the task. */\r
+ "PoolDemo", /* Text name for the task - only used for debugging. */\r
+ configMINIMAL_STACK_SIZE, /* Size of stack (in words, not bytes) to allocate for the task. */\r
+ NULL, /* Task parameter - not used in this case. */\r
+ tskIDLE_PRIORITY, /* Task priority, must be between 0 and configMAX_PRIORITIES - 1. */\r
+ NULL ); /* Used to pass out a handle to the created tsak - not used in this case. */\r
\r
vTaskStartScheduler();\r
\r
static void prvTaskPoolDemoTask( void *pvParameters )\r
{\r
IotTaskPoolError_t xResult;\r
+uint32_t ulLoops;\r
\r
/* Remove compiler warnings about unused parameters. */\r
( void ) pvParameters;\r
\r
/* The task pool must be created before it can be used. */\r
-// xResult = IotTaskPool_CreateSystemTaskPool( &xTaskPoolParameters );\r
-// configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+ xResult = IotTaskPool_CreateSystemTaskPool( &xTaskPoolParameters );\r
+ configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
\r
/* Attempting to create the task pool again should then appear to succeed\r
(in case it is initialised by more than one library), but have no effect. */\r
-// xResult = IotTaskPool_CreateSystemTaskPool( &xTaskPoolParameters );\r
-// configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+ xResult = IotTaskPool_CreateSystemTaskPool( &xTaskPoolParameters );\r
+ configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
\r
for( ;; )\r
{\r
- /* Run through each task pool example in turn. See the comments in the\r
- below functions for details of their behaviour. */\r
+ /* Demonstrate the most basic use case where a non persistent job is\r
+ created and scheduled to run immediately. The task pool worker tasks\r
+ (in which the job callback function executes) have a priority above the\r
+ priority of this task so the job's callback executes as soon as it is\r
+ scheduled. */\r
prvExample_BasicSingleJob();\r
+\r
+ /* Demonstrate a job being scheduled to run at some time in the\r
+ future, and how a job scheduled to run in the future can be cancelled if\r
+ it has not yet started executing. */\r
+ prvExample_DeferredSingleJob();\r
+\r
+ /* Demonstrate the most basic use of a recyclable job. This is similar\r
+ to prvExample_BasicSingleJob() but using a recyclable job. Creating a\r
+ recyclable job will re-use a previously created and now spare job from\r
+ the task pool's job cache if one is available, or otherwise dynamically\r
+ create a new job if a spare job is not available in the cache but space\r
+ remains in the cache. */\r
prvExample_BasicRecyclableJob();\r
\r
- vTaskDelete( NULL );\r
+ /* Demonstrate multiple recyclable jobs being created, used, and then\r
+ re-used. In this the task pool worker tasks (in which the job callback\r
+ functions execute) have a priority above the priority of this task so\r
+ the job's callback functions execute as soon as they are scheduled. */\r
+ prvExample_ReuseRecyclableJobFromLowPriorityTask();\r
+\r
+ /* Again demonstrate multiple recyclable jobs being used, but this time\r
+ the priority of the task pool worker tasks (in which the job callback\r
+ functions execute) are lower than the priority of this task so the job's\r
+ callback functions don't execute until this task enteres the blocked\r
+ state. */\r
+ prvExample_ReuseRecyclableJobFromHighPriorityTask();\r
+\r
+ ulLoops++;\r
+ if( ( ulLoops % 10UL ) == 0 )\r
+ {\r
+ printf( "Performed %u successful iterations.\r\n", ulLoops );\r
+ fflush( stdout );\r
+ }\r
}\r
}\r
/*-----------------------------------------------------------*/\r
IotTaskPoolJob_t xJob;\r
IotTaskPoolError_t xResult;\r
uint32_t ulReturn;\r
-const TickType_t xShortDelay = pdMS_TO_TICKS( 200 );\r
+const uint32_t ulNoFlags = 0UL;\r
+const TickType_t xNoDelay = ( TickType_t ) 0;\r
+size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize();\r
+IotTaskPoolJobStatus_t xJobStatus;\r
\r
- /* Ensure the notification count is 0 before scheduling the job. */\r
- while( ulTaskNotifyTake( pdTRUE, 0 ) != 0 );\r
+ /* Don't expect any notifications to be pending yet. */\r
+ configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 );\r
\r
/* Create and schedule a job using the handle of this task as the job's\r
context and the function that sends a notification to the task handle as\r
&xJob );\r
configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
\r
- xResult = IotTaskPool_ScheduleSystemJob( xJob, 0 );\r
+ /* The job has been created but not scheduled so is now ready. */\r
+ IotTaskPool_GetStatus( NULL, xJob, &xJobStatus );\r
+ configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_READY );\r
+\r
+ /* This is not a persistent (recyclable) job and its storage is on the\r
+ stack of this function, so the amount of heap space available should not\r
+ have chanced since entering this function. */\r
+ configASSERT( xFreeHeapBeforeCreatingJob == xPortGetFreeHeapSize() );\r
+\r
+ /* In the full task pool implementation the first parameter is used to\r
+ pass the handle of the task pool to schedule. The lean task pool\r
+ implementation used in this demo only supports a single task pool, which\r
+ is created internally within the library, so the first parameter is NULL. */\r
+ xResult = IotTaskPool_Schedule( NULL, xJob, ulNoFlags );\r
configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
\r
- /* Wait for the notification coming from the job's callback function. */\r
- ulReturn = ulTaskNotifyTake( pdTRUE, xShortDelay );\r
+ /* Look for the notification coming from the job's callback function. The\r
+ priority of the task pool worker task that executes the callback is higher\r
+ than the priority of this task so a block time is not needed - the task pool\r
+ worker task pre-empts this task and sends the notification (from the job's\r
+ callback) as soon as the job is scheduled. */\r
+ ulReturn = ulTaskNotifyTake( pdTRUE, xNoDelay );\r
configASSERT( ulReturn );\r
+\r
+ /* The job's callback has executed so the job has now completed. */\r
+ IotTaskPool_GetStatus( NULL, xJob, &xJobStatus );\r
+ configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_COMPLETED );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvExample_DeferredSingleJob( void )\r
+{\r
+IotTaskPoolJobStorage_t xJobStorage;\r
+IotTaskPoolJob_t xJob;\r
+IotTaskPoolError_t xResult;\r
+uint32_t ulReturn;\r
+const uint32_t ulShortDelay_ms = 100UL;\r
+const TickType_t xNoDelay = ( TickType_t ) 0, xAllowableMargin = ( TickType_t ) 5; /* Large margin for Windows port, which is not real time. */\r
+TickType_t xTimeBefore, xElapsedTime, xShortDelay_ticks;\r
+size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize();\r
+IotTaskPoolJobStatus_t xJobStatus;\r
+\r
+ /* Don't expect any notifications to be pending yet. */\r
+ configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 );\r
+\r
+ /* Create a job using the handle of this task as the job's context and the\r
+ function that sends a notification to the task handle as the jobs callback\r
+ function. The job is created using storage allocated on the stack of this\r
+ function - so no memory is allocated. */\r
+ xResult = IotTaskPool_CreateJob( prvSimpleTaskNotifyCallback, /* Callback function. */\r
+ ( void * ) xTaskGetCurrentTaskHandle(), /* Job context. */\r
+ &xJobStorage,\r
+ &xJob );\r
+ configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+ /* The job has been created but not scheduled so is now ready. */\r
+ IotTaskPool_GetStatus( NULL, xJob, &xJobStatus );\r
+ configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_READY );\r
+\r
+ /* This is not a persistent (recyclable) job and its storage is on the\r
+ stack of this function, so the amount of heap space available should not\r
+ have chanced since entering this function. */\r
+ configASSERT( xFreeHeapBeforeCreatingJob == xPortGetFreeHeapSize() );\r
+\r
+ /* Schedule the job to run its callback in xShortDelay_ms milliseconds time.\r
+ In the full task pool implementation the first parameter is used to pass the\r
+ handle of the task pool to schedule. The lean task pool implementation used\r
+ in this demo only supports a single task pool, which is created internally\r
+ within the library, so the first parameter is NULL. */\r
+ xResult = IotTaskPool_ScheduleDeferred( NULL, xJob, ulShortDelay_ms );\r
+ configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+ /* The scheduled job should not have executed yet, so don't expect any\r
+ notifications and expect the job's status to be 'deferred'. */\r
+ ulReturn = ulTaskNotifyTake( pdTRUE, xNoDelay );\r
+ configASSERT( ulReturn == 0 );\r
+ IotTaskPool_GetStatus( NULL, xJob, &xJobStatus );\r
+ configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_DEFERRED );\r
+\r
+ /* As the job has not yet been executed it can be stopped. */\r
+ xResult = IotTaskPool_TryCancel( NULL, xJob, &xJobStatus );\r
+ configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+ IotTaskPool_GetStatus( NULL, xJob, &xJobStatus );\r
+ configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_CANCELED );\r
+\r
+ /* Schedule the job again, and this time wait until its callback is\r
+ executed (the callback function sends a notification to this task) to see\r
+ that it executes at the right time. */\r
+ xTimeBefore = xTaskGetTickCount();\r
+ xResult = IotTaskPool_ScheduleDeferred( NULL, xJob, ulShortDelay_ms );\r
+ configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+ /* Wait twice the deferred execution time to ensure the callback is executed\r
+ before the call below times out. */\r
+ ulReturn = ulTaskNotifyTake( pdTRUE, pdMS_TO_TICKS( ulShortDelay_ms * 2UL ) );\r
+ xElapsedTime = xTaskGetTickCount() - xTimeBefore;\r
+\r
+ /* A single notification should not have been received... */\r
+ configASSERT( ulReturn == 1 );\r
+\r
+ /* ...and the time since scheduling the job should be greater than or\r
+ equal to the deferred execution time - which is converted to ticks for\r
+ comparison. */\r
+ xShortDelay_ticks = pdMS_TO_TICKS( ulShortDelay_ms );\r
+ configASSERT( ( xElapsedTime >= xShortDelay_ticks ) && ( xElapsedTime < ( xShortDelay_ticks + xAllowableMargin ) ) );\r
}\r
/*-----------------------------------------------------------*/\r
\r
IotTaskPoolJob_t xJob;\r
IotTaskPoolError_t xResult;\r
uint32_t ulReturn;\r
-const TickType_t xShortDelay = pdMS_TO_TICKS( 200 );\r
+const uint32_t ulNoFlags = 0UL;\r
+const TickType_t xNoDelay = ( TickType_t ) 0;\r
+size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize();\r
\r
- /* Ensure the notification count is 0 before scheduling the job. */\r
- while( ulTaskNotifyTake( pdTRUE, 0 ) != 0 );\r
+ /* Don't expect any notifications to be pending yet. */\r
+ configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 );\r
\r
/* Create and schedule a job using the handle of this task as the job's\r
context and the function that sends a notification to the task handle as\r
- the jobs callback function. The job is created as a recyclable job - so it\r
- is allocated inside the create function, but can then be used again and\r
- again. */\r
- xResult = IotTaskPool_CreateRecyclableSystemJob( prvSimpleTaskNotifyCallback,\r
- ( void * ) xTaskGetCurrentTaskHandle(),\r
- &xJob );\r
+ the jobs callback function. The job is created as a recyclable job and in\r
+ this case the memory used to hold the job status is allocated inside the\r
+ create function. As the job is persistent it can be used multiple times,\r
+ as demonstrated in other examples within this demo. In the full task pool\r
+ implementation the first parameter is used to pass the handle of the task\r
+ pool this recyclable job is to be associated with. In the lean\r
+ implementation of the task pool used by this demo there is only one task\r
+ pool (the system task pool created within the task pool library) so the\r
+ first parameter is NULL. */\r
+ xResult = IotTaskPool_CreateRecyclableJob( NULL,\r
+ prvSimpleTaskNotifyCallback,\r
+ (void * ) xTaskGetCurrentTaskHandle(),\r
+ &xJob );\r
configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
\r
- xResult = IotTaskPool_ScheduleSystemJob( xJob, 0 );\r
+ /* This recyclable job is persistent, and in this case created dynamically,\r
+ so expect there to be less heap space then when entering the function. */\r
+ configASSERT( xPortGetFreeHeapSize() < xFreeHeapBeforeCreatingJob );\r
+\r
+ /* In the full task pool implementation the first parameter is used to\r
+ pass the handle of the task pool to schedule. The lean task pool\r
+ implementation used in this demo only supports a single task pool, which\r
+ is created internally within the library, so the first parameter is NULL. */\r
+ xResult = IotTaskPool_Schedule( NULL, xJob, ulNoFlags );\r
configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
\r
- /* Wait for the notification coming from the job's callback function. */\r
- ulReturn = ulTaskNotifyTake( pdTRUE, xShortDelay );\r
+ /* Look for the notification coming from the job's callback function. The\r
+ priority of the task pool worker task that executes the callback is higher\r
+ than the priority of this task so a block time is not needed - the task pool\r
+ worker task pre-empts this task and sends the notification (from the job's\r
+ callback) as soon as the job is scheduled. */\r
+ ulReturn = ulTaskNotifyTake( pdTRUE, xNoDelay );\r
configASSERT( ulReturn );\r
+\r
+ /* Clean up recyclable job. In the full implementation of the task pool\r
+ the first parameter is used to pass a handle to the task pool the job is\r
+ associated with. In the lean implementation of the task pool used by this\r
+ demo there is only one task pool (the system task pool created in the\r
+ task pool library itself) so the first parameter is NULL. */\r
+ IotTaskPool_DestroyRecyclableJob( NULL, xJob );\r
+\r
+ /* Once the job has been deleted the memory used to hold the job is\r
+ returned, so the available heap should be exactly as when entering this\r
+ function. */\r
+ configASSERT( xPortGetFreeHeapSize() == xFreeHeapBeforeCreatingJob );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvExample_ReuseRecyclableJobFromLowPriorityTask( void )\r
+{\r
+IotTaskPoolError_t xResult;\r
+uint32_t x, xIndex, ulNotificationValue;\r
+const uint32_t ulJobsToCreate = 5UL, ulNoFlags = 0UL;\r
+IotTaskPoolJob_t xJobs[ ulJobsToCreate ];\r
+size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize();\r
+IotTaskPoolJobStatus_t xJobStatus;\r
+\r
+ /* Don't expect any notifications to be pending yet. */\r
+ configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 );\r
+\r
+ /* Create ulJobsToCreate jobs using the handle of this task as the job's\r
+ context and the function that sends a notification to the task handle as\r
+ the jobs callback function. The jobs are created as a recyclable job and\r
+ in this case the memory to store the job information is allocated within\r
+ the create function as at this time there are no recyclable jobs in the\r
+ task pool jobs cache. As the jobs are persistent they can be used multiple\r
+ times. In the full task pool implementation the first parameter is used to\r
+ pass the handle of the task pool this recyclable job is to be associated\r
+ with. In the lean implementation of the task pool used by this demo there\r
+ is only one task pool (the system task pool created within the task pool\r
+ library) so the first parameter is NULL. */\r
+ for( x = 0; x < ulJobsToCreate; x++ )\r
+ {\r
+ xResult = IotTaskPool_CreateRecyclableJob( NULL,\r
+ prvSimpleTaskNotifyCallback,\r
+ (void * ) xTaskGetCurrentTaskHandle(),\r
+ &( xJobs[ x ] ) );\r
+ configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+ /* The job has been created but not scheduled so is now ready. */\r
+ IotTaskPool_GetStatus( NULL, xJobs[ x ], &xJobStatus );\r
+ configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_READY );\r
+ }\r
+\r
+ /* Demonstrate that the jobs can be recycled by performing twice the number\r
+ of iterations of scheduling jobs than there actually are created jobs. This\r
+ works because the task pool task priorities are above the priority of this\r
+ task, so the tasks that run the jobs pre-empt this task as soon as a job is\r
+ ready. */\r
+ for( x = 0; x < ( ulJobsToCreate * 2UL ); x++ )\r
+ {\r
+ /* Make sure array index does not go out of bounds. */\r
+ xIndex = x % ulJobsToCreate;\r
+\r
+ xResult = IotTaskPool_Schedule( NULL, xJobs[ xIndex ], ulNoFlags );\r
+ configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+ /* The priority of the task pool task(s) is higher than the priority\r
+ of this task, so the job's callback function should have already\r
+ executed, sending a notification to this task, and incrementing this\r
+ task's notification value. */\r
+ xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */\r
+ 0UL, /* Don't clear any bits on exit. */\r
+ &ulNotificationValue, /* Obtain the notification value. */\r
+ 0UL ); /* No block time, return immediately. */\r
+ configASSERT( ulNotificationValue == ( x + 1 ) );\r
+\r
+ /* The job's callback has executed so the job is now completed. */\r
+ IotTaskPool_GetStatus( NULL, xJobs[ xIndex ], &xJobStatus );\r
+ configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_COMPLETED );\r
+\r
+ /* To leave the list of jobs empty we can stop re-creating jobs half\r
+ way through iterations of this loop. */\r
+ if( x < ulJobsToCreate )\r
+ {\r
+ /* Recycle the job so it can be used again. In the full task pool\r
+ implementation the first parameter is used to pass the handle of the\r
+ task pool this job will be associated with. In this lean task pool\r
+ implementation only the system task pool exists (the task pool created\r
+ internally to the task pool library) so the first parameter is just\r
+ passed as NULL. *//*_RB_ Why not recycle it automatically? */\r
+ IotTaskPool_RecycleJob( NULL, xJobs[ xIndex ] );\r
+ xResult = IotTaskPool_CreateRecyclableJob( NULL,\r
+ prvSimpleTaskNotifyCallback,\r
+ (void * ) xTaskGetCurrentTaskHandle(),\r
+ &( xJobs[ xIndex ] ) );\r
+ }\r
+ }\r
+\r
+ /* Clear all the notification value bits again. */\r
+ xTaskNotifyWait( portMAX_DELAY, /* Clear all bits on entry - portMAX_DELAY is used as it is a portable way of having all bits set. */\r
+ 0UL, /* Don't clear any bits on exit. */\r
+ NULL, /* Don't need the notification value this time. */\r
+ 0UL ); /* No block time, return immediately. */\r
+ configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 );\r
+\r
+ /* Clean up all the recyclable job. In the full implementation of the task\r
+ pool the first parameter is used to pass a handle to the task pool the job\r
+ is associated with. In the lean implementation of the task pool used by\r
+ this demo there is only one task pool (the system task pool created in the\r
+ task pool library itself) so the first parameter is NULL. */\r
+ for( x = 0; x < ulJobsToCreate; x++ )\r
+ {\r
+ xResult = IotTaskPool_DestroyRecyclableJob( NULL, xJobs[ x ] );\r
+ configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+ /* Attempting to destroy the same job twice will fail. */\r
+//_RB_ vPortFree() asserts because it attempts to free memory again. xResult = IotTaskPool_DestroyRecyclableJob( NULL, xJobs[ x ] );\r
+// configASSERT( xResult != IOT_TASKPOOL_SUCCESS );\r
+ }\r
+\r
+ /* Once the job has been deleted the memory used to hold the job is\r
+ returned, so the available heap should be exactly as when entering this\r
+ function. */\r
+ configASSERT( xPortGetFreeHeapSize() == xFreeHeapBeforeCreatingJob );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvExample_ReuseRecyclableJobFromHighPriorityTask( void )\r
+{\r
+IotTaskPoolError_t xResult;\r
+uint32_t x, ulNotificationValue;\r
+const uint32_t ulJobsToCreate = 5UL;\r
+const uint32_t ulNoFlags = 0UL;\r
+IotTaskPoolJob_t xJobs[ ulJobsToCreate ];\r
+IotTaskPoolJobStorage_t xJobStorage[ ulJobsToCreate ];\r
+size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize();\r
+TickType_t xShortDelay = pdMS_TO_TICKS( 150 );\r
+IotTaskPoolJobStatus_t xJobStatus;\r
+\r
+ /* Don't expect any notifications to be pending yet. */\r
+ configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 );\r
+\r
+ /* prvExample_ReuseRecyclableJobFromLowPriorityTask() executes in a task\r
+ that has a lower [task] priority than the task pool's worker tasks.\r
+ Therefore a talk pool worker preempts the task that calls\r
+ prvExample_ReuseRecyclableJobFromHighPriorityTask() as soon as the job is\r
+ scheduled. prvExample_ReuseRecyclableJobFromHighPriorityTask() reverses the\r
+ priorities - prvExample_ReuseRecyclableJobFromHighPriorityTask() raises its\r
+ priority to above the task pool's worker tasks, so the worker tasks do not\r
+ execute until the calling task enters the blocked state. First raise the\r
+ priority - passing NULL means raise the priority of the calling task. */\r
+ vTaskPrioritySet( NULL, tpTASK_POOL_WORKER_PRIORITY + 1 );\r
+\r
+ /* Create ulJobsToCreate jobs using the handle of this task as the job's\r
+ context and the function that sends a notification to the task handle as\r
+ the jobs callback function. */\r
+ for( x = 0; x < ulJobsToCreate; x++ )\r
+ {\r
+ xResult = IotTaskPool_CreateJob( prvSimpleTaskNotifyCallback, /* Callback function. */\r
+ ( void * ) xTaskGetCurrentTaskHandle(), /* Job context. */\r
+ &( xJobStorage[ x ] ),\r
+ &( xJobs[ x ] ) );\r
+ configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+ /* This is not a persistent (recyclable) job and its storage is on the\r
+ stack of this function, so the amount of heap space available should not\r
+ have chanced since entering this function. */\r
+ configASSERT( xFreeHeapBeforeCreatingJob == xPortGetFreeHeapSize() );\r
+ }\r
+\r
+ for( x = 0; x < ulJobsToCreate; x++ )\r
+ {\r
+ /* Schedule the next job. */\r
+ xResult = IotTaskPool_Schedule( NULL, xJobs[ x ], ulNoFlags );\r
+ configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+ /* Although scheduled, the job's callback has not executed, so the job\r
+ reports itself as scheduled. */\r
+ IotTaskPool_GetStatus( NULL, xJobs[ x ], &xJobStatus );\r
+ configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_SCHEDULED );\r
+\r
+ /* The priority of the task pool task(s) is lower than the priority\r
+ of this task, so the job's callback function should not have executed\r
+ yes, so don't expect the notification value for this task to have\r
+ changed. */\r
+ xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */\r
+ 0UL, /* Don't clear any bits on exit. */\r
+ &ulNotificationValue, /* Obtain the notification value. */\r
+ 0UL ); /* No block time, return immediately. */\r
+ configASSERT( ulNotificationValue == 0 );\r
+ }\r
+\r
+ /* At this point there are ulJobsToCreate scheduled, but none have executed\r
+ their callbacks because the priority of this task is higher than the\r
+ priority of the task pool worker threads. When this task blocks to wait for\r
+ a notification a worker thread will be able to executes - but as soon as its\r
+ callback function sends a notification to this task this task will\r
+ preempt it (because it has a higher priority) so this task only expects to\r
+ receive one notification at a time. */\r
+ for( x = 0; x < ulJobsToCreate; x++ )\r
+ {\r
+ xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */\r
+ 0UL, /* Don't clear any bits on exit. */\r
+ &ulNotificationValue, /* Obtain the notification value. */\r
+ xShortDelay ); /* Short delay to allow a task pool worker to execute. */\r
+ configASSERT( ulNotificationValue == ( x + 1 ) );\r
+ }\r
+\r
+ /* All the scheduled jobs have now executed, so waiting for another\r
+ notification should timeout without the notification value changing. */\r
+ xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */\r
+ 0UL, /* Don't clear any bits on exit. */\r
+ &ulNotificationValue, /* Obtain the notification value. */\r
+ xShortDelay ); /* Short delay to allow a task pool worker to execute. */\r
+ configASSERT( ulNotificationValue == x );\r
+\r
+ /* Reset the priority of this task and clear the notifications ready for the\r
+ next example. */\r
+ vTaskPrioritySet( NULL, tskIDLE_PRIORITY );\r
+ xTaskNotifyWait( portMAX_DELAY, /* Clear all bits on entry - portMAX_DELAY is used as it is a portable way of having all bits set. */\r
+ 0UL, /* Don't clear any bits on exit. */\r
+ NULL, /* Don't need the notification value this time. */\r
+ 0UL ); /* No block time, return immediately. */\r
}\r
/*-----------------------------------------------------------*/\r
\r
\r
taskENTER_CRITICAL();\r
{\r
+ printf( "Assert hit on line %lu of %s\r\n", ulLine, pcFileName );\r
+ fflush( stdout );\r
+\r
/* You can step out of this function to debug the assertion by using\r
the debugger to set ulSetToNonZeroInDebuggerToContinue to a non-zero\r
value. */\r
* - @functionname{taskpool_function_setmaxthreads}\r
* - @functionname{taskpool_function_createjob}\r
* - @functionname{taskpool_function_createrecyclablejob}\r
- * - @functionname{taskpool_function_createrecyclablesystemjob}\r
* - @functionname{taskpool_function_destroyrecyclablejob}\r
* - @functionname{taskpool_function_recyclejob}\r
* - @functionname{taskpool_function_schedule}\r
- * - @functionname{taskpool_function_schedulesystemjob}\r
* - @functionname{taskpool_function_scheduledeferred}\r
* - @functionname{taskpool_function_getstatus}\r
* - @functionname{taskpool_function_trycancel}\r
* @functionpage{IotTaskPool_SetMaxThreads,taskpool,setmaxthreads}\r
* @functionpage{IotTaskPool_CreateJob,taskpool,createjob}\r
* @functionpage{IotTaskPool_CreateRecyclableJob,taskpool,createrecyclablejob}\r
- * @functionpage{IotTaskPool_CreateRecyclableSystemJob,taskpool,createrecyclablesystemjob}\r
* @functionpage{IotTaskPool_DestroyRecyclableJob,taskpool,destroyrecyclablejob}\r
* @functionpage{IotTaskPool_RecycleJob,taskpool,recyclejob}\r
* @functionpage{IotTaskPool_Schedule,taskpool,schedule}\r
- * @functionpage{IotTaskPool_ScheduleSystemJob,taskpool,schedule}\r
* @functionpage{IotTaskPool_ScheduleDeferred,taskpool,scheduledeferred}\r
* @functionpage{IotTaskPool_GetStatus,taskpool,getstatus}\r
* @functionpage{IotTaskPool_TryCancel,taskpool,trycancel}\r
* This function should be called to destroy one instance of a task pool previously created with a call\r
* to @ref IotTaskPool_Create or @ref IotTaskPool_CreateSystemTaskPool.\r
* Calling this fuction release all underlying resources. After calling this function, any job scheduled but not yet executed\r
- * will be cancelled and destroyed.\r
+ * will be canceled and destroyed.\r
* The `taskPool` instance will no longer be valid after this function returns.\r
*\r
* @param[in] taskPool A handle to the task pool, e.g. as returned by a call to @ref IotTaskPool_Create or\r
* - #IOT_TASKPOOL_NO_MEMORY\r
* - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS\r
*\r
- * @note This function will not allocate memory.\r
+ * @note This function will not allocate memory. //_RB_ Incorrect comment.\r
*\r
* @warning A recyclable job should be recycled with a call to @ref IotTaskPool_RecycleJob rather than destroyed.\r
*\r
IotTaskPoolJob_t * const pJob );\r
/* @[declare_taskpool_createrecyclablejob] */\r
\r
-/**\r
- * brief Creates a job for the system task pool by allocating the job dynamically.\r
- * The system task pool is the task pool created by @ref IotTaskPool_CreateSystemTaskPool.\r
- *\r
- * A recyclable job does not need to be allocated twice, but it can rather be reused through\r
- * subsequent calls to @ref IotTaskPool_CreateRecyclableJob.\r
- *\r
- * @param[in] userCallback A user-specified callback for the job.\r
- * @param[in] pUserContext A user-specified context for the callback.\r
- * @param[out] pJob A pointer to an instance of @ref IotTaskPoolJob_t that will be initialized when this\r
- * function returns successfully. This handle can be used to inspect the job status with\r
- * @ref IotTaskPool_GetStatus or cancel the job with @ref IotTaskPool_TryCancel, etc....\r
- *\r
- * @return One of the following:\r
- * - #IOT_TASKPOOL_SUCCESS\r
- * - #IOT_TASKPOOL_BAD_PARAMETER\r
- * - #IOT_TASKPOOL_NO_MEMORY\r
- * - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS\r
- *\r
- * @note This function will not allocate memory.\r
- *\r
- * @warning A recyclable job should be recycled with a call to @ref IotTaskPool_RecycleJob rather than destroyed.\r
- *\r
- */\r
-/* @[declare_taskpool_createrecyclablesystemjob] */\r
-IotTaskPoolError_t IotTaskPool_CreateRecyclableSystemJob( IotTaskPoolRoutine_t userCallback,\r
- void * pUserContext,\r
- IotTaskPoolJob_t * const pJob );\r
-/* @[declare_taskpool_createrecyclablesystemjob] */\r
-\r
/**\r
* @brief This function un-initializes a job.\r
*\r
IotTaskPoolError_t IotTaskPool_Schedule( IotTaskPool_t taskPool,\r
IotTaskPoolJob_t job,\r
uint32_t flags );\r
-\r
-/**\r
- * @brief This function schedules a job created with @ref IotTaskPool_CreateJob or @ref IotTaskPool_CreateRecyclableJob @ref IotTaskPool_CreateRecyclableSystemJob\r
- * against the system task pool. The system task pool is the task pool created by @ref IotTaskPool_CreateSystemTaskPool.\r
- *\r
- * See @ref taskpool_design for a description of the jobs lifetime and interaction with the threads used in the task pool\r
- * library.\r
- *\r
- * @param[in] job A job to schedule for execution. This must be first initialized with a call to @ref IotTaskPool_CreateJob.\r
- * @param[in] flags Flags to be passed by the user, e.g. to identify the job as high priority by specifying #IOT_TASKPOOL_JOB_HIGH_PRIORITY.\r
- *\r
- * @return One of the following:\r
- * - #IOT_TASKPOOL_SUCCESS\r
- * - #IOT_TASKPOOL_BAD_PARAMETER\r
- * - #IOT_TASKPOOL_ILLEGAL_OPERATION\r
- * - #IOT_TASKPOOL_NO_MEMORY\r
- * - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS\r
- *\r
- *\r
- * @note This function will not allocate memory, so it is guaranteed to succeed if the parameters are correct and the task pool\r
- * was correctly initialized, and not yet destroyed.\r
- *\r
- * <b>Example</b>\r
- * @code{c}\r
- * // An example of a user context to pass to a callback through a task pool thread.\r
- * typedef struct JobUserContext\r
- * {\r
- * uint32_t counter;\r
- * } JobUserContext_t;\r
- *\r
- * // An example of a user callback to invoke through a task pool thread.\r
- * static void ExecutionCb( IotTaskPool_t taskPool, IotTaskPoolJob_t job, void * context )\r
- * {\r
- * ( void )taskPool;\r
- * ( void )job;\r
- *\r
- * JobUserContext_t * pUserContext = ( JobUserContext_t * )context;\r
- *\r
- * pUserContext->counter++;\r
- * }\r
- *\r
- * void TaskPoolExample( )\r
- * {\r
- * JobUserContext_t userContext = { 0 };\r
- * IotTaskPoolJob_t job;\r
- *\r
- * // Create the system task pool. This example assumes the task pool is created successfully.\r
- * // It is recommended to test the function's return value in production code.\r
- * IotTaskPool_CreateSystemTaskPool( &xTaskPoolParameters );\r
- *\r
- * // Statically allocate one job, schedule it.\r
- * IotTaskPool_CreateJob( &ExecutionCb, &userContext, &job );\r
- *\r
- * IotTaskPoolError_t errorSchedule = IotTaskPool_ScheduleSystemJob( &job, 0 );\r
- *\r
- * switch ( errorSchedule )\r
- * {\r
- * case IOT_TASKPOOL_SUCCESS:\r
- * break;\r
- * case IOT_TASKPOOL_BAD_PARAMETER: // Invalid parameters, such as a NULL handle, can trigger this error.\r
- * case IOT_TASKPOOL_ILLEGAL_OPERATION: // Scheduling a job that was previously scheduled or destroyed could trigger this error.\r
- * case IOT_TASKPOOL_NO_MEMORY: // Scheduling a with flag #IOT_TASKPOOL_JOB_HIGH_PRIORITY could trigger this error.\r
- * case IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS: // Scheduling a job after trying to destroy the task pool could trigger this error.\r
- * // ASSERT\r
- * break;\r
- * default:\r
- * // ASSERT\r
- * }\r
- *\r
- * //\r
- * // ... Perform other operations ...\r
- * //\r
- *\r
- * IotTaskPool_Destroy( taskPool );\r
- * }\r
- * @endcode\r
- */\r
-/* @[declare_taskpool_schedulesystemjob] */\r
-IotTaskPoolError_t IotTaskPool_ScheduleSystemJob( IotTaskPoolJob_t pJob,\r
- uint32_t flags );\r
-\r
-/* @[declare_taskpool_schedulesystemjob] */\r
+/* @[declare_taskpool_schedule] */\r
\r
/**\r
* @brief This function schedules a job created with @ref IotTaskPool_CreateJob against the task pool\r
\r
/* Standard includes. */\r
#include <stdbool.h>\r
+#include <stdio.h>\r
#include <stddef.h>\r
#include <stdint.h>\r
#include <string.h>\r
\r
/*-----------------------------------------------------------*/\r
\r
-IotTaskPoolError_t IotTaskPool_CreateRecyclableSystemJob( IotTaskPoolRoutine_t userCallback,\r
- void * pUserContext,\r
- IotTaskPoolJob_t * const pJob )\r
-{\r
- return IotTaskPool_CreateRecyclableJob ( &_IotSystemTaskPool, userCallback, pUserContext, pJob );\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
IotTaskPoolError_t IotTaskPool_CreateRecyclableJob( IotTaskPool_t taskPoolHandle,\r
IotTaskPoolRoutine_t userCallback,\r
void * pUserContext,\r
{\r
TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
\r
- _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;\r
+ _taskPool_t * const pTaskPool = &_IotSystemTaskPool;\r
_taskPoolJob_t * pTempJob = NULL;\r
\r
+ /* This lean version of the task pool only supports the task pool created\r
+ by this library (the system task pool). NULL means use the system task\r
+ pool - no other values are allowed. Use the full implementation of this\r
+ library if you want multiple task pools (there is more than one task in\r
+ each pool. */\r
+ configASSERT( ( taskPoolHandle == NULL ) || ( taskPoolHandle == &_IotSystemTaskPool ) );\r
+\r
+ /* Avoid compiler warnings about unused parameters if configASSERT() is not\r
+ defined. */\r
+ ( void ) taskPoolHandle;\r
+\r
/* Parameter checking. */\r
- TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );\r
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( userCallback );\r
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( ppJob );\r
\r
{\r
TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
\r
- ( void ) taskPoolHandle;\r
-\r
_taskPoolJob_t * pJob = ( _taskPoolJob_t * ) pJobHandle;\r
\r
+ /* This lean version of the task pool only supports the task pool created\r
+ by this library (the system task pool). NULL means use the system task\r
+ pool - no other values are allowed. Use the full implementation of this\r
+ library if you want multiple task pools (there is more than one task in\r
+ each pool. */\r
+#warning could use a TASKPOOL macro to check value and return error.\r
+ configASSERT( ( taskPoolHandle == NULL ) || ( taskPoolHandle == &_IotSystemTaskPool ) );\r
+\r
+ /* Avoid compiler warnings about unused parameters if configASSERT() is not\r
+ defined. */\r
+ ( void ) taskPoolHandle;\r
+\r
/* Parameter checking. */\r
- TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );\r
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJobHandle );\r
\r
IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) == false );\r
{\r
TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
\r
- _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;\r
+ _taskPool_t * pTaskPool = ( _taskPool_t * ) &_IotSystemTaskPool;\r
+\r
+ /* This lean version of the task pool only supports the task pool created\r
+ by this library (the system task pool). NULL means use the system task\r
+ pool - no other values are allowed. Use the full implementation of this\r
+ library if you want multiple task pools (there is more than one task in\r
+ each pool. */\r
+ configASSERT( ( taskPoolHandle == NULL ) || ( taskPoolHandle == &_IotSystemTaskPool ) );\r
+\r
+ /* Ensure unused parameters do not cause compiler warnings in case\r
+ configASSERT() is not defined. */\r
+ ( void ) taskPoolHandle;\r
\r
- /* Parameter checking. */\r
- TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );\r
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJob );\r
\r
taskENTER_CRITICAL();\r
{\r
TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
\r
- _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;\r
+ _taskPool_t * const pTaskPool = &_IotSystemTaskPool;\r
\r
+ /* Task pool must have been created. */\r
configASSERT( pTaskPool->running != false );\r
\r
+ /* This lean version of the task pool only supports the task pool created\r
+ by this library (the system task pool). NULL means use the system task\r
+ pool - no other values are allowed. Use the full implementation of this\r
+ library if you want multiple task pools (there is more than one task in\r
+ each pool. */\r
+ configASSERT( ( taskPoolHandle == NULL ) || ( taskPoolHandle == &_IotSystemTaskPool ) );\r
+\r
+ /* Avoid compiler warnings about unused parameters if configASSERT() is not\r
+ defined. */\r
+ ( void ) taskPoolHandle;\r
+\r
/* Parameter checking. */\r
- TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );\r
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJob );\r
TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( ( flags != 0UL ) && ( flags != IOT_TASKPOOL_JOB_HIGH_PRIORITY ) );\r
\r
\r
/*-----------------------------------------------------------*/\r
\r
-IotTaskPoolError_t IotTaskPool_ScheduleSystemJob( IotTaskPoolJob_t pJob,\r
- uint32_t flags )\r
-{\r
- return IotTaskPool_Schedule( &_IotSystemTaskPool, pJob, flags );\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
IotTaskPoolError_t IotTaskPool_ScheduleDeferred( IotTaskPool_t taskPoolHandle,\r
IotTaskPoolJob_t job,\r
uint32_t timeMs )\r
{\r
TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
\r
- _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;\r
+ _taskPool_t * pTaskPool = &_IotSystemTaskPool;\r
+\r
+ /* This lean version of the task pool only supports the task pool created\r
+ by this library (the system task pool). NULL means use the system task\r
+ pool - no other values are allowed. Use the full implementation of this\r
+ library if you want multiple task pools (there is more than one task in\r
+ each pool. */\r
+ configASSERT( ( taskPoolHandle == NULL ) || ( taskPoolHandle == &_IotSystemTaskPool ) );\r
\r
- /* Parameter checking. */\r
- TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );\r
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( job );\r
\r
if( timeMs == 0UL )\r
TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
\r
/* Parameter checking. */\r
- TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );\r
+//_RB_ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle ); /* What is the point of this parameter? */\r
+ ( void ) taskPoolHandle;\r
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( job );\r
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pStatus );\r
*pStatus = IOT_TASKPOOL_STATUS_UNDEFINED;\r
{\r
TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
\r
- _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;\r
+ _taskPool_t * pTaskPool = &_IotSystemTaskPool;\r
\r
- /* Parameter checking. */\r
- TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );\r
+ /* This lean version of the task pool only supports the task pool created\r
+ by this library (the system task pool). NULL means use the system task\r
+ pool - no other values are allowed. Use the full implementation of this\r
+ library if you want multiple task pools (there is more than one task in\r
+ each pool. */\r
+ configASSERT( ( taskPoolHandle == NULL ) || ( taskPoolHandle == &_IotSystemTaskPool ) );\r
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( job );\r
\r
if( pStatus != NULL )\r
\r
uint32_t count;\r
uint32_t threadsCreated;\r
+ char cTaskName[ 10 ];\r
\r
/* Check input values for consistency. */\r
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pTaskPool );\r
/* Create the minimum number of threads specified by the user, and if one fails shutdown and return error. */\r
for( threadsCreated = 0; threadsCreated < pInfo->minThreads; )\r
{\r
- TaskHandle_t task = NULL;\r
+ TaskHandle_t task = NULL; //_RB_ need to check compiles with C89\r
+\r
+ snprintf( cTaskName, sizeof( cTaskName ), "pool%d", ( int ) threadsCreated );\r
\r
BaseType_t res = xTaskCreate( _taskPoolWorker,\r
- NULL,\r
+ cTaskName,\r
pInfo->stackSize,\r
pTaskPool,\r
pInfo->priority,\r
pJob = IotLink_Container( _taskPoolJob_t, pFirst, link );\r
\r
/* Update status to 'executing'. */\r
- pJob->status = IOT_TASKPOOL_STATUS_COMPLETED;\r
+ pJob->status = IOT_TASKPOOL_STATUS_COMPLETED; /*_RB_ Should this be 'executing'? */\r
userCallback = pJob->userCallback;\r
}\r
}\r
_taskPoolJob_t * const pJob )\r
{\r
/* We should never try and recycling a job that is linked into some queue. */\r
- IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) == false );\r
+ IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) == false );//_RB_ Seems to be duplicate of test before this is called.\r
\r
/* We will recycle the job if there is space in the cache. */\r
if( pCache->freeCount < IOT_TASKPOOL_JOBS_RECYCLE_LIMIT )\r
/* Update the job status to 'scheduled'. */\r
pJob->status = IOT_TASKPOOL_STATUS_SCHEDULED;\r
\r
- BaseType_t higherPriorityTaskWoken;\r
-\r
/* Append the job to the dispatch queue. */\r
IotDeQueue_EnqueueTail( &pTaskPool->dispatchQueue, &pJob->link );\r
\r
/* Signal a worker to pick up the job. */\r
- ( void ) xSemaphoreGiveFromISR( pTaskPool->dispatchSignal, &higherPriorityTaskWoken );\r
-\r
- portYIELD_FROM_ISR( higherPriorityTaskWoken );\r
+ xSemaphoreGive( pTaskPool->dispatchSignal );\r
\r
TASKPOOL_NO_FUNCTION_CLEANUP_NOLABEL();\r
}\r
{\r
bool shouldReschedule = false;\r
\r
- /* If the job being cancelled was at the head of the timeouts queue, then we need to reschedule the timer\r
+ /* If the job being canceled was at the head of the timeouts queue, then we need to reschedule the timer\r
* with the next job timeout */\r
IotLink_t * pHeadLink = IotListDouble_PeekHead( &pTaskPool->timerEventsList );\r
\r