00001 /***************************************************************************************** 00002 Copyright (c) 2002-2004 The UbixOS Project 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without modification, are 00006 permitted provided that the following conditions are met: 00007 00008 Redistributions of source code must retain the above copyright notice, this list of 00009 conditions, the following disclaimer and the list of authors. Redistributions in binary 00010 form must reproduce the above copyright notice, this list of conditions, the following 00011 disclaimer and the list of authors in the documentation and/or other materials provided 00012 with the distribution. Neither the name of the UbixOS Project nor the names of its 00013 contributors may be used to endorse or promote products derived from this software 00014 without specific prior written permission. 00015 00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 00017 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00018 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 00019 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00020 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00021 OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00022 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 00023 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00024 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00025 00026 $Id$ 00027 00028 *****************************************************************************************/ 00029 00030 #include <lib/kmalloc.h> 00031 #include <lib/kprintf.h> 00032 #include <ubixos/kpanic.h> 00033 #include <ubixos/sched.h> 00034 #include <ubixos/spinlock.h> 00035 #include <vmm/vmm.h> 00036 #include <string.h> 00037 #include <assert.h> 00038 00039 /* 00040 Set up three descriptor tables: 00041 00042 kernDesc - The inuse descriptor table 00043 freeKernDesc - The free descriptor table (descriptors with memory backing just not in use) 00044 emptyKernDesc - The empty descriptor table (descriptors with out a memory backing) 00045 00046 */ 00047 static struct memDescriptor *usedKernDesc = 0x0; 00048 static struct memDescriptor *freeKernDesc = 0x0; 00049 static struct memDescriptor *emptyKernDesc = 0x0; 00050 00051 /* 00052 Set up our spinlocks so we do not corrupt linked lists if we have re-entrancy 00053 */ 00054 static spinLock_t mallocSpinLock = SPIN_LOCK_INITIALIZER; 00055 static spinLock_t emptyDescSpinLock = SPIN_LOCK_INITIALIZER; 00056 00057 /************************************************************************ 00058 00059 Function: void *getEmptyDesc() 00060 Description: Find An Empty Descriptor 00061 00062 Notes: 00063 00064 02/17/03 - Is This Efficient? 00065 00066 ************************************************************************/ 00067 static void *getEmptyDesc() { 00068 int i = 0x0; 00069 struct memDescriptor *tmpDesc = 0x0; 00070 00071 spinLock(&emptyDescSpinLock); 00072 00073 tmpDesc = emptyKernDesc; 00074 00075 if (tmpDesc != 0x0) { 00076 emptyKernDesc = tmpDesc->next; 00077 if (emptyKernDesc != 0x0) 00078 emptyKernDesc->prev = 0x0; 00079 00080 00081 tmpDesc->next = 0x0; 00082 tmpDesc->prev = 0x0; 00083 spinUnlock(&emptyDescSpinLock); 00084 return(tmpDesc); 00085 } 00086 00087 if ((emptyKernDesc = (struct memDescriptor *)vmm_getFreeMallocPage(4)) == 0x0) 00088 kpanic("Error: vmmGetFreeKernelPage returned NULL\n"); 00089 00090 /* zero out the memory so we know there is no garbage */ 00091 memset(emptyKernDesc,0x0,0x4000); 00092 00093 emptyKernDesc[0].next = &emptyKernDesc[1]; 00094 00095 for (i = 0x1;i < ((0x4000/sizeof(struct memDescriptor)));i++) { 00096 if (i+1 < (0x4000/sizeof(struct memDescriptor))) 00097 emptyKernDesc[i].next = &emptyKernDesc[i+1]; 00098 else 00099 emptyKernDesc[i].next = 0x0; 00100 emptyKernDesc[i].prev = &emptyKernDesc[i-1]; 00101 } 00102 00103 tmpDesc = &emptyKernDesc[0]; 00104 00105 emptyKernDesc = tmpDesc->next; 00106 emptyKernDesc->prev = 0x0; 00107 tmpDesc->next = 0x0; 00108 tmpDesc->prev = 0x0; 00109 spinUnlock(&emptyDescSpinLock); 00110 return(tmpDesc); 00111 } 00112 00113 /************************************************************************ 00114 00115 Function: void insertFreeDesc(struct memDescriptor *freeDesc) 00116 Description: This Function Inserts A Free Descriptor On The List Which Is 00117 Kept In Size Order 00118 00119 Notes: 00120 00121 02/17/03 - This Was Inspired By TCA's Great Wisdom - 00122 "[20:20:59] <TCA> You should just insert it in order" 00123 00124 ************************************************************************/ 00125 static int insertFreeDesc(struct memDescriptor *freeDesc) { 00126 struct memDescriptor *tmpDesc = 0x0; 00127 assert(freeDesc); 00128 00129 if (freeDesc->limit <= 0x0) 00130 kpanic("Inserting Descriptor with no limit\n"); 00131 00132 if (freeKernDesc != 0x0) { 00133 00134 #if 0 00135 freeDesc->next = freeKernDesc; 00136 freeDesc->prev = 0x0; 00137 freeKernDesc->prev = freeDesc; 00138 freeKernDesc = freeDesc; 00139 #endif 00140 00141 for (tmpDesc = freeKernDesc;tmpDesc != 0x0;tmpDesc = tmpDesc->next) { 00142 if (freeDesc->limit <= tmpDesc->limit) { 00143 00144 freeDesc->prev = tmpDesc->prev; 00145 if (tmpDesc->prev != 0x0) 00146 tmpDesc->prev->next = freeDesc; 00147 00148 00149 tmpDesc->prev = freeDesc; 00150 freeDesc->next = tmpDesc; 00151 00152 if (tmpDesc == freeKernDesc) 00153 freeKernDesc = freeDesc; 00154 return(0x0); 00155 } 00156 if (tmpDesc->next == 0x0) { 00157 tmpDesc->next = freeDesc; 00158 freeDesc->prev = tmpDesc; 00159 freeDesc->next = 0x0; 00160 return(0x0); 00161 } 00162 } 00163 kpanic("didnt Insert\n"); 00164 return(0x0); 00165 } 00166 else { 00167 freeDesc->prev = 0x0; 00168 freeDesc->next = 0x0; 00169 freeKernDesc = freeDesc; 00170 return(0x0); 00171 } 00172 00173 return(0x1); 00174 } 00175 00176 /************************************************************************ 00177 00178 Function: void mergeMemBlocks() 00179 Description: This Function Will Merge Free Blocks And Free Pages 00180 00181 Notes: 00182 00183 03/05/03 - We Have A Problem It Seems The First Block Is Limit 0x0 00184 00185 ************************************************************************/ 00186 static void mergeMemBlocks() { 00187 struct memDescriptor *tmpDesc1 = 0x0; 00188 struct memDescriptor *tmpDesc2 = 0x0; 00189 uInt32 baseAddr = 0x0; 00190 00191 return; 00192 00193 //Loop The Free Descriptors See If We Can Merge Them 00194 mergeStart: 00195 for (tmpDesc1=freeKernDesc;tmpDesc1 != 0x0;tmpDesc1=tmpDesc1->next) { 00196 /* 00197 Compare The Base Addr With The Other Descriptors If You Find The One 00198 That You Are Looking For Lets Merge Them 00199 */ 00200 if (tmpDesc1->limit != 0x0) { 00201 baseAddr = (uInt32)tmpDesc1->baseAddr + (uInt32)tmpDesc1->limit; 00202 for (tmpDesc2=freeKernDesc;tmpDesc2;tmpDesc2=tmpDesc2->next) { 00203 if ((uInt32)tmpDesc2->baseAddr == baseAddr) { 00204 tmpDesc1->limit += tmpDesc2->limit; 00205 tmpDesc2->baseAddr = 0x0; 00206 tmpDesc2->limit = 0x0; 00207 if (tmpDesc2->prev) { 00208 tmpDesc2->prev->next = tmpDesc2->next; 00209 } 00210 if (tmpDesc2->next) { 00211 tmpDesc2->next->prev = tmpDesc2->prev; 00212 } 00213 tmpDesc2->prev = 0x0; 00214 tmpDesc2->next = emptyKernDesc; 00215 emptyKernDesc->prev = tmpDesc2; 00216 emptyKernDesc = tmpDesc2; 00217 if (tmpDesc1->prev) { 00218 tmpDesc1->prev->next = tmpDesc1->next; 00219 } 00220 if (tmpDesc1->next) { 00221 tmpDesc1->next->prev = tmpDesc1->prev; 00222 } 00223 tmpDesc1->prev = 0x0; 00224 tmpDesc1->next = 0x0; 00225 kprintf("mergememBlocks: [%i]\n",tmpDesc1->limit); 00226 insertFreeDesc(tmpDesc1); 00227 //tmpDesc1 = freeKernDesc; 00228 goto mergeStart; 00229 break; 00230 } 00231 } 00232 } 00233 } 00234 return; 00235 } 00236 00237 00238 /************************************************************************ 00239 00240 Function: void *kmalloc(uInt32 len) 00241 Description: Allocate Kernel Memory 00242 00243 Notes: 00244 00245 02/17/03 - Do I Still Need To Pass In The Pid? 00246 00247 ************************************************************************/ 00248 void *kmalloc(uInt32 len) { 00249 struct memDescriptor *tmpDesc1 = 0x0; 00250 struct memDescriptor *tmpDesc2 = 0x0; 00251 char *buf = 0x0; 00252 int i = 0x0; 00253 uInt16 pages = 0x0; 00254 00255 spinLock(&mallocSpinLock); 00256 00257 len = MALLOC_ALIGN(len); 00258 00259 if (len == 0x0) { 00260 spinUnlock(&mallocSpinLock); 00261 kprintf("kmalloc: len = 0!\n"); 00262 return(0x0); 00263 } 00264 for (tmpDesc1 = freeKernDesc;tmpDesc1 != 0x0;tmpDesc1=tmpDesc1->next) { 00265 assert(tmpDesc1); 00266 if (tmpDesc1->limit >= len) { 00267 if (tmpDesc1->prev != 0x0) 00268 tmpDesc1->prev->next = tmpDesc1->next; 00269 if (tmpDesc1->next != 0x0) 00270 tmpDesc1->next->prev = tmpDesc1->prev; 00271 00272 if (tmpDesc1 == freeKernDesc) 00273 freeKernDesc = tmpDesc1->next; 00274 00275 tmpDesc1->prev = 0x0; 00276 tmpDesc1->next = usedKernDesc; 00277 if (usedKernDesc != 0x0) 00278 usedKernDesc->prev = tmpDesc1; 00279 usedKernDesc = tmpDesc1; 00280 if (tmpDesc1->limit > len) { 00281 tmpDesc2 = getEmptyDesc(); 00282 assert(tmpDesc2); 00283 tmpDesc2->limit = tmpDesc1->limit - len; 00284 tmpDesc1->limit = len; 00285 tmpDesc2->baseAddr = tmpDesc1->baseAddr + len; 00286 tmpDesc2->next = 0x0; 00287 tmpDesc2->prev = 0x0; 00288 insertFreeDesc(tmpDesc2); 00289 } 00290 buf = (char *)tmpDesc1->baseAddr; 00291 for (i=0;i<tmpDesc1->limit;i++) { 00292 (char)buf[i] = (char)0x0; 00293 } 00294 spinUnlock(&mallocSpinLock); 00295 //kprintf("m1[%i:%i:0x%X]",tmpDesc1->limit,len,tmpDesc1->baseAddr); 00296 assert(tmpDesc1->baseAddr); 00297 return(tmpDesc1->baseAddr); 00298 } 00299 } 00300 tmpDesc1 = getEmptyDesc(); 00301 //kprintf("no empty desc\n"); 00302 if (tmpDesc1 != 0x0) { 00303 pages = ((len + 4095)/4096); 00304 tmpDesc1->baseAddr = (struct memDescriptor *)vmm_getFreeMallocPage(pages); 00305 tmpDesc1->limit = len; 00306 tmpDesc1->next = usedKernDesc; 00307 tmpDesc1->prev = 0x0; 00308 if (usedKernDesc != 0x0) 00309 usedKernDesc->prev = tmpDesc1; 00310 usedKernDesc = tmpDesc1; 00311 00312 if (((pages * 4096)-len) > 0x0) { 00313 tmpDesc2 = getEmptyDesc(); 00314 assert(tmpDesc2); 00315 tmpDesc2->baseAddr = tmpDesc1->baseAddr + tmpDesc1->limit; 00316 tmpDesc2->limit = ((pages * 4096)-len); 00317 tmpDesc2->prev = 0x0; 00318 tmpDesc2->next = 0x0; 00319 if (tmpDesc2->limit <= 0x0) 00320 kprintf("kmalloc-2 tmpDesc2: [%i]\n",tmpDesc2->limit); 00321 insertFreeDesc(tmpDesc2); 00322 } 00323 00324 buf = (char *)tmpDesc1->baseAddr; 00325 for (i=0;i<tmpDesc1->limit;i++) { 00326 (char)buf[i] = (char)0x0; 00327 } 00328 spinUnlock(&mallocSpinLock); 00329 //kprintf("baseAddr2[0x%X:0x%X]",tmpDesc1,tmpDesc1->baseAddr); 00330 //kprintf("m2[%i:%i:0x%X]",tmpDesc1->limit,len,tmpDesc1->baseAddr); 00331 assert(tmpDesc1->baseAddr); 00332 return(tmpDesc1->baseAddr); 00333 } 00334 //Return Null If Unable To Malloc 00335 spinUnlock(&mallocSpinLock); 00336 //kprintf("baseAddr3[0x0]"); 00337 return(0x0); 00338 } 00339 00340 /************************************************************************ 00341 00342 Function: void kfree(void *baseAddr) 00343 Description: This Will Find The Descriptor And Free It 00344 00345 Notes: 00346 00347 02/17/03 - I need To Make It Join Descriptors 00348 00349 ************************************************************************/ 00350 void kfree(void *baseAddr) { 00351 struct memDescriptor *tmpDesc = 0x0; 00352 00353 if (baseAddr == 0x0) return; 00354 assert(baseAddr); 00355 00356 assert(usedKernDesc); 00357 spinLock(&mallocSpinLock); 00358 00359 for (tmpDesc = usedKernDesc;tmpDesc != 0x0;tmpDesc = tmpDesc->next) { 00360 00361 if (tmpDesc->baseAddr == baseAddr) { 00362 memset(tmpDesc->baseAddr,0xBE,tmpDesc->limit); 00363 00364 if (usedKernDesc == tmpDesc) 00365 usedKernDesc = tmpDesc->next; 00366 00367 if (tmpDesc->prev != 0x0) 00368 tmpDesc->prev->next = tmpDesc->next; 00369 00370 if (tmpDesc->next != 0x0) 00371 tmpDesc->next->prev = tmpDesc->prev; 00372 00373 00374 tmpDesc->next = 0x0; 00375 tmpDesc->prev = 0x0; 00376 00377 if (tmpDesc->limit <= 0x0) 00378 kprintf("kfree tmpDesc1: [%i]\n",tmpDesc->limit); 00379 //kprintf("{0x%X}",tmpDesc->baseAddr); 00380 insertFreeDesc(tmpDesc); 00381 00382 // mergeMemBlocks(); 00383 spinUnlock(&mallocSpinLock); 00384 return; 00385 } 00386 } 00387 spinUnlock(&mallocSpinLock); 00388 kprintf("Kernel: Error Freeing Descriptor! [0x%X]\n",(uInt32)baseAddr); 00389 return; 00390 } 00391 00392 /*** 00393 $Log$ 00394 Revision 1.2 2006/10/06 15:48:01 reddawg 00395 Starting to make ubixos work with UFS2 00396 00397 Revision 1.1.1.1 2006/06/01 12:46:16 reddawg 00398 ubix2 00399 00400 Revision 1.4 2006/06/01 12:42:09 reddawg 00401 Getting back to the basics 00402 00403 Revision 1.3 2006/06/01 03:58:33 reddawg 00404 wondering about this stuff here 00405 00406 Revision 1.2 2005/10/12 00:13:37 reddawg 00407 Removed 00408 00409 Revision 1.1.1.1 2005/09/26 17:24:11 reddawg 00410 no message 00411 00412 Revision 1.35 2005/08/04 18:32:59 fsdfs 00413 00414 added error reporting 00415 00416 Revision 1.34 2005/08/04 18:23:41 reddawg 00417 BUG: Assert has issues that must be looked into 00418 00419 Revision 1.33 2005/08/04 17:11:11 fsdfs 00420 00421 ---------------------------------------- 00422 00423 ------------------- 00424 00425 Revision 1.32 2004/09/28 21:50:04 reddawg 00426 kmalloc: now when we kfree memory is filled with 0xBE so it is easy to debug if we continue to use free'd memory 00427 00428 Revision 1.31 2004/09/19 16:17:25 reddawg 00429 fixed memory leak we now lose no memory.... 00430 00431 Revision 1.30 2004/09/14 21:51:24 reddawg 00432 Debug info 00433 00434 Revision 1.29 2004/09/11 23:39:31 reddawg 00435 ok time for bed 00436 00437 Revision 1.28 2004/09/11 23:21:26 reddawg 00438 run now do you get fegfaults with BB? 00439 00440 Revision 1.27 2004/09/11 22:49:28 reddawg 00441 pat look at lines 276-285 does the math seem right? 00442 00443 Revision 1.26 2004/09/11 22:33:13 reddawg 00444 minor changes 00445 00446 Revision 1.25 2004/09/11 12:11:11 reddawg 00447 Cleaning up the VFS more changes to follow... 00448 00449 Revision 1.24 2004/09/08 23:19:58 reddawg 00450 hmm 00451 00452 Revision 1.23 2004/09/06 15:13:25 reddawg 00453 Last commit before FreeBSD 6.0 00454 00455 Revision 1.22 2004/08/26 22:51:18 reddawg 00456 TCA touched me :( i think he likes men.... 00457 00458 00459 sched.h: kTask_t added parentPid 00460 endtask.c: fixed term back to parentPid 00461 exec.c: cleaned warnings 00462 fork.c: fixed term to childPid 00463 sched.c: clean up for dead tasks 00464 systemtask.c: clean up dead tasks 00465 kmalloc.c: cleaned up warnings 00466 udp.c: cleaned up warnings 00467 bot.c: cleaned up warnings 00468 shell.c: cleaned up warnings 00469 tcpdump.c: took a dump 00470 hd.c: cleaned up warnings 00471 ubixfs.c: stopped prning debug info 00472 00473 Revision 1.21 2004/07/28 15:05:43 reddawg 00474 Major: 00475 Pages now have strict security enforcement. 00476 Many null dereferences have been resolved. 00477 When apps loaded permissions set for pages rw and ro 00478 00479 Revision 1.20 2004/07/28 00:17:05 reddawg 00480 Major: 00481 Disconnected page 0x0 from the system... Unfortunately this broke many things 00482 all of which have been fixed. This was good because nothing deferences NULL 00483 any more. 00484 00485 Things affected: 00486 malloc,kmalloc,getfreepage,getfreevirtualpage,pagefault,fork,exec,ld,ld.so,exec,file 00487 00488 Revision 1.19 2004/07/26 19:15:49 reddawg 00489 test code, fixes and the like 00490 00491 Revision 1.18 2004/07/26 16:52:45 reddawg 00492 here we go 00493 00494 Revision 1.17 2004/07/24 23:04:44 reddawg 00495 Changes... mark let me know if you fault at pid 185 when you type stress 00496 00497 Revision 1.16 2004/07/21 10:02:09 reddawg 00498 devfs: renamed functions 00499 device system: renamed functions 00500 fdc: fixed a few potential bugs and cleaned up some unused variables 00501 strol: fixed definition 00502 endtask: made it print out freepage debug info 00503 kmalloc: fixed a huge memory leak we had some unhandled descriptor insertion so some descriptors were lost 00504 ld: fixed a pointer conversion 00505 file: cleaned up a few unused variables 00506 sched: broke task deletion 00507 kprintf: fixed ogPrintf definition 00508 00509 Revision 1.15 2004/07/20 23:20:50 reddawg 00510 kmalloc: forgot to remove an assert 00511 00512 Revision 1.14 2004/07/20 23:18:11 reddawg 00513 Made malloc a little more robust but we have a serious memory leak somewhere 00514 00515 Revision 1.13 2004/07/20 22:29:55 reddawg 00516 assert: remade assert 00517 00518 Revision 1.12 2004/07/20 18:58:24 reddawg 00519 Few fixes 00520 00521 Revision 1.11 2004/07/18 05:24:15 reddawg 00522 Fixens 00523 00524 Revision 1.10 2004/07/17 18:00:47 reddawg 00525 kmalloc: added assert() 00526 00527 Revision 1.9 2004/07/17 15:54:52 reddawg 00528 kmalloc: added assert() 00529 bioscall: fixed some potential problem by not making 16bit code 00530 paging: added assert() 00531 00532 Revision 1.8 2004/06/17 14:50:32 reddawg 00533 kmalloc: converted some variables to static 00534 00535 Revision 1.7 2004/06/17 02:54:54 flameshadow 00536 chg: fixed cast 00537 00538 Revision 1.6 2004/05/26 11:56:51 reddawg 00539 kmalloc: fixed memrgeMemBlocks hopefully it will prevent future segfault issues 00540 by not having any more overlapping blocks 00541 00542 Revision 1.5 2004/05/25 14:01:14 reddawg 00543 Implimented Better Spinlocking No More Issues With KMALLOC which actually 00544 was causing bizzare problems 00545 00546 END 00547 ***/ 00548
1.4.7