Initial commit
This commit is contained in:
847
external/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_mempool.c
vendored
Normal file
847
external/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_mempool.c
vendored
Normal file
@@ -0,0 +1,847 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2023 Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* Project: CMSIS-RTOS RTX
|
||||
* Title: Memory Pool functions
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "rtx_lib.h"
|
||||
|
||||
|
||||
// OS Runtime Object Memory Usage
|
||||
#ifdef RTX_OBJ_MEM_USAGE
|
||||
osRtxObjectMemUsage_t osRtxMemoryPoolMemUsage \
|
||||
__attribute__((section(".data.os.mempool.obj"))) =
|
||||
{ 0U, 0U, 0U };
|
||||
#endif
|
||||
|
||||
|
||||
// ==== Helper functions ====
|
||||
|
||||
/// Verify that Memory Pool object pointer is valid.
|
||||
/// \param[in] mp memory pool object.
|
||||
/// \return true - valid, false - invalid.
|
||||
static bool_t IsMemoryPoolPtrValid (const os_memory_pool_t *mp) {
|
||||
#ifdef RTX_OBJ_PTR_CHECK
|
||||
//lint --e{923} --e{9078} "cast from pointer to unsigned int" [MISRA Note 7]
|
||||
uint32_t cb_start = (uint32_t)&__os_mempool_cb_start__;
|
||||
uint32_t cb_length = (uint32_t)&__os_mempool_cb_length__;
|
||||
|
||||
// Check the section boundaries
|
||||
if (((uint32_t)mp - cb_start) >= cb_length) {
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return FALSE;
|
||||
}
|
||||
// Check the object alignment
|
||||
if ((((uint32_t)mp - cb_start) % sizeof(os_memory_pool_t)) != 0U) {
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
// Check NULL pointer
|
||||
if (mp == NULL) {
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
// ==== Library functions ====
|
||||
|
||||
/// Initialize Memory Pool.
|
||||
/// \param[in] mp_info memory pool info.
|
||||
/// \param[in] block_count maximum number of memory blocks in memory pool.
|
||||
/// \param[in] block_size size of a memory block in bytes.
|
||||
/// \param[in] block_mem pointer to memory for block storage.
|
||||
/// \return 1 - success, 0 - failure.
|
||||
uint32_t osRtxMemoryPoolInit (os_mp_info_t *mp_info, uint32_t block_count, uint32_t block_size, void *block_mem) {
|
||||
//lint --e{9079} --e{9087} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
|
||||
void *mem;
|
||||
void *block;
|
||||
|
||||
// Check parameters
|
||||
if ((mp_info == NULL) || (block_count == 0U) || (block_size == 0U) || (block_mem == NULL)) {
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return 0U;
|
||||
}
|
||||
|
||||
// Initialize information structure
|
||||
mp_info->max_blocks = block_count;
|
||||
mp_info->used_blocks = 0U;
|
||||
mp_info->block_size = block_size;
|
||||
mp_info->block_base = block_mem;
|
||||
mp_info->block_free = block_mem;
|
||||
mp_info->block_lim = &(((uint8_t *)block_mem)[block_count * block_size]);
|
||||
|
||||
EvrRtxMemoryBlockInit(mp_info, block_count, block_size, block_mem);
|
||||
|
||||
// Link all free blocks
|
||||
mem = block_mem;
|
||||
while (--block_count != 0U) {
|
||||
block = &((uint8_t *)mem)[block_size];
|
||||
*((void **)mem) = block;
|
||||
mem = block;
|
||||
}
|
||||
*((void **)mem) = NULL;
|
||||
|
||||
return 1U;
|
||||
}
|
||||
|
||||
/// Allocate a memory block from a Memory Pool.
|
||||
/// \param[in] mp_info memory pool info.
|
||||
/// \return address of the allocated memory block or NULL in case of no memory is available.
|
||||
void *osRtxMemoryPoolAlloc (os_mp_info_t *mp_info) {
|
||||
#if (EXCLUSIVE_ACCESS == 0)
|
||||
uint32_t primask = __get_PRIMASK();
|
||||
#endif
|
||||
void *block;
|
||||
|
||||
if (mp_info == NULL) {
|
||||
EvrRtxMemoryBlockAlloc(NULL, NULL);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if (EXCLUSIVE_ACCESS == 0)
|
||||
__disable_irq();
|
||||
|
||||
block = mp_info->block_free;
|
||||
if (block != NULL) {
|
||||
//lint --e{9079} --e{9087} "conversion from pointer to void to pointer to other type"
|
||||
mp_info->block_free = *((void **)block);
|
||||
mp_info->used_blocks++;
|
||||
}
|
||||
|
||||
if (primask == 0U) {
|
||||
__enable_irq();
|
||||
}
|
||||
#else
|
||||
block = atomic_link_get(&mp_info->block_free);
|
||||
if (block != NULL) {
|
||||
(void)atomic_inc32(&mp_info->used_blocks);
|
||||
}
|
||||
#endif
|
||||
|
||||
EvrRtxMemoryBlockAlloc(mp_info, block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
/// Return an allocated memory block back to a Memory Pool.
|
||||
/// \param[in] mp_info memory pool info.
|
||||
/// \param[in] block address of the allocated memory block to be returned to the memory pool.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus_t osRtxMemoryPoolFree (os_mp_info_t *mp_info, void *block) {
|
||||
#if (EXCLUSIVE_ACCESS == 0)
|
||||
uint32_t primask = __get_PRIMASK();
|
||||
#endif
|
||||
|
||||
//lint -e{946} "Relational operator applied to pointers"
|
||||
if ((mp_info == NULL) || (block < mp_info->block_base) || (block >= mp_info->block_lim)) {
|
||||
EvrRtxMemoryBlockFree(mp_info, block, (int32_t)osErrorParameter);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return osErrorParameter;
|
||||
}
|
||||
|
||||
#if (EXCLUSIVE_ACCESS == 0)
|
||||
__disable_irq();
|
||||
|
||||
//lint --e{9079} --e{9087} "conversion from pointer to void to pointer to other type"
|
||||
*((void **)block) = mp_info->block_free;
|
||||
mp_info->block_free = block;
|
||||
mp_info->used_blocks--;
|
||||
|
||||
if (primask == 0U) {
|
||||
__enable_irq();
|
||||
}
|
||||
#else
|
||||
atomic_link_put(&mp_info->block_free, block);
|
||||
(void)atomic_dec32(&mp_info->used_blocks);
|
||||
#endif
|
||||
|
||||
EvrRtxMemoryBlockFree(mp_info, block, (int32_t)osOK);
|
||||
|
||||
return osOK;
|
||||
}
|
||||
|
||||
/// Destroy a Memory Pool object.
|
||||
/// \param[in] mp memory pool object.
|
||||
static void osRtxMemoryPoolDestroy (os_memory_pool_t *mp) {
|
||||
|
||||
// Mark object as invalid
|
||||
mp->id = osRtxIdInvalid;
|
||||
|
||||
// Free data memory
|
||||
if ((mp->flags & osRtxFlagSystemMemory) != 0U) {
|
||||
(void)osRtxMemoryFree(osRtxInfo.mem.mp_data, mp->mp_info.block_base);
|
||||
}
|
||||
|
||||
// Free object memory
|
||||
if ((mp->flags & osRtxFlagSystemObject) != 0U) {
|
||||
#ifdef RTX_OBJ_PTR_CHECK
|
||||
(void)osRtxMemoryPoolFree(osRtxInfo.mpi.memory_pool, mp);
|
||||
#else
|
||||
if (osRtxInfo.mpi.memory_pool != NULL) {
|
||||
(void)osRtxMemoryPoolFree(osRtxInfo.mpi.memory_pool, mp);
|
||||
} else {
|
||||
(void)osRtxMemoryFree(osRtxInfo.mem.common, mp);
|
||||
}
|
||||
#endif
|
||||
#ifdef RTX_OBJ_MEM_USAGE
|
||||
osRtxMemoryPoolMemUsage.cnt_free++;
|
||||
#endif
|
||||
}
|
||||
|
||||
EvrRtxMemoryPoolDestroyed(mp);
|
||||
}
|
||||
|
||||
#ifdef RTX_SAFETY_CLASS
|
||||
/// Delete a Memory Pool safety class.
|
||||
/// \param[in] safety_class safety class.
|
||||
/// \param[in] mode safety mode.
|
||||
void osRtxMemoryPoolDeleteClass (uint32_t safety_class, uint32_t mode) {
|
||||
os_memory_pool_t *mp;
|
||||
os_thread_t *thread;
|
||||
uint32_t length;
|
||||
|
||||
//lint --e{923} --e{9078} "cast from pointer to unsigned int" [MISRA Note 7]
|
||||
mp = (os_memory_pool_t *)(uint32_t)&__os_mempool_cb_start__;
|
||||
length = (uint32_t)&__os_mempool_cb_length__;
|
||||
while (length >= sizeof(os_memory_pool_t)) {
|
||||
if ( (mp->id == osRtxIdMemoryPool) &&
|
||||
((((mode & osSafetyWithSameClass) != 0U) &&
|
||||
((mp->attr >> osRtxAttrClass_Pos) == (uint8_t)safety_class)) ||
|
||||
(((mode & osSafetyWithLowerClass) != 0U) &&
|
||||
((mp->attr >> osRtxAttrClass_Pos) < (uint8_t)safety_class)))) {
|
||||
while (mp->thread_list != NULL) {
|
||||
thread = osRtxThreadListGet(osRtxObject(mp));
|
||||
osRtxThreadWaitExit(thread, (uint32_t)osErrorResource, FALSE);
|
||||
}
|
||||
osRtxMemoryPoolDestroy(mp);
|
||||
}
|
||||
length -= sizeof(os_memory_pool_t);
|
||||
mp++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// ==== Post ISR processing ====
|
||||
|
||||
/// Memory Pool post ISR processing.
|
||||
/// \param[in] mp memory pool object.
|
||||
static void osRtxMemoryPoolPostProcess (os_memory_pool_t *mp) {
|
||||
void *block;
|
||||
os_thread_t *thread;
|
||||
|
||||
// Check if Thread is waiting to allocate memory
|
||||
if (mp->thread_list != NULL) {
|
||||
// Allocate memory
|
||||
block = osRtxMemoryPoolAlloc(&mp->mp_info);
|
||||
if (block != NULL) {
|
||||
// Wakeup waiting Thread with highest Priority
|
||||
thread = osRtxThreadListGet(osRtxObject(mp));
|
||||
//lint -e{923} "cast from pointer to unsigned int"
|
||||
osRtxThreadWaitExit(thread, (uint32_t)block, FALSE);
|
||||
EvrRtxMemoryPoolAllocated(mp, block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ==== Service Calls ====
|
||||
|
||||
/// Create and Initialize a Memory Pool object.
|
||||
/// \note API identical to osMemoryPoolNew
|
||||
static osMemoryPoolId_t svcRtxMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr) {
|
||||
os_memory_pool_t *mp;
|
||||
#ifdef RTX_SAFETY_CLASS
|
||||
const os_thread_t *thread = osRtxThreadGetRunning();
|
||||
uint32_t attr_bits;
|
||||
#endif
|
||||
void *mp_mem;
|
||||
uint32_t mp_size;
|
||||
uint32_t b_count;
|
||||
uint32_t b_size;
|
||||
uint32_t size;
|
||||
uint8_t flags;
|
||||
const char *name;
|
||||
|
||||
// Check parameters
|
||||
if ((block_count == 0U) || (block_size == 0U) ||
|
||||
((__CLZ(block_count) + __CLZ(block_size)) < 32U)) {
|
||||
EvrRtxMemoryPoolError(NULL, (int32_t)osErrorParameter);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return NULL;
|
||||
}
|
||||
|
||||
b_count = block_count;
|
||||
b_size = (block_size + 3U) & ~3UL;
|
||||
size = b_count * b_size;
|
||||
|
||||
// Process attributes
|
||||
if (attr != NULL) {
|
||||
name = attr->name;
|
||||
#ifdef RTX_SAFETY_CLASS
|
||||
attr_bits = attr->attr_bits;
|
||||
#endif
|
||||
//lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
|
||||
mp = attr->cb_mem;
|
||||
//lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
|
||||
mp_mem = attr->mp_mem;
|
||||
mp_size = attr->mp_size;
|
||||
#ifdef RTX_SAFETY_CLASS
|
||||
if ((attr_bits & osSafetyClass_Valid) != 0U) {
|
||||
if ((thread != NULL) &&
|
||||
((thread->attr >> osRtxAttrClass_Pos) <
|
||||
(uint8_t)((attr_bits & osSafetyClass_Msk) >> osSafetyClass_Pos))) {
|
||||
EvrRtxMemoryPoolError(NULL, (int32_t)osErrorSafetyClass);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (mp != NULL) {
|
||||
if (!IsMemoryPoolPtrValid(mp) || (attr->cb_size != sizeof(os_memory_pool_t))) {
|
||||
EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidControlBlock);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (attr->cb_size != 0U) {
|
||||
EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidControlBlock);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (mp_mem != NULL) {
|
||||
//lint -e{923} "cast from pointer to unsigned int" [MISRA Note 7]
|
||||
if ((((uint32_t)mp_mem & 3U) != 0U) || (mp_size < size)) {
|
||||
EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidDataMemory);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (mp_size != 0U) {
|
||||
EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidDataMemory);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
name = NULL;
|
||||
#ifdef RTX_SAFETY_CLASS
|
||||
attr_bits = 0U;
|
||||
#endif
|
||||
mp = NULL;
|
||||
mp_mem = NULL;
|
||||
}
|
||||
|
||||
// Allocate object memory if not provided
|
||||
if (mp == NULL) {
|
||||
if (osRtxInfo.mpi.memory_pool != NULL) {
|
||||
//lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
|
||||
mp = osRtxMemoryPoolAlloc(osRtxInfo.mpi.memory_pool);
|
||||
#ifndef RTX_OBJ_PTR_CHECK
|
||||
} else {
|
||||
//lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
|
||||
mp = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_memory_pool_t), 1U);
|
||||
#endif
|
||||
}
|
||||
#ifdef RTX_OBJ_MEM_USAGE
|
||||
if (mp != NULL) {
|
||||
uint32_t used;
|
||||
osRtxMemoryPoolMemUsage.cnt_alloc++;
|
||||
used = osRtxMemoryPoolMemUsage.cnt_alloc - osRtxMemoryPoolMemUsage.cnt_free;
|
||||
if (osRtxMemoryPoolMemUsage.max_used < used) {
|
||||
osRtxMemoryPoolMemUsage.max_used = used;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
flags = osRtxFlagSystemObject;
|
||||
} else {
|
||||
flags = 0U;
|
||||
}
|
||||
|
||||
// Allocate data memory if not provided
|
||||
if ((mp != NULL) && (mp_mem == NULL)) {
|
||||
//lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
|
||||
mp_mem = osRtxMemoryAlloc(osRtxInfo.mem.mp_data, size, 0U);
|
||||
if (mp_mem == NULL) {
|
||||
if ((flags & osRtxFlagSystemObject) != 0U) {
|
||||
#ifdef RTX_OBJ_PTR_CHECK
|
||||
(void)osRtxMemoryPoolFree(osRtxInfo.mpi.memory_pool, mp);
|
||||
#else
|
||||
if (osRtxInfo.mpi.memory_pool != NULL) {
|
||||
(void)osRtxMemoryPoolFree(osRtxInfo.mpi.memory_pool, mp);
|
||||
} else {
|
||||
(void)osRtxMemoryFree(osRtxInfo.mem.common, mp);
|
||||
}
|
||||
#endif
|
||||
#ifdef RTX_OBJ_MEM_USAGE
|
||||
osRtxMemoryPoolMemUsage.cnt_free++;
|
||||
#endif
|
||||
}
|
||||
mp = NULL;
|
||||
} else {
|
||||
(void)memset(mp_mem, 0, size);
|
||||
}
|
||||
flags |= osRtxFlagSystemMemory;
|
||||
}
|
||||
|
||||
if (mp != NULL) {
|
||||
// Initialize control block
|
||||
mp->id = osRtxIdMemoryPool;
|
||||
mp->flags = flags;
|
||||
mp->attr = 0U;
|
||||
mp->name = name;
|
||||
mp->thread_list = NULL;
|
||||
#ifdef RTX_SAFETY_CLASS
|
||||
if ((attr_bits & osSafetyClass_Valid) != 0U) {
|
||||
mp->attr |= (uint8_t)((attr_bits & osSafetyClass_Msk) >>
|
||||
(osSafetyClass_Pos - osRtxAttrClass_Pos));
|
||||
} else {
|
||||
// Inherit safety class from the running thread
|
||||
if (thread != NULL) {
|
||||
mp->attr |= (uint8_t)(thread->attr & osRtxAttrClass_Msk);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
(void)osRtxMemoryPoolInit(&mp->mp_info, b_count, b_size, mp_mem);
|
||||
|
||||
// Register post ISR processing function
|
||||
osRtxInfo.post_process.memory_pool = osRtxMemoryPoolPostProcess;
|
||||
|
||||
EvrRtxMemoryPoolCreated(mp, mp->name);
|
||||
} else {
|
||||
EvrRtxMemoryPoolError(NULL, (int32_t)osErrorNoMemory);
|
||||
}
|
||||
|
||||
return mp;
|
||||
}
|
||||
|
||||
/// Get name of a Memory Pool object.
|
||||
/// \note API identical to osMemoryPoolGetName
|
||||
static const char *svcRtxMemoryPoolGetName (osMemoryPoolId_t mp_id) {
|
||||
os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
|
||||
|
||||
// Check parameters
|
||||
if (!IsMemoryPoolPtrValid(mp) || (mp->id != osRtxIdMemoryPool)) {
|
||||
EvrRtxMemoryPoolGetName(mp, NULL);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EvrRtxMemoryPoolGetName(mp, mp->name);
|
||||
|
||||
return mp->name;
|
||||
}
|
||||
|
||||
/// Allocate a memory block from a Memory Pool.
|
||||
/// \note API identical to osMemoryPoolAlloc
|
||||
static void *svcRtxMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
|
||||
os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
|
||||
#ifdef RTX_SAFETY_CLASS
|
||||
const os_thread_t *thread;
|
||||
#endif
|
||||
void *block;
|
||||
|
||||
// Check parameters
|
||||
if (!IsMemoryPoolPtrValid(mp) || (mp->id != osRtxIdMemoryPool)) {
|
||||
EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef RTX_SAFETY_CLASS
|
||||
// Check running thread safety class
|
||||
thread = osRtxThreadGetRunning();
|
||||
if ((thread != NULL) &&
|
||||
((thread->attr >> osRtxAttrClass_Pos) < (mp->attr >> osRtxAttrClass_Pos))) {
|
||||
EvrRtxMemoryPoolError(mp, (int32_t)osErrorSafetyClass);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Allocate memory
|
||||
block = osRtxMemoryPoolAlloc(&mp->mp_info);
|
||||
if (block != NULL) {
|
||||
EvrRtxMemoryPoolAllocated(mp, block);
|
||||
} else {
|
||||
// No memory available
|
||||
if (timeout != 0U) {
|
||||
EvrRtxMemoryPoolAllocPending(mp, timeout);
|
||||
// Suspend current Thread
|
||||
if (osRtxThreadWaitEnter(osRtxThreadWaitingMemoryPool, timeout)) {
|
||||
osRtxThreadListPut(osRtxObject(mp), osRtxThreadGetRunning());
|
||||
} else {
|
||||
EvrRtxMemoryPoolAllocTimeout(mp);
|
||||
}
|
||||
} else {
|
||||
EvrRtxMemoryPoolAllocFailed(mp);
|
||||
}
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
/// Return an allocated memory block back to a Memory Pool.
|
||||
/// \note API identical to osMemoryPoolFree
|
||||
static osStatus_t svcRtxMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
|
||||
os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
|
||||
void *block0;
|
||||
os_thread_t *thread;
|
||||
osStatus_t status;
|
||||
|
||||
// Check parameters
|
||||
if (!IsMemoryPoolPtrValid(mp) || (mp->id != osRtxIdMemoryPool)) {
|
||||
EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return osErrorParameter;
|
||||
}
|
||||
|
||||
#ifdef RTX_SAFETY_CLASS
|
||||
// Check running thread safety class
|
||||
thread = osRtxThreadGetRunning();
|
||||
if ((thread != NULL) &&
|
||||
((thread->attr >> osRtxAttrClass_Pos) < (mp->attr >> osRtxAttrClass_Pos))) {
|
||||
EvrRtxMemoryPoolError(mp, (int32_t)osErrorSafetyClass);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return osErrorSafetyClass;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Free memory
|
||||
status = osRtxMemoryPoolFree(&mp->mp_info, block);
|
||||
if (status == osOK) {
|
||||
EvrRtxMemoryPoolDeallocated(mp, block);
|
||||
// Check if Thread is waiting to allocate memory
|
||||
if (mp->thread_list != NULL) {
|
||||
// Allocate memory
|
||||
block0 = osRtxMemoryPoolAlloc(&mp->mp_info);
|
||||
if (block0 != NULL) {
|
||||
// Wakeup waiting Thread with highest Priority
|
||||
thread = osRtxThreadListGet(osRtxObject(mp));
|
||||
//lint -e{923} "cast from pointer to unsigned int"
|
||||
osRtxThreadWaitExit(thread, (uint32_t)block0, TRUE);
|
||||
EvrRtxMemoryPoolAllocated(mp, block0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
EvrRtxMemoryPoolFreeFailed(mp, block);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/// Get maximum number of memory blocks in a Memory Pool.
|
||||
/// \note API identical to osMemoryPoolGetCapacity
|
||||
static uint32_t svcRtxMemoryPoolGetCapacity (osMemoryPoolId_t mp_id) {
|
||||
os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
|
||||
|
||||
// Check parameters
|
||||
if (!IsMemoryPoolPtrValid(mp) || (mp->id != osRtxIdMemoryPool)) {
|
||||
EvrRtxMemoryPoolGetCapacity(mp, 0U);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return 0U;
|
||||
}
|
||||
|
||||
EvrRtxMemoryPoolGetCapacity(mp, mp->mp_info.max_blocks);
|
||||
|
||||
return mp->mp_info.max_blocks;
|
||||
}
|
||||
|
||||
/// Get memory block size in a Memory Pool.
|
||||
/// \note API identical to osMemoryPoolGetBlockSize
|
||||
static uint32_t svcRtxMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id) {
|
||||
os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
|
||||
|
||||
// Check parameters
|
||||
if (!IsMemoryPoolPtrValid(mp) || (mp->id != osRtxIdMemoryPool)) {
|
||||
EvrRtxMemoryPoolGetBlockSize(mp, 0U);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return 0U;
|
||||
}
|
||||
|
||||
EvrRtxMemoryPoolGetBlockSize(mp, mp->mp_info.block_size);
|
||||
|
||||
return mp->mp_info.block_size;
|
||||
}
|
||||
|
||||
/// Get number of memory blocks used in a Memory Pool.
|
||||
/// \note API identical to osMemoryPoolGetCount
|
||||
static uint32_t svcRtxMemoryPoolGetCount (osMemoryPoolId_t mp_id) {
|
||||
os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
|
||||
|
||||
// Check parameters
|
||||
if (!IsMemoryPoolPtrValid(mp) || (mp->id != osRtxIdMemoryPool)) {
|
||||
EvrRtxMemoryPoolGetCount(mp, 0U);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return 0U;
|
||||
}
|
||||
|
||||
EvrRtxMemoryPoolGetCount(mp, mp->mp_info.used_blocks);
|
||||
|
||||
return mp->mp_info.used_blocks;
|
||||
}
|
||||
|
||||
/// Get number of memory blocks available in a Memory Pool.
|
||||
/// \note API identical to osMemoryPoolGetSpace
|
||||
static uint32_t svcRtxMemoryPoolGetSpace (osMemoryPoolId_t mp_id) {
|
||||
os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
|
||||
|
||||
// Check parameters
|
||||
if (!IsMemoryPoolPtrValid(mp) || (mp->id != osRtxIdMemoryPool)) {
|
||||
EvrRtxMemoryPoolGetSpace(mp, 0U);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return 0U;
|
||||
}
|
||||
|
||||
EvrRtxMemoryPoolGetSpace(mp, mp->mp_info.max_blocks - mp->mp_info.used_blocks);
|
||||
|
||||
return (mp->mp_info.max_blocks - mp->mp_info.used_blocks);
|
||||
}
|
||||
|
||||
/// Delete a Memory Pool object.
|
||||
/// \note API identical to osMemoryPoolDelete
|
||||
static osStatus_t svcRtxMemoryPoolDelete (osMemoryPoolId_t mp_id) {
|
||||
os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
|
||||
os_thread_t *thread;
|
||||
|
||||
// Check parameters
|
||||
if (!IsMemoryPoolPtrValid(mp) || (mp->id != osRtxIdMemoryPool)) {
|
||||
EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return osErrorParameter;
|
||||
}
|
||||
|
||||
#ifdef RTX_SAFETY_CLASS
|
||||
// Check running thread safety class
|
||||
thread = osRtxThreadGetRunning();
|
||||
if ((thread != NULL) &&
|
||||
((thread->attr >> osRtxAttrClass_Pos) < (mp->attr >> osRtxAttrClass_Pos))) {
|
||||
EvrRtxMemoryPoolError(mp, (int32_t)osErrorSafetyClass);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return osErrorSafetyClass;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Unblock waiting threads
|
||||
if (mp->thread_list != NULL) {
|
||||
do {
|
||||
thread = osRtxThreadListGet(osRtxObject(mp));
|
||||
osRtxThreadWaitExit(thread, 0U, FALSE);
|
||||
} while (mp->thread_list != NULL);
|
||||
osRtxThreadDispatch(NULL);
|
||||
}
|
||||
|
||||
osRtxMemoryPoolDestroy(mp);
|
||||
|
||||
return osOK;
|
||||
}
|
||||
|
||||
// Service Calls definitions
|
||||
//lint ++flb "Library Begin" [MISRA Note 11]
|
||||
SVC0_3(MemoryPoolNew, osMemoryPoolId_t, uint32_t, uint32_t, const osMemoryPoolAttr_t *)
|
||||
SVC0_1(MemoryPoolGetName, const char *, osMemoryPoolId_t)
|
||||
SVC0_2(MemoryPoolAlloc, void *, osMemoryPoolId_t, uint32_t)
|
||||
SVC0_2(MemoryPoolFree, osStatus_t, osMemoryPoolId_t, void *)
|
||||
SVC0_1(MemoryPoolGetCapacity, uint32_t, osMemoryPoolId_t)
|
||||
SVC0_1(MemoryPoolGetBlockSize, uint32_t, osMemoryPoolId_t)
|
||||
SVC0_1(MemoryPoolGetCount, uint32_t, osMemoryPoolId_t)
|
||||
SVC0_1(MemoryPoolGetSpace, uint32_t, osMemoryPoolId_t)
|
||||
SVC0_1(MemoryPoolDelete, osStatus_t, osMemoryPoolId_t)
|
||||
//lint --flb "Library End"
|
||||
|
||||
|
||||
// ==== ISR Calls ====
|
||||
|
||||
/// Allocate a memory block from a Memory Pool.
|
||||
/// \note API identical to osMemoryPoolAlloc
|
||||
__STATIC_INLINE
|
||||
void *isrRtxMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
|
||||
os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
|
||||
void *block;
|
||||
|
||||
// Check parameters
|
||||
if (!IsMemoryPoolPtrValid(mp) || (mp->id != osRtxIdMemoryPool) || (timeout != 0U)) {
|
||||
EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Allocate memory
|
||||
block = osRtxMemoryPoolAlloc(&mp->mp_info);
|
||||
if (block == NULL) {
|
||||
EvrRtxMemoryPoolAllocFailed(mp);
|
||||
} else {
|
||||
EvrRtxMemoryPoolAllocated(mp, block);
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
/// Return an allocated memory block back to a Memory Pool.
|
||||
/// \note API identical to osMemoryPoolFree
|
||||
__STATIC_INLINE
|
||||
osStatus_t isrRtxMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
|
||||
os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
|
||||
osStatus_t status;
|
||||
|
||||
// Check parameters
|
||||
if (!IsMemoryPoolPtrValid(mp) || (mp->id != osRtxIdMemoryPool)) {
|
||||
EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
|
||||
//lint -e{904} "Return statement before end of function" [MISRA Note 1]
|
||||
return osErrorParameter;
|
||||
}
|
||||
|
||||
// Free memory
|
||||
status = osRtxMemoryPoolFree(&mp->mp_info, block);
|
||||
if (status == osOK) {
|
||||
// Register post ISR processing
|
||||
osRtxPostProcess(osRtxObject(mp));
|
||||
EvrRtxMemoryPoolDeallocated(mp, block);
|
||||
} else {
|
||||
EvrRtxMemoryPoolFreeFailed(mp, block);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// ==== Public API ====
|
||||
|
||||
/// Create and Initialize a Memory Pool object.
|
||||
osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr) {
|
||||
osMemoryPoolId_t mp_id;
|
||||
|
||||
EvrRtxMemoryPoolNew(block_count, block_size, attr);
|
||||
if (IsException() || IsIrqMasked()) {
|
||||
EvrRtxMemoryPoolError(NULL, (int32_t)osErrorISR);
|
||||
mp_id = NULL;
|
||||
} else {
|
||||
mp_id = __svcMemoryPoolNew(block_count, block_size, attr);
|
||||
}
|
||||
return mp_id;
|
||||
}
|
||||
|
||||
/// Get name of a Memory Pool object.
|
||||
const char *osMemoryPoolGetName (osMemoryPoolId_t mp_id) {
|
||||
const char *name;
|
||||
|
||||
if (IsException() || IsIrqMasked()) {
|
||||
name = svcRtxMemoryPoolGetName(mp_id);
|
||||
} else {
|
||||
name = __svcMemoryPoolGetName(mp_id);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/// Allocate a memory block from a Memory Pool.
|
||||
void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
|
||||
void *memory;
|
||||
|
||||
EvrRtxMemoryPoolAlloc(mp_id, timeout);
|
||||
if (IsException() || IsIrqMasked()) {
|
||||
memory = isrRtxMemoryPoolAlloc(mp_id, timeout);
|
||||
} else {
|
||||
memory = __svcMemoryPoolAlloc(mp_id, timeout);
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
|
||||
/// Return an allocated memory block back to a Memory Pool.
|
||||
osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
|
||||
osStatus_t status;
|
||||
|
||||
EvrRtxMemoryPoolFree(mp_id, block);
|
||||
if (IsException() || IsIrqMasked()) {
|
||||
status = isrRtxMemoryPoolFree(mp_id, block);
|
||||
} else {
|
||||
status = __svcMemoryPoolFree(mp_id, block);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/// Get maximum number of memory blocks in a Memory Pool.
|
||||
uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id) {
|
||||
uint32_t capacity;
|
||||
|
||||
if (IsException() || IsIrqMasked()) {
|
||||
capacity = svcRtxMemoryPoolGetCapacity(mp_id);
|
||||
} else {
|
||||
capacity = __svcMemoryPoolGetCapacity(mp_id);
|
||||
}
|
||||
return capacity;
|
||||
}
|
||||
|
||||
/// Get memory block size in a Memory Pool.
|
||||
uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id) {
|
||||
uint32_t block_size;
|
||||
|
||||
if (IsException() || IsIrqMasked()) {
|
||||
block_size = svcRtxMemoryPoolGetBlockSize(mp_id);
|
||||
} else {
|
||||
block_size = __svcMemoryPoolGetBlockSize(mp_id);
|
||||
}
|
||||
return block_size;
|
||||
}
|
||||
|
||||
/// Get number of memory blocks used in a Memory Pool.
|
||||
uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id) {
|
||||
uint32_t count;
|
||||
|
||||
if (IsException() || IsIrqMasked()) {
|
||||
count = svcRtxMemoryPoolGetCount(mp_id);
|
||||
} else {
|
||||
count = __svcMemoryPoolGetCount(mp_id);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/// Get number of memory blocks available in a Memory Pool.
|
||||
uint32_t osMemoryPoolGetSpace (osMemoryPoolId_t mp_id) {
|
||||
uint32_t space;
|
||||
|
||||
if (IsException() || IsIrqMasked()) {
|
||||
space = svcRtxMemoryPoolGetSpace(mp_id);
|
||||
} else {
|
||||
space = __svcMemoryPoolGetSpace(mp_id);
|
||||
}
|
||||
return space;
|
||||
}
|
||||
|
||||
/// Delete a Memory Pool object.
|
||||
osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id) {
|
||||
osStatus_t status;
|
||||
|
||||
EvrRtxMemoryPoolDelete(mp_id);
|
||||
if (IsException() || IsIrqMasked()) {
|
||||
EvrRtxMemoryPoolError(mp_id, (int32_t)osErrorISR);
|
||||
status = osErrorISR;
|
||||
} else {
|
||||
status = __svcMemoryPoolDelete(mp_id);
|
||||
}
|
||||
return status;
|
||||
}
|
Reference in New Issue
Block a user