-\r
-/*-----------------------------------------------------------*/\r
-\r
-IotTaskPoolError_t IotTaskPool_Create( const IotTaskPoolInfo_t * const pInfo,\r
- IotTaskPool_t * const pTaskPool )\r
-{\r
- TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
-\r
- _taskPool_t * pTempTaskPool = NULL;\r
-\r
- /* Verify that the task pool storage is valid. */\r
- TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pTaskPool );\r
-\r
- /* Parameter checking. */\r
- TASKPOOL_ON_ERROR_GOTO_CLEANUP( _performTaskPoolParameterValidation( pInfo ) );\r
-\r
- /* Allocate the memory for the task pool */\r
- pTempTaskPool = ( _taskPool_t * ) IotTaskPool_MallocTaskPool( sizeof( _taskPool_t ) );\r
-\r
- if( pTempTaskPool == NULL )\r
- {\r
- TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY );\r
- }\r
-\r
- memset( pTempTaskPool, 0x00, sizeof( _taskPool_t ) );\r
-\r
- TASKPOOL_SET_AND_GOTO_CLEANUP( _createTaskPool( pInfo, pTempTaskPool ) );\r
-\r
- TASKPOOL_FUNCTION_CLEANUP();\r
-\r
- if( TASKPOOL_FAILED( status ) )\r
- {\r
- if( pTempTaskPool != NULL )\r
- {\r
- IotTaskPool_FreeTaskPool( pTempTaskPool );\r
- }\r
- }\r
- else\r
- {\r
- *pTaskPool = pTempTaskPool;\r
- }\r
-\r
- TASKPOOL_FUNCTION_CLEANUP_END();\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-IotTaskPoolError_t IotTaskPool_Destroy( IotTaskPool_t taskPoolHandle )\r
-{\r
- TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );\r
-\r
- uint32_t count;\r
- bool completeShutdown = true;\r
-\r
- _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;\r
-\r
- /* Track how many threads the task pool owns. */\r
- uint32_t activeThreads;\r
-\r
- /* Parameter checking. */\r
- TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pTaskPool );\r
-\r
- /* 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
- taskENTER_CRITICAL();\r
- {\r
- IotLink_t * pItemLink;\r
-\r
- /* Record how many active threads in the task pool. */\r
- activeThreads = pTaskPool->activeThreads;\r
-\r
- /* Destroying a Task pool happens in six (6) stages: First, (1) we clear the job queue and (2) the timer queue.\r
- * Then (3) we clear the jobs cache. We will then (4) wait for all worker threads to signal exit,\r
- * before (5) setting the exit condition and wake up all active worker threads. Finally (6) destroying\r
- * all task pool data structures and release the associated memory.\r
- */\r
-\r
- /* (1) Clear the job queue. */\r
- do\r
- {\r
- pItemLink = NULL;\r
-\r
- pItemLink = IotDeQueue_DequeueHead( &pTaskPool->dispatchQueue );\r
-\r
- if( pItemLink != NULL )\r
- {\r
- _taskPoolJob_t * pJob = IotLink_Container( _taskPoolJob_t, pItemLink, link );\r
-\r
- _destroyJob( pJob );\r
- }\r
- } while( pItemLink );\r
-\r
- /* (2) Clear the timer queue. */\r
- {\r
- _taskPoolTimerEvent_t * pTimerEvent;\r
-\r
- /* A deferred job may have fired already. Since deferred jobs will go through the same mutex\r
- * the shutdown sequence is holding at this stage, there is no risk for race conditions. Yet, we\r
- * need to let the deferred job to destroy the task pool. */\r
-\r
- pItemLink = IotListDouble_PeekHead( &pTaskPool->timerEventsList );\r
-\r
- if( pItemLink != NULL )\r
- {\r
- TickType_t now = xTaskGetTickCount();\r
-\r
- pTimerEvent = IotLink_Container( _taskPoolTimerEvent_t, pItemLink, link );\r
-\r
- if( pTimerEvent->expirationTime <= now )\r
- {\r
- IotLogDebug( "Shutdown will be deferred to the timer thread" );\r
-\r
- /* Timer may have fired already! Let the timer thread destroy\r
- * complete the taskpool destruction sequence. */\r
- completeShutdown = false;\r
- }\r
-\r
- /* Remove all timers from the timeout list. */\r
- for( ; ; )\r
- {\r
- pItemLink = IotListDouble_RemoveHead( &pTaskPool->timerEventsList );\r
-\r
- if( pItemLink == NULL )\r
- {\r
- break;\r
- }\r
-\r
- pTimerEvent = IotLink_Container( _taskPoolTimerEvent_t, pItemLink, link );\r
-\r
- _destroyJob( pTimerEvent->job );\r
-\r
- IotTaskPool_FreeTimerEvent( pTimerEvent );\r
- }\r
- }\r
- }\r
-\r
- /* (3) Clear the job cache. */\r
- do\r
- {\r
- pItemLink = NULL;\r
-\r
- pItemLink = IotListDouble_RemoveHead( &pTaskPool->jobsCache.freeList );\r
-\r
- if( pItemLink != NULL )\r
- {\r
- _taskPoolJob_t * pJob = IotLink_Container( _taskPoolJob_t, pItemLink, link );\r
-\r
- _destroyJob( pJob );\r
- }\r
- } while( pItemLink );\r
-\r
- /* (4) Set the exit condition. */\r
- _signalShutdown( pTaskPool, activeThreads );\r
- }\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
- {\r
- xSemaphoreTake( pTaskPool->startStopSignal, portMAX_DELAY );\r
- }\r
-\r
- IotTaskPool_Assert( uxSemaphoreGetCount( pTaskPool->startStopSignal ) == 0 );\r
- IotTaskPool_Assert( pTaskPool->activeThreads == 0 );\r
-\r
- /* (6) Destroy all signaling objects. */\r
- if( completeShutdown == true )\r
- {\r
- _destroyTaskPool( pTaskPool );\r
-\r
- /* Do not free the system task pool which is statically allocated. */\r
- if( pTaskPool != &_IotSystemTaskPool )\r
- {\r
- IotTaskPool_FreeTaskPool( pTaskPool );\r
- }\r
- }\r
-\r
- TASKPOOL_NO_FUNCTION_CLEANUP();\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-IotTaskPoolError_t IotTaskPool_SetMaxThreads( IotTaskPool_t taskPoolHandle,\r
- uint32_t maxThreads )\r
-{\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( pTaskPool );\r
- TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( maxThreads < 1UL );\r
-\r
- TASKPOOL_NO_FUNCTION_CLEANUP();\r
-}\r
-\r