]> git.sur5r.net Git - freertos/commitdiff
Remove IotTaskPool_CreateRecyclableSystemJob() and IotTaskPool_ScheduleSystemJob...
authorrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Mon, 8 Jul 2019 15:48:21 +0000 (15:48 +0000)
committerrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Mon, 8 Jul 2019 15:48:21 +0000 (15:48 +0000)
Update the task pool demo app to include a lot more functionality.

git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2674 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

FreeRTOS-Plus/Demo/FreeRTOS_Plus_IoT_SDK/TaskPool/.settings/language.settings.xml
FreeRTOS-Plus/Demo/FreeRTOS_Plus_IoT_SDK/TaskPool/main.c
FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/c_sdk/standard/common/include/iot_taskpool.h
FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/c_sdk/standard/common/taskpool/iot_taskpool.c

index 782b97ca1286a77daf64968f4be5be18faef43fb..aa36f48103da1936674f98fb56bbbf7775d9f063 100644 (file)
@@ -5,7 +5,7 @@
                        <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>\r
                        <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>\r
                        <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>\r
-                       <provider class="org.eclipse.cdt.managedbuilder.internal.language.settings.providers.GCCBuiltinSpecsDetectorMinGW" console="false" env-hash="-610351291490083443" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetectorMinGW" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings MinGW" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">\r
+                       <provider class="org.eclipse.cdt.managedbuilder.internal.language.settings.providers.GCCBuiltinSpecsDetectorMinGW" console="false" env-hash="1351656224547092082" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetectorMinGW" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings MinGW" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">\r
                                <language-scope id="org.eclipse.cdt.core.gcc"/>\r
                                <language-scope id="org.eclipse.cdt.core.g++"/>\r
                        </provider>\r
index bde06ef9390876ded94f91277c46b22b8728576c..a18b3666322c5fa2e98776b9c9f0ac833bba5e3b 100644 (file)
 #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
@@ -65,7 +75,7 @@ static const IotTaskPoolInfo_t xTaskPoolParameters = {
                                                                                                                /* 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
@@ -74,12 +84,12 @@ int main( void )
 {\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
@@ -93,27 +103,61 @@ int main( void )
 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
@@ -137,10 +181,13 @@ IotTaskPoolJobStorage_t xJobStorage;
 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
@@ -152,12 +199,111 @@ const TickType_t xShortDelay = pdMS_TO_TICKS( 200 );
                                                                          &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
@@ -166,27 +312,269 @@ static void prvExample_BasicRecyclableJob( void )
 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
@@ -269,6 +657,9 @@ volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0;
 \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
index 7e94e7264cf71638eaf26c71263517afb1f9d393..a91ccf1520f10d1450bd359131394ed9d0f9d4a8 100644 (file)
  * - @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
@@ -164,7 +160,7 @@ IotTaskPoolError_t IotTaskPool_Create( const IotTaskPoolInfo_t * const pInfo,
  * 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
@@ -247,7 +243,7 @@ IotTaskPoolError_t IotTaskPool_CreateJob( IotTaskPoolRoutine_t userCallback,
  * - #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
@@ -259,36 +255,6 @@ IotTaskPoolError_t IotTaskPool_CreateRecyclableJob( IotTaskPool_t taskPool,
                                                     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
@@ -445,88 +411,7 @@ IotTaskPoolError_t IotTaskPool_RecycleJob( IotTaskPool_t taskPool,
 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
index fff69ca83aec0b9eba9d221e6b05dbb26719bc79..a01e6423c2c760561183909c540025839e6c55d5 100644 (file)
@@ -32,6 +32,7 @@
 \r
 /* Standard includes. */\r
 #include <stdbool.h>\r
+#include <stdio.h>\r
 #include <stddef.h>\r
 #include <stdint.h>\r
 #include <string.h>\r
@@ -490,15 +491,6 @@ IotTaskPoolError_t IotTaskPool_CreateJob( IotTaskPoolRoutine_t userCallback,
 \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
@@ -506,11 +498,21 @@ IotTaskPoolError_t IotTaskPool_CreateRecyclableJob( IotTaskPool_t taskPoolHandle
 {\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
@@ -542,12 +544,21 @@ IotTaskPoolError_t IotTaskPool_DestroyRecyclableJob( IotTaskPool_t taskPoolHandl
 {\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
@@ -564,10 +575,19 @@ IotTaskPoolError_t IotTaskPool_RecycleJob( IotTaskPool_t taskPoolHandle,
 {\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
@@ -589,12 +609,23 @@ IotTaskPoolError_t IotTaskPool_Schedule( IotTaskPool_t taskPoolHandle,
 {\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
@@ -609,24 +640,21 @@ IotTaskPoolError_t IotTaskPool_Schedule( IotTaskPool_t taskPoolHandle,
 \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
@@ -688,7 +716,8 @@ IotTaskPoolError_t IotTaskPool_GetStatus( IotTaskPool_t taskPoolHandle,
     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
@@ -710,10 +739,14 @@ IotTaskPoolError_t IotTaskPool_TryCancel( IotTaskPool_t taskPoolHandle,
 {\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
@@ -859,6 +892,7 @@ static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo
 \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
@@ -887,10 +921,12 @@ static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo
     /* 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
@@ -1019,7 +1055,7 @@ static void _taskPoolWorker( void * pUserContext )
                 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
@@ -1156,7 +1192,7 @@ static void _recycleJob( _taskPoolCache_t * const pCache,
                          _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
@@ -1232,15 +1268,11 @@ static IotTaskPoolError_t _scheduleInternal( _taskPool_t * const pTaskPool,
     /* 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
@@ -1333,7 +1365,7 @@ static IotTaskPoolError_t _tryCancelInternal( _taskPool_t * const pTaskPool,
             {\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