]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Source/FreeRTOS-IoT-Libraries/c_sdk/standard/common/taskpool/iot_taskpool.c
Remove the FreeRTOS-IoT-Libraries from FreeRTOS-Plus as it was an old copy with a...
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-IoT-Libraries / c_sdk / standard / common / taskpool / iot_taskpool.c
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-IoT-Libraries/c_sdk/standard/common/taskpool/iot_taskpool.c b/FreeRTOS-Plus/Source/FreeRTOS-IoT-Libraries/c_sdk/standard/common/taskpool/iot_taskpool.c
deleted file mode 100644 (file)
index 5684993..0000000
+++ /dev/null
@@ -1,1192 +0,0 @@
-/*\r
- * Amazon FreeRTOS Common V1.0.0\r
- * Copyright (C) 2018 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://aws.amazon.com/freertos\r
- * http://www.FreeRTOS.org\r
- */\r
-/**\r
- * @file iot_taskpool.c\r
- * @brief Implements the task pool functions in iot_taskpool.h\r
- */\r
-\r
-\r
-/*\r
- * The full IoT Task Pool Library has many use cases, including Linux\r
- * development.  Typical FreeRTOS use cases do not require the full\r
- * functionality so an optimised implementation is provided specifically for use\r
- * with FreeRTOS.  The optimised version has a fixed number of tasks in the\r
- * pool, each of which uses statically allocated memory to ensure creation of\r
- * the pool is guaranteed (it does not run out of heap space).  The constant\r
- * IOT_TASKPOOL_NUMBER_OF_WORKERS sets the number of tasks in the pool.\r
- *\r
- * Unlike the full version, this optimised version:\r
- *   + Only supports a single task pool (system task pool) at a time.\r
- *   + Does not auto-scale by dynamically adding more tasks if the number of\r
- *   + tasks in the pool becomes exhausted.  The number of tasks in the pool\r
- *     are fixed at compile time.  See the task pool configuration options for\r
- *     more information.\r
- *   + Cannot be shut down - it exists for the lifetime of the application.\r
- *\r
- * As such this file does not implement the following API functions:\r
- *   + IotTaskPool_GetSystemTaskPool()\r
- *   + IotTaskPool_Create()\r
- *   + IotTaskPool_Destroy()\r
- *   + IotTaskPool_SetMaxThreads()\r
- *\r
- * Users who are interested in the functionality of the full IoT Task Pool\r
- * library can us it in place of this optimised version.\r
- */\r
-\r
-\r
-/* Kernel includes. */\r
-#include "FreeRTOS.h"\r
-#include "semphr.h"\r
-\r
-/* IoT libraries includes. */\r
-#include "iot_config.h"\r
-\r
-/* Standard includes. */\r
-#include <stdbool.h>\r
-#include <stdio.h>\r
-#include <stddef.h>\r
-#include <stdint.h>\r
-#include <string.h>\r
-\r
-#if !defined( configSUPPORT_STATIC_ALLOCATION ) || ( configSUPPORT_STATIC_ALLOCATION != 1 )\r
-    #error configSUPPORT_STATIC_ALLOCATION must be set to 1 in FreeRTOSConfig.h to build this file.\r
-#endif\r
-\r
-/* Task pool internal include. */\r
-#include "private/iot_taskpool_internal.h"\r
-\r
-/**\r
- * @brief Maximum semaphore value for wait operations.\r
- */\r
-#define TASKPOOL_MAX_SEM_VALUE              0xFFFF\r
-\r
-/**\r
- * @brief Reschedule delay in milliseconds for deferred jobs.\r
- */\r
-#define TASKPOOL_JOB_RESCHEDULE_DELAY_MS    ( 10ULL )\r
-\r
-/* ---------------------------------------------------------------------------------- */\r
-\r
-/**\r
- * Doxygen should ignore this section.\r
- *\r
- * @brief The system task pool handle for all libraries to use.\r
- * User application can use the system task pool as well knowing that the usage will be shared with\r
- * the system libraries as well. The system task pool needs to be initialized before any library is used or\r
- * before any code that posts jobs to the task pool runs.\r
- */\r
-static _taskPool_t _IotSystemTaskPool = { .dispatchQueue = IOT_DEQUEUE_INITIALIZER };\r
-\r
-/* -------------- Convenience functions to create/recycle/destroy jobs -------------- */\r
-\r
-/**\r
- * @brief Initializes one instance of a Task pool cache.\r
- *\r
- * @param[in] pCache The pre-allocated instance of the cache to initialize.\r
- */\r
-static void _initJobsCache( _taskPoolCache_t * const pCache );\r
-\r
-/**\r
- * @brief Initialize a job.\r
- *\r
- * @param[in] pJob The job to initialize.\r
- * @param[in] userCallback The user callback for the job.\r
- * @param[in] pUserContext The context tp be passed to the callback.\r
- * @param[in] isStatic A flag to indicate whether the job is statically or synamically allocated.\r
- */\r
-static void _initializeJob( _taskPoolJob_t * const pJob,\r
-                            IotTaskPoolRoutine_t userCallback,\r
-                            void * pUserContext,\r
-                            bool isStatic );\r
-\r
-/**\r
- * @brief Extracts and initializes one instance of a job from the cache or, if there is none available, it allocates and initialized a new one.\r
- *\r
- * @param[in] pCache The instance of the cache to extract the job from.\r
- */\r
-static _taskPoolJob_t * _fetchOrAllocateJob( _taskPoolCache_t * const pCache );\r
-\r
-/**\r
- * Recycles one instance of a job into the cache or, if the cache is full, it destroys it.\r
- *\r
- * @param[in] pCache The instance of the cache to recycle the job into.\r
- * @param[in] pJob The job to recycle.\r
- *\r
- */\r
-static void _recycleJob( _taskPoolCache_t * const pCache,\r
-                         _taskPoolJob_t * const pJob );\r
-\r
-/**\r
- * Destroys one instance of a job.\r
- *\r
- * @param[in] pJob The job to destroy.\r
- *\r
- */\r
-static void _destroyJob( _taskPoolJob_t * const pJob );\r
-\r
-/* -------------- The worker thread procedure for a task pool thread -------------- */\r
-\r
-/**\r
- * The procedure for a task pool worker thread.\r
- *\r
- * @param[in] pUserContext The user context.\r
- *\r
- */\r
-static void _taskPoolWorker( void * pUserContext );\r
-\r
-/* -------------- Convenience functions to handle timer events  -------------- */\r
-\r
-/**\r
- * Comparer for the time list.\r
- *\r
- * param[in] pTimerEventLink1 The link to the first timer event.\r
- * param[in] pTimerEventLink1 The link to the first timer event.\r
- */\r
-static int32_t _timerEventCompare( const IotLink_t * const pTimerEventLink1,\r
-                                   const IotLink_t * const pTimerEventLink2 );\r
-\r
-/**\r
- * Reschedules the timer for handling deferred jobs to the next timeout.\r
- *\r
- * param[in] timer The timer to reschedule.\r
- * param[in] pFirstTimerEvent The timer event that carries the timeout and job inforamtion.\r
- */\r
-static void _rescheduleDeferredJobsTimer( TimerHandle_t const timer,\r
-                                          _taskPoolTimerEvent_t * const pFirstTimerEvent );\r
-\r
-/**\r
- * The task pool timer procedure for scheduling deferred jobs.\r
- *\r
- * param[in] timer The timer to handle.\r
- */\r
-static void _timerCallback( TimerHandle_t xTimer );\r
-\r
-/* -------------- Convenience functions to create/initialize/destroy the task pool -------------- */\r
-\r
-/**\r
- * Parameter validation for a task pool initialization.\r
- *\r
- * @param[in] pInfo The initialization information for the task pool.\r
- *\r
- */\r
-static IotTaskPoolError_t _performTaskPoolParameterValidation( const IotTaskPoolInfo_t * const pInfo );\r
-\r
-/**\r
- * Initializes a pre-allocated instance of a task pool.\r
- *\r
- * @param[in] pTaskPool The pre-allocated instance of the task pool to initialize.\r
- *\r
- */\r
-static void _initTaskPoolControlStructures( _taskPool_t * const pTaskPool );\r
-\r
-/**\r
- * Initializes a pre-allocated instance of a task pool.\r
- *\r
- * @param[in] pInfo The initialization information for the task pool.\r
- * @param[out] pTaskPool A pointer to the task pool data structure to initialize.\r
- *\r
- */\r
-static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo,\r
-                                           _taskPool_t * const pTaskPool );\r
-\r
-/**\r
- * Destroys one instance of a task pool.\r
- *\r
- * @param[in] pTaskPool The task pool to destroy.\r
- *\r
- */\r
-static void _destroyTaskPool( _taskPool_t * const pTaskPool );\r
-\r
-/**\r
- * Places a job in the dispatch queue.\r
- *\r
- * @param[in] pTaskPool The task pool to scheduel the job with.\r
- * @param[in] pJob The job to schedule.\r
- * @param[in] flags The job flags.\r
- *\r
- */\r
-static IotTaskPoolError_t _scheduleInternal( _taskPool_t * const pTaskPool,\r
-                                             _taskPoolJob_t * const pJob );\r
-/**\r
- * Matches a deferred job in the timer queue with its timer event wrapper.\r
- *\r
- * @param[in] pLink A pointer to the timer event link in the timer queue.\r
- * @param[in] pMatch A pointer to the job to match.\r
- *\r
- */\r
-static bool _matchJobByPointer( const IotLink_t * const pLink,\r
-                                void * pMatch );\r
-\r
-/**\r
- * Tries to cancel a job.\r
- *\r
- * @param[in] pTaskPool The task pool to cancel an operation against.\r
- * @param[in] pJob The job to cancel.\r
- * @param[out] pStatus The status of the job at the time of cancellation.\r
- *\r
- */\r
-static IotTaskPoolError_t _tryCancelInternal( _taskPool_t * const pTaskPool,\r
-                                              _taskPoolJob_t * const pJob,\r
-                                              IotTaskPoolJobStatus_t * const pStatus );\r
-\r
-/* ---------------------------------------------------------------------------------------------- */\r
-\r
-IotTaskPoolError_t IotTaskPool_CreateSystemTaskPool( const IotTaskPoolInfo_t * const pInfo )\r
-{\r
-    TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
-\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
-    /* 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
-/*-----------------------------------------------------------*/\r
-\r
-IotTaskPoolError_t IotTaskPool_CreateJob( IotTaskPoolRoutine_t userCallback,\r
-                                          void * pUserContext,\r
-                                          IotTaskPoolJobStorage_t * const pJobStorage,\r
-                                          IotTaskPoolJob_t * const ppJob )\r
-{\r
-    TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
-\r
-    /* Parameter checking. */\r
-    TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( userCallback );\r
-    TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJobStorage );\r
-    TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( ppJob );\r
-\r
-    /* Build a job around the user-provided storage. */\r
-    _initializeJob( ( _taskPoolJob_t * ) pJobStorage, userCallback, pUserContext, true );\r
-\r
-    *ppJob = ( IotTaskPoolJob_t ) pJobStorage;\r
-\r
-    TASKPOOL_NO_FUNCTION_CLEANUP();\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-IotTaskPoolError_t IotTaskPool_CreateRecyclableJob( IotTaskPool_t taskPoolHandle,\r
-                                                    IotTaskPoolRoutine_t userCallback,\r
-                                                    void * pUserContext,\r
-                                                    IotTaskPoolJob_t * const ppJob )\r
-{\r
-    TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
-\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( userCallback );\r
-    TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( ppJob );\r
-\r
-    taskENTER_CRITICAL();\r
-    {\r
-        /* Bail out early if this task pool is shutting down. */\r
-        pTempJob = _fetchOrAllocateJob( &pTaskPool->jobsCache );\r
-    }\r
-    taskEXIT_CRITICAL();\r
-\r
-    if( pTempJob == NULL )\r
-    {\r
-        IotLogInfo( "Failed to allocate a job." );\r
-\r
-        TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY );\r
-    }\r
-\r
-    _initializeJob( pTempJob, userCallback, pUserContext, false );\r
-\r
-    *ppJob = pTempJob;\r
-\r
-    TASKPOOL_NO_FUNCTION_CLEANUP();\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-IotTaskPoolError_t IotTaskPool_DestroyRecyclableJob( IotTaskPool_t taskPoolHandle,\r
-                                                     IotTaskPoolJob_t pJobHandle )\r
-{\r
-    TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\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
-    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( pJobHandle );\r
-\r
-    IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) == false );\r
-\r
-    _destroyJob( pJob );\r
-\r
-    TASKPOOL_NO_FUNCTION_CLEANUP();\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-IotTaskPoolError_t IotTaskPool_RecycleJob( IotTaskPool_t taskPoolHandle,\r
-                                           IotTaskPoolJob_t pJob )\r
-{\r
-    TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
-\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
-    TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJob );\r
-\r
-    taskENTER_CRITICAL();\r
-    {\r
-        IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) == false );\r
-\r
-        _recycleJob( &pTaskPool->jobsCache, pJob );\r
-    }\r
-    taskEXIT_CRITICAL();\r
-\r
-    TASKPOOL_NO_FUNCTION_CLEANUP();\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-IotTaskPoolError_t IotTaskPool_Schedule( IotTaskPool_t taskPoolHandle,\r
-                                         IotTaskPoolJob_t pJob,\r
-                                         uint32_t flags )\r
-{\r
-    TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
-\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( pJob );\r
-    TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( ( flags != 0UL ) && ( flags != IOT_TASKPOOL_JOB_HIGH_PRIORITY ) );\r
-\r
-    taskENTER_CRITICAL(); //_RB_ Critical section is too long - does the whole thing need to be protected?\r
-    {\r
-        _scheduleInternal( pTaskPool, pJob );\r
-    }\r
-    taskEXIT_CRITICAL();\r
-\r
-    TASKPOOL_NO_FUNCTION_CLEANUP();\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 = &_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
-    TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( job );\r
-\r
-    if( timeMs == 0UL )\r
-    {\r
-        TASKPOOL_SET_AND_GOTO_CLEANUP( IotTaskPool_Schedule( pTaskPool, job, 0 ) );\r
-    }\r
-\r
-    taskENTER_CRITICAL();\r
-    {\r
-        _taskPoolTimerEvent_t * pTimerEvent = IotTaskPool_MallocTimerEvent( sizeof( _taskPoolTimerEvent_t ) );\r
-\r
-        if( pTimerEvent == NULL )\r
-        {\r
-            taskEXIT_CRITICAL();\r
-\r
-            TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY );\r
-        }\r
-\r
-        IotLink_t * pTimerEventLink;\r
-\r
-        TickType_t now = xTaskGetTickCount();\r
-\r
-        pTimerEvent->link.pNext = NULL;\r
-        pTimerEvent->link.pPrevious = NULL;\r
-        pTimerEvent->expirationTime = now + pdMS_TO_TICKS( timeMs );\r
-        pTimerEvent->job = job; //_RB_ Think up to here can be outside the critical section.\r
-\r
-        /* Append the timer event to the timer list. */\r
-        IotListDouble_InsertSorted( &pTaskPool->timerEventsList, &pTimerEvent->link, _timerEventCompare );\r
-\r
-        /* Update the job status to 'scheduled'. */\r
-        job->status = IOT_TASKPOOL_STATUS_DEFERRED;\r
-\r
-        /* Peek the first event in the timer event list. There must be at least one,\r
-         * since we just inserted it. */\r
-        pTimerEventLink = IotListDouble_PeekHead( &pTaskPool->timerEventsList );\r
-        IotTaskPool_Assert( pTimerEventLink != NULL );\r
-\r
-        /* If the event we inserted is at the front of the queue, then\r
-         * we need to reschedule the underlying timer. */\r
-        if( pTimerEventLink == &pTimerEvent->link )\r
-        {\r
-            pTimerEvent = IotLink_Container( _taskPoolTimerEvent_t, pTimerEventLink, link );\r
-\r
-            _rescheduleDeferredJobsTimer( pTaskPool->timer, pTimerEvent );\r
-        }\r
-    }\r
-    taskEXIT_CRITICAL();\r
-\r
-    TASKPOOL_NO_FUNCTION_CLEANUP();\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-IotTaskPoolError_t IotTaskPool_GetStatus( IotTaskPool_t taskPoolHandle,\r
-                                          IotTaskPoolJob_t job,\r
-                                          IotTaskPoolJobStatus_t * const pStatus )\r
-{\r
-    TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\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
-    ( void ) taskPoolHandle;\r
-\r
-    /* Parameter checking. */\r
-    TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( job );\r
-    TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pStatus );\r
-    *pStatus = IOT_TASKPOOL_STATUS_UNDEFINED;\r
-\r
-    taskENTER_CRITICAL();\r
-    {\r
-        *pStatus = job->status;\r
-    }\r
-    taskEXIT_CRITICAL();\r
-\r
-    TASKPOOL_NO_FUNCTION_CLEANUP();\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-IotTaskPoolError_t IotTaskPool_TryCancel( IotTaskPool_t taskPoolHandle,\r
-                                          IotTaskPoolJob_t job,\r
-                                          IotTaskPoolJobStatus_t * const pStatus )\r
-{\r
-    TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
-\r
-    _taskPool_t * const 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
-    TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( job );\r
-\r
-    if( pStatus != NULL )\r
-    {\r
-        *pStatus = IOT_TASKPOOL_STATUS_UNDEFINED;\r
-    }\r
-\r
-    taskENTER_CRITICAL();\r
-    {\r
-        status = _tryCancelInternal( pTaskPool, job, pStatus );\r
-    }\r
-    taskEXIT_CRITICAL();\r
-\r
-    TASKPOOL_NO_FUNCTION_CLEANUP();\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-IotTaskPoolJobStorage_t * IotTaskPool_GetJobStorageFromHandle( IotTaskPoolJob_t pJob )\r
-{\r
-    return ( IotTaskPoolJobStorage_t * ) pJob;\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-const char * IotTaskPool_strerror( IotTaskPoolError_t status )\r
-{\r
-    const char * pMessage = NULL;\r
-\r
-    switch( status )\r
-    {\r
-        case IOT_TASKPOOL_SUCCESS:\r
-            pMessage = "SUCCESS";\r
-            break;\r
-\r
-        case IOT_TASKPOOL_BAD_PARAMETER:\r
-            pMessage = "BAD PARAMETER";\r
-            break;\r
-\r
-        case IOT_TASKPOOL_ILLEGAL_OPERATION:\r
-            pMessage = "ILLEGAL OPERATION";\r
-            break;\r
-\r
-        case IOT_TASKPOOL_NO_MEMORY:\r
-            pMessage = "NO MEMORY";\r
-            break;\r
-\r
-        case IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS:\r
-            pMessage = "SHUTDOWN IN PROGRESS";\r
-            break;\r
-\r
-        case IOT_TASKPOOL_CANCEL_FAILED:\r
-            pMessage = "CANCEL FAILED";\r
-            break;\r
-\r
-        default:\r
-            pMessage = "INVALID STATUS";\r
-            break;\r
-    }\r
-\r
-    return pMessage;\r
-}\r
-\r
-/* ---------------------------------------------------------------------------------------------- */\r
-/* ---------------------------------------------------------------------------------------------- */\r
-/* ---------------------------------------------------------------------------------------------- */\r
-\r
-static IotTaskPoolError_t _performTaskPoolParameterValidation( const IotTaskPoolInfo_t * const pInfo )\r
-{\r
-    TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
-\r
-    /* Check input values for consistency. */\r
-    TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pInfo );\r
-    TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( pInfo->minThreads > pInfo->maxThreads );\r
-    TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( pInfo->minThreads < 1UL );\r
-    TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( pInfo->maxThreads < 1UL );\r
-\r
-    TASKPOOL_NO_FUNCTION_CLEANUP();\r
-}\r
-\r
-static void _initTaskPoolControlStructures( _taskPool_t * const pTaskPool )\r
-{\r
-    /* Initialize a job data structures that require no de-initialization.\r
-     * All other data structures carry a value of 'NULL' before initailization.\r
-     */\r
-    IotDeQueue_Create( &pTaskPool->dispatchQueue );\r
-    IotListDouble_Create( &pTaskPool->timerEventsList );\r
-\r
-    _initJobsCache( &pTaskPool->jobsCache );\r
-\r
-    /* Initialize the semaphore for waiting for incoming work.  Cannot fail as\r
-    statically allocated. */\r
-    pTaskPool->dispatchSignal = xSemaphoreCreateCountingStatic( TASKPOOL_MAX_SEM_VALUE, 0, &pTaskPool->dispatchSignalBuffer );\r
-}\r
-\r
-static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo,\r
-                                           _taskPool_t * const pTaskPool )\r
-{\r
-    TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
-\r
-    /* Static TCB structures and arrays to be used by statically allocated\r
-    worker tasks. */\r
-    static StaticTask_t workerTaskTCBs[ IOT_TASKPOOL_NUMBER_OF_WORKERS ];\r
-    static StackType_t workerTaskStacks[ IOT_TASKPOOL_NUMBER_OF_WORKERS ][ IOT_TASKPOOL_WORKER_STACK_SIZE_BYTES / sizeof( portSTACK_TYPE ) ];\r
-\r
-    /* Static structure to hold te software timer. */\r
-    static StaticTimer_t staticTimer;\r
-\r
-    uint32_t threadsCreated = 0; /* Although initialised before use removing the initialiser here results in compiler warnings. */\r
-    char taskName[ 10 ];\r
-\r
-    /* Check input values for consistency. */\r
-    TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pTaskPool );\r
-\r
-    /* Zero out all data structures. */\r
-    memset( ( void * ) pTaskPool, 0x00, sizeof( _taskPool_t ) );\r
-\r
-    /* Initialize all internal data structure prior to creating all threads. */\r
-    _initTaskPoolControlStructures( pTaskPool );\r
-\r
-    /* Create the timer for a new connection. */\r
-    pTaskPool->timer = xTimerCreateStatic( NULL, /* Text name for the timer, only used for debugging. */\r
-                                           portMAX_DELAY, /* Timer period in ticks. */\r
-                                           pdFALSE, /* pdFALSE means its a one-shot timer. */\r
-                                          ( void * ) pTaskPool, /* Parameter passed into callback. */\r
-                                          _timerCallback, /* Callback that executes when the timer expires. */\r
-                                          &staticTimer ); /* Static storage for the timer's data structure. */\r
-\r
-    /* The task pool will initialize the minimum number of threads requested by the user upon start.\r
-    Note this tailored version of the task pool does not autoscale, but fixes the number of tasks\r
-    in the pool to the originally specified minimum, and the specified maximum value is ignored. */\r
-    /* Create the minimum number of threads specified by the user, and if one fails shutdown and return error. */\r
-    for( threadsCreated = 0; threadsCreated < pInfo->minThreads; )\r
-    {\r
-        /* Generate a unique name for the task. */\r
-        snprintf( taskName, sizeof( taskName ), "pool%d", ( int ) threadsCreated );\r
-\r
-        xTaskCreateStatic( _taskPoolWorker, /* Function that implements the task. */\r
-                           taskName,       /* Text name for the task, used for debugging only. */\r
-                           IOT_TASKPOOL_WORKER_STACK_SIZE_BYTES / sizeof( portSTACK_TYPE ), /* xTaskCreate() expects the stack size to be specified in words. */\r
-                           pTaskPool,       /* Parameter passed into the task. */\r
-                           pInfo->priority, /* Priority at which the task starts running. */\r
-                           &( workerTaskStacks[ threadsCreated ][ 0 ] ), /* Pointer to static storage for the task's stack. */\r
-                           &( workerTaskTCBs[ threadsCreated ] ) ); /* Pointer to static storage for te task's TCB. */\r
-\r
-        /* Upon successful thread creation, increase the number of active threads. */\r
-        pTaskPool->activeThreads++;\r
-        ++threadsCreated;\r
-    }\r
-    pTaskPool->running = true;\r
-\r
-    TASKPOOL_FUNCTION_CLEANUP();\r
-\r
-    TASKPOOL_FUNCTION_CLEANUP_END();\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-static void _destroyTaskPool( _taskPool_t * const pTaskPool )\r
-{\r
-    if( pTaskPool->timer != NULL )\r
-    {\r
-        xTimerDelete( pTaskPool->timer, 0 );\r
-    }\r
-}\r
-\r
-/* ---------------------------------------------------------------------------------------------- */\r
-\r
-static void _taskPoolWorker( void * pUserContext )\r
-{\r
-    IotTaskPool_Assert( pUserContext != NULL );\r
-\r
-    IotTaskPoolRoutine_t userCallback = NULL;\r
-\r
-    /* Extract pTaskPool pointer from context. */\r
-    _taskPool_t * pTaskPool = ( _taskPool_t * ) pUserContext;\r
-\r
-    /* OUTER LOOP: it controls the lifetime of the worker thread. */\r
-    for( ;; )\r
-    {\r
-        IotLink_t * pFirst = NULL;\r
-        _taskPoolJob_t * pJob = NULL;\r
-\r
-        /* Wait on incoming notifications... */\r
-        configASSERT( pTaskPool->dispatchSignal );\r
-        xSemaphoreTake( pTaskPool->dispatchSignal, portMAX_DELAY );\r
-\r
-        /* Acquire the lock to check for incoming notifications. */\r
-        taskENTER_CRITICAL();\r
-        {\r
-            /* Dequeue the first job in FIFO order. */\r
-            pFirst = IotDeQueue_DequeueHead( &pTaskPool->dispatchQueue );\r
-\r
-            /* If there is indeed a job, then update status under lock, and release the lock before processing the job. */\r
-            if( pFirst != NULL )\r
-            {\r
-                /* Extract the job from its link. */\r
-                pJob = IotLink_Container( _taskPoolJob_t, pFirst, link );\r
-\r
-                /* Update status to 'executing'. */\r
-                pJob->status = IOT_TASKPOOL_STATUS_COMPLETED; /*_RB_ Should this be 'executing'? */\r
-                userCallback = pJob->userCallback;\r
-            }\r
-        }\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
-        {\r
-            /* Process the job by invoking the associated callback with the user context.\r
-             * This task pool thread will not be available until the user callback returns.\r
-             */\r
-            {\r
-                IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) == false );\r
-                IotTaskPool_Assert( userCallback != NULL );\r
-\r
-                userCallback( pTaskPool, pJob, pJob->pUserContext );\r
-\r
-                /* This job is finished, clear its pointer. */\r
-                pJob = NULL;\r
-                userCallback = NULL;\r
-            }\r
-\r
-            /* Acquire the lock before updating the job status. */\r
-            taskENTER_CRITICAL();\r
-            {\r
-                /* Try and dequeue the next job in the dispatch queue. */\r
-                IotLink_t * pItem = NULL;\r
-\r
-                /* Dequeue the next job from the dispatch queue. */\r
-                pItem = IotDeQueue_DequeueHead( &pTaskPool->dispatchQueue );\r
-\r
-                /* If there is no job left in the dispatch queue, update the worker status and leave. */\r
-                if( pItem == NULL )\r
-                {\r
-                    taskEXIT_CRITICAL();\r
-\r
-                    /* Abandon the INNER LOOP. Execution will transfer back to the OUTER LOOP condition. */\r
-                    break;\r
-                }\r
-                else\r
-                {\r
-                    pJob = IotLink_Container( _taskPoolJob_t, pItem, link );\r
-\r
-                    userCallback = pJob->userCallback;\r
-                }\r
-\r
-                pJob->status = IOT_TASKPOOL_STATUS_COMPLETED;\r
-            }\r
-            taskEXIT_CRITICAL();\r
-        }\r
-    }\r
-}\r
-\r
-/* ---------------------------------------------------------------------------------------------- */\r
-\r
-static void _initJobsCache( _taskPoolCache_t * const pCache )\r
-{\r
-    IotDeQueue_Create( &pCache->freeList );\r
-\r
-    pCache->freeCount = 0;\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-static void _initializeJob( _taskPoolJob_t * const pJob,\r
-                            IotTaskPoolRoutine_t userCallback,\r
-                            void * pUserContext,\r
-                            bool isStatic )\r
-{\r
-    pJob->link.pNext = NULL;\r
-    pJob->link.pPrevious = NULL;\r
-    pJob->userCallback = userCallback;\r
-    pJob->pUserContext = pUserContext;\r
-\r
-    if( isStatic )\r
-    {\r
-        pJob->flags = IOT_TASK_POOL_INTERNAL_STATIC;\r
-        pJob->status = IOT_TASKPOOL_STATUS_READY;\r
-    }\r
-    else\r
-    {\r
-        pJob->status = IOT_TASKPOOL_STATUS_READY;\r
-    }\r
-}\r
-\r
-static _taskPoolJob_t * _fetchOrAllocateJob( _taskPoolCache_t * const pCache )\r
-{\r
-    _taskPoolJob_t * pJob = NULL;\r
-    IotLink_t * pLink = IotListDouble_RemoveHead( &( pCache->freeList ) );\r
-\r
-    if( pLink != NULL )\r
-    {\r
-        pJob = IotLink_Container( _taskPoolJob_t, pLink, link );\r
-    }\r
-\r
-    /* If there is no available job in the cache, then allocate one. */\r
-    if( pJob == NULL )\r
-    {\r
-        pJob = ( _taskPoolJob_t * ) IotTaskPool_MallocJob( sizeof( _taskPoolJob_t ) );\r
-\r
-        if( pJob != NULL )\r
-        {\r
-            memset( pJob, 0x00, sizeof( _taskPoolJob_t ) );\r
-        }\r
-        else\r
-        {\r
-            /* Log allocation failure for troubleshooting purposes. */\r
-            IotLogInfo( "Failed to allocate job." );\r
-        }\r
-    }\r
-    /* If there was a job in the cache, then make sure we keep the counters up-to-date. */\r
-    else\r
-    {\r
-        IotTaskPool_Assert( pCache->freeCount > 0 );\r
-\r
-        pCache->freeCount--;\r
-    }\r
-\r
-    return pJob;\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-static void _recycleJob( _taskPoolCache_t * const pCache,\r
-                         _taskPoolJob_t * const pJob )\r
-{\r
-    /* We should never try and recycling a job that is linked into some queue. */\r
-    IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) == false );//_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
-    {\r
-        /* Destroy user data, for added safety&security. */\r
-        pJob->userCallback = NULL;\r
-        pJob->pUserContext = NULL;\r
-\r
-        /* Reset the status for added debuggability. */\r
-        pJob->status = IOT_TASKPOOL_STATUS_UNDEFINED;\r
-\r
-        IotListDouble_InsertTail( &pCache->freeList, &pJob->link );\r
-\r
-        pCache->freeCount++;\r
-\r
-        IotTaskPool_Assert( pCache->freeCount >= 1 );\r
-    }\r
-    else\r
-    {\r
-        _destroyJob( pJob );\r
-    }\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-static void _destroyJob( _taskPoolJob_t * const pJob )\r
-{\r
-    /* Destroy user data, for added safety & security. */\r
-    pJob->userCallback = NULL;\r
-    pJob->pUserContext = NULL;\r
-\r
-    /* Reset the status for added debuggability. */\r
-    pJob->status = IOT_TASKPOOL_STATUS_UNDEFINED;\r
-\r
-    /* Only dispose of dynamically allocated jobs. */\r
-    if( ( pJob->flags & IOT_TASK_POOL_INTERNAL_STATIC ) == 0UL )\r
-    {\r
-        IotTaskPool_FreeJob( pJob );\r
-    }\r
-}\r
-\r
-/* ---------------------------------------------------------------------------------------------- */\r
-\r
-static IotTaskPoolError_t _scheduleInternal( _taskPool_t * const pTaskPool,\r
-                                             _taskPoolJob_t * const pJob )\r
-{\r
-    TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
-\r
-    /* Update the job status to 'scheduled'. */\r
-    pJob->status = IOT_TASKPOOL_STATUS_SCHEDULED;\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
-    xSemaphoreGive( pTaskPool->dispatchSignal );\r
-\r
-    TASKPOOL_NO_FUNCTION_CLEANUP_NOLABEL();\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-static bool _matchJobByPointer( const IotLink_t * const pLink,\r
-                                void * pMatch )\r
-{\r
-    const _taskPoolJob_t * const pJob = ( _taskPoolJob_t * ) pMatch;\r
-\r
-    const _taskPoolTimerEvent_t * const pTimerEvent = IotLink_Container( _taskPoolTimerEvent_t, pLink, link );\r
-\r
-    if( pJob == pTimerEvent->job )\r
-    {\r
-        return true;\r
-    }\r
-\r
-    return false;\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-static IotTaskPoolError_t _tryCancelInternal( _taskPool_t * const pTaskPool,\r
-                                              _taskPoolJob_t * const pJob,\r
-                                              IotTaskPoolJobStatus_t * const pStatus )\r
-{\r
-    TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
-\r
-    bool cancelable = false;\r
-\r
-    /* We can only cancel jobs that are either 'ready' (waiting to be scheduled). 'deferred', or 'scheduled'. */\r
-\r
-    IotTaskPoolJobStatus_t currentStatus = pJob->status;\r
-\r
-    switch( currentStatus )\r
-    {\r
-        case IOT_TASKPOOL_STATUS_READY:\r
-        case IOT_TASKPOOL_STATUS_DEFERRED:\r
-        case IOT_TASKPOOL_STATUS_SCHEDULED:\r
-        case IOT_TASKPOOL_STATUS_CANCELED:\r
-            cancelable = true;\r
-            break;\r
-\r
-        case IOT_TASKPOOL_STATUS_COMPLETED:\r
-            /* Log message for debug purposes. */\r
-            IotLogWarn( "Attempt to cancel a job that is already executing, or canceled." );\r
-            break;\r
-\r
-        default:\r
-            /* Log message for debug purposes purposes. */\r
-            IotLogError( "Attempt to cancel a job with an undefined state." );\r
-            break;\r
-    }\r
-\r
-    /* Update the returned status to the current status of the job. */\r
-    if( pStatus != NULL )\r
-    {\r
-        *pStatus = currentStatus;\r
-    }\r
-\r
-    if( cancelable == false )\r
-    {\r
-        TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_CANCEL_FAILED );\r
-    }\r
-    else\r
-    {\r
-        /* Update the status of the job. */\r
-        pJob->status = IOT_TASKPOOL_STATUS_CANCELED;\r
-\r
-        /* If the job is cancelable and its current status is 'scheduled' then unlink it from the dispatch\r
-         * queue and signal any waiting threads. */\r
-        if( currentStatus == IOT_TASKPOOL_STATUS_SCHEDULED )\r
-        {\r
-            /* A scheduled work items must be in the dispatch queue. */\r
-            IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) );\r
-\r
-            IotDeQueue_Remove( &pJob->link );\r
-        }\r
-\r
-        /* If the job current status is 'deferred' then the job has to be pending\r
-         * in the timeouts queue. */\r
-        else if( currentStatus == IOT_TASKPOOL_STATUS_DEFERRED )\r
-        {\r
-            /* Find the timer event associated with the current job. There MUST be one, hence assert if not. */\r
-            IotLink_t * pTimerEventLink = IotListDouble_FindFirstMatch( &pTaskPool->timerEventsList, NULL, _matchJobByPointer, pJob );\r
-            IotTaskPool_Assert( pTimerEventLink != NULL );\r
-\r
-            if( pTimerEventLink != NULL )\r
-            {\r
-                bool shouldReschedule = false;\r
-\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
-                if( pHeadLink == pTimerEventLink )\r
-                {\r
-                    shouldReschedule = true;\r
-                }\r
-\r
-                /* Remove the timer event associated with the canceled job and free the associated memory. */\r
-                IotListDouble_Remove( pTimerEventLink );\r
-                IotTaskPool_FreeTimerEvent( IotLink_Container( _taskPoolTimerEvent_t, pTimerEventLink, link ) );\r
-\r
-                if( shouldReschedule )\r
-                {\r
-                    IotLink_t * pNextTimerEventLink = IotListDouble_PeekHead( &pTaskPool->timerEventsList );\r
-\r
-                    if( pNextTimerEventLink != NULL )\r
-                    {\r
-                        _rescheduleDeferredJobsTimer( pTaskPool->timer, IotLink_Container( _taskPoolTimerEvent_t, pNextTimerEventLink, link ) );\r
-                    }\r
-                }\r
-            }\r
-        }\r
-        else\r
-        {\r
-            /* A cancelable job status should be either 'scheduled' or 'deferrred'. */\r
-            IotTaskPool_Assert( ( currentStatus == IOT_TASKPOOL_STATUS_READY ) || ( currentStatus == IOT_TASKPOOL_STATUS_CANCELED ) );\r
-        }\r
-    }\r
-\r
-    TASKPOOL_NO_FUNCTION_CLEANUP();\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-static int32_t _timerEventCompare( const IotLink_t * const pTimerEventLink1,\r
-                                   const IotLink_t * const pTimerEventLink2 )\r
-{\r
-    const _taskPoolTimerEvent_t * const pTimerEvent1 = IotLink_Container( _taskPoolTimerEvent_t,\r
-                                                                          pTimerEventLink1,\r
-                                                                          link );\r
-    const _taskPoolTimerEvent_t * const pTimerEvent2 = IotLink_Container( _taskPoolTimerEvent_t,\r
-                                                                          pTimerEventLink2,\r
-                                                                          link );\r
-\r
-    if( pTimerEvent1->expirationTime < pTimerEvent2->expirationTime )\r
-    {\r
-        return -1;\r
-    }\r
-\r
-    if( pTimerEvent1->expirationTime > pTimerEvent2->expirationTime )\r
-    {\r
-        return 1;\r
-    }\r
-\r
-    return 0;\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-static void _rescheduleDeferredJobsTimer( TimerHandle_t const timer,\r
-                                          _taskPoolTimerEvent_t * const pFirstTimerEvent )\r
-{\r
-    uint64_t delta = 0;\r
-    TickType_t now = xTaskGetTickCount();\r
-\r
-    if( pFirstTimerEvent->expirationTime > now )\r
-    {\r
-        delta = pFirstTimerEvent->expirationTime - now;\r
-    }\r
-\r
-    if( delta < TASKPOOL_JOB_RESCHEDULE_DELAY_MS )\r
-    {\r
-        delta = TASKPOOL_JOB_RESCHEDULE_DELAY_MS; /* The job will be late... */\r
-    }\r
-\r
-    IotTaskPool_Assert( delta > 0 );\r
-\r
-    if( xTimerChangePeriod( timer, ( uint32_t ) delta, portMAX_DELAY ) == pdFAIL )\r
-    {\r
-        IotLogWarn( "Failed to re-arm timer for task pool" );\r
-    }\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-static void _timerCallback( TimerHandle_t xTimer )\r
-{\r
-    _taskPool_t * pTaskPool = pvTimerGetTimerID( xTimer );\r
-\r
-    IotTaskPool_Assert( pTaskPool );\r
-\r
-    _taskPoolTimerEvent_t * pTimerEvent = NULL;\r
-\r
-    IotLogDebug( "Timer thread started for task pool %p.", pTaskPool );\r
-\r
-    /* Attempt to lock the timer mutex. Return immediately if the mutex cannot be locked.\r
-     * 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
-    taskENTER_CRITICAL(); //_RB_ Critical section is too long.\r
-    {\r
-        /* Dispatch all deferred job whose timer expired, then reset the timer for the next\r
-         * job down the line. */\r
-        for( ; ; )\r
-        {\r
-            /* Peek the first event in the timer event list. */\r
-            IotLink_t * pLink = IotListDouble_PeekHead( &pTaskPool->timerEventsList );\r
-\r
-            /* Check if the timer misfired for any reason.  */\r
-            if( pLink != NULL )\r
-            {\r
-                /* Record the current time. */\r
-                TickType_t now = xTaskGetTickCount();\r
-\r
-                /* Extract the job from its envelope. */\r
-                pTimerEvent = IotLink_Container( _taskPoolTimerEvent_t, pLink, link );\r
-\r
-                /* Check if the first event should be processed now. */\r
-                if( pTimerEvent->expirationTime <= now )\r
-                {\r
-                    /*  Remove the timer event for immediate processing. */\r
-                    IotListDouble_Remove( &( pTimerEvent->link ) );\r
-                }\r
-                else\r
-                {\r
-                    /* The first element in the timer queue shouldn't be processed yet.\r
-                     * Arm the timer for when it should be processed and leave altogether. */\r
-                    _rescheduleDeferredJobsTimer( pTaskPool->timer, pTimerEvent );\r
-\r
-                    break;\r
-                }\r
-            }\r
-            /* If there are no timer events to process, terminate this thread. */\r
-            else\r
-            {\r
-                IotLogDebug( "No further timer events to process. Exiting timer thread." );\r
-\r
-                break;\r
-            }\r
-\r
-            IotLogDebug( "Scheduling job from timer event." );\r
-\r
-            /* Queue the job associated with the received timer event. */\r
-            ( void ) _scheduleInternal( pTaskPool, pTimerEvent->job );\r
-\r
-            /* Free the timer event. */\r
-            IotTaskPool_FreeTimerEvent( pTimerEvent );\r
-        }\r
-    }\r
-    taskEXIT_CRITICAL();\r
-}\r