]> git.sur5r.net Git - freertos/commitdiff
In small FreeRTOS applications it is unlikely there will be any task pools other...
authorrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Mon, 1 Jul 2019 17:05:20 +0000 (17:05 +0000)
committerrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Mon, 1 Jul 2019 17:05:20 +0000 (17:05 +0000)
IotTaskPool_CreateSystemTaskPool() calls synchronisation primitives, so cannot be called before the scheduler starts.  Add a configASSERT() to ensure the scheduler is running when it executes.
IotTaskPool_CreateSystemTaskPool() can conceivably be called from multiple different libraries that depend on the thread pool.  In this version _IotSystemTaskPool.running can be used to check the system task pool has not already been created.  If the task pool has been created simply return from IotTaskPool_CreateSystemTaskPool() instead of re-creating it (which would leak memory and leave orphaned tasks).
Call taskENTER_CRITICAL() and taskEXIT_CRITICAL() directly in place of mapping them to TASKPOOL_ENTER_CRITICAL() and TASKPOOL_EXIT_CRITICAL() in the same file.
Rename _timerThread() _timerCallback(), as it is a callback function and not a thread.
Remove the unused flags parameter from _scheduleInternal().

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

FreeRTOS-Plus/Demo/FreeRTOS_Plus_IoT_SDK/TaskPool/.project
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 f3fa6ed3690cb6e878d1626fdc07a2b9cfd93e47..ad46abe4c83529248c65be60aa791b597842951a 100644 (file)
                <link>\r
                        <name>FreeRTOS-Plus-IoT-SDK/c_sdk/standard/common/taskpool/iot_taskpool.c</name>\r
                        <type>1</type>\r
-                       <locationURI>PARENT-5-FREERTOS_ROOT/T/amazon-freertos-master_fr_task_pool/libraries/c_sdk/standard/common/taskpool/iot_taskpool.c</locationURI>\r
+                       <locationURI>FREERTOS_ROOT/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/c_sdk/standard/common/taskpool/iot_taskpool.c</locationURI>\r
                </link>\r
        </linkedResources>\r
        <variableList>\r
index c3181f570a437c26d0a7a2dae4c89f29f893d84c..bde06ef9390876ded94f91277c46b22b8728576c 100644 (file)
@@ -1,3 +1,30 @@
+/*\r
+ * FreeRTOS Kernel V10.2.1\r
+ * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://aws.amazon.com/freertos\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ */\r
+\r
 /* Kernel includes. */\r
 #include "FreeRTOS.h"\r
 #include "task.h"\r
@@ -9,6 +36,7 @@
  * Prototypes for the functions that demonstrate the task pool API.\r
  */\r
 static void prvExample_BasicSingleJob( void );\r
+static void prvExample_BasicRecyclableJob( 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
@@ -62,6 +90,34 @@ int main( void )
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+static void prvTaskPoolDemoTask( void *pvParameters )\r
+{\r
+IotTaskPoolError_t xResult;\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
+\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
+\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
+               prvExample_BasicSingleJob();\r
+               prvExample_BasicRecyclableJob();\r
+\r
+               vTaskDelete( NULL );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
 static void prvSimpleTaskNotifyCallback( IotTaskPool_t pTaskPool, IotTaskPoolJob_t pJob, void *pUserContext )\r
 {\r
 TaskHandle_t xTaskToNotify = ( TaskHandle_t ) pUserContext;\r
@@ -80,46 +136,57 @@ static void prvExample_BasicSingleJob( void )
 IotTaskPoolJobStorage_t xJobStorage;\r
 IotTaskPoolJob_t xJob;\r
 IotTaskPoolError_t xResult;\r
+uint32_t ulReturn;\r
+const TickType_t xShortDelay = pdMS_TO_TICKS( 200 );\r
 \r
        /* Ensure the notification count is 0 before scheduling the job. */\r
        while( 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.   */\r
+       the jobs callback function.  The job is created using storage allocated on\r
+       the stack of this 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
-       IotTaskPool_ScheduleSystem( xJob, 0 );\r
+\r
+       xResult = IotTaskPool_ScheduleSystemJob( xJob, 0 );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
 \r
        /* Wait for the notification coming from the job's callback function. */\r
-       ulTaskNotifyTake( pdTRUE, portMAX_DELAY );\r
+       ulReturn = ulTaskNotifyTake( pdTRUE, xShortDelay );\r
+       configASSERT( ulReturn );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static void prvTaskPoolDemoTask( void *pvParameters )\r
+static void prvExample_BasicRecyclableJob( void )\r
 {\r
+IotTaskPoolJob_t xJob;\r
 IotTaskPoolError_t xResult;\r
+uint32_t ulReturn;\r
+const TickType_t xShortDelay = pdMS_TO_TICKS( 200 );\r
 \r
-       /* Remove compiler warnings about unused parameters. */\r
-       ( void ) pvParameters;\r
+       /* Ensure the notification count is 0 before scheduling the job. */\r
+       while( ulTaskNotifyTake( pdTRUE, 0 ) != 0 );\r
 \r
-       /* The task pool must be created before it can be used. */\r
-       xResult = IotTaskPool_CreateSystemTaskPool( &xTaskPoolParameters );\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
        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
-               prvExample_BasicSingleJob();\r
-\r
-\r
+       xResult = IotTaskPool_ScheduleSystemJob( xJob, 0 );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
 \r
-               vTaskDelete( NULL );\r
-       }\r
+       /* Wait for the notification coming from the job's callback function. */\r
+       ulReturn = ulTaskNotifyTake( pdTRUE, xShortDelay );\r
+       configASSERT( ulReturn );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
index 142c431efaea082c574e0082f1183e291e724d71..7e94e7264cf71638eaf26c71263517afb1f9d393 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
@@ -255,6 +259,36 @@ 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
@@ -413,7 +447,7 @@ IotTaskPoolError_t IotTaskPool_Schedule( IotTaskPool_t taskPool,
                                          uint32_t flags );\r
 \r
 /**\r
- * @brief This function schedules a job created with @ref IotTaskPool_CreateJob or @ref IotTaskPool_CreateRecyclableJob\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
@@ -464,7 +498,7 @@ IotTaskPoolError_t IotTaskPool_Schedule( IotTaskPool_t taskPool,
  *     // Statically allocate one job, schedule it.\r
  *     IotTaskPool_CreateJob( &ExecutionCb, &userContext, &job );\r
  *\r
- *     IotTaskPoolError_t errorSchedule = IotTaskPool_ScheduleSystem( &job, 0 );\r
+ *     IotTaskPoolError_t errorSchedule = IotTaskPool_ScheduleSystemJob( &job, 0 );\r
  *\r
  *     switch ( errorSchedule )\r
  *     {\r
@@ -488,11 +522,11 @@ IotTaskPoolError_t IotTaskPool_Schedule( IotTaskPool_t taskPool,
  * }\r
  * @endcode\r
  */\r
-/* @[declare_taskpool_schedule] */\r
-IotTaskPoolError_t IotTaskPool_ScheduleSystem( IotTaskPoolJob_t pJob,\r
+/* @[declare_taskpool_schedulesystemjob] */\r
+IotTaskPoolError_t IotTaskPool_ScheduleSystemJob( IotTaskPoolJob_t pJob,\r
                                                uint32_t flags );\r
 \r
-/* @[declare_taskpool_schedule] */\r
+/* @[declare_taskpool_schedulesystemjob] */\r
 \r
 /**\r
  * @brief This function schedules a job created with @ref IotTaskPool_CreateJob against the task pool\r
index 214bffb0e3bb56c11d2186c1d1bf2c618f13e388..fff69ca83aec0b9eba9d221e6b05dbb26719bc79 100644 (file)
 /* Task pool internal include. */\r
 #include "private/iot_taskpool_internal.h"\r
 \r
-/**\r
- * @brief Enter a critical section by disabling interrupts.\r
- *\r
- */\r
-#define TASKPOOL_ENTER_CRITICAL()               taskENTER_CRITICAL()\r
-\r
-/**\r
- * @brief Enter a critical section by disabling interrupts.\r
- *\r
- */\r
-#define TASKPOOL_ENTER_CRITICAL_FROM_ISR()      taskENTER_CRITICAL_FROM_ISR()\r
-\r
-/**\r
- * @brief Exit a critical section by re-enabling interrupts.\r
- *\r
- */\r
-#define TASKPOOL_EXIT_CRITICAL()                taskEXIT_CRITICAL()\r
-\r
-/**\r
- * @brief Exit a critical section by re-enabling interrupts.\r
- *\r
- */\r
-#define TASKPOOL_EXIT_CRITICAL_FROM_ISR( x )    taskEXIT_CRITICAL_FROM_ISR( x )\r
-\r
 /**\r
  * @brief Maximum semaphore value for wait operations.\r
  */\r
@@ -171,7 +147,7 @@ static void _rescheduleDeferredJobsTimer( TimerHandle_t const timer,
  *\r
  * param[in] timer The timer to handle.\r
  */\r
-static void _timerThread( TimerHandle_t xTimer );\r
+static void _timerCallback( TimerHandle_t xTimer );\r
 \r
 /* -------------- Convenience functions to create/initialize/destroy the task pool -------------- */\r
 \r
@@ -238,8 +214,7 @@ static void _signalShutdown( _taskPool_t * const pTaskPool,
  *\r
  */\r
 static IotTaskPoolError_t _scheduleInternal( _taskPool_t * const pTaskPool,\r
-                                             _taskPoolJob_t * const pJob,\r
-                                             uint32_t flags );\r
+                                             _taskPoolJob_t * const pJob );\r
 \r
 /**\r
  * Matches a deferred job in the timer queue with its timer event wrapper.\r
@@ -276,11 +251,21 @@ IotTaskPoolError_t IotTaskPool_CreateSystemTaskPool( const IotTaskPoolInfo_t * c
 {\r
     TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
 \r
-    /* Parameter checking. */\r
-    TASKPOOL_ON_ERROR_GOTO_CLEANUP( _performTaskPoolParameterValidation( pInfo ) );\r
+    /* At this time the task pool cannot be created before the scheduler has\r
+    started because the function attempts to block on synchronization\r
+    primitives (although I'm not sure why). */\r
+    configASSERT( xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED );\r
 \r
-    /* Create the system task pool pool. */\r
-    TASKPOOL_SET_AND_GOTO_CLEANUP( _createTaskPool( pInfo, &_IotSystemTaskPool ) );\r
+    /* Guard against multiple attempts to create the system task pool in case\r
+    this function is called by more than one library initialization routine. */\r
+    if( _IotSystemTaskPool.running == false )\r
+    {\r
+        /* Parameter checking. */\r
+        TASKPOOL_ON_ERROR_GOTO_CLEANUP( _performTaskPoolParameterValidation( pInfo ) );\r
+\r
+        /* Create the system task pool pool. */\r
+        TASKPOOL_SET_AND_GOTO_CLEANUP( _createTaskPool( pInfo, &_IotSystemTaskPool ) );\r
+    }\r
 \r
     TASKPOOL_NO_FUNCTION_CLEANUP();\r
 }\r
@@ -349,7 +334,7 @@ IotTaskPoolError_t IotTaskPool_Destroy( IotTaskPool_t taskPoolHandle )
     /* Destroying the task pool should be safe, and therefore we will grab the task pool lock.\r
      * No worker thread or application thread should access any data structure\r
      * in the task pool while the task pool is being destroyed. */\r
-    TASKPOOL_ENTER_CRITICAL();\r
+    taskENTER_CRITICAL();\r
     {\r
         IotLink_t * pItemLink;\r
 \r
@@ -439,7 +424,7 @@ IotTaskPoolError_t IotTaskPool_Destroy( IotTaskPool_t taskPoolHandle )
         /* (4) Set the exit condition. */\r
         _signalShutdown( pTaskPool, activeThreads );\r
     }\r
-    TASKPOOL_EXIT_CRITICAL();\r
+    taskEXIT_CRITICAL();\r
 \r
     /* (5) Wait for all active threads to reach the end of their life-span. */\r
     for( count = 0; count < activeThreads; ++count )\r
@@ -505,6 +490,15 @@ 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
@@ -520,12 +514,12 @@ IotTaskPoolError_t IotTaskPool_CreateRecyclableJob( IotTaskPool_t taskPoolHandle
     TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( userCallback );\r
     TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( ppJob );\r
 \r
-    TASKPOOL_ENTER_CRITICAL();\r
+    taskENTER_CRITICAL();\r
     {\r
         /* Bail out early if this task pool is shutting down. */\r
         pTempJob = _fetchOrAllocateJob( &pTaskPool->jobsCache );\r
     }\r
-    TASKPOOL_EXIT_CRITICAL();\r
+    taskEXIT_CRITICAL();\r
 \r
     if( pTempJob == NULL )\r
     {\r
@@ -548,7 +542,8 @@ IotTaskPoolError_t IotTaskPool_DestroyRecyclableJob( IotTaskPool_t taskPoolHandl
 {\r
     TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
 \r
-    _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;\r
+    ( void ) taskPoolHandle;\r
+\r
     _taskPoolJob_t * pJob = ( _taskPoolJob_t * ) pJobHandle;\r
 \r
     /* Parameter checking. */\r
@@ -575,13 +570,13 @@ IotTaskPoolError_t IotTaskPool_RecycleJob( IotTaskPool_t taskPoolHandle,
     TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );\r
     TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJob );\r
 \r
-    TASKPOOL_ENTER_CRITICAL();\r
+    taskENTER_CRITICAL();\r
     {\r
         IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) == false );\r
 \r
         _recycleJob( &pTaskPool->jobsCache, pJob );\r
     }\r
-    TASKPOOL_EXIT_CRITICAL();\r
+    taskEXIT_CRITICAL();\r
 \r
     TASKPOOL_NO_FUNCTION_CLEANUP();\r
 }\r
@@ -596,22 +591,32 @@ IotTaskPoolError_t IotTaskPool_Schedule( IotTaskPool_t taskPoolHandle,
 \r
     _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;\r
 \r
+    configASSERT( pTaskPool->running != false );\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
-    TASKPOOL_ENTER_CRITICAL();\r
+    taskENTER_CRITICAL(); //_RB_ Critical section is too long - does the whole thing need to be protected?\r
     {\r
-        _scheduleInternal( pTaskPool, pJob, flags );\r
+        _scheduleInternal( pTaskPool, pJob );\r
     }\r
-    TASKPOOL_EXIT_CRITICAL();\r
+    taskEXIT_CRITICAL();\r
 \r
     TASKPOOL_NO_FUNCTION_CLEANUP();\r
 }\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
+IotTaskPoolError_t IotTaskPool_ScheduleSystemJob( IotTaskPoolJob_t pJob,\r
+                                                  uint32_t flags )\r
+{\r
+    return IotTaskPool_Schedule( &_IotSystemTaskPool, pJob, flags );\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
 IotTaskPoolError_t IotTaskPool_ScheduleDeferred( IotTaskPool_t taskPoolHandle,\r
                                                  IotTaskPoolJob_t job,\r
                                                  uint32_t timeMs )\r
@@ -629,13 +634,13 @@ IotTaskPoolError_t IotTaskPool_ScheduleDeferred( IotTaskPool_t taskPoolHandle,
         TASKPOOL_SET_AND_GOTO_CLEANUP( IotTaskPool_Schedule( pTaskPool, job, 0 ) );\r
     }\r
 \r
-    TASKPOOL_ENTER_CRITICAL();\r
+    taskENTER_CRITICAL();\r
     {\r
         _taskPoolTimerEvent_t * pTimerEvent = IotTaskPool_MallocTimerEvent( sizeof( _taskPoolTimerEvent_t ) );\r
 \r
         if( pTimerEvent == NULL )\r
         {\r
-            TASKPOOL_EXIT_CRITICAL();\r
+            taskEXIT_CRITICAL();\r
 \r
             TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY );\r
         }\r
@@ -669,7 +674,7 @@ IotTaskPoolError_t IotTaskPool_ScheduleDeferred( IotTaskPool_t taskPoolHandle,
             _rescheduleDeferredJobsTimer( pTaskPool->timer, pTimerEvent );\r
         }\r
     }\r
-    TASKPOOL_EXIT_CRITICAL();\r
+    taskEXIT_CRITICAL();\r
 \r
     TASKPOOL_NO_FUNCTION_CLEANUP();\r
 }\r
@@ -682,19 +687,17 @@ IotTaskPoolError_t IotTaskPool_GetStatus( IotTaskPool_t taskPoolHandle,
 {\r
     TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
 \r
-    _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;\r
-\r
     /* Parameter checking. */\r
     TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );\r
     TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( job );\r
     TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pStatus );\r
     *pStatus = IOT_TASKPOOL_STATUS_UNDEFINED;\r
 \r
-    TASKPOOL_ENTER_CRITICAL();\r
+    taskENTER_CRITICAL();\r
     {\r
         *pStatus = job->status;\r
     }\r
-    TASKPOOL_EXIT_CRITICAL();\r
+    taskEXIT_CRITICAL();\r
 \r
     TASKPOOL_NO_FUNCTION_CLEANUP();\r
 }\r
@@ -718,11 +721,11 @@ IotTaskPoolError_t IotTaskPool_TryCancel( IotTaskPool_t taskPoolHandle,
         *pStatus = IOT_TASKPOOL_STATUS_UNDEFINED;\r
     }\r
 \r
-    TASKPOOL_ENTER_CRITICAL();\r
+    taskENTER_CRITICAL();\r
     {\r
         status = _tryCancelInternal( pTaskPool, job, pStatus );\r
     }\r
-    TASKPOOL_EXIT_CRITICAL();\r
+    taskEXIT_CRITICAL();\r
 \r
     TASKPOOL_NO_FUNCTION_CLEANUP();\r
 }\r
@@ -855,7 +858,7 @@ static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo
     TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
 \r
     uint32_t count;\r
-    uint32_t threadsCreated = 0;\r
+    uint32_t threadsCreated;\r
 \r
     /* Check input values for consistency. */\r
     TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pTaskPool );\r
@@ -866,8 +869,8 @@ static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo
     /* Initialize all internal data structure prior to creating all threads. */\r
     TASKPOOL_ON_ERROR_GOTO_CLEANUP( _initTaskPoolControlStructures( pInfo, pTaskPool ) );\r
 \r
-    /* Create the timer mutex for a new connection. */\r
-    pTaskPool->timer = xTimerCreate( NULL, portMAX_DELAY, pdFALSE, ( void * ) pTaskPool, _timerThread );\r
+    /* Create the timer for a new connection. */\r
+    pTaskPool->timer = xTimerCreate( NULL, portMAX_DELAY, pdFALSE, ( void * ) pTaskPool, _timerCallback );\r
 \r
     if( pTaskPool->timer == NULL )\r
     {\r
@@ -876,13 +879,13 @@ static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo
         TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY );\r
     }\r
 \r
-    /* The task pool will initialize the minimum number of threads reqeusted by the user upon start. */\r
+    /* The task pool will initialize the minimum number of threads requested by the user upon start. */\r
     /* When a thread is created, it will signal a semaphore to signify that it is about to wait on incoming */\r
     /* jobs. A thread can be woken up for exit or for new jobs only at that point in time.  */\r
     /* The exit condition is setting the maximum number of threads to 0. */\r
 \r
     /* Create the minimum number of threads specified by the user, and if one fails shutdown and return error. */\r
-    for( ; threadsCreated < pInfo->minThreads; )\r
+    for( threadsCreated = 0; threadsCreated < pInfo->minThreads; )\r
     {\r
         TaskHandle_t task = NULL;\r
 \r
@@ -914,7 +917,7 @@ static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo
     /* Wait for threads to be ready to wait on the condition, so that threads are actually able to receive messages. */\r
     for( count = 0; count < threadsCreated; ++count )\r
     {\r
-        xSemaphoreTake( pTaskPool->startStopSignal, portMAX_DELAY );\r
+        xSemaphoreTake( pTaskPool->startStopSignal, portMAX_DELAY ); /*_RB_ Is waiting necessary, and if so, is a semaphore necessary? */\r
     }\r
 \r
     /* In case of failure, wait on the created threads to exit. */\r
@@ -987,7 +990,7 @@ static void _taskPoolWorker( void * pUserContext )
         /* Acquire the lock to check the exit condition, and release the lock if the exit condition is verified,\r
          * or before waiting for incoming notifications.\r
          */\r
-        TASKPOOL_ENTER_CRITICAL();\r
+        taskENTER_CRITICAL();\r
         {\r
             /* If the exit condition is verified, update the number of active threads and exit the loop. */\r
             if( _IsShutdownStarted( pTaskPool ) )\r
@@ -997,7 +1000,7 @@ static void _taskPoolWorker( void * pUserContext )
                 /* Decrease the number of active threads. */\r
                 pTaskPool->activeThreads--;\r
 \r
-                TASKPOOL_EXIT_CRITICAL();\r
+                taskEXIT_CRITICAL();\r
 \r
                 /* Signal that this worker is exiting. */\r
                 xSemaphoreGive( pTaskPool->startStopSignal );\r
@@ -1020,7 +1023,7 @@ static void _taskPoolWorker( void * pUserContext )
                 userCallback = pJob->userCallback;\r
             }\r
         }\r
-        TASKPOOL_EXIT_CRITICAL();\r
+        taskEXIT_CRITICAL();\r
 \r
         /* INNER LOOP: it controls the execution of jobs: the exit condition is the lack of a job to execute. */\r
         while( pJob != NULL )\r
@@ -1047,7 +1050,7 @@ static void _taskPoolWorker( void * pUserContext )
             }\r
 \r
             /* Acquire the lock before updating the job status. */\r
-            TASKPOOL_ENTER_CRITICAL();\r
+            taskENTER_CRITICAL();\r
             {\r
                 /* Try and dequeue the next job in the dispatch queue. */\r
                 IotLink_t * pItem = NULL;\r
@@ -1058,7 +1061,7 @@ static void _taskPoolWorker( void * pUserContext )
                 /* If there is no job left in the dispatch queue, update the worker status and leave. */\r
                 if( pItem == NULL )\r
                 {\r
-                    TASKPOOL_EXIT_CRITICAL();\r
+                    taskEXIT_CRITICAL();\r
 \r
                     /* Abandon the INNER LOOP. Execution will tranfer back to the OUTER LOOP condition. */\r
                     break;\r
@@ -1072,7 +1075,7 @@ static void _taskPoolWorker( void * pUserContext )
 \r
                 pJob->status = IOT_TASKPOOL_STATUS_COMPLETED;\r
             }\r
-            TASKPOOL_EXIT_CRITICAL();\r
+            taskEXIT_CRITICAL();\r
         }\r
     } while( running == true );\r
 \r
@@ -1222,8 +1225,7 @@ static void _signalShutdown( _taskPool_t * const pTaskPool,
 /* ---------------------------------------------------------------------------------------------- */\r
 \r
 static IotTaskPoolError_t _scheduleInternal( _taskPool_t * const pTaskPool,\r
-                                             _taskPoolJob_t * const pJob,\r
-                                             uint32_t flags )\r
+                                             _taskPoolJob_t * const pJob )\r
 {\r
     TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
 \r
@@ -1418,7 +1420,7 @@ static void _rescheduleDeferredJobsTimer( TimerHandle_t const timer,
 \r
 /*-----------------------------------------------------------*/\r
 \r
-static void _timerThread( TimerHandle_t xTimer )\r
+static void _timerCallback( TimerHandle_t xTimer )\r
 {\r
     _taskPool_t * pTaskPool = pvTimerGetTimerID( xTimer );\r
 \r
@@ -1432,12 +1434,12 @@ static void _timerThread( TimerHandle_t xTimer )
      * If this mutex cannot be locked it means that another thread is manipulating the\r
      * timeouts list, and will reset the timer to fire again, although it will be late.\r
      */\r
-    TASKPOOL_ENTER_CRITICAL();\r
+    taskENTER_CRITICAL();\r
     {\r
         /* Check again for shutdown and bail out early in case. */\r
         if( _IsShutdownStarted( pTaskPool ) )\r
         {\r
-            TASKPOOL_EXIT_CRITICAL();\r
+            taskEXIT_CRITICAL();\r
 \r
             /* Complete the shutdown sequence. */\r
             _destroyTaskPool( pTaskPool );\r
@@ -1487,11 +1489,11 @@ static void _timerThread( TimerHandle_t xTimer )
             IotLogDebug( "Scheduling job from timer event." );\r
 \r
             /* Queue the job associated with the received timer event. */\r
-            ( void ) _scheduleInternal( pTaskPool, pTimerEvent->job, 0 );\r
+            ( void ) _scheduleInternal( pTaskPool, pTimerEvent->job );\r
 \r
             /* Free the timer event. */\r
             IotTaskPool_FreeTimerEvent( pTimerEvent );\r
         }\r
     }\r
-    TASKPOOL_EXIT_CRITICAL();\r
+    taskEXIT_CRITICAL();\r
 }\r