blob: 35e4489f3d3cabfad29271a38130cd1a96ffd11b [file] [log] [blame]
/*
* FreeRTOS Common V1.1.1
* Copyright (C) 2020 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_static_memory_common.c
* @brief Implementation of common static memory functions in iot_static_memory.h
*/
/* The config header is always included first. */
#include "iot_config.h"
/* This file should only be compiled if dynamic memory allocation is forbidden. */
#if IOT_STATIC_MEMORY_ONLY == 1
/* Standard includes. */
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
/* Platform layer includes. */
#include "platform/iot_threads.h"
/* Static memory include. */
#include "private/iot_static_memory.h"
/*-----------------------------------------------------------*/
/**
* @cond DOXYGEN_IGNORE
* Doxygen should ignore this section.
*
* Provide default values for undefined configuration constants.
*/
#ifndef IOT_MESSAGE_BUFFERS
#define IOT_MESSAGE_BUFFERS ( 8 )
#endif
#ifndef IOT_MESSAGE_BUFFER_SIZE
#define IOT_MESSAGE_BUFFER_SIZE ( 1024 )
#endif
/** @endcond */
/* Validate static memory configuration settings. */
#if IOT_MESSAGE_BUFFERS <= 0
#error "IOT_MESSAGE_BUFFERS cannot be 0 or negative."
#endif
#if IOT_MESSAGE_BUFFER_SIZE <= 0
#error "IOT_MESSAGE_BUFFER_SIZE cannot be 0 or negative."
#endif
/*-----------------------------------------------------------*/
/**
* @brief Guards access to critical sections.
*/
static IotMutex_t _mutex;
/*
* Static memory buffers and flags, allocated and zeroed at compile-time.
*/
static bool _pInUseMessageBuffers[ IOT_MESSAGE_BUFFERS ] = { 0 }; /**< @brief Message buffer in-use flags. */
static char _pMessageBuffers[ IOT_MESSAGE_BUFFERS ][ IOT_MESSAGE_BUFFER_SIZE ] = { { 0 } }; /**< @brief Message buffers. */
/*-----------------------------------------------------------*/
int32_t IotStaticMemory_FindFree( bool * pInUse,
size_t limit )
{
size_t i = 0;
int32_t freeIndex = -1;
/* Perform the search for a free buffer in a critical section. */
IotMutex_Lock( &( _mutex ) );
for( i = 0; i < limit; i++ )
{
if( pInUse[ i ] == false )
{
/* If a free buffer is found, mark it "in-use" and return its index. */
pInUse[ i ] = true;
freeIndex = ( int32_t ) i;
break;
}
}
/* Exit the critical section. */
IotMutex_Unlock( &( _mutex ) );
return freeIndex;
}
/*-----------------------------------------------------------*/
void IotStaticMemory_ReturnInUse( void * ptr,
void * pPool,
bool * pInUse,
size_t limit,
size_t elementSize )
{
size_t i = 0;
uint8_t * element = NULL;
/* Clear ptr. */
( void ) memset( ptr, 0x00, elementSize );
/* Perform a search for ptr to make sure it's part of pPool. This search
* is done in a critical section. */
IotMutex_Lock( &( _mutex ) );
for( i = 0; i < limit; i++ )
{
/* Calculate address of the i-th element in pPool. */
element = ( ( uint8_t * ) pPool ) + elementSize * i;
/* Check for a match. */
if( ( ( void * ) element == ptr ) &&
( pInUse[ i ] == true ) )
{
pInUse[ i ] = false;
break;
}
}
/* Exit the critical section. */
IotMutex_Unlock( &( _mutex ) );
}
/*-----------------------------------------------------------*/
bool IotStaticMemory_Init( void )
{
return IotMutex_Create( &( _mutex ), false );
}
/*-----------------------------------------------------------*/
void IotStaticMemory_Cleanup( void )
{
IotMutex_Destroy( &( _mutex ) );
}
/*-----------------------------------------------------------*/
size_t Iot_MessageBufferSize( void )
{
return ( size_t ) IOT_MESSAGE_BUFFER_SIZE;
}
/*-----------------------------------------------------------*/
void * Iot_MallocMessageBuffer( size_t size )
{
int32_t freeIndex = -1;
void * pNewBuffer = NULL;
/* Check that size is within the fixed message buffer size. */
if( size <= IOT_MESSAGE_BUFFER_SIZE )
{
/* Get the index of a free message buffer. */
freeIndex = IotStaticMemory_FindFree( _pInUseMessageBuffers,
IOT_MESSAGE_BUFFERS );
if( freeIndex != -1 )
{
pNewBuffer = &( _pMessageBuffers[ freeIndex ][ 0 ] );
}
}
return pNewBuffer;
}
/*-----------------------------------------------------------*/
void Iot_FreeMessageBuffer( void * ptr )
{
/* Return the in-use message buffer. */
IotStaticMemory_ReturnInUse( ptr,
_pMessageBuffers,
_pInUseMessageBuffers,
IOT_MESSAGE_BUFFERS,
IOT_MESSAGE_BUFFER_SIZE );
}
/*-----------------------------------------------------------*/
#endif /* if IOT_STATIC_MEMORY_ONLY == 1 */