Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

umalloc.c File Reference

Virtual Memory Allocator for the User Space. More...

#include <const.h>
#include <arch/paging.h>
#include <kernel/task.h>
#include <kernel/video.h>
#include <kernel/umalloc.h>

Go to the source code of this file.

Functions

void umalloc_init (size_t heap_start, size_t heap_size)
 Initialize the user virtual memory area.
Parameters:
heap_start  The start of the user heap.
heap_size  The size of the user heap.


void * umalloc (size_t size)
 Allocate a memory block from the user memory area. This is a best-fit like allocator.
Parameters:
size  The size of the block you want to allocate.
Exceptions:
NULL  Out-of-memory.
Returns:
A pointer to a memory area.
Note:
The memory area is not initialized when it's just allocated.


void deallocate (umem_block_t *ptr)
 Try to release physical frames occupied by the freed block.
Parameters:
ptr  The pointer to deallocate.


void ufree (void *ptr)
 Frees the memory space pointed by ptr, which must have been returned by a previous call to umalloc(size_t size).
Parameters:
ptr  The pointer you want to free.



Detailed Description

Virtual Memory Allocator for the User Space.

Author:
Andrea Righi <drizzt@inwind.it>
Date:
Last update: 2004-01-01
Note:
Copyright (©) 2003 Andrea Righi

Definition in file umalloc.c.


Function Documentation

void deallocate umem_block_t   ptr [static]
 

Try to release physical frames occupied by the freed block.

Parameters:
ptr  The pointer to deallocate.

Definition at line 127 of file umalloc.c.

00128 {
00129         size_t start =
00130                 PAGE_ALIGN_UP((uint32_t)((void *)ptr + sizeof(umem_block_t)));
00131         size_t end =
00132                 PAGE_ALIGN((uint32_t)((void *)ptr + sizeof(umem_block_t) + ptr->size));
00133 
00134         while( start<end )
00135         {
00136                 if (*ADDR_TO_PDE(start) != NULL)
00137                 {
00138                         delete_page( start );
00139                         start += PAGE_SIZE;
00140                 }
00141                 else
00142                         start = PAGE_DIR_ALIGN_UP( start );
00143         }
00144 }

void ufree void *    ptr
 

Frees the memory space pointed by ptr, which must have been returned by a previous call to umalloc(size_t size).

Parameters:
ptr  The pointer you want to free.

Definition at line 150 of file umalloc.c.

00151 {
00152         task_t *t;
00153         umem_block_t *p, *p2;
00154 
00155         if (ptr == NULL) return;
00156 
00157         // Point to the header.
00158         p = (void *)ptr - sizeof(umem_block_t);
00159 
00160         if (p->magic != UM_MAGIC) return; // Is the process crazy?! :)
00161         if (p->flags != UM_ALLOC) return; // Crazy again?! :)
00162 
00163         // Get the current task structure.
00164         t = get_curr_task();
00165 
00166         // Free the block.
00167         p->flags = UM_FREE;
00168         p->owner = NULL;
00169 
00170         // Try to combine the block wih the next one...
00171         p2 = (void *)p + p->size + sizeof(umem_block_t);
00172 
00173         if (p2 < (umem_block_t *)(t->heap_start + t->heap_size))
00174                 if (p2->flags == UM_FREE)
00175                 {
00176                         // Let's merge the two blocks!
00177                         p->size += p2->size + sizeof(umem_block_t);
00178                         p2->magic = NULL;
00179                 }
00180 
00181         // Try to combine the block with the previous one...
00182         if (p != (umem_block_t *)(t->heap_start))
00183         {
00184                 // Find the previous block.
00185                 p2 = (void *)(t->heap_start);
00186                 for(;;)
00187                 {
00188                         if (((void *)p2 + p2->size + sizeof(umem_block_t)) == p)
00189                         {
00190                                 // Block found!
00191                                 // Check if it's a free block.
00192                                 if (p2->flags == UM_FREE)
00193                                 {
00194                                         // Let's merge the two blocks!
00195                                         p2->size += (p->size + sizeof(umem_block_t));
00196                                         p->magic = NULL;
00197                                         p = p2;
00198                                 }
00199                                 break;
00200                         }
00201                         p2 = (void *)p2 + p2->size + sizeof(umem_block_t);
00202                 }
00203         }
00204 
00205         // Release the physical space occupied by the block.
00206         deallocate( p );
00207 }

void* umalloc size_t    size
 

Allocate a memory block from the user memory area. This is a best-fit like allocator.

Parameters:
size  The size of the block you want to allocate.
Exceptions:
NULL  Out-of-memory.
Returns:
A pointer to a memory area.
Note:
The memory area is not initialized when it's just allocated.

Definition at line 48 of file umalloc.c.

00049 {
00050         task_t *t;
00051         umem_block_t *p, *p_best=NULL;
00052 
00053         if ( !size ) return( NULL ); // Is the process crazy?! :-)
00054 
00055         // Get the current task structure.
00056         t = get_curr_task();
00057 
00058         // Round the size up to sizeof(umem_block_t); this is the unit
00059         // of allocation.
00060         size = ( size & -(sizeof(umem_block_t)) ) + sizeof(umem_block_t);
00061 
00062         // Explore the heap for the best-fit hole.
00063         p=(umem_block_t *)(t->heap_start);
00064         if( !p ) return( NULL );
00065         while(p < (umem_block_t *)(t->heap_start + t->heap_size))
00066         {
00067                 // Find a free block.
00068                 if (p->flags == UM_FREE)
00069                 {
00070                         // This block is free... let's proceed!
00071                         if (p->size == size)
00072                         {
00073                                 // Best fit block found! You're lucky!
00074                                 p_best = p;
00075                                 break;
00076                         }
00077                         if (p->size > size)
00078                         {
00079                                 // The hole is bigger than size...
00080                                 // ...check if it's the best-fit hole!
00081                                 if (p_best==NULL)
00082                                         p_best = p;
00083                                 else
00084                                         if (p_best->size > p->size)
00085                                                 p_best = p;
00086                         }
00087                 }
00088                 // Examine the next memory block.
00089                 p = (void *)p+p->size+sizeof(umem_block_t);
00090         }
00091 
00092         // Have you found a free block?!
00093         if (p_best == NULL)
00094         {
00095                 // No free memory :(
00096                 return( NULL );
00097         }
00098 
00099         // Found, now allocate it!
00100         p_best->magic = UM_MAGIC;
00101         p_best->flags = UM_ALLOC;
00102         p_best->owner = get_pid();
00103 
00104         if (p_best->size == size)
00105         {
00106                 p_best = (void *)p_best + sizeof(umem_block_t);
00107                 // The block cover the size perfectly.
00108                 return( (void *)p_best );
00109         }
00110 
00111         // Otherwise split the hole in two blocks.
00112         p = (void *)p_best + sizeof(umem_block_t) + size;
00113         p->magic = UM_MAGIC;
00114         p->flags = UM_FREE;
00115         p->size = p_best->size - size - sizeof(umem_block_t);
00116         p->owner = NULL;
00117 
00118         p_best->size = size;
00119         p_best = (void *)p_best + sizeof(umem_block_t);
00120 
00121         // Return the best-fit pointer.
00122         return ( (void *)p_best );
00123 }

void umalloc_init size_t    heap_start,
size_t    heap_size
 

Initialize the user virtual memory area.

Parameters:
heap_start  The start of the user heap.
heap_size  The size of the user heap.

Definition at line 20 of file umalloc.c.

00021 {
00022         task_t *t;
00023         umem_block_t *p;
00024 
00025         t = get_curr_task();
00026         if( t==NULL )
00027                 return;
00028 
00029         // Setup the heap in the task structure.
00030         t->heap_start = heap_start;
00031         t->heap_size = heap_size;
00032 
00033         // Create only one hudge block.
00034         p = (umem_block_t *)heap_start;
00035         p->magic = UM_MAGIC;
00036         p->flags = UM_FREE;
00037         p->size = heap_size - sizeof(umem_block_t);
00038         p->owner = NULL;
00039 }


Generated on Fri Feb 20 15:32:20 2004 for Minirighi by doxygen1.2.18