created. */\r
#define tpTASK_POOL_WORKER_PRIORITY 1\r
\r
-/* The number of jobs created in the example functions that create more than\r
-one job. */\r
-#define tpJOBS_TO_CREATE 5\r
-\r
/*\r
* Prototypes for the functions that demonstrate the task pool API.\r
* See the implementation of the prvTaskPoolDemoTask() function within this file\r
/*-----------------------------------------------------------*/\r
\r
/* Parameters used to create the system task pool - see TBD for more information\r
-as the task pool used in this example is a slimmed down version of the full\r
-library - the slimmed down version being intended specifically for FreeRTOS\r
-kernel use cases. */\r
+ * as the task pool used in this example is a slimmed down version of the full\r
+ * library - the slimmed down version being intended specifically for FreeRTOS\r
+ * kernel use cases. */\r
static const IotTaskPoolInfo_t xTaskPoolParameters = {\r
/* Minimum number of threads in a task pool.\r
- Note the slimmed down version of the task\r
- pool used by this library does not autoscale\r
- the number of tasks in the pool so in this\r
- case this sets the number of tasks in the\r
- pool. */\r
+ * Note the slimmed down version of the task\r
+ * pool used by this library does not autoscale\r
+ * the number of tasks in the pool so in this\r
+ * case this sets the number of tasks in the\r
+ * pool. */\r
2,\r
/* Maximum number of threads in a task pool.\r
- Note the slimmed down version of the task\r
- pool used by this library does not autoscale\r
- the number of tasks in the pool so in this\r
- case this parameter is just ignored. */\r
+ * Note the slimmed down version of the task\r
+ * pool used by this library does not autoscale\r
+ * the number of tasks in the pool so in this\r
+ * case this parameter is just ignored. */\r
2,\r
/* Stack size for every task pool thread - in\r
- bytes, hence multiplying by the number of bytes\r
- in a word as configMINIMAL_STACK_SIZE is\r
- specified in words. */\r
+ * bytes, hence multiplying by the number of bytes\r
+ * in a word as configMINIMAL_STACK_SIZE is\r
+ * specified in words. */\r
configMINIMAL_STACK_SIZE * sizeof( portSTACK_TYPE ),\r
/* Priority for every task pool thread. */\r
tpTASK_POOL_WORKER_PRIORITY,\r
void vStartSimpleTaskPoolDemo( void )\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
+ * create and send jobs to task pool tasks. */\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
+ NULL ); /* Used to pass out a handle to the created task - not used in this case. */\r
}\r
/*-----------------------------------------------------------*/\r
\r
( void ) pvParameters;\r
\r
/* The task pool must be created before it can be used. The system task\r
- pool is the task pool managed by the task pool library itself - the storage\r
- used by the task pool is provided by the library. */\r
+ * pool is the task pool managed by the task pool library itself - the storage\r
+ * used by the task pool is provided by the library. */\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
+ * (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
\r
for( ;; )\r
{\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
+ * 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
+ * future, and how a job scheduled to run in the future can be cancelled\r
+ * if it has not yet started executing. */\r
prvExample_DeferredJobAndCancellingJobs();\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
+ * 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
- /* 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
+ /* Demonstrate a recyclable job being created, used, and then re-used.\r
+ * 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
+ /* Again demonstrate a recyclable job being created, used, and then\r
+ * re-usedbut this time the priority of the task pool worker tasks (in\r
+ * which the job callback functions execute) are lower than the priority\r
+ * of this task so the job's callback functions don't execute until this\r
+ * task enters the blocked state. */\r
prvExample_ReuseRecyclableJobFromHighPriorityTask();\r
\r
ulLoops++;\r
static void prvSimpleTaskNotifyCallback( IotTaskPool_t pTaskPool, IotTaskPoolJob_t pJob, void *pUserContext )\r
{\r
/* The jobs context is the handle of the task to which a notification should\r
-be sent. */\r
+ * be sent. */\r
TaskHandle_t xTaskToNotify = ( TaskHandle_t ) pUserContext;\r
\r
/* Remove warnings about unused parameters. */\r
IotTaskPoolJobStatus_t xJobStatus;\r
\r
/* Don't expect any notifications to be pending yet. */\r
- configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 );\r
+ configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 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. This is not a recyclable job so the storage\r
- required to hold information about the job is provided by this task - in\r
- this case the storage is on the stack of this task so no memory is allocated\r
- dynamically but the stack frame must remain in scope for the lifetime of\r
- the job. */\r
+ * context and the function that sends a notification to the task handle as\r
+ * the job's callback function. This is not a recyclable job so the storage\r
+ * required to hold information about the job is provided by this task - in\r
+ * this case the storage is on the stack of this task so no memory is allocated\r
+ * dynamically but the stack frame must remain in scope for the lifetime of\r
+ * the job. */\r
xResult = IotTaskPool_CreateJob( prvSimpleTaskNotifyCallback, /* Callback function. */\r
( void * ) xTaskGetCurrentTaskHandle(), /* Job context. */\r
&xJobStorage,\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
+ * stack of this function, so the amount of heap space available should not\r
+ * have changed 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
+ * 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
/* 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
+ * 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 preempts 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
IotTaskPoolJobStatus_t xJobStatus;\r
\r
/* Don't expect any notifications to be pending yet. */\r
- configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 );\r
+ configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 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
+ * function that sends a notification to the task handle as the job's 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
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
+ * stack of this function, so the amount of heap space available should not\r
+ * have changed 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
+ /* Schedule the job to run its callback in ulShortDelay_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
+ * 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
+ /* As the job has not yet been executed it can be cancelled. */\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
+ * 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
+ * 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
+ /* A single notification should 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
+ * 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
size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize();\r
\r
/* Don't expect any notifications to be pending yet. */\r
- configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 );\r
+ configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 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 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
+ * context and the function that sends a notification to the task handle as\r
+ * the job's 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
configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
\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
+ * so expect there to be less heap space than 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
+ * 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
/* 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
+ * 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 preempts 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
+ * 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
+ * returned, so the available heap should be exactly as when entering this\r
+ * function. */\r
configASSERT( xPortGetFreeHeapSize() == xFreeHeapBeforeCreatingJob );\r
}\r
/*-----------------------------------------------------------*/\r
static void prvExample_ReuseRecyclableJobFromLowPriorityTask( void )\r
{\r
IotTaskPoolError_t xResult;\r
-uint32_t x, xIndex, ulNotificationValue;\r
+uint32_t ulNotificationValue;\r
const uint32_t ulNoFlags = 0UL;\r
-IotTaskPoolJob_t xJobs[ tpJOBS_TO_CREATE ];\r
-size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize();\r
+const TickType_t xNoDelay = ( TickType_t ) 0;\r
+IotTaskPoolJob_t xJob, xJobRecycled;\r
+size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize(), xFreeHeapAfterCreatingJob = 0;\r
IotTaskPoolJobStatus_t xJobStatus;\r
\r
/* Don't expect any notifications to be pending yet. */\r
- configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 );\r
-\r
- /* Create tpJOBS_TO_CREATE 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 < tpJOBS_TO_CREATE; 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
+ configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 0 );\r
+\r
+ /* Create a recycleable 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 job's callback function. In the full task pool implementation the\r
+ * first parameter is used to pass the handle of the task pool this\r
+ * recyclable job is to be associated with. In the lean implementation of\r
+ * the task pool used by this demo there is only one task pool (the system\r
+ * task pool created within the task pool library) so the first parameter is\r
+ * NULL. */\r
+ xResult = IotTaskPool_CreateRecyclableJob( NULL,\r
+ prvSimpleTaskNotifyCallback,\r
+ (void * ) xTaskGetCurrentTaskHandle(),\r
+ &( xJob ) );\r
+ configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\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 < ( tpJOBS_TO_CREATE * 2UL ); x++ )\r
- {\r
- /* Make sure array index does not go out of bounds. */\r
- xIndex = x % tpJOBS_TO_CREATE;\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 < tpJOBS_TO_CREATE )\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
- configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
- }\r
- }\r
+ /* The job is created as a recyclable job and in this case the memory to\r
+ * store the job information is allocated within the create function as at\r
+ * this time there are no recyclable jobs in the task pool jobs cache. So\r
+ * expect there to be less heap space than when entering the function. */\r
+ xFreeHeapAfterCreatingJob = xPortGetFreeHeapSize();\r
+ configASSERT( xFreeHeapAfterCreatingJob < xFreeHeapBeforeCreatingJob );\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
+ /* 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
+ /* 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
+ xNoDelay ); /* No block time, return immediately. */\r
+ configASSERT( ulNotificationValue == 1 );\r
+\r
+ /* The job's callback has executed so the job is now completed. */\r
+ IotTaskPool_GetStatus( NULL, xJob, &xJobStatus );\r
+ configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_COMPLETED );\r
\r
- /* Clear all the notification value bits again. */\r
+ /* Return the job to the task pool's job cache. */\r
+ IotTaskPool_RecycleJob( NULL, xJob );\r
+\r
+ /* Create a recycleable job again 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 job's callback function. In the full task pool implementation the\r
+ * first parameter is used to pass the handle of the task pool this\r
+ * recyclable job is to be associated with. In the lean implementation of\r
+ * the task pool used by this demo there is only one task pool (the system\r
+ * task pool created within the task pool library) so the first parameter is\r
+ * NULL. */\r
+ xResult = IotTaskPool_CreateRecyclableJob( NULL,\r
+ prvSimpleTaskNotifyCallback,\r
+ (void * ) xTaskGetCurrentTaskHandle(),\r
+ &( xJobRecycled ) );\r
+ configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+ /* Since this time the task pool's job cache had a recycleable job, it must\r
+ * have been re-used. Thefore expect the free heap space to be same as after\r
+ * the creation of first job */\r
+ configASSERT( xPortGetFreeHeapSize() == xFreeHeapAfterCreatingJob );\r
+\r
+ /* Expect the task pool to re-use the job in its cache as opposed to\r
+ * allocating a new one. */\r
+ configASSERT( xJobRecycled == xJob );\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, xJobRecycled, 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
+ xNoDelay ); /* No block time, return immediately. */\r
+ configASSERT( ulNotificationValue == 2 );\r
+\r
+ /* The job's callback has executed so the job is now completed. */\r
+ IotTaskPool_GetStatus( NULL, xJobRecycled, &xJobStatus );\r
+ configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_COMPLETED );\r
+\r
+ /* Clean up 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
+ xResult = IotTaskPool_DestroyRecyclableJob( NULL, xJobRecycled );\r
+ configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+ /* Clear all the notification value bits ready for the next example. */\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 < tpJOBS_TO_CREATE; x++ )\r
- {\r
- xResult = IotTaskPool_DestroyRecyclableJob( NULL, xJobs[ x ] );\r
- configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
- }\r
+ xNoDelay ); /* No block time, return immediately. */\r
+ configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 0 );\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
+ * returned, so the available heap should be exactly as when entering this\r
+ * function. */\r
configASSERT( xPortGetFreeHeapSize() == xFreeHeapBeforeCreatingJob );\r
}\r
/*-----------------------------------------------------------*/\r
static void prvExample_ReuseRecyclableJobFromHighPriorityTask( void )\r
{\r
IotTaskPoolError_t xResult;\r
-uint32_t x, ulNotificationValue;\r
+uint32_t ulNotificationValue;\r
const uint32_t ulNoFlags = 0UL;\r
-IotTaskPoolJob_t xJobs[ tpJOBS_TO_CREATE ];\r
-IotTaskPoolJobStorage_t xJobStorage[ tpJOBS_TO_CREATE ];\r
-size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize();\r
+const TickType_t xNoDelay = ( TickType_t ) 0;\r
TickType_t xShortDelay = pdMS_TO_TICKS( 150 );\r
+IotTaskPoolJob_t xJob, xJobRecycled;\r
+size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize(), xFreeHeapAfterCreatingJob = 0;\r
IotTaskPoolJobStatus_t xJobStatus;\r
\r
/* Don't expect any notifications to be pending yet. */\r
- configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 );\r
+ configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 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
+ * that has a lower [task] priority than the task pool's worker tasks.\r
+ * Therefore a task 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 tpJOBS_TO_CREATE 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 < tpJOBS_TO_CREATE; 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
+ /* Create a recycleable 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 job's callback function. In the full task pool implementation the\r
+ * first parameter is used to pass the handle of the task pool this\r
+ * recyclable job is to be associated with. In the lean implementation of\r
+ * the task pool used by this demo there is only one task pool (the system\r
+ * task pool created within the task pool library) so the first parameter is\r
+ * NULL. */\r
+ xResult = IotTaskPool_CreateRecyclableJob( NULL,\r
+ prvSimpleTaskNotifyCallback,\r
+ (void * ) xTaskGetCurrentTaskHandle(),\r
+ &( xJob ) );\r
+ configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
\r
- for( x = 0; x < tpJOBS_TO_CREATE; 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
+ /* The job is created as a recyclable job and in this case the memory to\r
+ * store the job information is allocated within the create function as at\r
+ * this time there are no recyclable jobs in the task pool jobs cache. So\r
+ * expect there to be less heap space than when entering the function. */\r
+ xFreeHeapAfterCreatingJob = xPortGetFreeHeapSize();\r
+ configASSERT( xFreeHeapAfterCreatingJob < xFreeHeapBeforeCreatingJob );\r
\r
- /* At this point there are tpJOBS_TO_CREATE 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 < tpJOBS_TO_CREATE; 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
+ /* 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
+ /* 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
+ /* 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
+ * yet, 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
+ xNoDelay ); /* No block time, return immediately. */\r
+ configASSERT( ulNotificationValue == 0 );\r
+\r
+ /* When this task blocks to wait for a notification, a worker thread will be\r
+ * able to execute - but as soon as its callback function sends a\r
+ * notification to this task, this task will preempt it (because it has a\r
+ * higher priority). So this task expects to receive one notification. */\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 == 1 );\r
+\r
+ /* Since the scheduled job has 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 == 1 );\r
+\r
+ /* The job's callback has executed so the job is now completed. */\r
+ IotTaskPool_GetStatus( NULL, xJob, &xJobStatus );\r
+ configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_COMPLETED );\r
\r
- /* All the scheduled jobs have now executed, so waiting for another\r
- notification should timeout without the notification value changing. */\r
+ /* Return the job to the task pool's job cache. */\r
+ IotTaskPool_RecycleJob( NULL, xJob );\r
+\r
+ /* Create a recycleable job again 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 job's callback function. In the full task pool implementation the\r
+ * first parameter is used to pass the handle of the task pool this\r
+ * recyclable job is to be associated with. In the lean implementation of\r
+ * the task pool used by this demo there is only one task pool (the system\r
+ * task pool created within the task pool library) so the first parameter is\r
+ * NULL. */\r
+ xResult = IotTaskPool_CreateRecyclableJob( NULL,\r
+ prvSimpleTaskNotifyCallback,\r
+ (void * ) xTaskGetCurrentTaskHandle(),\r
+ &( xJobRecycled ) );\r
+ configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+ /* Since this time the task pool's job cache had a recycleable job, it must\r
+ * have been re-used. Thefore expect the free heap space to be same as after\r
+ * the creation of first job */\r
+ configASSERT( xPortGetFreeHeapSize() == xFreeHeapAfterCreatingJob );\r
+\r
+ /* Expect the task pool to re-use the job in its cache as opposed to\r
+ * allocating a new one. */\r
+ configASSERT( xJobRecycled == xJob );\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, xJobRecycled, ulNoFlags );\r
+ configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\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
+ * yet, 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
+ xNoDelay ); /* No block time, return immediately. */\r
+ configASSERT( ulNotificationValue == 1 );\r
+\r
+ /* When this task blocks to wait for a notification, a worker thread will be\r
+ * able to execute - but as soon as its callback function sends a\r
+ * notification to this task, this task will preempt it (because it has a\r
+ * higher priority). So this task expects to receive one notification. */\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
+ configASSERT( ulNotificationValue == 2 );\r
\r
- /* Reset the priority of this task and clear the notifications ready for the\r
- next example. */\r
+ /* Since the scheduled job has 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 == 2 );\r
+\r
+ /* The job's callback has executed so the job is now completed. */\r
+ IotTaskPool_GetStatus( NULL, xJobRecycled, &xJobStatus );\r
+ configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_COMPLETED );\r
+\r
+ /* Clean up 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
+ xResult = IotTaskPool_DestroyRecyclableJob( NULL, xJobRecycled );\r
+ configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+ /* Reset this task's priority. */\r
vTaskPrioritySet( NULL, tskIDLE_PRIORITY );\r
+\r
+ /* Clear all the notification value bits ready for the next example. */\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
+ xNoDelay ); /* No block time, return immediately. */\r
+ configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 0 );\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