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

Subversion Repositories openfire2

[/] [openfire2/] [trunk/] [sw/] [freertos/] [heap_2.c] - Blame information for rev 6

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 toni32
/*
2
        FreeRTOS.org V4.2.0 - Copyright (C) 2003-2007 Richard Barry.
3
 
4
        This file is part of the FreeRTOS.org distribution.
5
 
6
        FreeRTOS.org is free software; you can redistribute it and/or modify
7
        it under the terms of the GNU General Public License as published by
8
        the Free Software Foundation; either version 2 of the License, or
9
        (at your option) any later version.
10
 
11
        FreeRTOS.org is distributed in the hope that it will be useful,
12
        but WITHOUT ANY WARRANTY; without even the implied warranty of
13
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
        GNU General Public License for more details.
15
 
16
        You should have received a copy of the GNU General Public License
17
        along with FreeRTOS.org; if not, write to the Free Software
18
        Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 
20
        A special exception to the GPL can be applied should you wish to distribute
21
        a combined work that includes FreeRTOS.org, without being obliged to provide
22
        the source code for any proprietary components.  See the licensing section
23
        of http://www.FreeRTOS.org for full details of how and when the exception
24
        can be applied.
25
 
26
        ***************************************************************************
27
        See http://www.FreeRTOS.org for documentation, latest information, license
28
        and contact details.  Please ensure to read the configuration and relevant
29
        port sections of the online documentation.
30
        ***************************************************************************
31
*/
32
 
33
/*
34
 * A sample implementation of pvPortMalloc() and vPortFree() that permits
35
 * allocated blocks to be freed, but does not combine adjacent free blocks
36
 * into a single larger block.
37
 *
38
 * See heap_1.c and heap_3.c for alternative implementations, and the memory
39
 * management pages of http://www.FreeRTOS.org for more information.
40
 */
41
#include <stdio.h>
42
#include <stdlib.h>
43
 
44
#include "FreeRTOS.h"
45
#include "task.h"
46
 
47
/* Setup the correct byte alignment mask for the defined byte alignment. */
48
#if portBYTE_ALIGNMENT == 4
49
        #define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0003 )
50
#endif
51
 
52
#if portBYTE_ALIGNMENT == 2
53
        #define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0001 )
54
#endif
55
 
56
#if portBYTE_ALIGNMENT == 1
57
        #define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0000 )
58
#endif
59
 
60
#ifndef heapBYTE_ALIGNMENT_MASK
61
        #error "Invalid portBYTE_ALIGNMENT definition"
62
#endif
63
 
64
/* Allocate the memory for the heap.  The struct is used to force byte
65
alignment without using any non-portable code. */
66
extern void *_HEAP_SIZE;
67
extern void *_heap;
68
unsigned char *ucHeap = (unsigned char *) &_heap;       /* heap starts here (word aligned) */
69
 
70
/* Define the linked list structure.  This is used to link free blocks in order
71
of their size. */
72
typedef struct A_BLOCK_LINK
73
{
74
        struct A_BLOCK_LINK *pxNextFreeBlock;   /*<< The next free block in the list. */
75
        size_t xBlockSize;                      /*<< The size of the free block. */
76
} xBlockLink;
77
 
78
 
79
static const unsigned portSHORT  heapSTRUCT_SIZE        = ( sizeof( xBlockLink ) + ( sizeof( xBlockLink ) % portBYTE_ALIGNMENT ) );
80
#define heapMINIMUM_BLOCK_SIZE  ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) )
81
 
82
/* Create a couple of list links to mark the start and end of the list. */
83
static xBlockLink xStart, xEnd;
84
 
85
/* STATIC FUNCTIONS ARE DEFINED AS MACROS TO MINIMIZE THE FUNCTION CALL DEPTH. */
86
 
87
/*
88
 * Insert a block into the list of free blocks - which is ordered by size of
89
 * the block.  Small blocks at the start of the list and large blocks at the end
90
 * of the list.
91
 */
92
#define prvInsertBlockIntoFreeList( pxBlockToInsert )                                   \
93
{                                                                                       \
94
xBlockLink *pxIterator;                                                                 \
95
size_t xBlockSize;                                                                      \
96
                                                                                        \
97
        xBlockSize = pxBlockToInsert->xBlockSize;                                       \
98
                                                                                        \
99
        /* Iterate through the list until a block is found that has a larger size */    \
100
        /* than the block we are inserting. */                                          \
101
        for( pxIterator = &xStart; pxIterator->pxNextFreeBlock->xBlockSize < xBlockSize; pxIterator = pxIterator->pxNextFreeBlock )     \
102
        {                                                                               \
103
        /* There is nothing to do here - just iterate to the correct position. */       \
104
        }                                                                               \
105
                                                                                        \
106
        /* Update the list to include the block being inserted in the correct */        \
107
        /* position. */                                                                 \
108
        pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;                 \
109
        pxIterator->pxNextFreeBlock = pxBlockToInsert;                                  \
110
}
111
/*-----------------------------------------------------------*/
112
 
113
#define prvHeapInit()                                                                   \
114
{                                                                                       \
115
xBlockLink *pxFirstFreeBlock;                                                           \
116
                                                                                        \
117
        /* xStart is used to hold a pointer to the first item in the list of free */    \
118
        /* blocks.  The void cast is used to prevent compiler warnings. */              \
119
        xStart.pxNextFreeBlock = ( void * ) ucHeap;                                     \
120
        xStart.xBlockSize = ( size_t ) 0;                                                \
121
                                                                                        \
122
        /* xEnd is used to mark the end of the list of free blocks. */                  \
123
        xEnd.xBlockSize = (unsigned portLONG) &_HEAP_SIZE;                              \
124
        xEnd.pxNextFreeBlock = NULL;                                                    \
125
                                                                                        \
126
        /* To start with there is a single free block that is sized to take up the      \
127
        entire heap space. */                                                           \
128
        pxFirstFreeBlock = ( void * ) ucHeap;                                           \
129
        pxFirstFreeBlock->xBlockSize = (unsigned portLONG) &_HEAP_SIZE;                 \
130
        pxFirstFreeBlock->pxNextFreeBlock = &xEnd;                                      \
131
}
132
/*-----------------------------------------------------------*/
133
 
134
void *pvPortMalloc( size_t xWantedSize )
135
{
136
xBlockLink *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
137
static portBASE_TYPE xHeapHasBeenInitialised = pdFALSE;
138
void *pvReturn = NULL;
139
 
140
        vTaskSuspendAll();
141
        {
142
                /* If this is the first call to malloc then the heap will require
143
                initialisation to setup the list of free blocks. */
144
                if( xHeapHasBeenInitialised == pdFALSE )
145
                {
146
                        prvHeapInit();
147
                        xHeapHasBeenInitialised = pdTRUE;
148
                }
149
 
150
                /* The wanted size is increased so it can contain a xBlockLink
151
                structure in addition to the requested amount of bytes. */
152
                if( xWantedSize > 0 )
153
                {
154
                        xWantedSize += heapSTRUCT_SIZE;
155
 
156
                        /* Ensure that blocks are always aligned to the required number of bytes. */
157
                        if( xWantedSize & heapBYTE_ALIGNMENT_MASK )
158
                        {
159
                                /* Byte alignment required. */
160
                                xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & heapBYTE_ALIGNMENT_MASK ) );
161
                        }
162
                }
163
 
164
                if( ( xWantedSize > 0 ) && ( xWantedSize < (unsigned portLONG) &_HEAP_SIZE ) )
165
                {
166
                        /* Blocks are stored in byte order - traverse the list from the start
167
                        (smallest) block until one of adequate size is found. */
168
                        pxPreviousBlock = &xStart;
169
                        pxBlock = xStart.pxNextFreeBlock;
170
                        while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock ) )
171
                        {
172
                                pxPreviousBlock = pxBlock;
173
                                pxBlock = pxBlock->pxNextFreeBlock;
174
                        }
175
 
176
                        /* If we found the end marker then a block of adequate size was not found. */
177
                        if( pxBlock != &xEnd )
178
                        {
179
                                /* Return the memory space - jumping over the xBlockLink structure
180
                                at its start. */
181
                                pvReturn = ( void * ) ( ( ( unsigned portCHAR * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE );
182
 
183
                                /* This block is being returned for use so must be taken our of the
184
                                list of free blocks. */
185
                                pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
186
 
187
                                /* If the block is larger than required it can be split into two. */
188
                                if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
189
                                {
190
                                        /* This block is to be split into two.  Create a new block
191
                                        following the number of bytes requested. The void cast is
192
                                        used to prevent byte alignment warnings from the compiler. */
193
                                        pxNewBlockLink = ( void * ) ( ( ( unsigned portCHAR * ) pxBlock ) + xWantedSize );
194
 
195
                                        /* Calculate the sizes of two blocks split from the single
196
                                        block. */
197
                                        pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
198
                                        pxBlock->xBlockSize = xWantedSize;
199
 
200
                                        /* Insert the new block into the list of free blocks. */
201
                                        prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
202
                                }
203
                        }
204
                }
205
        }
206
        xTaskResumeAll();
207
 
208
        return pvReturn;
209
}
210
/*-----------------------------------------------------------*/
211
 
212
void vPortFree( void *pv )
213
{
214
unsigned portCHAR *puc = ( unsigned portCHAR * ) pv;
215
xBlockLink *pxLink;
216
 
217
        if( pv )
218
        {
219
                /* The memory being freed will have an xBlockLink structure immediately
220
                before it. */
221
                puc -= heapSTRUCT_SIZE;
222
 
223
                /* This casting is to keep the compiler from issuing warnings. */
224
                pxLink = ( void * ) puc;
225
 
226
                vTaskSuspendAll();
227
                {
228
                        /* Add this block to the list of free blocks. */
229
                        prvInsertBlockIntoFreeList( ( ( xBlockLink * ) pxLink ) );
230
                }
231
                xTaskResumeAll();
232
        }
233
}
234
/*-----------------------------------------------------------*/
235
 

powered by: WebSVN 2.1.0

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