00001
00002
00003
00004
00005
00006
00007
00008 #include <const.h>
00009
00010 #include <arch/i386.h>
00011 #include <arch/mem.h>
00012 #include <arch/paging.h>
00013
00014 #include <kernel/console.h>
00015 #include <kernel/kernel_map.h>
00016 #include <kernel/keyboard.h>
00017 #include <kernel/task.h>
00018
00019 #include <kernel/kmalloc.h>
00020
00021
00022 void kmalloc_init()
00023 {
00024 mem_block_t *p;
00025
00026
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 }
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 void *kmalloc(size_t size)
00046 {
00047 mem_block_t *p, *p_best=NULL;
00048 dword IF = GET_IF();
00049
00050 if (!size) return NULL;
00051
00052 disable();
00053
00054
00055
00056 size = ( size & -((uint32_t)sizeof(mem_block_t)) ) + sizeof(mem_block_t);
00057
00058
00059 p=(mem_block_t *)K_HEAP_START;
00060 while(p < (mem_block_t *)K_HEAP_END)
00061 {
00062
00063 if (p->flags == M_FREE)
00064 {
00065
00066 if (p->size == size)
00067 {
00068
00069 p_best = p;
00070 break;
00071 }
00072 if (p->size > size)
00073 {
00074
00075
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
00084 p = (void *)p+p->size+sizeof(mem_block_t);
00085 }
00086
00087
00088 if (p_best == NULL)
00089 {
00090
00091 SET_IF(IF);
00092 return NULL;
00093 }
00094
00095
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
00105 return ((void *)p_best);
00106 }
00107
00108
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
00120 return ((void *)p_best);
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 // NOTE!!! IF YOU WANT TO USE A FIRST-FIT LIKE ALLOCATOR FOR THE KERNEL //
00133 // MEMORY AREA, YOU MUST CHANGE THE kmalloc(size_t size) FUNCTION WITH //
00134 // THIS ONE AND RECOMPILE THE KERNEL.
00135 void *kmalloc(size_t size)
00136 {
00137 // This is a first-fit allocator for the kernel memory area. //
00138 // This function allocates size bytes and returns a pointer to the //
00139 // allocated memory. The memory is not cleaned. //
00140
00141 mem_block_t *p, *p2;
00142 dword IF = GET_IF();
00143
00144 if (!size) return NULL; // Is the process crazy?! :-) //
00145
00146 // Round the size up to sizeof(mem_block_t); the //
00147 // sizeof(mem_block_t) is the unit of allocation. //
00148 size = ( size & -((uint32_t)sizeof(mem_block_t)) ) + sizeof(mem_block_t);
00149
00150 disable();
00151
00152 // Let's start! //
00153 p = (mem_block_t *)K_HEAP_START;
00154 while(p < (mem_block_t *)K_HEAP_END)
00155 {
00156 if (p->flags == M_FREE)
00157 {
00158 // We found a free block, now allocate it! //
00159 p->magic = M_MAGIC;
00160 p->flags = M_ALLOC;
00161 p->owner = get_pid();
00162
00163 if (p->size == size)
00164 {
00165 // The block cover the size perfectly, //
00166 // splitting is not required //
00167 p = (void *)p + sizeof(mem_block_t);
00168
00169 SET_IF(IF);
00170
00171 // Return the pointer //
00172 return ((void *)p);
00173 }
00174
00175 // Otherwise split the hole in two blocks //
00176 p2 = (void *)p + sizeof(mem_block_t) + size;
00177 p2->magic = M_MAGIC;
00178 p2->flags = M_FREE;
00179 p2->size = p->size - size - sizeof(mem_block_t);
00180 p2->owner = NULL;
00181
00182 p->size = size;
00183 p = (void *)p + sizeof(mem_block_t);
00184
00185 SET_IF(IF);
00186
00187 // Return the pointer //
00188 return ((void *)p);
00189 }
00190
00191 // Examine the next memory block //
00192 p = (void *)p + p->size + sizeof(mem_block_t);
00193 }
00194
00195 // Out of memory! Return 0... //
00196 return(0);
00197 }
00198 */
00199
00200
00201
00202 static void deallocate(mem_block_t *ptr)
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 }
00218
00219
00220
00221
00222
00223 void kfree(void *ptr)
00224 {
00225 mem_block_t *p, *p2;
00226 dword IF = GET_IF();
00227
00228 if (ptr == NULL) return;
00229
00230 disable();
00231
00232
00233 p = (void *)ptr - sizeof(mem_block_t);
00234
00235 if (p->magic != M_MAGIC) return;
00236 if (p->flags != M_ALLOC) return;
00237
00238
00239 p->flags = M_FREE;
00240 p->owner = NULL;
00241
00242
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
00249 p->size += p2->size + sizeof(mem_block_t);
00250 p2->magic = NULL;
00251 }
00252
00253
00254 if (p != (mem_block_t *)K_HEAP_START)
00255 {
00256
00257 p2 = (void *)K_HEAP_START;
00258 for(;;)
00259 {
00260 if (((void *)p2 + p2->size + sizeof(mem_block_t)) == p)
00261 {
00262
00263
00264 if (p2->flags == M_FREE)
00265 {
00266
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
00277 deallocate(p);
00278
00279 SET_IF(IF);
00280 }
00281
00282
00283
00284
00285
00286
00287 int mem_sizeof(void *ptr)
00288 {
00289
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 }
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 void *kmemalign(size_t alignment, size_t size)
00309 {
00310 mem_block_t *p, *p2;
00311 dword IF = GET_IF();
00312
00313
00314 if ( !size )
00315 return(NULL);
00316
00317
00318 p = kmalloc(size + alignment + 2*sizeof(mem_block_t));
00319 if ( p == NULL )
00320 return(NULL);
00321
00322
00323 if ( alignment == 0 )
00324 {
00325 return(p);
00326 }
00327
00328
00329 if ( (size_t)(p) % alignment )
00330 {
00331
00332 disable();
00333
00334
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
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
00352 return(p);
00353 }
00354
00355
00356
00357
00358 void dump_memory_map()
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
00381 if (kgetchar() == CTRL_C) break;
00382 }
00383 }