OpenCores
URL https://opencores.org/ocsvn/openfire2/openfire2/trunk

Subversion Repositories openfire2

[/] [openfire2/] [trunk/] [sw/] [freertos/] [heap_2.c] - Diff between revs 4 and 6

Only display areas with differences | Details | Blame | View Log

Rev 4 Rev 6
/*
/*
        FreeRTOS.org V4.2.0 - Copyright (C) 2003-2007 Richard Barry.
        FreeRTOS.org V4.2.0 - Copyright (C) 2003-2007 Richard Barry.
 
 
        This file is part of the FreeRTOS.org distribution.
        This file is part of the FreeRTOS.org distribution.
 
 
        FreeRTOS.org is free software; you can redistribute it and/or modify
        FreeRTOS.org is free software; you can redistribute it and/or modify
        it under the terms of the GNU General Public License as published by
        it under the terms of the GNU General Public License as published by
        the Free Software Foundation; either version 2 of the License, or
        the Free Software Foundation; either version 2 of the License, or
        (at your option) any later version.
        (at your option) any later version.
 
 
        FreeRTOS.org is distributed in the hope that it will be useful,
        FreeRTOS.org is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Public License for more details.
        GNU General Public License for more details.
 
 
        You should have received a copy of the GNU General Public License
        You should have received a copy of the GNU General Public License
        along with FreeRTOS.org; if not, write to the Free Software
        along with FreeRTOS.org; if not, write to the Free Software
        Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
        Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 
        A special exception to the GPL can be applied should you wish to distribute
        A special exception to the GPL can be applied should you wish to distribute
        a combined work that includes FreeRTOS.org, without being obliged to provide
        a combined work that includes FreeRTOS.org, without being obliged to provide
        the source code for any proprietary components.  See the licensing section
        the source code for any proprietary components.  See the licensing section
        of http://www.FreeRTOS.org for full details of how and when the exception
        of http://www.FreeRTOS.org for full details of how and when the exception
        can be applied.
        can be applied.
 
 
        ***************************************************************************
        ***************************************************************************
        See http://www.FreeRTOS.org for documentation, latest information, license
        See http://www.FreeRTOS.org for documentation, latest information, license
        and contact details.  Please ensure to read the configuration and relevant
        and contact details.  Please ensure to read the configuration and relevant
        port sections of the online documentation.
        port sections of the online documentation.
        ***************************************************************************
        ***************************************************************************
*/
*/
 
 
/*
/*
 * A sample implementation of pvPortMalloc() and vPortFree() that permits
 * A sample implementation of pvPortMalloc() and vPortFree() that permits
 * allocated blocks to be freed, but does not combine adjacent free blocks
 * allocated blocks to be freed, but does not combine adjacent free blocks
 * into a single larger block.
 * into a single larger block.
 *
 *
 * See heap_1.c and heap_3.c for alternative implementations, and the memory
 * See heap_1.c and heap_3.c for alternative implementations, and the memory
 * management pages of http://www.FreeRTOS.org for more information.
 * management pages of http://www.FreeRTOS.org for more information.
 */
 */
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
 
 
#include "FreeRTOS.h"
#include "FreeRTOS.h"
#include "task.h"
#include "task.h"
 
 
/* Setup the correct byte alignment mask for the defined byte alignment. */
/* Setup the correct byte alignment mask for the defined byte alignment. */
#if portBYTE_ALIGNMENT == 4
#if portBYTE_ALIGNMENT == 4
        #define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0003 )
        #define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0003 )
#endif
#endif
 
 
#if portBYTE_ALIGNMENT == 2
#if portBYTE_ALIGNMENT == 2
        #define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0001 )
        #define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0001 )
#endif
#endif
 
 
#if portBYTE_ALIGNMENT == 1
#if portBYTE_ALIGNMENT == 1
        #define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0000 )
        #define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0000 )
#endif
#endif
 
 
#ifndef heapBYTE_ALIGNMENT_MASK
#ifndef heapBYTE_ALIGNMENT_MASK
        #error "Invalid portBYTE_ALIGNMENT definition"
        #error "Invalid portBYTE_ALIGNMENT definition"
#endif
#endif
 
 
/* Allocate the memory for the heap.  The struct is used to force byte
/* Allocate the memory for the heap.  The struct is used to force byte
alignment without using any non-portable code. */
alignment without using any non-portable code. */
extern void *_HEAP_SIZE;
extern void *_HEAP_SIZE;
extern void *_heap;
extern void *_heap;
unsigned char *ucHeap = (unsigned char *) &_heap;       /* heap starts here (word aligned) */
unsigned char *ucHeap = (unsigned char *) &_heap;       /* heap starts here (word aligned) */
 
 
/* Define the linked list structure.  This is used to link free blocks in order
/* Define the linked list structure.  This is used to link free blocks in order
of their size. */
of their size. */
typedef struct A_BLOCK_LINK
typedef struct A_BLOCK_LINK
{
{
        struct A_BLOCK_LINK *pxNextFreeBlock;   /*<< The next free block in the list. */
        struct A_BLOCK_LINK *pxNextFreeBlock;   /*<< The next free block in the list. */
        size_t xBlockSize;                      /*<< The size of the free block. */
        size_t xBlockSize;                      /*<< The size of the free block. */
} xBlockLink;
} xBlockLink;
 
 
 
 
static const unsigned portSHORT  heapSTRUCT_SIZE        = ( sizeof( xBlockLink ) + ( sizeof( xBlockLink ) % portBYTE_ALIGNMENT ) );
static const unsigned portSHORT  heapSTRUCT_SIZE        = ( sizeof( xBlockLink ) + ( sizeof( xBlockLink ) % portBYTE_ALIGNMENT ) );
#define heapMINIMUM_BLOCK_SIZE  ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) )
#define heapMINIMUM_BLOCK_SIZE  ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) )
 
 
/* Create a couple of list links to mark the start and end of the list. */
/* Create a couple of list links to mark the start and end of the list. */
static xBlockLink xStart, xEnd;
static xBlockLink xStart, xEnd;
 
 
/* STATIC FUNCTIONS ARE DEFINED AS MACROS TO MINIMIZE THE FUNCTION CALL DEPTH. */
/* STATIC FUNCTIONS ARE DEFINED AS MACROS TO MINIMIZE THE FUNCTION CALL DEPTH. */
 
 
/*
/*
 * Insert a block into the list of free blocks - which is ordered by size of
 * Insert a block into the list of free blocks - which is ordered by size of
 * the block.  Small blocks at the start of the list and large blocks at the end
 * the block.  Small blocks at the start of the list and large blocks at the end
 * of the list.
 * of the list.
 */
 */
#define prvInsertBlockIntoFreeList( pxBlockToInsert )                                   \
#define prvInsertBlockIntoFreeList( pxBlockToInsert )                                   \
{                                                                                       \
{                                                                                       \
xBlockLink *pxIterator;                                                                 \
xBlockLink *pxIterator;                                                                 \
size_t xBlockSize;                                                                      \
size_t xBlockSize;                                                                      \
                                                                                        \
                                                                                        \
        xBlockSize = pxBlockToInsert->xBlockSize;                                       \
        xBlockSize = pxBlockToInsert->xBlockSize;                                       \
                                                                                        \
                                                                                        \
        /* Iterate through the list until a block is found that has a larger size */    \
        /* Iterate through the list until a block is found that has a larger size */    \
        /* than the block we are inserting. */                                          \
        /* than the block we are inserting. */                                          \
        for( pxIterator = &xStart; pxIterator->pxNextFreeBlock->xBlockSize < xBlockSize; pxIterator = pxIterator->pxNextFreeBlock )     \
        for( pxIterator = &xStart; pxIterator->pxNextFreeBlock->xBlockSize < xBlockSize; pxIterator = pxIterator->pxNextFreeBlock )     \
        {                                                                               \
        {                                                                               \
        /* There is nothing to do here - just iterate to the correct position. */       \
        /* There is nothing to do here - just iterate to the correct position. */       \
        }                                                                               \
        }                                                                               \
                                                                                        \
                                                                                        \
        /* Update the list to include the block being inserted in the correct */        \
        /* Update the list to include the block being inserted in the correct */        \
        /* position. */                                                                 \
        /* position. */                                                                 \
        pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;                 \
        pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;                 \
        pxIterator->pxNextFreeBlock = pxBlockToInsert;                                  \
        pxIterator->pxNextFreeBlock = pxBlockToInsert;                                  \
}
}
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/
 
 
#define prvHeapInit()                                                                   \
#define prvHeapInit()                                                                   \
{                                                                                       \
{                                                                                       \
xBlockLink *pxFirstFreeBlock;                                                           \
xBlockLink *pxFirstFreeBlock;                                                           \
                                                                                        \
                                                                                        \
        /* xStart is used to hold a pointer to the first item in the list of free */    \
        /* xStart is used to hold a pointer to the first item in the list of free */    \
        /* blocks.  The void cast is used to prevent compiler warnings. */              \
        /* blocks.  The void cast is used to prevent compiler warnings. */              \
        xStart.pxNextFreeBlock = ( void * ) ucHeap;                                     \
        xStart.pxNextFreeBlock = ( void * ) ucHeap;                                     \
        xStart.xBlockSize = ( size_t ) 0;                                                \
        xStart.xBlockSize = ( size_t ) 0;                                                \
                                                                                        \
                                                                                        \
        /* xEnd is used to mark the end of the list of free blocks. */                  \
        /* xEnd is used to mark the end of the list of free blocks. */                  \
        xEnd.xBlockSize = (unsigned portLONG) &_HEAP_SIZE;                              \
        xEnd.xBlockSize = (unsigned portLONG) &_HEAP_SIZE;                              \
        xEnd.pxNextFreeBlock = NULL;                                                    \
        xEnd.pxNextFreeBlock = NULL;                                                    \
                                                                                        \
                                                                                        \
        /* To start with there is a single free block that is sized to take up the      \
        /* To start with there is a single free block that is sized to take up the      \
        entire heap space. */                                                           \
        entire heap space. */                                                           \
        pxFirstFreeBlock = ( void * ) ucHeap;                                           \
        pxFirstFreeBlock = ( void * ) ucHeap;                                           \
        pxFirstFreeBlock->xBlockSize = (unsigned portLONG) &_HEAP_SIZE;                 \
        pxFirstFreeBlock->xBlockSize = (unsigned portLONG) &_HEAP_SIZE;                 \
        pxFirstFreeBlock->pxNextFreeBlock = &xEnd;                                      \
        pxFirstFreeBlock->pxNextFreeBlock = &xEnd;                                      \
}
}
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/
 
 
void *pvPortMalloc( size_t xWantedSize )
void *pvPortMalloc( size_t xWantedSize )
{
{
xBlockLink *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
xBlockLink *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
static portBASE_TYPE xHeapHasBeenInitialised = pdFALSE;
static portBASE_TYPE xHeapHasBeenInitialised = pdFALSE;
void *pvReturn = NULL;
void *pvReturn = NULL;
 
 
        vTaskSuspendAll();
        vTaskSuspendAll();
        {
        {
                /* If this is the first call to malloc then the heap will require
                /* If this is the first call to malloc then the heap will require
                initialisation to setup the list of free blocks. */
                initialisation to setup the list of free blocks. */
                if( xHeapHasBeenInitialised == pdFALSE )
                if( xHeapHasBeenInitialised == pdFALSE )
                {
                {
                        prvHeapInit();
                        prvHeapInit();
                        xHeapHasBeenInitialised = pdTRUE;
                        xHeapHasBeenInitialised = pdTRUE;
                }
                }
 
 
                /* The wanted size is increased so it can contain a xBlockLink
                /* The wanted size is increased so it can contain a xBlockLink
                structure in addition to the requested amount of bytes. */
                structure in addition to the requested amount of bytes. */
                if( xWantedSize > 0 )
                if( xWantedSize > 0 )
                {
                {
                        xWantedSize += heapSTRUCT_SIZE;
                        xWantedSize += heapSTRUCT_SIZE;
 
 
                        /* Ensure that blocks are always aligned to the required number of bytes. */
                        /* Ensure that blocks are always aligned to the required number of bytes. */
                        if( xWantedSize & heapBYTE_ALIGNMENT_MASK )
                        if( xWantedSize & heapBYTE_ALIGNMENT_MASK )
                        {
                        {
                                /* Byte alignment required. */
                                /* Byte alignment required. */
                                xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & heapBYTE_ALIGNMENT_MASK ) );
                                xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & heapBYTE_ALIGNMENT_MASK ) );
                        }
                        }
                }
                }
 
 
                if( ( xWantedSize > 0 ) && ( xWantedSize < (unsigned portLONG) &_HEAP_SIZE ) )
                if( ( xWantedSize > 0 ) && ( xWantedSize < (unsigned portLONG) &_HEAP_SIZE ) )
                {
                {
                        /* Blocks are stored in byte order - traverse the list from the start
                        /* Blocks are stored in byte order - traverse the list from the start
                        (smallest) block until one of adequate size is found. */
                        (smallest) block until one of adequate size is found. */
                        pxPreviousBlock = &xStart;
                        pxPreviousBlock = &xStart;
                        pxBlock = xStart.pxNextFreeBlock;
                        pxBlock = xStart.pxNextFreeBlock;
                        while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock ) )
                        while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock ) )
                        {
                        {
                                pxPreviousBlock = pxBlock;
                                pxPreviousBlock = pxBlock;
                                pxBlock = pxBlock->pxNextFreeBlock;
                                pxBlock = pxBlock->pxNextFreeBlock;
                        }
                        }
 
 
                        /* If we found the end marker then a block of adequate size was not found. */
                        /* If we found the end marker then a block of adequate size was not found. */
                        if( pxBlock != &xEnd )
                        if( pxBlock != &xEnd )
                        {
                        {
                                /* Return the memory space - jumping over the xBlockLink structure
                                /* Return the memory space - jumping over the xBlockLink structure
                                at its start. */
                                at its start. */
                                pvReturn = ( void * ) ( ( ( unsigned portCHAR * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE );
                                pvReturn = ( void * ) ( ( ( unsigned portCHAR * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE );
 
 
                                /* This block is being returned for use so must be taken our of the
                                /* This block is being returned for use so must be taken our of the
                                list of free blocks. */
                                list of free blocks. */
                                pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
                                pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
 
 
                                /* If the block is larger than required it can be split into two. */
                                /* If the block is larger than required it can be split into two. */
                                if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
                                if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
                                {
                                {
                                        /* This block is to be split into two.  Create a new block
                                        /* This block is to be split into two.  Create a new block
                                        following the number of bytes requested. The void cast is
                                        following the number of bytes requested. The void cast is
                                        used to prevent byte alignment warnings from the compiler. */
                                        used to prevent byte alignment warnings from the compiler. */
                                        pxNewBlockLink = ( void * ) ( ( ( unsigned portCHAR * ) pxBlock ) + xWantedSize );
                                        pxNewBlockLink = ( void * ) ( ( ( unsigned portCHAR * ) pxBlock ) + xWantedSize );
 
 
                                        /* Calculate the sizes of two blocks split from the single
                                        /* Calculate the sizes of two blocks split from the single
                                        block. */
                                        block. */
                                        pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
                                        pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
                                        pxBlock->xBlockSize = xWantedSize;
                                        pxBlock->xBlockSize = xWantedSize;
 
 
                                        /* Insert the new block into the list of free blocks. */
                                        /* Insert the new block into the list of free blocks. */
                                        prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
                                        prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
                                }
                                }
                        }
                        }
                }
                }
        }
        }
        xTaskResumeAll();
        xTaskResumeAll();
 
 
        return pvReturn;
        return pvReturn;
}
}
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/
 
 
void vPortFree( void *pv )
void vPortFree( void *pv )
{
{
unsigned portCHAR *puc = ( unsigned portCHAR * ) pv;
unsigned portCHAR *puc = ( unsigned portCHAR * ) pv;
xBlockLink *pxLink;
xBlockLink *pxLink;
 
 
        if( pv )
        if( pv )
        {
        {
                /* The memory being freed will have an xBlockLink structure immediately
                /* The memory being freed will have an xBlockLink structure immediately
                before it. */
                before it. */
                puc -= heapSTRUCT_SIZE;
                puc -= heapSTRUCT_SIZE;
 
 
                /* This casting is to keep the compiler from issuing warnings. */
                /* This casting is to keep the compiler from issuing warnings. */
                pxLink = ( void * ) puc;
                pxLink = ( void * ) puc;
 
 
                vTaskSuspendAll();
                vTaskSuspendAll();
                {
                {
                        /* Add this block to the list of free blocks. */
                        /* Add this block to the list of free blocks. */
                        prvInsertBlockIntoFreeList( ( ( xBlockLink * ) pxLink ) );
                        prvInsertBlockIntoFreeList( ( ( xBlockLink * ) pxLink ) );
                }
                }
                xTaskResumeAll();
                xTaskResumeAll();
        }
        }
}
}
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.