00001
00007 #include <string.h>
00008
00009 #include "uffs/uffs_types.h"
00010 #include "uffs/uffs_public.h"
00011 #include "uffs/uffs_os.h"
00012 #include "uffs/uffs_mem.h"
00013
00014
00015 #define PFX "mem:"
00016
00017
00018 #define HEAP_MAGIC_SIZE 8
00019
00020
00021
00022
00023
00024
00025
00026 #define K_HEAP_ALLOCK_BEST_FIT
00027
00028
00029
00030 #define ALLOC_PAGE_BIT_OFFSET 5
00031 #define ALLOC_PAGE_SIZE (1 << ALLOC_PAGE_BIT_OFFSET)
00032 #define ALLOC_PAGE_MASK (ALLOC_PAGE_SIZE - 1)
00033 #define ALLOC_THRESHOLD (ALLOC_PAGE_SIZE * 1)
00034
00035
00036 #define HEAP_NODE_FREE 0x123455aa
00037 #define HEAP_NODE_ALLOCED 0xaa551234
00038
00039 #define ALLOC_OFFSET 12
00040
00041
00042 typedef struct _HEAPNODE {
00043 int mark;
00044 int size;
00045 struct _HEAPNODE *prevNode;
00046 struct _HEAPNODE *prevFree;
00047 struct _HEAPNODE *nextFree;
00048 } HEAPNODE;
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 static HEAPNODE* volatile _k_heapFreeList = NULL;
00098 static HEAPNODE * _k_heapTail_ = NULL;
00099 static u32 _k_heap_available = 0;
00100 static u32 _minimu_heap_avaiable = 0x0fffffff;
00101 static u32 _kernel_heap_total = 0;
00102
00103 static void HeapDeleteFromFreeList(HEAPNODE *node);
00104 static void HeapChainToFreeList(HEAPNODE *node);
00105 static void *_k_allock_node(HEAPNODE *node, int size);
00106 static void * _kmalloc_clear(int size);
00107 static int _kfree(void *block);
00108
00109
00110
00111
00112
00113 static void HeapDeleteFromFreeList(HEAPNODE *node)
00114 {
00115 if(node->nextFree)
00116 node->nextFree->prevFree = node->prevFree;
00117 if(node->prevFree)
00118 node->prevFree->nextFree = node->nextFree;
00119 if(node == _k_heapFreeList)
00120 _k_heapFreeList = node->nextFree;
00121 }
00122
00123
00124
00125
00126 static void HeapChainToFreeList(HEAPNODE *node)
00127 {
00128 node->nextFree = NULL;
00129 node->prevFree = NULL;
00130 if(_k_heapFreeList == NULL){
00131 _k_heapFreeList = node;
00132 return;
00133 }
00134 else{
00135 _k_heapFreeList->prevFree = node;
00136 node->nextFree = _k_heapFreeList;
00137 _k_heapFreeList = node;
00138 }
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 static void *_k_allock_node(HEAPNODE *node, int size)
00153 {
00154 HEAPNODE *newNode;
00155
00156 if(node->size >= size + ALLOC_THRESHOLD){
00157
00158
00159
00160 newNode = (HEAPNODE *)((u32)node + size);
00161 newNode->size = node->size - size;
00162 newNode->mark = HEAP_NODE_FREE;
00163 newNode->prevNode = node;
00164 node->size = size;
00165
00166
00167
00168 HeapChainToFreeList(newNode);
00169
00170
00171
00172
00173 ((HEAPNODE *)((u32)newNode + newNode->size))->prevNode = newNode;
00174 }
00175
00176
00177
00178
00179 node->mark = HEAP_NODE_ALLOCED;
00180
00181
00182
00183
00184 HeapDeleteFromFreeList(node);
00185
00186 _k_heap_available -= node->size;
00187 if(_minimu_heap_avaiable > _k_heap_available)
00188 _minimu_heap_avaiable = _k_heap_available;
00189
00190 uffs_CriticalExit();
00191
00192 return (void *)((u32)node + ALLOC_OFFSET);
00193 }
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 static void *_kmalloc(int size)
00227 {
00228 HEAPNODE *node;
00229 #if defined(K_HEAP_ALLOCK_BEST_FIT)
00230 HEAPNODE *fit;
00231 #endif
00232 if(size <= 0)
00233 return NULL;
00234
00235
00236
00237
00238 size += ALLOC_OFFSET;
00239 if(size & ALLOC_PAGE_MASK){
00240 size += ALLOC_PAGE_SIZE;
00241 size &= ~ALLOC_PAGE_MASK;
00242 }
00243
00244 uffs_CriticalEnter();
00245
00246 node = _k_heapFreeList;
00247
00248 #if defined(K_HEAP_ALLOCK_BEST_FIT)
00249
00250
00251
00252 fit = NULL;
00253 while(node){
00254
00255
00256
00257 if(node->size >= size){
00258
00259
00260
00261
00262 if(node->size == size){
00263 fit = node;
00264 break;
00265 }
00266
00267
00268
00269 if(fit){
00270 if(node->size < fit->size)
00271 fit = node;
00272 }
00273 else
00274 fit = node;
00275 }
00276 node = node->nextFree;
00277 }
00278
00279 if(fit){
00280 if(fit->size >= size)
00281 return _k_allock_node(fit, size);
00282 }
00283 #else
00284 while(node){
00285 if(node->size >= size)
00286 return _k_allock_node(node, size);
00287 node = node->nextFree;
00288 }
00289 #endif
00290
00291 uffs_CriticalExit();
00292
00293 return NULL;
00294
00295 }
00296
00297
00298 static void *_kcalloc(int num, int size)
00299 {
00300 return _kmalloc_clear(num * size);
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 static void *_krealloc(void *block, int size)
00316 {
00317 HEAPNODE *node;
00318 HEAPNODE *newNode;
00319 void *p;
00320 int old_data_size;
00321
00322 if(block == NULL){
00323 return _kmalloc(size);
00324 }
00325
00326 if(size == 0) {
00327 _kfree(block);
00328 return NULL;
00329 }
00330
00331 uffs_CriticalEnter();
00332
00333 node = (HEAPNODE *)((u32)block - ALLOC_OFFSET);
00334 old_data_size = node->size - ALLOC_OFFSET;
00335 if(node->mark != HEAP_NODE_ALLOCED || old_data_size <= 0) {
00336 uffs_CriticalExit();
00337 return NULL;
00339 }
00340
00341 if(old_data_size < size) {
00342
00343 p = _kmalloc(size);
00344 if(!p) {
00345 uffs_CriticalExit();
00346 return NULL;
00347 }
00348
00349
00350
00351
00352 memcpy(p, block, old_data_size);
00353 _kfree(block);
00354 uffs_CriticalExit();
00355 return p;
00356 }
00357 else {
00358
00359 size += ALLOC_OFFSET;
00360 if(size & ALLOC_PAGE_MASK) {
00361 size += ALLOC_PAGE_SIZE;
00362 size &= ~ALLOC_PAGE_MASK;
00363 }
00364
00365 if(node->size - size < ALLOC_PAGE_SIZE) {
00366
00367 uffs_CriticalExit();
00368 return block;
00369 }
00370 else {
00371
00372
00373 newNode = (HEAPNODE *)((u32)node + size);
00374 newNode->prevNode = node;
00375 newNode->mark = HEAP_NODE_ALLOCED;
00376 newNode->size = node->size - size;
00377
00378
00379 ((HEAPNODE *)((u32)node + node->size))->prevNode = newNode;
00380 node->size = size;
00381
00382
00383 _kfree((void *)((u32)newNode + ALLOC_OFFSET));
00384
00385 uffs_CriticalExit();
00386 return block;
00387 }
00388 }
00389 }
00390
00391 static void * _kmalloc_clear(int size)
00392 {
00393 void *p;
00394
00395 p = _kmalloc(size);
00396 if(p)
00397 memset(p, 0, size);
00398 return p;
00399 }
00400
00420 static int _kfree(void *block)
00421 {
00422 HEAPNODE *node;
00423 HEAPNODE *prev;
00424 HEAPNODE *next;
00425 if (block == NULL) {
00426 return -1;
00427 }
00428 uffs_CriticalEnter();
00429
00430 node = (HEAPNODE *)((u32)block - ALLOC_OFFSET);
00431 if(node->mark != HEAP_NODE_ALLOCED || node->size <= ALLOC_OFFSET) {
00432 uffs_CriticalExit();
00433 return -1;
00435 }
00436 _k_heap_available += node->size;
00437
00438 prev = node->prevNode;
00439 next = (HEAPNODE *)((u32)node + node->size);
00440
00441 if(prev->mark == HEAP_NODE_FREE){
00442
00443
00444
00445 prev->size += node->size;
00446 next->prevNode = prev;
00447 HeapDeleteFromFreeList(prev);
00448 node = prev;
00449 }
00450
00451 if(next->mark == HEAP_NODE_FREE){
00452
00453
00454
00455 node->size += next->size;
00456 ((HEAPNODE *)((u32)next + next->size))->prevNode = node;
00457 HeapDeleteFromFreeList(next);
00458 }
00459
00460
00461
00462
00463 node->mark = HEAP_NODE_FREE;
00464 HeapChainToFreeList(node);
00465 uffs_CriticalExit();
00466
00467 return 0;
00468 }
00469
00470
00483 void uffs_InitHeapMemory(void *addr, int size)
00484 {
00485 HEAPNODE *np;
00486
00487
00488 if(!((u32)addr & 3)){
00489 addr = (void *)(((u32)addr) + 4);
00490 addr = (void *)(((u32)addr) & ~3);
00491 }
00492 size &= ~ALLOC_PAGE_MASK;
00493 if(size < ALLOC_PAGE_SIZE * 3) return;
00494
00495 uffs_CriticalEnter();
00496
00497
00498 np = (HEAPNODE *)addr;
00499 np->size = ALLOC_PAGE_SIZE;
00500 np->mark = HEAP_NODE_ALLOCED;
00501 np->prevNode = NULL;
00502
00503
00504 np = (HEAPNODE *)((u32)addr + size - ALLOC_PAGE_SIZE);
00505 np->mark = HEAP_NODE_ALLOCED;
00506 np->size = -1;
00507 np->prevNode = (HEAPNODE *)((u32)addr + ALLOC_PAGE_SIZE);
00508 _k_heapTail_ = np;
00509
00510
00511 np = (HEAPNODE *)((u32)addr + ALLOC_PAGE_SIZE);
00512 np->mark = HEAP_NODE_FREE;
00513 np->prevNode = (HEAPNODE *)addr;
00514 np->size = size - 2 * ALLOC_PAGE_SIZE;
00515 np->nextFree = NULL;
00516 np->prevFree = NULL;
00517 _k_heapFreeList = np;
00518 _k_heap_available = np->size;
00519 _minimu_heap_avaiable = _k_heap_available;
00520
00521 _kernel_heap_total += size;
00522
00523 uffs_CriticalExit();
00524 }
00525
00526
00527
00528
00529 static void *__umalloc(uffs_memAllocator *mem, unsigned int size, HASHTBL * heapHashTbl);
00530 static void *__ucalloc(uffs_memAllocator *mem, unsigned int num, unsigned int size, HASHTBL *heapHashTbl);
00531 static void *__urealloc(uffs_memAllocator *mem, void *block, unsigned int size, HASHTBL *heapHashTbl);
00532 static int __ufree(uffs_memAllocator *mem, void *p, HASHTBL * heapHashTbl);
00533
00534
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 static int ReleaseHeap(uffs_memAllocator *mem, HASHTBL *heapHashTbl)
00553 {
00554 int i;
00555 int count = 0;
00556 HEAP_MM volatile * node;
00557
00558 if(heapHashTbl == NULL) return -1;
00559 for(i = 0; i < HEAP_HASH_SIZE; i++){
00560 while((node = heapHashTbl[i]) != NULL){
00561 __ufree(mem, node->p, heapHashTbl);
00562 count++;
00563 }
00564 }
00565 _kfree(heapHashTbl);
00566 return count;
00567 }
00568
00569 static void *uffs_malloc(uffs_memAllocator *mem, unsigned int size)
00570 {
00571 HASHTBL * heapHashTbl;
00572
00573 if((int)size < 0) return NULL;
00574 heapHashTbl = mem->tbl;
00575 if(heapHashTbl){
00576 return __umalloc(mem, size, heapHashTbl);
00577 }
00578 else{
00579 return NULL;
00580 }
00581 }
00582
00583 static void *uffs_calloc(uffs_memAllocator *mem, unsigned int num, unsigned int size)
00584 {
00585 HASHTBL * heapHashTbl;
00586
00587 if((int)size < 0 || num == 0) return NULL;
00588 heapHashTbl = mem->tbl;
00589 if(heapHashTbl){
00590 return __ucalloc(mem, num, size, heapHashTbl);
00591 }
00592 else{
00593 return NULL;
00594 }
00595 }
00596
00597 static void *uffs_realloc(uffs_memAllocator *mem, void *block, unsigned int size)
00598 {
00599 HASHTBL * heapHashTbl;
00600
00601 if((int)size <= 0) return NULL;
00602 heapHashTbl = mem->tbl;
00603 if(heapHashTbl){
00604 return __urealloc(mem, block, size, heapHashTbl);
00605 }
00606 else{
00607 return NULL;
00608 }
00609 }
00610
00611
00612 static void *__umalloc(uffs_memAllocator *mem, unsigned int size, HASHTBL *heapHashTbl)
00613 {
00614 void *p;
00615 HEAP_MM *node;
00616 int index;
00617
00618
00619 p = _kmalloc(HEAP_MAGIC_SIZE + size + HEAP_MAGIC_SIZE);
00620
00621 if(p){
00622 node = (HEAP_MM *)_kmalloc(sizeof(HEAP_MM));
00623 if(node == NULL){
00624 _kfree(p);
00625 return NULL;
00626 }
00627 p = (void *)((u32)p + HEAP_MAGIC_SIZE);
00628 node->p = p;
00629 node->size = size;
00630 mem->count += size;
00631 if (mem->maxused < mem->count) mem->maxused = mem->count;
00632 node->task_id = uffs_OSGetTaskId();
00633
00634 uffs_CriticalEnter();
00635
00636
00637 index = GET_HASH_INDEX(p);
00638 node->next = heapHashTbl[index];
00639 heapHashTbl[index] = node;
00640
00641 uffs_CriticalExit();
00642 return p;
00643 }
00644 return NULL;
00645 }
00646
00647
00648 static void *__ucalloc(uffs_memAllocator *mem, unsigned int num, unsigned int size, HASHTBL *heapHashTbl)
00649 {
00650 return __umalloc(mem, num * size, heapHashTbl);
00651 }
00652
00653
00654
00655 static void *__urealloc(uffs_memAllocator *mem, void *block, unsigned int size, HASHTBL *heapHashTbl)
00656 {
00657 void *p, *pNew;
00658 HEAP_MM *prev, *node;
00659 int index;
00660
00661 if(block == NULL) {
00662 return __umalloc(mem, size, heapHashTbl);
00663 }
00664
00665 if(size == 0) {
00666 __ufree(mem, block, heapHashTbl);
00667 return NULL;
00668 }
00669
00670
00671 index = GET_HASH_INDEX(block);
00672
00673
00674 uffs_CriticalEnter();
00675 node = heapHashTbl[index];
00676 prev = NULL;
00677 while(node){
00678 if(node->p == block){
00679 break;
00680 }
00681 prev = node;
00682 node = node->next;
00683 }
00684
00685 if(!node) {
00686
00687 uffs_CriticalExit();
00688 return NULL;
00689 }
00690
00691
00692
00693 p = (void *)((u32)block - HEAP_MAGIC_SIZE);
00694 pNew = _krealloc(p, HEAP_MAGIC_SIZE + size + HEAP_MAGIC_SIZE);
00695
00696 if(pNew == NULL) {
00697 uffs_CriticalExit();
00698 return NULL;
00699 }
00700
00701 if(pNew == p) {
00702
00703 uffs_CriticalExit();
00704 return block;
00705 }
00706
00707
00708 if(prev){
00709
00710 prev->next = node->next;
00711 }
00712 else{
00713
00714 heapHashTbl[index] = node->next;
00715 }
00716 uffs_CriticalExit();
00717
00718 node->p = (void *)((u32)pNew + HEAP_MAGIC_SIZE);
00719 node->size = size;
00720 node->task_id = uffs_OSGetTaskId();
00721
00722
00723 index = GET_HASH_INDEX(node->p);
00724 uffs_CriticalEnter();
00725 node->next = heapHashTbl[index];
00726 heapHashTbl[index] = node;
00727 uffs_CriticalExit();
00728
00729 return node->p;
00730
00731 }
00732
00733
00734
00735
00736
00737
00738 static int __ufree(uffs_memAllocator *mem, void *p, HASHTBL *heapHashTbl)
00739 {
00740 HEAP_MM *node, *prev;
00741
00742 if(p){
00743 uffs_CriticalEnter();
00744 node = heapHashTbl[GET_HASH_INDEX(p)];
00745 prev = NULL;
00746 while(node){
00747 if(node->p == p){
00748
00749 if(prev){
00750
00751 prev->next = node->next;
00752 }
00753 else{
00754
00755 heapHashTbl[GET_HASH_INDEX(p)] = node->next;
00756 }
00757
00758 mem->count -= node->size;
00759
00760 uffs_CriticalExit();
00761 if(_kfree(node) == -1)
00762 return -1;
00763
00764
00765 return _kfree((void *)((u32)p - HEAP_MAGIC_SIZE));
00766 }
00767 prev = node;
00768 node = node->next;
00769 }
00770 uffs_CriticalExit();
00771 }
00772 return -1;
00773 }
00774
00775 static void uffs_free(uffs_memAllocator *mem, void *block)
00776 {
00777 HASHTBL *heapHashTbl;
00778 heapHashTbl = mem->tbl;
00779 if(heapHashTbl){
00780 if (__ufree(mem, block, heapHashTbl) < 0) {
00781 uffs_Perror(UFFS_ERR_SERIOUS, PFX"Try to free unmanaged memory ?\n");
00782 }
00783 }
00784 }
00785
00786 URET uffs_initNativeMemAllocator(uffs_Device *dev)
00787 {
00788 uffs_memAllocator * mem;
00789 mem = _kmalloc(sizeof(uffs_memAllocator));
00790 if (mem == NULL) {
00791 return U_FAIL;
00792 }
00793
00794 memset(mem->tbl, 0, sizeof(mem->tbl));
00795
00796
00797
00798
00799
00800 mem->malloc = uffs_malloc;
00801 mem->realloc = uffs_realloc;
00802 mem->calloc = uffs_calloc;
00803 mem->free = uffs_free;
00804 dev->mem = mem;
00805
00806 return U_SUCC;
00807 }
00808
00809 int uffs_releaseNativeMemAllocator(uffs_Device *dev)
00810 {
00811 if (dev) {
00812 if (dev->mem)
00813 return ReleaseHeap(dev->mem, dev->mem->tbl);
00814 }
00815 return -1;
00816 }