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

kmalloc.c File Reference

Memory Allocator. More...

#include <const.h>
#include <arch/i386.h>
#include <arch/mem.h>
#include <arch/paging.h>
#include <kernel/console.h>
#include <kernel/kernel_map.h>
#include <kernel/keyboard.h>
#include <kernel/task.h>
#include <kernel/kmalloc.h>

Go to the source code of this file.

Functions

void kmalloc_init ()
 Initialize the kernel virtual memory area.

void * kmalloc (size_t size)
 Allocate a memory block from the kernel 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 (mem_block_t *ptr)
 Try to release physical frames occupied by the freed block.
Parameters:
ptr  The pointer to deallocate.


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


int mem_sizeof (void *ptr)
 Return the size of the pointer ptr passed as argument.
Parameters:
ptr  The pointer you want to know the size.
Exceptions:
NULL  Invalid pointer ptr.
Returns:
The size of the pointer ptr passed as argument.


void * kmemalign (size_t alignment, size_t size)
 Allocate some memory aligned to a boundary.
Parameters:
alignment  The boundary.
size  The size you want to allocate.
Exceptions:
NULL  Out-of-memory.
Returns:
A pointer to a memory area aligned to the boundary. The pointer is a aligned_mem_block_t pointer, so if you want to access to the data area of this pointer you must specify the p->start filed.
Note:
Use kfree(void *ptr) to free the allocated block.


void dump_memory_map ()
 This is a routine for debug only. It prints all the memory block headers.
Note:
Prints the result to the current console.



Detailed Description

Memory Allocator.

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

Definition in file kmalloc.c.


Function Documentation

void deallocate mem_block_t   ptr [static]
 

Try to release physical frames occupied by the freed block.

Parameters:
ptr  The pointer to deallocate.

Definition at line 202 of file kmalloc.c.

00203 {
00204         dword start = PAGE_ALIGN_UP((dword)((void *)ptr + sizeof(mem_block_t)));
00205         dword end = PAGE_ALIGN((dword)((void *)ptr + sizeof(mem_block_t) + ptr->size));
00206 
00207         while(start < end)
00208         {
00209                 if (*ADDR_TO_PDE(start) != NULL)
00210                 {
00211                         delete_page(start);
00212                         start += PAGE_SIZE;
00213                 }
00214                 else
00215                         start = PAGE_DIR_ALIGN_UP(start);
00216         }
00217 }

void dump_memory_map  
 

This is a routine for debug only. It prints all the memory block headers.

Note:
Prints the result to the current console.

Definition at line 358 of file kmalloc.c.

00359 {
00360         mem_block_t *p = (mem_block_t *)K_HEAP_START;
00361 
00362         for(;;)
00363         {
00364                 kprintf(
00365                         "\n\rp        = %#010x"
00366                         "\n\rp->magic = %s"
00367                         "\n\rp->flags = %#010x"
00368                         "\n\rp->size  = %u"
00369                         "\n\rp->owner = %i\n\r",
00370                         (dword)p + sizeof(mem_block_t),
00371                         (byte *)p->magic,
00372                         p->flags,
00373                         p->size,
00374                         p->owner);
00375 
00376                 p = (void *)p + p->size + sizeof(mem_block_t);
00377 
00378                 if (p >= (mem_block_t *)K_HEAP_END) break;
00379 
00380                 // Wait for a key... //
00381                 if (kgetchar() == CTRL_C) break;
00382         }
00383 }

void kfree void *    ptr
 

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

Parameters:
ptr  The pointer you want to free.

Definition at line 223 of file kmalloc.c.

00224 {
00225         mem_block_t *p, *p2;
00226         dword IF = GET_IF();
00227 
00228         if (ptr == NULL) return;
00229 
00230         disable();
00231 
00232         // Point to the header                                          //
00233         p = (void *)ptr - sizeof(mem_block_t);
00234 
00235         if (p->magic != M_MAGIC) return; // Is the process crazy?! :)   //
00236         if (p->flags != M_ALLOC) return; // Crazy again?! :)            //
00237 
00238         // Free the block                                               //
00239         p->flags = M_FREE;
00240         p->owner = NULL;
00241 
00242         // Try to combine the block wih the next one...                 //
00243         p2 = (void *)p + p->size + sizeof(mem_block_t);
00244 
00245         if (p2 < (mem_block_t *)K_HEAP_END)
00246                 if (p2->flags == M_FREE)
00247                 {
00248                         // Let's merge the two blocks!                  //
00249                         p->size += p2->size + sizeof(mem_block_t);
00250                         p2->magic = NULL;
00251                 }
00252 
00253         // Try to combine the block with the previous one...            //
00254         if (p != (mem_block_t *)K_HEAP_START)
00255         {
00256                 // Find the previous block                              //
00257                 p2 = (void *)K_HEAP_START;
00258                 for(;;)
00259                 {
00260                         if (((void *)p2 + p2->size + sizeof(mem_block_t)) == p)
00261                         {
00262                                 // Block found!                         //
00263                                 // Check if it's a free block           //
00264                                 if (p2->flags == M_FREE)
00265                                 {
00266                                         // Let's merge the two blocks!  //
00267                                         p2->size += (p->size + sizeof(mem_block_t));
00268                                         p->magic = NULL;
00269                                         p = p2;
00270                                 }
00271                                 break;
00272                         }
00273                         p2 = (void *)p2 + p2->size + sizeof(mem_block_t);
00274                 }
00275         }
00276         // Release the physical space occupied by the block             //
00277         deallocate(p);
00278 
00279         SET_IF(IF);
00280 }

void* kmalloc size_t    size
 

Allocate a memory block from the kernel 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 45 of file kmalloc.c.

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

void kmalloc_init  
 

Initialize the kernel virtual memory area.

Definition at line 22 of file kmalloc.c.

00023 {
00024         mem_block_t *p;
00025 
00026         // Create only one hudge block                                  //
00027         p = (mem_block_t *)K_HEAP_START;
00028         p->magic = M_MAGIC;
00029         p->flags = M_FREE;
00030         p->size = K_HEAP_END - K_HEAP_START - sizeof(mem_block_t);
00031         p->owner = NULL;
00032 }

void* kmemalign size_t    alignment,
size_t    size
 

Allocate some memory aligned to a boundary.

Parameters:
alignment  The boundary.
size  The size you want to allocate.
Exceptions:
NULL  Out-of-memory.
Returns:
A pointer to a memory area aligned to the boundary. The pointer is a aligned_mem_block_t pointer, so if you want to access to the data area of this pointer you must specify the p->start filed.
Note:
Use kfree(void *ptr) to free the allocated block.

Definition at line 308 of file kmalloc.c.

00309 {
00310         mem_block_t *p, *p2;
00311         dword IF = GET_IF();
00312 
00313         // Cannot allocate memory with a size of zero                   //
00314         if ( !size )
00315                 return(NULL);
00316 
00317         // Allocate the pointer                                         //
00318         p = kmalloc(size + alignment + 2*sizeof(mem_block_t));
00319         if ( p == NULL )
00320                 return(NULL);
00321 
00322         // An alignment of zero is intended as a simple kmalloc(size)   //
00323         if ( alignment == 0 )
00324         {
00325                 return(p);
00326         }
00327 
00328         // Check if the pointer is correcly aligned                     //
00329         if ( (size_t)(p) % alignment )
00330         {
00331                 // Align the pointer p to the boundary.                 //
00332                 disable();
00333 
00334                 // Allocate the new block                               //
00335                 p2 = p + 2;
00336                 p2 = (mem_block_t *)ALIGN_UP((size_t)p2, alignment)  - 1;
00337                 p2->magic = M_MAGIC;
00338                 p2->flags = (p-1)->flags;
00339                 p2->owner = (p-1)->owner;
00340                 p2->size = mem_sizeof(p) - ((size_t)(p2+1) - (size_t)p);
00341 
00342                 // Free the unused space                                //
00343                 (p-1)->size = (size_t)p2 - (size_t)p;
00344                 kfree(p);
00345 
00346                 SET_IF(IF);
00347 
00348                 return(p2+1);
00349         }
00350         else
00351                 // The pointer p is already aligned to the boudary      //
00352                 return(p);
00353 }

int mem_sizeof void *    ptr
 

Return the size of the pointer ptr passed as argument.

Parameters:
ptr  The pointer you want to know the size.
Exceptions:
NULL  Invalid pointer ptr.
Returns:
The size of the pointer ptr passed as argument.

Definition at line 287 of file kmalloc.c.

00288 {
00289 // Return the size of the pointer "ptr", or NULL if an error occurs     //
00290         mem_block_t *p = ((mem_block_t *)ptr-1);
00291 
00292         if ( (p->magic == M_MAGIC) && (p->flags == M_ALLOC) )
00293                 return( p->size );
00294         else
00295                 return(NULL);
00296 }


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