/* * Amazon FreeRTOS Platform V1.0.0 * Copyright (C) 2019 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://aws.amazon.com/freertos * http://www.FreeRTOS.org */ /** * @file iot_threads_freertos.c * @brief Implementation of the functions in iot_threads.h for POSIX systems. */ /* The config header is always included first. */ #include "iot_config.h" #include "semphr.h" /* Platform threads include. */ #include "platform/iot_platform_types_freertos.h" #include "platform/iot_threads.h" #include "types/iot_platform_types.h" /* Configure logs for the functions in this file. */ #ifdef IOT_LOG_LEVEL_PLATFORM #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_PLATFORM #else #ifdef IOT_LOG_LEVEL_GLOBAL #define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_GLOBAL #else #define LIBRARY_LOG_LEVEL IOT_LOG_NONE #endif #endif #define LIBRARY_LOG_NAME ( "THREAD" ) #include "iot_logging_setup.h" /* * Provide default values for undefined memory allocation functions based on * the usage of dynamic memory allocation. */ #ifndef IotThreads_Malloc #include /** * @brief Memory allocation. This function should have the same signature * as [malloc](http://pubs.opengroup.org/onlinepubs/9699919799/functions/malloc.html). */ #define IotThreads_Malloc malloc #endif #ifndef IotThreads_Free #include /** * @brief Free memory. This function should have the same signature as * [free](http://pubs.opengroup.org/onlinepubs/9699919799/functions/free.html). */ #define IotThreads_Free free #endif /*-----------------------------------------------------------*/ static void _threadRoutineWrapper( void * pArgument ) { threadInfo_t * pThreadInfo = ( threadInfo_t * ) pArgument; /* Run the thread routine. */ pThreadInfo->threadRoutine( pThreadInfo->pArgument ); IotThreads_Free( pThreadInfo ); vTaskDelete( NULL ); } /*-----------------------------------------------------------*/ bool Iot_CreateDetachedThread( IotThreadRoutine_t threadRoutine, void * pArgument, int32_t priority, size_t stackSize ) { bool status = true; configASSERT( threadRoutine != NULL ); IotLogDebug( "Creating new thread." ); threadInfo_t * pThreadInfo = IotThreads_Malloc( sizeof( threadInfo_t ) ); if( pThreadInfo == NULL ) { IotLogDebug( "Unable to allocate memory for threadRoutine %p.", threadRoutine ); status = false; } /* Create the FreeRTOS task that will run the thread. */ if( status ) { pThreadInfo->threadRoutine = threadRoutine; pThreadInfo->pArgument = pArgument; if( xTaskCreate( _threadRoutineWrapper, "iot_thread", ( configSTACK_DEPTH_TYPE ) stackSize, pThreadInfo, priority, NULL ) != pdPASS ) { /* Task creation failed. */ IotLogWarn( "Failed to create thread." ); IotThreads_Free( pThreadInfo ); status = false; } } return status; } /*-----------------------------------------------------------*/ bool IotMutex_Create( IotMutex_t * pNewMutex, bool recursive ) { _IotSystemMutex_t * internalMutex = ( _IotSystemMutex_t * ) pNewMutex; configASSERT( internalMutex != NULL ); IotLogDebug( "Creating new mutex %p.", pNewMutex ); if( recursive ) { ( void ) xSemaphoreCreateRecursiveMutexStatic( &internalMutex->xMutex ); } else { ( void ) xSemaphoreCreateMutexStatic( &internalMutex->xMutex ); } /* remember the type of mutex */ if( recursive ) { internalMutex->recursive = pdTRUE; } else { internalMutex->recursive = pdFALSE; } return true; } /*-----------------------------------------------------------*/ void IotMutex_Destroy( IotMutex_t * pMutex ) { _IotSystemMutex_t * internalMutex = ( _IotSystemMutex_t * ) pMutex; configASSERT( internalMutex != NULL ); vSemaphoreDelete( ( SemaphoreHandle_t ) &internalMutex->xMutex ); } /*-----------------------------------------------------------*/ bool prIotMutexTimedLock( IotMutex_t * pMutex, TickType_t timeout ) { _IotSystemMutex_t * internalMutex = ( _IotSystemMutex_t * ) pMutex; BaseType_t lockResult; configASSERT( internalMutex != NULL ); IotLogDebug( "Locking mutex %p.", internalMutex ); /* Call the correct FreeRTOS mutex take function based on mutex type. */ if( internalMutex->recursive == pdTRUE ) { lockResult = xSemaphoreTakeRecursive( ( SemaphoreHandle_t ) &internalMutex->xMutex, timeout ); } else { lockResult = xSemaphoreTake( ( SemaphoreHandle_t ) &internalMutex->xMutex, timeout ); } return( lockResult == pdTRUE ); } /*-----------------------------------------------------------*/ void IotMutex_Lock( IotMutex_t * pMutex ) { prIotMutexTimedLock( pMutex, portMAX_DELAY ); } /*-----------------------------------------------------------*/ bool IotMutex_TryLock( IotMutex_t * pMutex ) { return prIotMutexTimedLock( pMutex, 0 ); } /*-----------------------------------------------------------*/ void IotMutex_Unlock( IotMutex_t * pMutex ) { _IotSystemMutex_t * internalMutex = ( _IotSystemMutex_t * ) pMutex; configASSERT( internalMutex != NULL ); IotLogDebug( "Unlocking mutex %p.", internalMutex ); /* Call the correct FreeRTOS mutex unlock function based on mutex type. */ if( internalMutex->recursive == pdTRUE ) { ( void ) xSemaphoreGiveRecursive( ( SemaphoreHandle_t ) &internalMutex->xMutex ); } else { ( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &internalMutex->xMutex ); } } /*-----------------------------------------------------------*/ bool IotSemaphore_Create( IotSemaphore_t * pNewSemaphore, uint32_t initialValue, uint32_t maxValue ) { _IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pNewSemaphore; configASSERT( internalSemaphore != NULL ); IotLogDebug( "Creating new semaphore %p.", pNewSemaphore ); ( void ) xSemaphoreCreateCountingStatic( maxValue, initialValue, &internalSemaphore->xSemaphore ); return true; } /*-----------------------------------------------------------*/ uint32_t IotSemaphore_GetCount( IotSemaphore_t * pSemaphore ) { _IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore; UBaseType_t count = 0; configASSERT( internalSemaphore != NULL ); count = uxSemaphoreGetCount( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore ); IotLogDebug( "Semaphore %p has count %d.", pSemaphore, count ); return ( uint32_t ) count; } /*-----------------------------------------------------------*/ void IotSemaphore_Destroy( IotSemaphore_t * pSemaphore ) { _IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore; configASSERT( internalSemaphore != NULL ); IotLogDebug( "Destroying semaphore %p.", internalSemaphore ); vSemaphoreDelete( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore ); } /*-----------------------------------------------------------*/ void IotSemaphore_Wait( IotSemaphore_t * pSemaphore ) { _IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore; configASSERT( internalSemaphore != NULL ); IotLogDebug( "Waiting on semaphore %p.", internalSemaphore ); /* Take the semaphore using the FreeRTOS API. */ if( xSemaphoreTake( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore, portMAX_DELAY ) != pdTRUE ) { IotLogWarn( "Failed to wait on semaphore %p.", pSemaphore ); /* Assert here, debugging we always want to know that this happened because you think * that you are waiting successfully on the semaphore but you are not */ configASSERT( false ); } } /*-----------------------------------------------------------*/ bool IotSemaphore_TryWait( IotSemaphore_t * pSemaphore ) { _IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore; configASSERT( internalSemaphore != NULL ); IotLogDebug( "Attempting to wait on semaphore %p.", internalSemaphore ); return IotSemaphore_TimedWait( pSemaphore, 0 ); } /*-----------------------------------------------------------*/ bool IotSemaphore_TimedWait( IotSemaphore_t * pSemaphore, uint32_t timeoutMs ) { _IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore; configASSERT( internalSemaphore != NULL ); /* Take the semaphore using the FreeRTOS API. Cast the calculation to 64 bit to avoid overflows*/ if( xSemaphoreTake( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore, pdMS_TO_TICKS( timeoutMs ) ) != pdTRUE ) { /* Only warn if timeout > 0 */ if( timeoutMs > 0 ) { IotLogWarn( "Timeout waiting on semaphore %p.", internalSemaphore ); } return false; } return true; } /*-----------------------------------------------------------*/ void IotSemaphore_Post( IotSemaphore_t * pSemaphore ) { _IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore; configASSERT( internalSemaphore != NULL ); IotLogDebug( "Posting to semaphore %p.", internalSemaphore ); /* Give the semaphore using the FreeRTOS API. */ BaseType_t result = xSemaphoreGive( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore ); if( result == pdFALSE ) { IotLogDebug( "Unable to give semaphore over maximum", internalSemaphore ); } } /*-----------------------------------------------------------*/