summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus
diff options
context:
space:
mode:
authorrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2019-07-22 21:46:13 +0000
committerrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2019-07-22 21:46:13 +0000
commit15fc1dd9a1924dd0736ca478744358ececcbf631 (patch)
tree47dfb4659e54bf4d11af78f53a9cf8921ecc00c5 /FreeRTOS-Plus
parent7b3ed0a651d923a79f32f41141fe13aa13195c9e (diff)
downloadfreertos-15fc1dd9a1924dd0736ca478744358ececcbf631.tar.gz
Backup checking on - part way through optimising task pool.
git-svn-id: http://svn.code.sf.net/p/freertos/code/trunk@2693 1d2547de-c912-0410-9cb9-b8ca96c0e9e2
Diffstat (limited to 'FreeRTOS-Plus')
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/c_sdk/standard/common/taskpool/iot_taskpool.c374
1 files changed, 44 insertions, 330 deletions
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/c_sdk/standard/common/taskpool/iot_taskpool.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/c_sdk/standard/common/taskpool/iot_taskpool.c
index 5c66bc2e2..f0826281a 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/c_sdk/standard/common/taskpool/iot_taskpool.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/c_sdk/standard/common/taskpool/iot_taskpool.c
@@ -45,10 +45,6 @@
#error configSUPPORT_STATIC_ALLOCATION must be set to 1 in FreeRTOSConfig.h to build this file.
#endif
-/* Platform layer includes. */
-//_RB_#include "platform/iot_threads.h"
-//_RB_#include "platform/iot_clock.h"
-
/* Task pool internal include. */
#include "private/iot_taskpool_internal.h"
@@ -72,7 +68,7 @@
* the system libraries as well. The system task pool needs to be initialized before any library is used or
* before any code that posts jobs to the task pool runs.
*/
-_taskPool_t _IotSystemTaskPool = { .dispatchQueue = IOT_DEQUEUE_INITIALIZER };
+static _taskPool_t _IotSystemTaskPool = { .dispatchQueue = IOT_DEQUEUE_INITIALIZER };
/* -------------- Convenience functions to create/recycle/destroy jobs -------------- */
@@ -171,12 +167,10 @@ static IotTaskPoolError_t _performTaskPoolParameterValidation( const IotTaskPool
/**
* Initializes a pre-allocated instance of a task pool.
*
- * @param[in] pInfo The initialization information for the task pool.
* @param[in] pTaskPool The pre-allocated instance of the task pool to initialize.
*
*/
-static IotTaskPoolError_t _initTaskPoolControlStructures( const IotTaskPoolInfo_t * const pInfo,
- _taskPool_t * const pTaskPool );
+static void _initTaskPoolControlStructures( _taskPool_t * const pTaskPool );
/**
* Initializes a pre-allocated instance of a task pool.
@@ -197,14 +191,6 @@ static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo
static void _destroyTaskPool( _taskPool_t * const pTaskPool );
/**
- * Check for the exit condition.
- *
- * @param[in] pTaskPool The task pool to destroy.
- *
- */
-static bool _IsShutdownStarted( const _taskPool_t * const pTaskPool );
-
-/**
* Set the exit condition.
*
* @param[in] pTaskPool The task pool to destroy.
@@ -224,7 +210,6 @@ static void _signalShutdown( _taskPool_t * const pTaskPool,
*/
static IotTaskPoolError_t _scheduleInternal( _taskPool_t * const pTaskPool,
_taskPoolJob_t * const pJob );
-
/**
* Matches a deferred job in the timer queue with its timer event wrapper.
*
@@ -249,12 +234,27 @@ static IotTaskPoolError_t _tryCancelInternal( _taskPool_t * const pTaskPool,
/* ---------------------------------------------------------------------------------------------- */
-IotTaskPool_t IotTaskPool_GetSystemTaskPool( void )
-{
- return &_IotSystemTaskPool;
-}
-
-/*-----------------------------------------------------------*/
+/*
+ * The full IoT Task Pool Library has many use cases, including Linux
+ * development.  Typical FreeRTOS use cases do not require the full
+ * functionality so optimised version is provided specifically for use with
+ * FreeRTOS. Unlike the full version, this optimised version:
+ * + Only supports a single task pool (system task pool) at a time.
+ * + Does not auto-scale by dynamically adding more tasks if the number of
+ * + tasks in the pool becomes exhausted.  The number of tasks in the pool
+ * are fixed at compile time.  See the task pool configuration options for
+ * more information.
+ * + Cannot be shut down - it exists for the lifetime of the application.
+ *
+ * As such this file does not implement the following API functions:
+ * + IotTaskPool_GetSystemTaskPool()
+ * + IotTaskPool_Create()
+ * + IotTaskPool_Destroy()
+ * + IotTaskPool_SetMaxThreads()
+ *
+ * Users who are interested in the functionality of the full IoT Task Pool
+ * library can us it in place of this optimised version.
+ */
IotTaskPoolError_t IotTaskPool_CreateSystemTaskPool( const IotTaskPoolInfo_t * const pInfo )
{
@@ -278,203 +278,6 @@ IotTaskPoolError_t IotTaskPool_CreateSystemTaskPool( const IotTaskPoolInfo_t * c
TASKPOOL_NO_FUNCTION_CLEANUP();
}
-
-/*-----------------------------------------------------------*/
-
-IotTaskPoolError_t IotTaskPool_Create( const IotTaskPoolInfo_t * const pInfo,
- IotTaskPool_t * const pTaskPool )
-{
- TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );
-
- _taskPool_t * pTempTaskPool = NULL;
-
- /* Verify that the task pool storage is valid. */
- TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pTaskPool );
-
- /* Parameter checking. */
- TASKPOOL_ON_ERROR_GOTO_CLEANUP( _performTaskPoolParameterValidation( pInfo ) );
-
- /* Allocate the memory for the task pool */
- pTempTaskPool = ( _taskPool_t * ) IotTaskPool_MallocTaskPool( sizeof( _taskPool_t ) );
-
- if( pTempTaskPool == NULL )
- {
- TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY );
- }
-
- memset( pTempTaskPool, 0x00, sizeof( _taskPool_t ) );
-
- TASKPOOL_SET_AND_GOTO_CLEANUP( _createTaskPool( pInfo, pTempTaskPool ) );
-
- TASKPOOL_FUNCTION_CLEANUP();
-
- if( TASKPOOL_FAILED( status ) )
- {
- if( pTempTaskPool != NULL )
- {
- IotTaskPool_FreeTaskPool( pTempTaskPool );
- }
- }
- else
- {
- *pTaskPool = pTempTaskPool;
- }
-
- TASKPOOL_FUNCTION_CLEANUP_END();
-}
-
-/*-----------------------------------------------------------*/
-
-IotTaskPoolError_t IotTaskPool_Destroy( IotTaskPool_t taskPoolHandle )
-{
- TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );
-
- uint32_t count;
- bool completeShutdown = true;
-
- _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;
-
- /* Track how many threads the task pool owns. */
- uint32_t activeThreads;
-
- /* Parameter checking. */
- TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pTaskPool );
-
- /* Destroying the task pool should be safe, and therefore we will grab the task pool lock.
- * No worker thread or application thread should access any data structure
- * in the task pool while the task pool is being destroyed. */
- taskENTER_CRITICAL();
- {
- IotLink_t * pItemLink;
-
- /* Record how many active threads in the task pool. */
- activeThreads = pTaskPool->activeThreads;
-
- /* Destroying a Task pool happens in six (6) stages: First, (1) we clear the job queue and (2) the timer queue.
- * Then (3) we clear the jobs cache. We will then (4) wait for all worker threads to signal exit,
- * before (5) setting the exit condition and wake up all active worker threads. Finally (6) destroying
- * all task pool data structures and release the associated memory.
- */
-
- /* (1) Clear the job queue. */
- do
- {
- pItemLink = NULL;
-
- pItemLink = IotDeQueue_DequeueHead( &pTaskPool->dispatchQueue );
-
- if( pItemLink != NULL )
- {
- _taskPoolJob_t * pJob = IotLink_Container( _taskPoolJob_t, pItemLink, link );
-
- _destroyJob( pJob );
- }
- } while( pItemLink );
-
- /* (2) Clear the timer queue. */
- {
- _taskPoolTimerEvent_t * pTimerEvent;
-
- /* A deferred job may have fired already. Since deferred jobs will go through the same mutex
- * the shutdown sequence is holding at this stage, there is no risk for race conditions. Yet, we
- * need to let the deferred job to destroy the task pool. */
-
- pItemLink = IotListDouble_PeekHead( &pTaskPool->timerEventsList );
-
- if( pItemLink != NULL )
- {
- TickType_t now = xTaskGetTickCount();
-
- pTimerEvent = IotLink_Container( _taskPoolTimerEvent_t, pItemLink, link );
-
- if( pTimerEvent->expirationTime <= now )
- {
- IotLogDebug( "Shutdown will be deferred to the timer thread" );
-
- /* Timer may have fired already! Let the timer thread destroy
- * complete the taskpool destruction sequence. */
- completeShutdown = false;
- }
-
- /* Remove all timers from the timeout list. */
- for( ; ; )
- {
- pItemLink = IotListDouble_RemoveHead( &pTaskPool->timerEventsList );
-
- if( pItemLink == NULL )
- {
- break;
- }
-
- pTimerEvent = IotLink_Container( _taskPoolTimerEvent_t, pItemLink, link );
-
- _destroyJob( pTimerEvent->job );
-
- IotTaskPool_FreeTimerEvent( pTimerEvent );
- }
- }
- }
-
- /* (3) Clear the job cache. */
- do
- {
- pItemLink = NULL;
-
- pItemLink = IotListDouble_RemoveHead( &pTaskPool->jobsCache.freeList );
-
- if( pItemLink != NULL )
- {
- _taskPoolJob_t * pJob = IotLink_Container( _taskPoolJob_t, pItemLink, link );
-
- _destroyJob( pJob );
- }
- } while( pItemLink );
-
- /* (4) Set the exit condition. */
- _signalShutdown( pTaskPool, activeThreads );
- }
- taskEXIT_CRITICAL();
-
- /* (5) Wait for all active threads to reach the end of their life-span. */
- for( count = 0; count < activeThreads; ++count )
- {
- xSemaphoreTake( pTaskPool->startStopSignal, portMAX_DELAY );
- }
-
- IotTaskPool_Assert( uxSemaphoreGetCount( pTaskPool->startStopSignal ) == 0 );
- IotTaskPool_Assert( pTaskPool->activeThreads == 0 );
-
- /* (6) Destroy all signaling objects. */
- if( completeShutdown == true )
- {
- _destroyTaskPool( pTaskPool );
-
- /* Do not free the system task pool which is statically allocated. */
- if( pTaskPool != &_IotSystemTaskPool )
- {
- IotTaskPool_FreeTaskPool( pTaskPool );
- }
- }
-
- TASKPOOL_NO_FUNCTION_CLEANUP();
-}
-
-/*-----------------------------------------------------------*/
-
-IotTaskPoolError_t IotTaskPool_SetMaxThreads( IotTaskPool_t taskPoolHandle,
- uint32_t maxThreads )
-{
- TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );
-
- _taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;
-
- /* Parameter checking. */
- TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pTaskPool );
- TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( maxThreads < 1UL );
-
- TASKPOOL_NO_FUNCTION_CLEANUP();
-}
-
/*-----------------------------------------------------------*/
IotTaskPoolError_t IotTaskPool_CreateJob( IotTaskPoolRoutine_t userCallback,
@@ -559,7 +362,6 @@ IotTaskPoolError_t IotTaskPool_DestroyRecyclableJob( IotTaskPool_t taskPoolHandl
pool - no other values are allowed. Use the full implementation of this
library if you want multiple task pools (there is more than one task in
each pool. */
-//_RB_could use a TASKPOOL macro to check value and return error.
configASSERT( ( taskPoolHandle == NULL ) || ( taskPoolHandle == &_IotSystemTaskPool ) );
/* Avoid compiler warnings about unused parameters if configASSERT() is not
@@ -688,7 +490,7 @@ IotTaskPoolError_t IotTaskPool_ScheduleDeferred( IotTaskPool_t taskPoolHandle,
pTimerEvent->link.pNext = NULL;
pTimerEvent->link.pPrevious = NULL;
pTimerEvent->expirationTime = now + pdMS_TO_TICKS( timeMs );
- pTimerEvent->job = job;
+ pTimerEvent->job = job; //_RB_ Think up to here can be outside the critical section.
/* Append the timer event to the timer list. */
IotListDouble_InsertSorted( &pTaskPool->timerEventsList, &pTimerEvent->link, _timerEventCompare );
@@ -723,9 +525,15 @@ IotTaskPoolError_t IotTaskPool_GetStatus( IotTaskPool_t taskPoolHandle,
{
TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );
- /* Parameter checking. */
-//_RB_ TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle ); /* What is the point of this parameter? */
+ /* This lean version of the task pool only supports the task pool created
+ by this library (the system task pool). NULL means use the system task
+ pool - no other values are allowed. Use the full implementation of this
+ library if you want multiple task pools (there is more than one task in
+ each pool. */
+ configASSERT( ( taskPoolHandle == NULL ) || ( taskPoolHandle == &_IotSystemTaskPool ) );
( void ) taskPoolHandle;
+
+ /* Parameter checking. */
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( job );
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pStatus );
*pStatus = IOT_TASKPOOL_STATUS_UNDEFINED;
@@ -747,7 +555,7 @@ IotTaskPoolError_t IotTaskPool_TryCancel( IotTaskPool_t taskPoolHandle,
{
TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );
- _taskPool_t * pTaskPool = &_IotSystemTaskPool;
+ _taskPool_t * const pTaskPool = &_IotSystemTaskPool;
/* This lean version of the task pool only supports the task pool created
by this library (the system task pool). NULL means use the system task
@@ -835,14 +643,8 @@ static IotTaskPoolError_t _performTaskPoolParameterValidation( const IotTaskPool
TASKPOOL_NO_FUNCTION_CLEANUP();
}
-static IotTaskPoolError_t _initTaskPoolControlStructures( const IotTaskPoolInfo_t * const pInfo,
- _taskPool_t * const pTaskPool )
+static void _initTaskPoolControlStructures( _taskPool_t * const pTaskPool )
{
- TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );
-
- bool semStartStopInit = false;
- bool semDispatchInit = false;
-
/* Initialize a job data structures that require no de-initialization.
* All other data structures carry a value of 'NULL' before initailization.
*/
@@ -851,46 +653,9 @@ static IotTaskPoolError_t _initTaskPoolControlStructures( const IotTaskPoolInfo_
_initJobsCache( &pTaskPool->jobsCache );
- /* Initialize the semaphore to ensure all threads have started. */
- pTaskPool->startStopSignal = xSemaphoreCreateCountingStatic( pInfo->minThreads, 0, &pTaskPool->startStopSignalBuffer );
-
- if( pTaskPool->startStopSignal != NULL )
- {
- semStartStopInit = true;
-
- /* Initialize the semaphore for waiting for incoming work. */
- pTaskPool->dispatchSignal = xSemaphoreCreateCountingStatic( TASKPOOL_MAX_SEM_VALUE, 0, &pTaskPool->dispatchSignalBuffer );
-
- if( pTaskPool->dispatchSignal != NULL )
- {
- semDispatchInit = true;
- }
- else
- {
- TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY );
- }
- }
- else
- {
- TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY );
- }
-
- TASKPOOL_FUNCTION_CLEANUP();
-
- if( TASKPOOL_FAILED( status ) )
- {
- if( semStartStopInit )
- {
- vSemaphoreDelete( &pTaskPool->startStopSignal );
- }
-
- if( semDispatchInit )
- {
- vSemaphoreDelete( &pTaskPool->dispatchSignal );
- }
- }
-
- TASKPOOL_FUNCTION_CLEANUP_END();
+ /* Initialize the semaphore for waiting for incoming work. Cannot fail as
+ statically allocated. */
+ pTaskPool->dispatchSignal = xSemaphoreCreateCountingStatic( TASKPOOL_MAX_SEM_VALUE, 0, &pTaskPool->dispatchSignalBuffer );
}
static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo,
@@ -898,7 +663,6 @@ static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo
{
TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );
- uint32_t count;
uint32_t threadsCreated = 0; /* Although initialised before use removing the initialiser here results in compiler warnings. */
char cTaskName[ 10 ];
@@ -909,7 +673,7 @@ static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo
memset( ( void * ) pTaskPool, 0x00, sizeof( _taskPool_t ) );
/* Initialize all internal data structure prior to creating all threads. */
- TASKPOOL_ON_ERROR_GOTO_CLEANUP( _initTaskPoolControlStructures( pInfo, pTaskPool ) );
+ _initTaskPoolControlStructures( pTaskPool );
/* Create the timer for a new connection. */
pTaskPool->timer = xTimerCreate( NULL, portMAX_DELAY, pdFALSE, ( void * ) pTaskPool, _timerCallback );
@@ -921,16 +685,15 @@ static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo
TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY );
}
- /* The task pool will initialize the minimum number of threads requested by the user upon start. */
- /* When a thread is created, it will signal a semaphore to signify that it is about to wait on incoming */
- /* jobs. A thread can be woken up for exit or for new jobs only at that point in time. */
- /* The exit condition is setting the maximum number of threads to 0. */
-
+ /* The task pool will initialize the minimum number of threads requested by the user upon start.
+ Note this tailored version of the task pool does not autoscale, but fixes the number of tasks
+ in the pool to the originally specified minimum, and the specified maximum value is ignored. */
/* Create the minimum number of threads specified by the user, and if one fails shutdown and return error. */
for( threadsCreated = 0; threadsCreated < pInfo->minThreads; )
{
- TaskHandle_t task = NULL; //_RB_ need to check compiles with C89
+ TaskHandle_t task = NULL;
+ /* Generate a unique name for the task. */
snprintf( cTaskName, sizeof( cTaskName ), "pool%d", ( int ) threadsCreated );
BaseType_t res = xTaskCreate( _taskPoolWorker,
@@ -941,7 +704,7 @@ static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo
&task );
/* Create one thread. */
- if( res == pdFALSE )
+ if( res == pdFALSE ) //_RB_ would not be needed if tasks are created statically.
{
IotLogError( "Could not create worker thread! Exiting..." );
@@ -958,24 +721,11 @@ static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo
TASKPOOL_FUNCTION_CLEANUP();
- /* Wait for threads to be ready to wait on the condition, so that threads are actually able to receive messages. */
- for( count = 0; count < threadsCreated; ++count )
- {
- xSemaphoreTake( pTaskPool->startStopSignal, portMAX_DELAY ); /*_RB_ Is waiting necessary, and if so, is a semaphore necessary? */
- }
-
/* In case of failure, wait on the created threads to exit. */
if( TASKPOOL_FAILED( status ) )
{
/* Set the exit condition for the newly created threads. */
_signalShutdown( pTaskPool, threadsCreated );
-
- /* Signal all threads to exit. */
- for( count = 0; count < threadsCreated; ++count )
- {
- xSemaphoreTake( pTaskPool->startStopSignal, portMAX_DELAY );
- }
-
_destroyTaskPool( pTaskPool );
}
@@ -997,11 +747,6 @@ static void _destroyTaskPool( _taskPool_t * const pTaskPool )
{
vSemaphoreDelete( pTaskPool->dispatchSignal );
}
-
- if( pTaskPool->startStopSignal != NULL )
- {
- vSemaphoreDelete( pTaskPool->startStopSignal );
- }
}
/* ---------------------------------------------------------------------------------------------- */
@@ -1016,9 +761,6 @@ static void _taskPoolWorker( void * pUserContext )
/* Extract pTaskPool pointer from context. */
_taskPool_t * pTaskPool = ( _taskPool_t * ) pUserContext;
- /* Signal that this worker completed initialization and it is ready to receive notifications. */
- ( void ) xSemaphoreGive( pTaskPool->startStopSignal );
-
/* OUTER LOOP: it controls the lifetiem of the worker thread: exit condition for a worker thread
* is setting maxThreads to zero. A worker thread is running until the maximum number of allowed
* threads is not zero and the active threads are less than the maximum number of allowed threads.
@@ -1036,23 +778,6 @@ static void _taskPoolWorker( void * pUserContext )
*/
taskENTER_CRITICAL();
{
- /* If the exit condition is verified, update the number of active threads and exit the loop. */
- if( _IsShutdownStarted( pTaskPool ) )
- {
- IotLogDebug( "Worker thread exiting because exit condition was set." );
-
- /* Decrease the number of active threads. */
- pTaskPool->activeThreads--;
-
- taskEXIT_CRITICAL();
-
- /* Signal that this worker is exiting. */
- xSemaphoreGive( pTaskPool->startStopSignal );
-
- /* On shutdown, abandon the OUTER LOOP immediately. */
- break;
- }
-
/* Dequeue the first job in FIFO order. */
pFirst = IotDeQueue_DequeueHead( &pTaskPool->dispatchQueue );
@@ -1476,17 +1201,6 @@ static void _timerCallback( TimerHandle_t xTimer )
*/
taskENTER_CRITICAL();
{
- /* Check again for shutdown and bail out early in case. */
- if( _IsShutdownStarted( pTaskPool ) )
- {
- taskEXIT_CRITICAL();
-
- /* Complete the shutdown sequence. */
- _destroyTaskPool( pTaskPool );
-
- return;
- }
-
/* Dispatch all deferred job whose timer expired, then reset the timer for the next
* job down the line. */
for( ; ; )