blob: 224ec6b957971709d0834864ae80481163696f32 [file] [log] [blame]
#include "FreeRTOS.h"
#include "static-allocator.h"
#include <stdlib.h>
#include <stdio.h>
#include "task.h"
typedef struct priv_static_pool_s {
uint8_t* backing_store;
uint32_t* flags;
int item_size;
int num_items;
} priv_static_pool_t;
#ifdef PORTABLE_ARCH_ARM_CM3
__attribute__( ( always_inline ) ) static inline uint8_t __CLZ(uint32_t value)
{
uint8_t result;
__asm__ volatile ("clz %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
#else
__attribute__( ( always_inline ) ) static inline uint8_t __CLZ(uint32_t value)
{
uint8_t result = 0;
uint32_t mask = 0x1<<31;
int i;
for (i = 0; i < 32; i++)
{
if ((mask & value) != 0)
{
break;
}
result++;
mask >>= 1;
}
return result;
}
#endif
#ifdef PORTABLE_ARCH_ARM_CM3
__attribute__((naked)) static void atomicClearFlag( uint32_t* address, int bitNumber )
{
__asm__ volatile (
"1: \n\t"
" ldrex r2, [%0] \n\t"
" bic r2, %1 \n\t"
" strex r3, r2, [%0] \n\t"
" cmp r3,#0 \n\t"
" bne 1b \n\t"
" bx lr \n\t"
: //Output Argument
:"r"(address),"r"(bitNumber) //Input Arguments
:"cc", "r2", "r3");
}
#else
static void atomicClearFlag( uint32_t* address, int bitNumber )
{
*address &= ~(bitNumber);
}
#endif
#ifdef PORTABLE_ARCH_ARM_CM3
__attribute__((naked)) static void atomicSetFlag( uint32_t* address, int bitNumber )
{
__asm__ volatile (
"1: \n\t"
" ldrex r2, [%0] \n\t"
" orr r2, %1 \n\t"
" strex r3, r2, [%0] \n\t"
" cmp r3,#0 \n\t"
" bne 1b \n\t"
" bx lr \n\t"
:
:"r"(address),"r"(bitNumber)
:"cc", "r2", "r3");
}
#else
static void atomicSetFlag( uint32_t* address, int bitNumber )
{
*address |= (bitNumber);
}
#endif
#define NUM_ITEMS_TO_NUM_FLAGS(items) (((items)+31)/32)
void poolInit( static_pool_t* inPool, int inItemSize, int inNumItems, void* inBackingStore, void* inFlags)
{
priv_static_pool_t* aPool = (priv_static_pool_t*) inPool;
int i;
aPool->item_size = inItemSize;
aPool->num_items = inNumItems;
aPool->backing_store = inBackingStore;
aPool->flags = inFlags;
for(i = 0; i < NUM_ITEMS_TO_NUM_FLAGS(inNumItems); i++)
{
aPool->flags[i] = ~((uint32_t)0x0ul);
}
if (inNumItems % 32)
{
//mark all flags as already taken that don't represent an item.
aPool->flags[i-1] = aPool->flags[i-1] << (32 - (inNumItems % 32));
}
}
void *poolAllocateBuffer( static_pool_t* inPool )
{
vTaskSuspendAll();
priv_static_pool_t* aPool = (priv_static_pool_t*) inPool;
void *retval = NULL;
int flagIndex;
for(flagIndex = 0; flagIndex < NUM_ITEMS_TO_NUM_FLAGS(aPool->num_items); flagIndex++)
{
int8_t leadingZeros = __CLZ(aPool->flags[flagIndex]);
if(leadingZeros != 32)
{
int8_t bitIndex = 31-leadingZeros;
int8_t itemIndex = 32*flagIndex+(31-bitIndex);
atomicClearFlag(&aPool->flags[flagIndex], 1 << bitIndex);
retval = &aPool->backing_store[aPool->item_size*itemIndex];
break;
}
}
xTaskResumeAll();
return retval;
}
void poolFreeBuffer( static_pool_t* inPool, void* inPointer)
{
vTaskSuspendAll();
priv_static_pool_t* aPool = (priv_static_pool_t*) inPool;
int itemIndex = ((intptr_t)inPointer - (intptr_t)inPool->backing_store)/inPool->item_size;
int flagIndex = itemIndex / 32;
int bitIndex = 31-(itemIndex % 32);
if(flagIndex >= NUM_ITEMS_TO_NUM_FLAGS(aPool->num_items))
{
printf("ERROR freeing pool %p, Pointer %p doesnt belong here\n", inPool, inPointer);
while(1)
;
}
atomicSetFlag(&aPool->flags[flagIndex], 1 << bitIndex);
xTaskResumeAll();
}