In small FreeRTOS applications it is unlikely there will be any task pools other than the system task pool. IotTaskPool_CreateRecyclableSystemJob() is therefore introduced to complement IotTaskPool_CreateRecyclableJob() that does not require the handle of the target task pool to be specified as a parameter. Likewise IotTaskPool_ScheduleSystemJob() is introduced to complement IotTaskPool_ScheduleJob() for the same reason.

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().
pull/4/head
Richard Barry 6 years ago
parent 76cc2a00c6
commit e75b609c74

@ -147,7 +147,7 @@
<link>
<name>FreeRTOS-Plus-IoT-SDK/c_sdk/standard/common/taskpool/iot_taskpool.c</name>
<type>1</type>
<locationURI>PARENT-5-FREERTOS_ROOT/T/amazon-freertos-master_fr_task_pool/libraries/c_sdk/standard/common/taskpool/iot_taskpool.c</locationURI>
<locationURI>FREERTOS_ROOT/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/c_sdk/standard/common/taskpool/iot_taskpool.c</locationURI>
</link>
</linkedResources>
<variableList>

@ -1,3 +1,30 @@
/*
* FreeRTOS Kernel V10.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
@ -9,6 +36,7 @@
* Prototypes for the functions that demonstrate the task pool API.
*/
static void prvExample_BasicSingleJob( void );
static void prvExample_BasicRecyclableJob( void );
/* Prototypes of the callback functions used in the examples. */
static void prvSimpleTaskNotifyCallback( IotTaskPool_t pTaskPool, IotTaskPoolJob_t pJob, void *pUserContext );
@ -62,6 +90,34 @@ int main( void )
}
/*-----------------------------------------------------------*/
static void prvTaskPoolDemoTask( void *pvParameters )
{
IotTaskPoolError_t xResult;
/* Remove compiler warnings about unused parameters. */
( void ) pvParameters;
/* The task pool must be created before it can be used. */
// xResult = IotTaskPool_CreateSystemTaskPool( &xTaskPoolParameters );
// configASSERT( xResult == IOT_TASKPOOL_SUCCESS );
/* Attempting to create the task pool again should then appear to succeed
(in case it is initialised by more than one library), but have no effect. */
// xResult = IotTaskPool_CreateSystemTaskPool( &xTaskPoolParameters );
// configASSERT( xResult == IOT_TASKPOOL_SUCCESS );
for( ;; )
{
/* Run through each task pool example in turn. See the comments in the
below functions for details of their behaviour. */
prvExample_BasicSingleJob();
prvExample_BasicRecyclableJob();
vTaskDelete( NULL );
}
}
/*-----------------------------------------------------------*/
static void prvSimpleTaskNotifyCallback( IotTaskPool_t pTaskPool, IotTaskPoolJob_t pJob, void *pUserContext )
{
TaskHandle_t xTaskToNotify = ( TaskHandle_t ) pUserContext;
@ -80,46 +136,57 @@ static void prvExample_BasicSingleJob( void )
IotTaskPoolJobStorage_t xJobStorage;
IotTaskPoolJob_t xJob;
IotTaskPoolError_t xResult;
uint32_t ulReturn;
const TickType_t xShortDelay = pdMS_TO_TICKS( 200 );
/* Ensure the notification count is 0 before scheduling the job. */
while( ulTaskNotifyTake( pdTRUE, 0 ) != 0 );
/* Create and schedule a job using the handle of this task as the job's
context and the function that sends a notification to the task handle as
the jobs callback function. */
the jobs callback function. The job is created using storage allocated on
the stack of this function - so no memory is allocated. */
xResult = IotTaskPool_CreateJob( prvSimpleTaskNotifyCallback, /* Callback function. */
( void * ) xTaskGetCurrentTaskHandle(), /* Job context. */
&xJobStorage,
&xJob );
configASSERT( xResult == IOT_TASKPOOL_SUCCESS );
IotTaskPool_ScheduleSystem( xJob, 0 );
xResult = IotTaskPool_ScheduleSystemJob( xJob, 0 );
configASSERT( xResult == IOT_TASKPOOL_SUCCESS );
/* Wait for the notification coming from the job's callback function. */
ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
ulReturn = ulTaskNotifyTake( pdTRUE, xShortDelay );
configASSERT( ulReturn );
}
/*-----------------------------------------------------------*/
static void prvTaskPoolDemoTask( void *pvParameters )
static void prvExample_BasicRecyclableJob( void )
{
IotTaskPoolJob_t xJob;
IotTaskPoolError_t xResult;
uint32_t ulReturn;
const TickType_t xShortDelay = pdMS_TO_TICKS( 200 );
/* Remove compiler warnings about unused parameters. */
( void ) pvParameters;
/* Ensure the notification count is 0 before scheduling the job. */
while( ulTaskNotifyTake( pdTRUE, 0 ) != 0 );
/* The task pool must be created before it can be used. */
xResult = IotTaskPool_CreateSystemTaskPool( &xTaskPoolParameters );
/* Create and schedule a job using the handle of this task as the job's
context and the function that sends a notification to the task handle as
the jobs callback function. The job is created as a recyclable job - so it
is allocated inside the create function, but can then be used again and
again. */
xResult = IotTaskPool_CreateRecyclableSystemJob( prvSimpleTaskNotifyCallback,
( void * ) xTaskGetCurrentTaskHandle(),
&xJob );
configASSERT( xResult == IOT_TASKPOOL_SUCCESS );
for( ;; )
{
/* Run through each task pool example in turn. See the comments in the
below functions for details of their behaviour. */
prvExample_BasicSingleJob();
xResult = IotTaskPool_ScheduleSystemJob( xJob, 0 );
configASSERT( xResult == IOT_TASKPOOL_SUCCESS );
vTaskDelete( NULL );
}
/* Wait for the notification coming from the job's callback function. */
ulReturn = ulTaskNotifyTake( pdTRUE, xShortDelay );
configASSERT( ulReturn );
}
/*-----------------------------------------------------------*/

@ -53,9 +53,11 @@
* - @functionname{taskpool_function_setmaxthreads}
* - @functionname{taskpool_function_createjob}
* - @functionname{taskpool_function_createrecyclablejob}
* - @functionname{taskpool_function_createrecyclablesystemjob}
* - @functionname{taskpool_function_destroyrecyclablejob}
* - @functionname{taskpool_function_recyclejob}
* - @functionname{taskpool_function_schedule}
* - @functionname{taskpool_function_schedulesystemjob}
* - @functionname{taskpool_function_scheduledeferred}
* - @functionname{taskpool_function_getstatus}
* - @functionname{taskpool_function_trycancel}
@ -71,9 +73,11 @@
* @functionpage{IotTaskPool_SetMaxThreads,taskpool,setmaxthreads}
* @functionpage{IotTaskPool_CreateJob,taskpool,createjob}
* @functionpage{IotTaskPool_CreateRecyclableJob,taskpool,createrecyclablejob}
* @functionpage{IotTaskPool_CreateRecyclableSystemJob,taskpool,createrecyclablesystemjob}
* @functionpage{IotTaskPool_DestroyRecyclableJob,taskpool,destroyrecyclablejob}
* @functionpage{IotTaskPool_RecycleJob,taskpool,recyclejob}
* @functionpage{IotTaskPool_Schedule,taskpool,schedule}
* @functionpage{IotTaskPool_ScheduleSystemJob,taskpool,schedule}
* @functionpage{IotTaskPool_ScheduleDeferred,taskpool,scheduledeferred}
* @functionpage{IotTaskPool_GetStatus,taskpool,getstatus}
* @functionpage{IotTaskPool_TryCancel,taskpool,trycancel}
@ -255,6 +259,36 @@ IotTaskPoolError_t IotTaskPool_CreateRecyclableJob( IotTaskPool_t taskPool,
IotTaskPoolJob_t * const pJob );
/* @[declare_taskpool_createrecyclablejob] */
/**
* brief Creates a job for the system task pool by allocating the job dynamically.
* The system task pool is the task pool created by @ref IotTaskPool_CreateSystemTaskPool.
*
* A recyclable job does not need to be allocated twice, but it can rather be reused through
* subsequent calls to @ref IotTaskPool_CreateRecyclableJob.
*
* @param[in] userCallback A user-specified callback for the job.
* @param[in] pUserContext A user-specified context for the callback.
* @param[out] pJob A pointer to an instance of @ref IotTaskPoolJob_t that will be initialized when this
* function returns successfully. This handle can be used to inspect the job status with
* @ref IotTaskPool_GetStatus or cancel the job with @ref IotTaskPool_TryCancel, etc....
*
* @return One of the following:
* - #IOT_TASKPOOL_SUCCESS
* - #IOT_TASKPOOL_BAD_PARAMETER
* - #IOT_TASKPOOL_NO_MEMORY
* - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS
*
* @note This function will not allocate memory.
*
* @warning A recyclable job should be recycled with a call to @ref IotTaskPool_RecycleJob rather than destroyed.
*
*/
/* @[declare_taskpool_createrecyclablesystemjob] */
IotTaskPoolError_t IotTaskPool_CreateRecyclableSystemJob( IotTaskPoolRoutine_t userCallback,
void * pUserContext,
IotTaskPoolJob_t * const pJob );
/* @[declare_taskpool_createrecyclablesystemjob] */
/**
* @brief This function un-initializes a job.
*
@ -413,7 +447,7 @@ IotTaskPoolError_t IotTaskPool_Schedule( IotTaskPool_t taskPool,
uint32_t flags );
/**
* @brief This function schedules a job created with @ref IotTaskPool_CreateJob or @ref IotTaskPool_CreateRecyclableJob
* @brief This function schedules a job created with @ref IotTaskPool_CreateJob or @ref IotTaskPool_CreateRecyclableJob @ref IotTaskPool_CreateRecyclableSystemJob
* against the system task pool. The system task pool is the task pool created by @ref IotTaskPool_CreateSystemTaskPool.
*
* See @ref taskpool_design for a description of the jobs lifetime and interaction with the threads used in the task pool
@ -464,7 +498,7 @@ IotTaskPoolError_t IotTaskPool_Schedule( IotTaskPool_t taskPool,
* // Statically allocate one job, schedule it.
* IotTaskPool_CreateJob( &ExecutionCb, &userContext, &job );
*
* IotTaskPoolError_t errorSchedule = IotTaskPool_ScheduleSystem( &job, 0 );
* IotTaskPoolError_t errorSchedule = IotTaskPool_ScheduleSystemJob( &job, 0 );
*
* switch ( errorSchedule )
* {
@ -488,11 +522,11 @@ IotTaskPoolError_t IotTaskPool_Schedule( IotTaskPool_t taskPool,
* }
* @endcode
*/
/* @[declare_taskpool_schedule] */
IotTaskPoolError_t IotTaskPool_ScheduleSystem( IotTaskPoolJob_t pJob,
/* @[declare_taskpool_schedulesystemjob] */
IotTaskPoolError_t IotTaskPool_ScheduleSystemJob( IotTaskPoolJob_t pJob,
uint32_t flags );
/* @[declare_taskpool_schedule] */
/* @[declare_taskpool_schedulesystemjob] */
/**
* @brief This function schedules a job created with @ref IotTaskPool_CreateJob against the task pool

@ -43,30 +43,6 @@
/* Task pool internal include. */
#include "private/iot_taskpool_internal.h"
/**
* @brief Enter a critical section by disabling interrupts.
*
*/
#define TASKPOOL_ENTER_CRITICAL() taskENTER_CRITICAL()
/**
* @brief Enter a critical section by disabling interrupts.
*
*/
#define TASKPOOL_ENTER_CRITICAL_FROM_ISR() taskENTER_CRITICAL_FROM_ISR()
/**
* @brief Exit a critical section by re-enabling interrupts.
*
*/
#define TASKPOOL_EXIT_CRITICAL() taskEXIT_CRITICAL()
/**
* @brief Exit a critical section by re-enabling interrupts.
*
*/
#define TASKPOOL_EXIT_CRITICAL_FROM_ISR( x ) taskEXIT_CRITICAL_FROM_ISR( x )
/**
* @brief Maximum semaphore value for wait operations.
*/
@ -171,7 +147,7 @@ static void _rescheduleDeferredJobsTimer( TimerHandle_t const timer,
*
* param[in] timer The timer to handle.
*/
static void _timerThread( TimerHandle_t xTimer );
static void _timerCallback( TimerHandle_t xTimer );
/* -------------- Convenience functions to create/initialize/destroy the task pool -------------- */
@ -238,8 +214,7 @@ static void _signalShutdown( _taskPool_t * const pTaskPool,
*
*/
static IotTaskPoolError_t _scheduleInternal( _taskPool_t * const pTaskPool,
_taskPoolJob_t * const pJob,
uint32_t flags );
_taskPoolJob_t * const pJob );
/**
* Matches a deferred job in the timer queue with its timer event wrapper.
@ -276,11 +251,21 @@ IotTaskPoolError_t IotTaskPool_CreateSystemTaskPool( const IotTaskPoolInfo_t * c
{
TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );
/* At this time the task pool cannot be created before the scheduler has
started because the function attempts to block on synchronization
primitives (although I'm not sure why). */
configASSERT( xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED );
/* Guard against multiple attempts to create the system task pool in case
this function is called by more than one library initialization routine. */
if( _IotSystemTaskPool.running == false )
{
/* Parameter checking. */
TASKPOOL_ON_ERROR_GOTO_CLEANUP( _performTaskPoolParameterValidation( pInfo ) );
/* Create the system task pool pool. */
TASKPOOL_SET_AND_GOTO_CLEANUP( _createTaskPool( pInfo, &_IotSystemTaskPool ) );
}
TASKPOOL_NO_FUNCTION_CLEANUP();
}
@ -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.
* No worker thread or application thread should access any data structure
* in the task pool while the task pool is being destroyed. */
TASKPOOL_ENTER_CRITICAL();
taskENTER_CRITICAL();
{
IotLink_t * pItemLink;
@ -439,7 +424,7 @@ IotTaskPoolError_t IotTaskPool_Destroy( IotTaskPool_t taskPoolHandle )
/* (4) Set the exit condition. */
_signalShutdown( pTaskPool, activeThreads );
}
TASKPOOL_EXIT_CRITICAL();
taskEXIT_CRITICAL();
/* (5) Wait for all active threads to reach the end of their life-span. */
for( count = 0; count < activeThreads; ++count )
@ -505,6 +490,15 @@ IotTaskPoolError_t IotTaskPool_CreateJob( IotTaskPoolRoutine_t userCallback,
/*-----------------------------------------------------------*/
IotTaskPoolError_t IotTaskPool_CreateRecyclableSystemJob( IotTaskPoolRoutine_t userCallback,
void * pUserContext,
IotTaskPoolJob_t * const pJob )
{
return IotTaskPool_CreateRecyclableJob ( &_IotSystemTaskPool, userCallback, pUserContext, pJob );
}
/*-----------------------------------------------------------*/
IotTaskPoolError_t IotTaskPool_CreateRecyclableJob( IotTaskPool_t taskPoolHandle,
IotTaskPoolRoutine_t userCallback,
void * pUserContext,
@ -520,12 +514,12 @@ IotTaskPoolError_t IotTaskPool_CreateRecyclableJob( IotTaskPool_t taskPoolHandle
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( userCallback );
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( ppJob );
TASKPOOL_ENTER_CRITICAL();
taskENTER_CRITICAL();
{
/* Bail out early if this task pool is shutting down. */
pTempJob = _fetchOrAllocateJob( &pTaskPool->jobsCache );
}
TASKPOOL_EXIT_CRITICAL();
taskEXIT_CRITICAL();
if( pTempJob == NULL )
{
@ -548,7 +542,8 @@ IotTaskPoolError_t IotTaskPool_DestroyRecyclableJob( IotTaskPool_t taskPoolHandl
{
TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );
_taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;
( void ) taskPoolHandle;
_taskPoolJob_t * pJob = ( _taskPoolJob_t * ) pJobHandle;
/* Parameter checking. */
@ -575,13 +570,13 @@ IotTaskPoolError_t IotTaskPool_RecycleJob( IotTaskPool_t taskPoolHandle,
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJob );
TASKPOOL_ENTER_CRITICAL();
taskENTER_CRITICAL();
{
IotTaskPool_Assert( IotLink_IsLinked( &pJob->link ) == false );
_recycleJob( &pTaskPool->jobsCache, pJob );
}
TASKPOOL_EXIT_CRITICAL();
taskEXIT_CRITICAL();
TASKPOOL_NO_FUNCTION_CLEANUP();
}
@ -596,22 +591,32 @@ IotTaskPoolError_t IotTaskPool_Schedule( IotTaskPool_t taskPoolHandle,
_taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;
configASSERT( pTaskPool->running != false );
/* Parameter checking. */
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pJob );
TASKPOOL_ON_ARG_ERROR_GOTO_CLEANUP( ( flags != 0UL ) && ( flags != IOT_TASKPOOL_JOB_HIGH_PRIORITY ) );
TASKPOOL_ENTER_CRITICAL();
taskENTER_CRITICAL(); //_RB_ Critical section is too long - does the whole thing need to be protected?
{
_scheduleInternal( pTaskPool, pJob, flags );
_scheduleInternal( pTaskPool, pJob );
}
TASKPOOL_EXIT_CRITICAL();
taskEXIT_CRITICAL();
TASKPOOL_NO_FUNCTION_CLEANUP();
}
/*-----------------------------------------------------------*/
IotTaskPoolError_t IotTaskPool_ScheduleSystemJob( IotTaskPoolJob_t pJob,
uint32_t flags )
{
return IotTaskPool_Schedule( &_IotSystemTaskPool, pJob, flags );
}
/*-----------------------------------------------------------*/
IotTaskPoolError_t IotTaskPool_ScheduleDeferred( IotTaskPool_t taskPoolHandle,
IotTaskPoolJob_t job,
uint32_t timeMs )
@ -629,13 +634,13 @@ IotTaskPoolError_t IotTaskPool_ScheduleDeferred( IotTaskPool_t taskPoolHandle,
TASKPOOL_SET_AND_GOTO_CLEANUP( IotTaskPool_Schedule( pTaskPool, job, 0 ) );
}
TASKPOOL_ENTER_CRITICAL();
taskENTER_CRITICAL();
{
_taskPoolTimerEvent_t * pTimerEvent = IotTaskPool_MallocTimerEvent( sizeof( _taskPoolTimerEvent_t ) );
if( pTimerEvent == NULL )
{
TASKPOOL_EXIT_CRITICAL();
taskEXIT_CRITICAL();
TASKPOOL_SET_AND_GOTO_CLEANUP( IOT_TASKPOOL_NO_MEMORY );
}
@ -669,7 +674,7 @@ IotTaskPoolError_t IotTaskPool_ScheduleDeferred( IotTaskPool_t taskPoolHandle,
_rescheduleDeferredJobsTimer( pTaskPool->timer, pTimerEvent );
}
}
TASKPOOL_EXIT_CRITICAL();
taskEXIT_CRITICAL();
TASKPOOL_NO_FUNCTION_CLEANUP();
}
@ -682,19 +687,17 @@ IotTaskPoolError_t IotTaskPool_GetStatus( IotTaskPool_t taskPoolHandle,
{
TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );
_taskPool_t * pTaskPool = ( _taskPool_t * ) taskPoolHandle;
/* Parameter checking. */
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( taskPoolHandle );
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( job );
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pStatus );
*pStatus = IOT_TASKPOOL_STATUS_UNDEFINED;
TASKPOOL_ENTER_CRITICAL();
taskENTER_CRITICAL();
{
*pStatus = job->status;
}
TASKPOOL_EXIT_CRITICAL();
taskEXIT_CRITICAL();
TASKPOOL_NO_FUNCTION_CLEANUP();
}
@ -718,11 +721,11 @@ IotTaskPoolError_t IotTaskPool_TryCancel( IotTaskPool_t taskPoolHandle,
*pStatus = IOT_TASKPOOL_STATUS_UNDEFINED;
}
TASKPOOL_ENTER_CRITICAL();
taskENTER_CRITICAL();
{
status = _tryCancelInternal( pTaskPool, job, pStatus );
}
TASKPOOL_EXIT_CRITICAL();
taskEXIT_CRITICAL();
TASKPOOL_NO_FUNCTION_CLEANUP();
}
@ -855,7 +858,7 @@ static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo
TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );
uint32_t count;
uint32_t threadsCreated = 0;
uint32_t threadsCreated;
/* Check input values for consistency. */
TASKPOOL_ON_NULL_ARG_GOTO_CLEANUP( pTaskPool );
@ -866,8 +869,8 @@ static IotTaskPoolError_t _createTaskPool( const IotTaskPoolInfo_t * const pInfo
/* Initialize all internal data structure prior to creating all threads. */
TASKPOOL_ON_ERROR_GOTO_CLEANUP( _initTaskPoolControlStructures( pInfo, pTaskPool ) );
/* Create the timer mutex for a new connection. */
pTaskPool->timer = xTimerCreate( NULL, portMAX_DELAY, pdFALSE, ( void * ) pTaskPool, _timerThread );
/* Create the timer for a new connection. */
pTaskPool->timer = xTimerCreate( NULL, portMAX_DELAY, pdFALSE, ( void * ) pTaskPool, _timerCallback );
if( pTaskPool->timer == NULL )
{
@ -876,13 +879,13 @@ 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 reqeusted by the user upon start. */
/* 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. */
/* Create the minimum number of threads specified by the user, and if one fails shutdown and return error. */
for( ; threadsCreated < pInfo->minThreads; )
for( threadsCreated = 0; threadsCreated < pInfo->minThreads; )
{
TaskHandle_t task = NULL;
@ -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. */
for( count = 0; count < threadsCreated; ++count )
{
xSemaphoreTake( pTaskPool->startStopSignal, portMAX_DELAY );
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. */
@ -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,
* or before waiting for incoming notifications.
*/
TASKPOOL_ENTER_CRITICAL();
taskENTER_CRITICAL();
{
/* If the exit condition is verified, update the number of active threads and exit the loop. */
if( _IsShutdownStarted( pTaskPool ) )
@ -997,7 +1000,7 @@ static void _taskPoolWorker( void * pUserContext )
/* Decrease the number of active threads. */
pTaskPool->activeThreads--;
TASKPOOL_EXIT_CRITICAL();
taskEXIT_CRITICAL();
/* Signal that this worker is exiting. */
xSemaphoreGive( pTaskPool->startStopSignal );
@ -1020,7 +1023,7 @@ static void _taskPoolWorker( void * pUserContext )
userCallback = pJob->userCallback;
}
}
TASKPOOL_EXIT_CRITICAL();
taskEXIT_CRITICAL();
/* INNER LOOP: it controls the execution of jobs: the exit condition is the lack of a job to execute. */
while( pJob != NULL )
@ -1047,7 +1050,7 @@ static void _taskPoolWorker( void * pUserContext )
}
/* Acquire the lock before updating the job status. */
TASKPOOL_ENTER_CRITICAL();
taskENTER_CRITICAL();
{
/* Try and dequeue the next job in the dispatch queue. */
IotLink_t * pItem = NULL;
@ -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. */
if( pItem == NULL )
{
TASKPOOL_EXIT_CRITICAL();
taskEXIT_CRITICAL();
/* Abandon the INNER LOOP. Execution will tranfer back to the OUTER LOOP condition. */
break;
@ -1072,7 +1075,7 @@ static void _taskPoolWorker( void * pUserContext )
pJob->status = IOT_TASKPOOL_STATUS_COMPLETED;
}
TASKPOOL_EXIT_CRITICAL();
taskEXIT_CRITICAL();
}
} while( running == true );
@ -1222,8 +1225,7 @@ static void _signalShutdown( _taskPool_t * const pTaskPool,
/* ---------------------------------------------------------------------------------------------- */
static IotTaskPoolError_t _scheduleInternal( _taskPool_t * const pTaskPool,
_taskPoolJob_t * const pJob,
uint32_t flags )
_taskPoolJob_t * const pJob )
{
TASKPOOL_FUNCTION_ENTRY( IOT_TASKPOOL_SUCCESS );
@ -1418,7 +1420,7 @@ static void _rescheduleDeferredJobsTimer( TimerHandle_t const timer,
/*-----------------------------------------------------------*/
static void _timerThread( TimerHandle_t xTimer )
static void _timerCallback( TimerHandle_t xTimer )
{
_taskPool_t * pTaskPool = pvTimerGetTimerID( xTimer );
@ -1432,12 +1434,12 @@ static void _timerThread( TimerHandle_t xTimer )
* If this mutex cannot be locked it means that another thread is manipulating the
* timeouts list, and will reset the timer to fire again, although it will be late.
*/
TASKPOOL_ENTER_CRITICAL();
taskENTER_CRITICAL();
{
/* Check again for shutdown and bail out early in case. */
if( _IsShutdownStarted( pTaskPool ) )
{
TASKPOOL_EXIT_CRITICAL();
taskEXIT_CRITICAL();
/* Complete the shutdown sequence. */
_destroyTaskPool( pTaskPool );
@ -1487,11 +1489,11 @@ static void _timerThread( TimerHandle_t xTimer )
IotLogDebug( "Scheduling job from timer event." );
/* Queue the job associated with the received timer event. */
( void ) _scheduleInternal( pTaskPool, pTimerEvent->job, 0 );
( void ) _scheduleInternal( pTaskPool, pTimerEvent->job );
/* Free the timer event. */
IotTaskPool_FreeTimerEvent( pTimerEvent );
}
}
TASKPOOL_EXIT_CRITICAL();
taskEXIT_CRITICAL();
}

Loading…
Cancel
Save