manualy generated blinky opcodes
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allocator implementation
|
||||
*/
|
||||
|
||||
#include "globals.h"
|
||||
#include "mem-allocator.h"
|
||||
#include "mem-heap.h"
|
||||
#include "mem-poolman.h"
|
||||
#include "ctx-manager.h"
|
||||
|
||||
/**
|
||||
* Area for heap
|
||||
*/
|
||||
static uint8_t mem_HeapArea[ MEM_HEAP_AREA_SIZE ] __attribute__((aligned(MEM_ALIGNMENT)));
|
||||
|
||||
/**
|
||||
* Check that heap area is less or equal than 64K.
|
||||
*/
|
||||
JERRY_STATIC_ASSERT( MEM_HEAP_AREA_SIZE <= 64 * 1024 );
|
||||
|
||||
/**
|
||||
* Initialize memory allocators.
|
||||
*/
|
||||
void
|
||||
mem_Init( void)
|
||||
{
|
||||
mem_HeapInit( mem_HeapArea, sizeof (mem_HeapArea));
|
||||
mem_PoolsInit();
|
||||
} /* mem_Init */
|
||||
|
||||
/**
|
||||
* Get base pointer for allocation area.
|
||||
*/
|
||||
uintptr_t
|
||||
mem_GetBasePointer( void)
|
||||
{
|
||||
return (uintptr_t) mem_HeapArea;
|
||||
} /* mem_GetBasePointer */
|
||||
@@ -0,0 +1,46 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
/** \addtogroup mem Memory allocation
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allocator interface
|
||||
*/
|
||||
#ifndef JERRY_MEM_ALLOCATOR_H
|
||||
#define JERRY_MEM_ALLOCATOR_H
|
||||
|
||||
#include "globals.h"
|
||||
#include "mem-heap.h"
|
||||
|
||||
/**
|
||||
* Logarithm of required alignment for allocated units/blocks
|
||||
*/
|
||||
#define MEM_ALIGNMENT_LOG 2
|
||||
|
||||
/**
|
||||
* Required alignment for allocated units/blocks
|
||||
*/
|
||||
#define MEM_ALIGNMENT (1 << MEM_ALIGNMENT_LOG)
|
||||
|
||||
extern void mem_Init(void);
|
||||
uintptr_t mem_GetBasePointer(void);
|
||||
|
||||
#endif /* !JERRY_MEM_ALLOCATOR_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,427 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
/** \addtogroup mem Memory allocation
|
||||
* @{
|
||||
*
|
||||
* \addtogroup heap Heap
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Heap implementation
|
||||
*/
|
||||
|
||||
#include "globals.h"
|
||||
#include "jerry-libc.h"
|
||||
#include "mem-allocator.h"
|
||||
#include "mem-heap.h"
|
||||
|
||||
/**
|
||||
* Magic numbers for heap memory blocks
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
MEM_MAGIC_NUM_OF_FREE_BLOCK = 0x31d7c809,
|
||||
MEM_MAGIC_NUM_OF_ALLOCATED_BLOCK = 0x59d75b46
|
||||
} mem_MagicNumOfBlock_t;
|
||||
|
||||
/**
|
||||
* State of the block to initialize (argument of mem_InitBlockHeader)
|
||||
*
|
||||
* @see mem_InitBlockHeader
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
MEM_BLOCK_FREE, /**< initializing free block */
|
||||
MEM_BLOCK_ALLOCATED /**< initializing allocated block */
|
||||
} mem_BlockState_t;
|
||||
|
||||
/**
|
||||
* Linked list direction descriptors
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
MEM_DIRECTION_PREV = 0, /**< direction from right to left */
|
||||
MEM_DIRECTION_NEXT = 1, /**< direction from left to right */
|
||||
MEM_DIRECTION_COUNT = 2 /**< count of possible directions */
|
||||
} mem_Direction_t;
|
||||
|
||||
/**
|
||||
* Description of heap memory block layout
|
||||
*/
|
||||
typedef struct mem_BlockHeader_t
|
||||
{
|
||||
mem_MagicNumOfBlock_t m_MagicNum; /**< magic number - MEM_MAGIC_NUM_OF_ALLOCATED_BLOCK for allocated block
|
||||
and MEM_MAGIC_NUM_OF_FREE_BLOCK for free block */
|
||||
struct mem_BlockHeader_t *m_Neighbours[ MEM_DIRECTION_COUNT ]; /**< neighbour blocks */
|
||||
size_t m_SizeInChunks; /**< size of block with header in chunks */
|
||||
} mem_BlockHeader_t;
|
||||
|
||||
/**
|
||||
* Calculate size in bytes of the block space, that can be used to store data
|
||||
*/
|
||||
#define mem_GetHeapBlockDataSpaceSizeInBytes( pBlockHeader) ( MEM_HEAP_CHUNK_SIZE * pBlockHeader->m_SizeInChunks - sizeof(mem_BlockHeader_t) )
|
||||
|
||||
/**
|
||||
* Calculate size in chunks of heap block from data space size in bytes
|
||||
*/
|
||||
#define mem_GetHeapBlockSizeInChunksFromDataSpaceSizeInBytes( size) ( ( sizeof(mem_BlockHeader_t) + size + MEM_HEAP_CHUNK_SIZE - 1 ) / MEM_HEAP_CHUNK_SIZE )
|
||||
|
||||
/**
|
||||
* Chunk should have enough space for block header
|
||||
*/
|
||||
JERRY_STATIC_ASSERT( MEM_HEAP_CHUNK_SIZE >= sizeof (mem_BlockHeader_t) );
|
||||
|
||||
/**
|
||||
* Chunk size should satisfy the required alignment value
|
||||
*/
|
||||
JERRY_STATIC_ASSERT( MEM_HEAP_CHUNK_SIZE % MEM_ALIGNMENT == 0 );
|
||||
|
||||
/**
|
||||
* Description of heap state
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t* m_HeapStart; /**< first address of heap space */
|
||||
size_t m_HeapSize; /**< heap space size */
|
||||
mem_BlockHeader_t* m_pFirstBlock; /**< first block of the heap */
|
||||
mem_BlockHeader_t* m_pLastBlock; /**< last block of the heap */
|
||||
} mem_HeapState_t;
|
||||
|
||||
/**
|
||||
* Heap state
|
||||
*/
|
||||
mem_HeapState_t mem_Heap;
|
||||
|
||||
static void mem_InitBlockHeader( uint8_t *pFirstChunk,
|
||||
size_t sizeInChunks,
|
||||
mem_BlockState_t blockState,
|
||||
mem_BlockHeader_t *pPrevBlock,
|
||||
mem_BlockHeader_t *pNextBlock);
|
||||
static void mem_CheckHeap( void);
|
||||
|
||||
/**
|
||||
* Startup initialization of heap
|
||||
*/
|
||||
void
|
||||
mem_HeapInit( uint8_t *heapStart, /**< first address of heap space */
|
||||
size_t heapSize) /**< heap space size */
|
||||
{
|
||||
JERRY_ASSERT( heapStart != NULL );
|
||||
JERRY_ASSERT( heapSize != 0 );
|
||||
JERRY_ASSERT( heapSize % MEM_HEAP_CHUNK_SIZE == 0 );
|
||||
JERRY_ASSERT( (uintptr_t) heapStart % MEM_ALIGNMENT == 0);
|
||||
|
||||
mem_Heap.m_HeapStart = heapStart;
|
||||
mem_Heap.m_HeapSize = heapSize;
|
||||
|
||||
mem_InitBlockHeader( mem_Heap.m_HeapStart,
|
||||
heapSize / MEM_HEAP_CHUNK_SIZE,
|
||||
MEM_BLOCK_FREE,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
mem_Heap.m_pFirstBlock = (mem_BlockHeader_t*) mem_Heap.m_HeapStart;
|
||||
mem_Heap.m_pLastBlock = mem_Heap.m_pFirstBlock;
|
||||
} /* mem_HeapInit */
|
||||
|
||||
/**
|
||||
* Initialize block header
|
||||
*/
|
||||
static void
|
||||
mem_InitBlockHeader( uint8_t *pFirstChunk, /**< address of the first chunk to use for the block */
|
||||
size_t sizeInChunks, /**< size of block with header in chunks */
|
||||
mem_BlockState_t blockState, /**< state of the block (allocated or free) */
|
||||
mem_BlockHeader_t *pPrevBlock, /**< previous block */
|
||||
mem_BlockHeader_t *pNextBlock) /**< next block */
|
||||
{
|
||||
mem_BlockHeader_t *pBlockHeader = (mem_BlockHeader_t*) pFirstChunk;
|
||||
|
||||
if ( blockState == MEM_BLOCK_FREE )
|
||||
{
|
||||
pBlockHeader->m_MagicNum = MEM_MAGIC_NUM_OF_FREE_BLOCK;
|
||||
} else
|
||||
{
|
||||
pBlockHeader->m_MagicNum = MEM_MAGIC_NUM_OF_ALLOCATED_BLOCK;
|
||||
}
|
||||
|
||||
pBlockHeader->m_Neighbours[ MEM_DIRECTION_PREV ] = pPrevBlock;
|
||||
pBlockHeader->m_Neighbours[ MEM_DIRECTION_NEXT ] = pNextBlock;
|
||||
pBlockHeader->m_SizeInChunks = sizeInChunks;
|
||||
} /* mem_InitFreeBlock */
|
||||
|
||||
/**
|
||||
* Allocation of memory region.
|
||||
*
|
||||
* To reduce heap fragmentation there are two allocation modes - short-term and long-term.
|
||||
*
|
||||
* If allocation is short-term then the beginning of the heap is preferred, else - the end of the heap.
|
||||
*
|
||||
* It is supposed, that all short-term allocation is used during relatively short discrete sessions.
|
||||
* After end of the session all short-term allocated regions are supposed to be freed.
|
||||
*
|
||||
* @return pointer to allocated memory block - if allocation is successful,\n
|
||||
* NULL - if there is not enough memory.
|
||||
*/
|
||||
uint8_t*
|
||||
mem_HeapAllocBlock( size_t sizeInBytes, /**< size of region to allocate in bytes */
|
||||
mem_HeapAllocTerm_t allocTerm) /**< expected allocation term */
|
||||
{
|
||||
mem_BlockHeader_t *pBlock;
|
||||
mem_Direction_t direction;
|
||||
|
||||
mem_CheckHeap();
|
||||
|
||||
if ( allocTerm == MEM_HEAP_ALLOC_SHORT_TERM )
|
||||
{
|
||||
pBlock = mem_Heap.m_pFirstBlock;
|
||||
direction = MEM_DIRECTION_NEXT;
|
||||
} else
|
||||
{
|
||||
pBlock = mem_Heap.m_pLastBlock;
|
||||
direction = MEM_DIRECTION_PREV;
|
||||
}
|
||||
|
||||
/* searching for appropriate block */
|
||||
while ( pBlock != NULL )
|
||||
{
|
||||
if ( pBlock->m_MagicNum == MEM_MAGIC_NUM_OF_FREE_BLOCK )
|
||||
{
|
||||
if ( mem_GetHeapBlockDataSpaceSizeInBytes( pBlock) >= sizeInBytes )
|
||||
{
|
||||
break;
|
||||
}
|
||||
} else
|
||||
{
|
||||
JERRY_ASSERT( pBlock->m_MagicNum == MEM_MAGIC_NUM_OF_ALLOCATED_BLOCK );
|
||||
}
|
||||
|
||||
pBlock = pBlock->m_Neighbours[ direction ];
|
||||
}
|
||||
|
||||
if ( pBlock == NULL )
|
||||
{
|
||||
/* not enough free space */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* appropriate block found, allocating space */
|
||||
size_t newBlockSizeInChunks = mem_GetHeapBlockSizeInChunksFromDataSpaceSizeInBytes( sizeInBytes);
|
||||
size_t foundBlockSizeInChunks = pBlock->m_SizeInChunks;
|
||||
|
||||
JERRY_ASSERT( newBlockSizeInChunks <= foundBlockSizeInChunks );
|
||||
|
||||
mem_BlockHeader_t *pPrevBlock = pBlock->m_Neighbours[ MEM_DIRECTION_PREV ];
|
||||
mem_BlockHeader_t *pNextBlock = pBlock->m_Neighbours[ MEM_DIRECTION_NEXT ];
|
||||
|
||||
if ( newBlockSizeInChunks < foundBlockSizeInChunks )
|
||||
{
|
||||
uint8_t *pNewFreeBlockFirstChunk = (uint8_t*) pBlock + newBlockSizeInChunks * MEM_HEAP_CHUNK_SIZE;
|
||||
mem_InitBlockHeader( pNewFreeBlockFirstChunk,
|
||||
foundBlockSizeInChunks - newBlockSizeInChunks,
|
||||
MEM_BLOCK_FREE,
|
||||
pBlock /* there we will place new allocated block */,
|
||||
pNextBlock);
|
||||
|
||||
mem_BlockHeader_t *pNewFreeBlock = (mem_BlockHeader_t*) pNewFreeBlockFirstChunk;
|
||||
|
||||
if ( pNextBlock == NULL )
|
||||
{
|
||||
mem_Heap.m_pLastBlock = pNewFreeBlock;
|
||||
}
|
||||
|
||||
pNextBlock = pNewFreeBlock;
|
||||
}
|
||||
|
||||
mem_InitBlockHeader( (uint8_t*) pBlock,
|
||||
newBlockSizeInChunks,
|
||||
MEM_BLOCK_ALLOCATED,
|
||||
pPrevBlock,
|
||||
pNextBlock);
|
||||
|
||||
JERRY_ASSERT( mem_GetHeapBlockDataSpaceSizeInBytes( pBlock) >= sizeInBytes );
|
||||
|
||||
mem_CheckHeap();
|
||||
|
||||
/* return data space beginning address */
|
||||
uint8_t *pDataSpace = (uint8_t*) (pBlock + 1);
|
||||
JERRY_ASSERT( (uintptr_t) pDataSpace % MEM_ALIGNMENT == 0);
|
||||
|
||||
return pDataSpace;
|
||||
} /* mem_Alloc */
|
||||
|
||||
/**
|
||||
* Free the memory block.
|
||||
*/
|
||||
void
|
||||
mem_HeapFreeBlock( uint8_t *ptr) /**< pointer to beginning of data space of the block */
|
||||
{
|
||||
/* checking that ptr points to the heap */
|
||||
JERRY_ASSERT( ptr >= mem_Heap.m_HeapStart
|
||||
&& ptr <= mem_Heap.m_HeapStart + mem_Heap.m_HeapSize );
|
||||
|
||||
mem_CheckHeap();
|
||||
|
||||
mem_BlockHeader_t *pBlock = (mem_BlockHeader_t*) ptr - 1;
|
||||
mem_BlockHeader_t *pPrevBlock = pBlock->m_Neighbours[ MEM_DIRECTION_PREV ];
|
||||
mem_BlockHeader_t *pNextBlock = pBlock->m_Neighbours[ MEM_DIRECTION_NEXT ];
|
||||
|
||||
/* checking magic nums that are neighbour to data space */
|
||||
JERRY_ASSERT( pBlock->m_MagicNum == MEM_MAGIC_NUM_OF_ALLOCATED_BLOCK );
|
||||
if ( pNextBlock != NULL )
|
||||
{
|
||||
JERRY_ASSERT( pNextBlock->m_MagicNum == MEM_MAGIC_NUM_OF_ALLOCATED_BLOCK
|
||||
|| pNextBlock->m_MagicNum == MEM_MAGIC_NUM_OF_FREE_BLOCK );
|
||||
}
|
||||
|
||||
pBlock->m_MagicNum = MEM_MAGIC_NUM_OF_FREE_BLOCK;
|
||||
|
||||
if ( pNextBlock != NULL
|
||||
&& pNextBlock->m_MagicNum == MEM_MAGIC_NUM_OF_FREE_BLOCK )
|
||||
{
|
||||
/* merge with the next block */
|
||||
pBlock->m_SizeInChunks += pNextBlock->m_SizeInChunks;
|
||||
pNextBlock = pNextBlock->m_Neighbours[ MEM_DIRECTION_NEXT ];
|
||||
pBlock->m_Neighbours[ MEM_DIRECTION_NEXT ] = pNextBlock;
|
||||
if ( pNextBlock != NULL )
|
||||
{
|
||||
pNextBlock->m_Neighbours[ MEM_DIRECTION_PREV ] = pBlock;
|
||||
} else
|
||||
{
|
||||
mem_Heap.m_pLastBlock = pBlock;
|
||||
}
|
||||
}
|
||||
|
||||
if ( pPrevBlock != NULL
|
||||
&& pPrevBlock->m_MagicNum == MEM_MAGIC_NUM_OF_FREE_BLOCK )
|
||||
{
|
||||
/* merge with the previous block */
|
||||
pPrevBlock->m_SizeInChunks += pBlock->m_SizeInChunks;
|
||||
pPrevBlock->m_Neighbours[ MEM_DIRECTION_NEXT ] = pNextBlock;
|
||||
if ( pNextBlock != NULL )
|
||||
{
|
||||
pNextBlock->m_Neighbours[ MEM_DIRECTION_PREV ] = pBlock->m_Neighbours[ MEM_DIRECTION_PREV ];
|
||||
} else
|
||||
{
|
||||
mem_Heap.m_pLastBlock = pPrevBlock;
|
||||
}
|
||||
}
|
||||
|
||||
mem_CheckHeap();
|
||||
} /* mem_Free */
|
||||
|
||||
/**
|
||||
* Recommend allocation size based on chunk size.
|
||||
*
|
||||
* @return recommended allocation size
|
||||
*/
|
||||
size_t
|
||||
mem_HeapRecommendAllocationSize( size_t minimumAllocationSize) /**< minimum allocation size */
|
||||
{
|
||||
size_t minimumAllocationSizeWithBlockHeader = minimumAllocationSize + sizeof (mem_BlockHeader_t);
|
||||
size_t heapChunkAlignedAllocationSize = JERRY_ALIGNUP( minimumAllocationSizeWithBlockHeader, MEM_HEAP_CHUNK_SIZE);
|
||||
|
||||
return heapChunkAlignedAllocationSize - sizeof (mem_BlockHeader_t);
|
||||
} /* mem_HeapRecommendAllocationSize */
|
||||
|
||||
/**
|
||||
* Print heap
|
||||
*/
|
||||
void
|
||||
mem_HeapPrint( bool dumpBlockData) /**< print block with data (true)
|
||||
or print only block header (false) */
|
||||
{
|
||||
mem_CheckHeap();
|
||||
|
||||
libc_printf("Heap: start=%p size=%lu, first block->%p, last block->%p\n",
|
||||
mem_Heap.m_HeapStart,
|
||||
mem_Heap.m_HeapSize,
|
||||
(void*) mem_Heap.m_pFirstBlock,
|
||||
(void*) mem_Heap.m_pLastBlock);
|
||||
|
||||
for ( mem_BlockHeader_t *pBlock = mem_Heap.m_pFirstBlock;
|
||||
pBlock != NULL;
|
||||
pBlock = pBlock->m_Neighbours[ MEM_DIRECTION_NEXT ] )
|
||||
{
|
||||
libc_printf("Block (%p): magic num=0x%08x, size in chunks=%lu, previous block->%p next block->%p\n",
|
||||
(void*) pBlock,
|
||||
pBlock->m_MagicNum,
|
||||
pBlock->m_SizeInChunks,
|
||||
(void*) pBlock->m_Neighbours[ MEM_DIRECTION_PREV ],
|
||||
(void*) pBlock->m_Neighbours[ MEM_DIRECTION_NEXT ]);
|
||||
|
||||
if ( dumpBlockData )
|
||||
{
|
||||
uint8_t *pBlockData = (uint8_t*) (pBlock + 1);
|
||||
for ( uint32_t offset = 0;
|
||||
offset < mem_GetHeapBlockDataSpaceSizeInBytes( pBlock);
|
||||
offset++ )
|
||||
{
|
||||
libc_printf("%02x ", pBlockData[ offset ]);
|
||||
}
|
||||
libc_printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
libc_printf("\n");
|
||||
} /* mem_PrintHeap */
|
||||
|
||||
/**
|
||||
* Check heap consistency
|
||||
*/
|
||||
static void
|
||||
mem_CheckHeap( void)
|
||||
{
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT( (uint8_t*) mem_Heap.m_pFirstBlock == mem_Heap.m_HeapStart );
|
||||
JERRY_ASSERT( mem_Heap.m_HeapSize % MEM_HEAP_CHUNK_SIZE == 0 );
|
||||
|
||||
size_t chunksCount = 0;
|
||||
bool isLastBlockWasMet = false;
|
||||
for ( mem_BlockHeader_t *pBlock = mem_Heap.m_pFirstBlock;
|
||||
pBlock != NULL;
|
||||
pBlock = pBlock->m_Neighbours[ MEM_DIRECTION_NEXT ] )
|
||||
{
|
||||
JERRY_ASSERT( pBlock != NULL );
|
||||
JERRY_ASSERT( pBlock->m_MagicNum == MEM_MAGIC_NUM_OF_FREE_BLOCK
|
||||
|| pBlock->m_MagicNum == MEM_MAGIC_NUM_OF_ALLOCATED_BLOCK );
|
||||
|
||||
chunksCount += pBlock->m_SizeInChunks;
|
||||
|
||||
mem_BlockHeader_t *pNextBlock = pBlock->m_Neighbours[ MEM_DIRECTION_NEXT ];
|
||||
if ( pBlock == mem_Heap.m_pLastBlock )
|
||||
{
|
||||
isLastBlockWasMet = true;
|
||||
|
||||
JERRY_ASSERT( pNextBlock == NULL );
|
||||
JERRY_ASSERT( mem_Heap.m_HeapStart + mem_Heap.m_HeapSize
|
||||
== (uint8_t*) pBlock + pBlock->m_SizeInChunks * MEM_HEAP_CHUNK_SIZE );
|
||||
} else
|
||||
{
|
||||
JERRY_ASSERT( pNextBlock != NULL );
|
||||
JERRY_ASSERT( (uint8_t*) pNextBlock == (uint8_t*) pBlock + pBlock->m_SizeInChunks * MEM_HEAP_CHUNK_SIZE );
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_ASSERT( isLastBlockWasMet );
|
||||
JERRY_ASSERT( chunksCount == mem_Heap.m_HeapSize / MEM_HEAP_CHUNK_SIZE );
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
} /* mem_CheckHeap */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,52 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
/** \addtogroup mem Memory allocation
|
||||
* @{
|
||||
*
|
||||
* \addtogroup heap Heap
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Heap allocator interface
|
||||
*/
|
||||
#ifndef JERRY_MEM_HEAP_H
|
||||
#define JERRY_MEM_HEAP_H
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
/**
|
||||
* Type of allocation (argument of mem_Alloc)
|
||||
*
|
||||
* @see mem_HeapAllocBlock
|
||||
*/
|
||||
typedef enum {
|
||||
MEM_HEAP_ALLOC_SHORT_TERM, /**< allocated region will be freed soon */
|
||||
MEM_HEAP_ALLOC_LONG_TERM /**< allocated region most likely will not be freed soon */
|
||||
} mem_HeapAllocTerm_t;
|
||||
|
||||
extern void mem_HeapInit(uint8_t *heapStart, size_t heapSize);
|
||||
extern uint8_t* mem_HeapAllocBlock(size_t sizeInBytes, mem_HeapAllocTerm_t allocTerm);
|
||||
extern void mem_HeapFreeBlock(uint8_t *ptr);
|
||||
extern size_t mem_HeapRecommendAllocationSize(size_t minimumAllocationSize);
|
||||
extern void mem_HeapPrint(bool dumpBlockData);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* !JERRY_MEM_HEAP_H */
|
||||
@@ -0,0 +1,257 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
/** \addtogroup mem Memory allocation
|
||||
* @{
|
||||
*
|
||||
* \addtogroup pool Memory pool
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Memory pool implementation
|
||||
*/
|
||||
|
||||
#define JERRY_MEM_POOL_INTERNAL
|
||||
|
||||
#include "globals.h"
|
||||
#include "jerry-libc.h"
|
||||
#include "mem-allocator.h"
|
||||
#include "mem-pool.h"
|
||||
|
||||
/**
|
||||
* Magic number to fill free chunks in debug version
|
||||
*/
|
||||
static const uint8_t mem_PoolFreeChunkMagicNum = 0x71;
|
||||
|
||||
/**
|
||||
* Number of bits in a single bitmap's bits' block.
|
||||
*/
|
||||
static const mword_t mem_BitmapBitsInBlock = sizeof (mword_t) * JERRY_BITSINBYTE;
|
||||
|
||||
static void mem_CheckPool( mem_PoolState_t *pPool);
|
||||
|
||||
/**
|
||||
* Initialization of memory pool.
|
||||
*
|
||||
* Pool will be located in the segment [poolStart; poolStart + poolSize).
|
||||
* Part of pool space will be used for bitmap and the rest will store chunks.
|
||||
*
|
||||
* Warning:
|
||||
* it is incorrect to suppose, that chunk number = poolSize / chunkSize.
|
||||
*/
|
||||
void
|
||||
mem_PoolInit(mem_PoolState_t *pPool, /**< pool */
|
||||
size_t chunkSize, /**< size of one chunk */
|
||||
uint8_t *poolStart, /**< start of pool space */
|
||||
size_t poolSize) /**< pool space size */
|
||||
{
|
||||
JERRY_ASSERT( pPool != NULL );
|
||||
JERRY_ASSERT( (uintptr_t) poolStart % MEM_ALIGNMENT == 0);
|
||||
JERRY_ASSERT( chunkSize % MEM_ALIGNMENT == 0 );
|
||||
|
||||
pPool->m_pPoolStart = poolStart;
|
||||
pPool->m_PoolSize = poolSize;
|
||||
pPool->m_ChunkSize = chunkSize;
|
||||
|
||||
const size_t bitsInByte = JERRY_BITSINBYTE;
|
||||
const size_t bitmapAreaSizeAlignment = JERRY_MAX( sizeof (mword_t), MEM_ALIGNMENT);
|
||||
|
||||
/*
|
||||
* Calculation chunks number
|
||||
*/
|
||||
|
||||
size_t bitmapAreaSize = 0;
|
||||
size_t chunksAreaSize = JERRY_ALIGNDOWN( poolSize - bitmapAreaSize, chunkSize);
|
||||
size_t chunksNumber = chunksAreaSize / chunkSize;
|
||||
|
||||
/* while there is not enough area to hold state of all chunks*/
|
||||
while ( bitmapAreaSize * bitsInByte < chunksNumber )
|
||||
{
|
||||
JERRY_ASSERT( bitmapAreaSize + chunksAreaSize <= poolSize );
|
||||
|
||||
/* correct bitmap area's size and, accordingly, chunks' area's size*/
|
||||
|
||||
size_t newBitmapAreaSize = bitmapAreaSize + bitmapAreaSizeAlignment;
|
||||
size_t newChunksAreaSize = JERRY_ALIGNDOWN( poolSize - newBitmapAreaSize, chunkSize);
|
||||
size_t newChunksNumber = newChunksAreaSize / chunkSize;
|
||||
|
||||
bitmapAreaSize = newBitmapAreaSize;
|
||||
chunksAreaSize = newChunksAreaSize;
|
||||
chunksNumber = newChunksNumber;
|
||||
}
|
||||
|
||||
/*
|
||||
* Final calculation checks
|
||||
*/
|
||||
JERRY_ASSERT( bitmapAreaSize * bitsInByte >= chunksNumber );
|
||||
JERRY_ASSERT( chunksAreaSize >= chunksNumber * chunkSize );
|
||||
JERRY_ASSERT( bitmapAreaSize + chunksAreaSize <= poolSize );
|
||||
|
||||
pPool->m_pBitmap = (mword_t*) poolStart;
|
||||
pPool->m_pChunks = poolStart + bitmapAreaSize;
|
||||
|
||||
JERRY_ASSERT( (uintptr_t) pPool->m_pChunks % MEM_ALIGNMENT == 0 );
|
||||
|
||||
pPool->m_ChunksNumber = chunksNumber;
|
||||
|
||||
/*
|
||||
* All chunks are free right after initialization
|
||||
*/
|
||||
pPool->m_FreeChunksNumber = chunksNumber;
|
||||
libc_memset( pPool->m_pBitmap, 0, bitmapAreaSize);
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
libc_memset( pPool->m_pChunks, mem_PoolFreeChunkMagicNum, chunksAreaSize);
|
||||
#endif /* JERRY_NDEBUG */
|
||||
|
||||
mem_CheckPool( pPool);
|
||||
} /* mem_PoolInit */
|
||||
|
||||
/**
|
||||
* Allocate a chunk in the pool
|
||||
*/
|
||||
uint8_t*
|
||||
mem_PoolAllocChunk(mem_PoolState_t *pPool) /**< pool */
|
||||
{
|
||||
mem_CheckPool( pPool);
|
||||
|
||||
if ( pPool->m_FreeChunksNumber == 0 )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t chunkIndex = 0;
|
||||
size_t bitmapBlockIndex = 0;
|
||||
|
||||
while ( chunkIndex < pPool->m_ChunksNumber )
|
||||
{
|
||||
if ( ~pPool->m_pBitmap[ bitmapBlockIndex ] != 0 )
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
bitmapBlockIndex++;
|
||||
chunkIndex += mem_BitmapBitsInBlock;
|
||||
}
|
||||
}
|
||||
|
||||
if ( chunkIndex >= pPool->m_ChunksNumber )
|
||||
{
|
||||
/* no free chunks */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* found bitmap block with a zero bit */
|
||||
|
||||
mword_t bit = 1;
|
||||
for ( size_t bitIndex = 0;
|
||||
bitIndex < mem_BitmapBitsInBlock && chunkIndex < pPool->m_ChunksNumber;
|
||||
bitIndex++, chunkIndex++, bit <<= 1 )
|
||||
{
|
||||
if ( ~pPool->m_pBitmap[ bitmapBlockIndex ] & bit )
|
||||
{
|
||||
/* found free chunk */
|
||||
pPool->m_pBitmap[ bitmapBlockIndex ] |= bit;
|
||||
|
||||
uint8_t *pChunk = &pPool->m_pChunks[ chunkIndex * pPool->m_ChunkSize ];
|
||||
pPool->m_FreeChunksNumber--;
|
||||
|
||||
mem_CheckPool( pPool);
|
||||
|
||||
return pChunk;
|
||||
}
|
||||
}
|
||||
|
||||
/* that zero bit is at the end of the bitmap and doesn't correspond to any chunk */
|
||||
return NULL;
|
||||
} /* mem_PoolAllocChunk */
|
||||
|
||||
/**
|
||||
* Free the chunk in the pool
|
||||
*/
|
||||
void
|
||||
mem_PoolFreeChunk(mem_PoolState_t *pPool, /**< pool */
|
||||
uint8_t *pChunk) /**< chunk pointer */
|
||||
{
|
||||
JERRY_ASSERT( pPool->m_FreeChunksNumber < pPool->m_ChunksNumber );
|
||||
JERRY_ASSERT( pChunk >= pPool->m_pChunks && pChunk <= pPool->m_pChunks + pPool->m_ChunksNumber * pPool->m_ChunkSize );
|
||||
JERRY_ASSERT( ( (uintptr_t) pChunk - (uintptr_t) pPool->m_pChunks ) % pPool->m_ChunkSize == 0 );
|
||||
|
||||
mem_CheckPool( pPool);
|
||||
|
||||
size_t chunkIndex = (size_t) (pChunk - pPool->m_pChunks) / pPool->m_ChunkSize;
|
||||
size_t bitmapBlockIndex = chunkIndex / mem_BitmapBitsInBlock;
|
||||
size_t bitmapBitInBlock = chunkIndex % mem_BitmapBitsInBlock;
|
||||
mword_t bitMask = ( 1lu << bitmapBitInBlock );
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
libc_memset( (uint8_t*) pChunk, mem_PoolFreeChunkMagicNum, pPool->m_ChunkSize);
|
||||
#endif /* JERRY_NDEBUG */
|
||||
JERRY_ASSERT( pPool->m_pBitmap[ bitmapBlockIndex ] & bitMask );
|
||||
|
||||
pPool->m_pBitmap[ bitmapBlockIndex ] &= ~bitMask;
|
||||
pPool->m_FreeChunksNumber++;
|
||||
|
||||
mem_CheckPool( pPool);
|
||||
} /* mem_PoolFreeChunk */
|
||||
|
||||
/**
|
||||
* Check pool state consistency
|
||||
*/
|
||||
static void
|
||||
mem_CheckPool( mem_PoolState_t __unused *pPool) /**< pool (unused #ifdef JERRY_NDEBUG) */
|
||||
{
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT( pPool->m_ChunksNumber != 0 );
|
||||
JERRY_ASSERT( pPool->m_FreeChunksNumber <= pPool->m_ChunksNumber );
|
||||
JERRY_ASSERT( (uint8_t*) pPool->m_pBitmap == pPool->m_pPoolStart );
|
||||
JERRY_ASSERT( (uint8_t*) pPool->m_pChunks > pPool->m_pPoolStart );
|
||||
|
||||
uint8_t freeChunkTemplate[ pPool->m_ChunkSize ];
|
||||
libc_memset( &freeChunkTemplate, mem_PoolFreeChunkMagicNum, sizeof (freeChunkTemplate));
|
||||
|
||||
size_t metFreeChunksNumber = 0;
|
||||
|
||||
for ( size_t chunkIndex = 0, bitmapBlockIndex = 0;
|
||||
chunkIndex < pPool->m_ChunksNumber;
|
||||
bitmapBlockIndex++ )
|
||||
{
|
||||
JERRY_ASSERT( (uint8_t*) & pPool->m_pBitmap[ bitmapBlockIndex ] < pPool->m_pChunks );
|
||||
|
||||
mword_t bitmapBlock = pPool->m_pBitmap[ bitmapBlockIndex ];
|
||||
|
||||
mword_t bitMask = 1;
|
||||
for ( size_t bitmapBitInBlock = 0;
|
||||
chunkIndex < pPool->m_ChunksNumber && bitmapBitInBlock < mem_BitmapBitsInBlock;
|
||||
bitmapBitInBlock++, bitMask <<= 1, chunkIndex++ )
|
||||
{
|
||||
if ( ~bitmapBlock & bitMask )
|
||||
{
|
||||
metFreeChunksNumber++;
|
||||
|
||||
JERRY_ASSERT( libc_memcmp( &pPool->m_pChunks[ chunkIndex * pPool->m_ChunkSize ], freeChunkTemplate, pPool->m_ChunkSize) == 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_ASSERT( metFreeChunksNumber == pPool->m_FreeChunksNumber );
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
} /* mem_CheckPool */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,56 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
/** \addtogroup pool Memory pool
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef JERRY_MEM_POOL_INTERNAL
|
||||
#error "Please, use mem_poolman.h instead of mem_pool.h"
|
||||
#endif
|
||||
|
||||
#ifndef JERRY_MEM_POOL_H
|
||||
#define JERRY_MEM_POOL_H
|
||||
|
||||
/**
|
||||
* State of a memory pool
|
||||
*
|
||||
* TODO:
|
||||
* Compact the struct
|
||||
*/
|
||||
typedef struct mem_PoolState_t {
|
||||
uint8_t *m_pPoolStart; /**< first address of pool space */
|
||||
size_t m_PoolSize; /**< pool space size */
|
||||
|
||||
size_t m_ChunkSize; /**< size of one chunk */
|
||||
|
||||
mword_t *m_pBitmap; /**< bitmap - pool chunks' state */
|
||||
uint8_t *m_pChunks; /**< chunks with data */
|
||||
|
||||
size_t m_ChunksNumber; /**< number of chunks */
|
||||
size_t m_FreeChunksNumber; /**< number of free chunks */
|
||||
|
||||
struct mem_PoolState_t *m_pNextPool; /**< pointer to the next pool with same chunk size */
|
||||
} mem_PoolState_t;
|
||||
|
||||
extern void mem_PoolInit(mem_PoolState_t *pPool, size_t chunkSize, uint8_t *poolStart, size_t poolSize);
|
||||
extern uint8_t* mem_PoolAllocChunk(mem_PoolState_t *pPool);
|
||||
extern void mem_PoolFreeChunk(mem_PoolState_t *pPool, uint8_t *pChunk);
|
||||
|
||||
#endif /* JERRY_MEM_POOL_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,233 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
/** \addtogroup mem Memory allocation
|
||||
* @{
|
||||
*
|
||||
* \addtogroup poolman Memory pool manager
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Memory pool manager implementation
|
||||
*/
|
||||
|
||||
#define JERRY_MEM_POOL_INTERNAL
|
||||
|
||||
#include "globals.h"
|
||||
#include "mem-allocator.h"
|
||||
#include "mem-heap.h"
|
||||
#include "mem-pool.h"
|
||||
#include "mem-poolman.h"
|
||||
|
||||
/**
|
||||
* Lists of pools for possible chunk sizes
|
||||
*/
|
||||
mem_PoolState_t *mem_Pools[ MEM_POOL_CHUNK_TYPE__COUNT ];
|
||||
|
||||
/**
|
||||
* Number of free chunks of possible chunk sizes
|
||||
*/
|
||||
size_t mem_FreeChunksNumber[ MEM_POOL_CHUNK_TYPE__COUNT ];
|
||||
|
||||
/**
|
||||
* Pool, containing pool headers
|
||||
*/
|
||||
mem_PoolState_t mem_PoolForPoolHeaders;
|
||||
|
||||
/**
|
||||
* Space for pool, containing pool headers
|
||||
*/
|
||||
uint8_t *mem_SpaceForPoolForPoolHeaders;
|
||||
|
||||
/**
|
||||
* Get chunk size from chunk type.
|
||||
*
|
||||
* @return size (in bytes) of chunk of specified type
|
||||
*/
|
||||
static size_t
|
||||
mem_GetChunkSize( mem_PoolChunkType_t chunkType) /**< chunk type */
|
||||
{
|
||||
uint32_t chunkTypeId = (uint32_t) chunkType;
|
||||
|
||||
JERRY_ASSERT( chunkTypeId < MEM_POOL_CHUNK_TYPE__COUNT );
|
||||
|
||||
return ( 1u << ( chunkTypeId + 2 ) );
|
||||
} /* mem_GetChunkSize */
|
||||
|
||||
/**
|
||||
* Initialize pool manager
|
||||
*/
|
||||
void
|
||||
mem_PoolsInit(void)
|
||||
{
|
||||
for ( uint32_t i = 0; i < MEM_POOL_CHUNK_TYPE__COUNT; i++ )
|
||||
{
|
||||
mem_Pools[ i ] = NULL;
|
||||
mem_FreeChunksNumber[ i ] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Space, at least for four pool headers and a bitmap entry.
|
||||
*
|
||||
* TODO: Research.
|
||||
*/
|
||||
size_t poolSpaceSize = mem_HeapRecommendAllocationSize( 4 * sizeof (mem_PoolState_t) + sizeof (mword_t) );
|
||||
|
||||
mem_SpaceForPoolForPoolHeaders = mem_HeapAllocBlock(poolSpaceSize,
|
||||
MEM_HEAP_ALLOC_LONG_TERM);
|
||||
|
||||
/*
|
||||
* Get chunk type, checking that there is a type corresponding to specified size.
|
||||
*/
|
||||
const mem_PoolChunkType_t chunkType = mem_SizeToPoolChunkType( sizeof(mem_PoolState_t));
|
||||
|
||||
mem_PoolInit(&mem_PoolForPoolHeaders,
|
||||
mem_GetChunkSize( chunkType),
|
||||
mem_SpaceForPoolForPoolHeaders,
|
||||
poolSpaceSize);
|
||||
} /* mem_PoolsInit */
|
||||
|
||||
/**
|
||||
* Allocate a chunk of specified size
|
||||
*
|
||||
* @return pointer to allocated chunk, if allocation was successful,
|
||||
* or NULL - if not enough memory.
|
||||
*/
|
||||
uint8_t*
|
||||
mem_PoolsAlloc( mem_PoolChunkType_t chunkType) /**< chunk type */
|
||||
{
|
||||
size_t chunkSize = mem_GetChunkSize( chunkType);
|
||||
|
||||
/**
|
||||
* If there are no free chunks, allocate new pool.
|
||||
*/
|
||||
if ( mem_FreeChunksNumber[ chunkType ] == 0 )
|
||||
{
|
||||
mem_PoolState_t *poolState = (mem_PoolState_t*) mem_PoolAllocChunk( &mem_PoolForPoolHeaders);
|
||||
|
||||
if ( poolState == NULL )
|
||||
{
|
||||
/**
|
||||
* Not enough space for new pool' header.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Space, at least for eight chunks and a bitmap entry.
|
||||
*
|
||||
* TODO: Research.
|
||||
*/
|
||||
size_t poolSpaceSize = mem_HeapRecommendAllocationSize( 8 * chunkSize + sizeof (mword_t) );
|
||||
|
||||
uint8_t *poolSpace = mem_HeapAllocBlock( poolSpaceSize,
|
||||
MEM_HEAP_ALLOC_LONG_TERM);
|
||||
|
||||
if ( poolSpace == NULL )
|
||||
{
|
||||
/**
|
||||
* Not enough memory.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mem_PoolInit( poolState,
|
||||
chunkSize,
|
||||
poolSpace,
|
||||
poolSpaceSize);
|
||||
|
||||
poolState->m_pNextPool = mem_Pools[ chunkType ];
|
||||
mem_Pools[ chunkType ] = poolState;
|
||||
|
||||
mem_FreeChunksNumber[ chunkType ] += poolState->m_FreeChunksNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Now there is definitely at least one pool of specified type with at least one free chunk.
|
||||
*
|
||||
* Search for the pool.
|
||||
*/
|
||||
mem_PoolState_t *poolState = mem_Pools[ chunkType ];
|
||||
|
||||
while ( poolState->m_FreeChunksNumber == 0 )
|
||||
{
|
||||
poolState = poolState->m_pNextPool;
|
||||
|
||||
JERRY_ASSERT( poolState != NULL );
|
||||
}
|
||||
|
||||
/**
|
||||
* And allocate chunk within it.
|
||||
*/
|
||||
mem_FreeChunksNumber[ chunkType ]--;
|
||||
|
||||
return mem_PoolAllocChunk( poolState);
|
||||
} /* mem_PoolsAlloc */
|
||||
|
||||
/**
|
||||
* Free the chunk
|
||||
*/
|
||||
void
|
||||
mem_PoolsFree( mem_PoolChunkType_t chunkType, /**< the chunk type */
|
||||
uint8_t *pChunk) /**< pointer to the chunk */
|
||||
{
|
||||
mem_PoolState_t *poolState = mem_Pools[ chunkType ], *prevPoolState = NULL;
|
||||
|
||||
/**
|
||||
* Search for the pool containing specified chunk.
|
||||
*/
|
||||
while ( !( pChunk >= poolState->m_pChunks
|
||||
&& pChunk <= poolState->m_pPoolStart + poolState->m_PoolSize ) )
|
||||
{
|
||||
prevPoolState = poolState;
|
||||
poolState = poolState->m_pNextPool;
|
||||
|
||||
JERRY_ASSERT( poolState != NULL );
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the chunk
|
||||
*/
|
||||
mem_PoolFreeChunk( poolState, pChunk);
|
||||
mem_FreeChunksNumber[ chunkType ]++;
|
||||
|
||||
/**
|
||||
* If all chunks of the pool are free, free the pool itself.
|
||||
*/
|
||||
if ( poolState->m_FreeChunksNumber == poolState->m_ChunksNumber )
|
||||
{
|
||||
if ( prevPoolState != NULL )
|
||||
{
|
||||
prevPoolState->m_pNextPool = poolState->m_pNextPool;
|
||||
} else
|
||||
{
|
||||
mem_Pools[ chunkType ] = poolState->m_pNextPool;
|
||||
}
|
||||
|
||||
mem_FreeChunksNumber[ chunkType ] -= poolState->m_ChunksNumber;
|
||||
|
||||
mem_HeapFreeBlock( poolState->m_pPoolStart);
|
||||
|
||||
mem_PoolFreeChunk( &mem_PoolForPoolHeaders, (uint8_t*) poolState);
|
||||
}
|
||||
} /* mem_PoolsFree */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,65 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
/** \addtogroup mem Memory allocation
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \addtogroup poolman Memory pool manager
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Pool manager interface
|
||||
*/
|
||||
#ifndef JERRY_MEM_POOLMAN_H
|
||||
#define JERRY_MEM_POOLMAN_H
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
/**
|
||||
* Pool chunks's possible sizes
|
||||
*/
|
||||
typedef enum {
|
||||
MEM_POOL_CHUNK_TYPE_4, /**< 4-byte chunk */
|
||||
MEM_POOL_CHUNK_TYPE_8, /**< 8-byte chunk */
|
||||
MEM_POOL_CHUNK_TYPE_16, /**< 16-byte chunk */
|
||||
MEM_POOL_CHUNK_TYPE_32, /**< 32-byte chunk */
|
||||
MEM_POOL_CHUNK_TYPE__COUNT /**< count of possible pool chunks' sizes */
|
||||
} mem_PoolChunkType_t;
|
||||
|
||||
/**
|
||||
* Convert size to pool chunk type.
|
||||
*/
|
||||
#define mem_SizeToPoolChunkType( size) ((size) == 4 ? MEM_POOL_CHUNK_TYPE_4 : \
|
||||
((size) == 8 ? MEM_POOL_CHUNK_TYPE_8 : \
|
||||
((size) == 16 ? MEM_POOL_CHUNK_TYPE_16 : \
|
||||
((size) == 32 ? MEM_POOL_CHUNK_TYPE_32 : \
|
||||
jerry_UnreferencedExpression))))
|
||||
|
||||
|
||||
extern void mem_PoolsInit(void);
|
||||
extern uint8_t* mem_PoolsAlloc(mem_PoolChunkType_t chunkType);
|
||||
extern void mem_PoolsFree(mem_PoolChunkType_t chunkType, uint8_t *pChunk);
|
||||
|
||||
#endif /* JERRY_MEM_POOLMAN_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
Reference in New Issue
Block a user