00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00051 #if !defined(q_malloc) && (defined F_MALLOC)
00052
00053 #include <string.h>
00054 #include <stdlib.h>
00055
00056 #include "f_malloc.h"
00057 #include "../dprint.h"
00058 #include "../globals.h"
00059 #include "../compiler_opt.h"
00060 #include "memdbg.h"
00061 #include "../bit_scan.h"
00062 #include "../cfg/cfg.h"
00063 #ifdef MALLOC_STATS
00064 #include "../events.h"
00065 #endif
00066
00067
00068
00069
00070 #define FRAG_NEXT(f) \
00071 ((struct fm_frag*)((char*)(f)+sizeof(struct fm_frag)+(f)->size ))
00072
00073 #define FRAG_OVERHEAD (sizeof(struct fm_frag))
00074 #define INIT_OVERHEAD \
00075 (ROUNDUP(sizeof(struct fm_block))+sizeof(struct fm_frag))
00076
00077
00078
00080 #define ROUNDTO_MASK (~((unsigned long)ROUNDTO-1))
00081 #define ROUNDUP(s) (((s)+(ROUNDTO-1))&ROUNDTO_MASK)
00082 #define ROUNDDOWN(s) ((s)&ROUNDTO_MASK)
00083
00084
00085
00087 #define GET_HASH(s) ( ((unsigned long)(s)<=F_MALLOC_OPTIMIZE)?\
00088 (unsigned long)(s)/ROUNDTO: \
00089 F_MALLOC_OPTIMIZE/ROUNDTO+big_hash_idx((s))- \
00090 F_MALLOC_OPTIMIZE_FACTOR+1 )
00091
00092 #define UN_HASH(h) ( ((unsigned long)(h)<=(F_MALLOC_OPTIMIZE/ROUNDTO))?\
00093 (unsigned long)(h)*ROUNDTO: \
00094 1UL<<((unsigned long)(h)-F_MALLOC_OPTIMIZE/ROUNDTO+\
00095 F_MALLOC_OPTIMIZE_FACTOR-1)\
00096 )
00097
00098
00099 #ifdef F_MALLOC_HASH_BITMAP
00100
00101 #define fm_bmp_set(qm, b) \
00102 do{ \
00103 (qm)->free_bitmap[(b)/FM_HASH_BMP_BITS] |= \
00104 1UL<<((b)%FM_HASH_BMP_BITS); \
00105 }while(0)
00106
00107 #define fm_bmp_reset(qm, b) \
00108 do{ \
00109 (qm)->free_bitmap[(b)/FM_HASH_BMP_BITS] &= \
00110 ~(1UL<<((b)%FM_HASH_BMP_BITS)); \
00111 }while(0)
00112
00114 #define fm_bmp_is_set(qm, b) \
00115 ((qm)->free_bitmap[(b)/FM_HASH_BMP_BITS] & (1UL<<((b)%FM_HASH_BMP_BITS)))
00116
00117
00118
00127 inline static int fm_bmp_first_set(struct fm_block* qm, int start)
00128 {
00129 int bmp_idx;
00130 int bit;
00131 int r;
00132 fm_hash_bitmap_t test_val;
00133 fm_hash_bitmap_t v;
00134
00135 bmp_idx=start/FM_HASH_BMP_BITS;
00136 bit=start%FM_HASH_BMP_BITS;
00137 test_val=1UL <<((unsigned long)bit);
00138 if (qm->free_bitmap[bmp_idx] & test_val)
00139 return start;
00140 else if (qm->free_bitmap[bmp_idx] & ~(test_val-1)){
00141 #if 0
00142 test_val<<=1;
00143 for (r=bit+1; r<FM_HASH_BMP_BITS; r++, test_val<<=1){
00144 if (qm->free_bitmap[bmp_idx] & test_val)
00145 return (start-bit+r);
00146 }
00147 #endif
00148 v=qm->free_bitmap[bmp_idx]>>(bit+1);
00149 return start+1+bit_scan_forward((unsigned long)v);
00150 }
00151 for (r=bmp_idx+1;r<FM_HASH_BMP_SIZE; r++){
00152 if (qm->free_bitmap[r]){
00153
00154 return r*FM_HASH_BMP_BITS+
00155 bit_scan_forward((unsigned long)qm->free_bitmap[r]);
00156 }
00157 }
00158
00159 return -1;
00160 }
00161 #endif
00162
00163
00164
00165
00166 #define FRAG_MARK_USED(f)
00167 #define FRAG_CLEAR_USED(f)
00168 #define FRAG_WAS_USED(f) (1)
00169
00170
00171
00172
00173
00174 #define MEM_FRAG_AVOIDANCE
00175
00176
00178 #define big_hash_idx(s) ((unsigned long)bit_scan_reverse((unsigned long)(s)))
00179
00180
00184
00185 #ifdef DBG_F_MALLOC
00186 #define ST_CHECK_PATTERN 0xf0f0f0f0
00187 #define END_CHECK_PATTERN1 0xc0c0c0c0
00188 #define END_CHECK_PATTERN2 0xabcdefed
00189
00190 #endif
00191
00192
00198 static inline void fm_insert_free(struct fm_block* qm, struct fm_frag* frag)
00199 {
00200 struct fm_frag** f;
00201 int hash;
00202
00203 hash=GET_HASH(frag->size);
00204 f=&(qm->free_hash[hash].first);
00205 if (frag->size > F_MALLOC_OPTIMIZE){
00206
00207
00208 for(; *f; f=&((*f)->u.nxt_free)){
00209 if (frag->size <= (*f)->size) break;
00210 }
00211 }
00212
00213
00214 frag->u.nxt_free=*f;
00215 *f=frag;
00216 qm->free_hash[hash].no++;
00217 #ifdef F_MALLOC_HASH_BITMAP
00218 fm_bmp_set(qm, hash);
00219 #endif
00220 }
00221
00222
00231 static inline
00232 #ifdef DBG_F_MALLOC
00233 void fm_split_frag(struct fm_block* qm, struct fm_frag* frag,
00234 unsigned long size,
00235 const char* file, const char* func, unsigned int line)
00236 #else
00237 void fm_split_frag(struct fm_block* qm, struct fm_frag* frag,
00238 unsigned long size)
00239 #endif
00240 {
00241 unsigned long rest;
00242 struct fm_frag* n;
00243
00244 rest=frag->size-size;
00245 #ifdef MEM_FRAG_AVOIDANCE
00246 if ((rest> (FRAG_OVERHEAD+F_MALLOC_OPTIMIZE))||
00247 (rest>=(FRAG_OVERHEAD+size))){
00248 #else
00249 if (rest>(FRAG_OVERHEAD+MIN_FRAG_SIZE)){
00250 #endif
00251 frag->size=size;
00252
00253 n=FRAG_NEXT(frag);
00254 n->size=rest-FRAG_OVERHEAD;
00255 FRAG_CLEAR_USED(n);
00256 #if defined(DBG_F_MALLOC) || defined(MALLOC_STATS)
00257 qm->real_used+=FRAG_OVERHEAD;
00258 #ifdef MALLOC_STATS
00259 sr_event_exec(SREV_PKG_SET_REAL_USED, (void*)qm->real_used);
00260 #endif
00261 #endif
00262 #ifdef DBG_F_MALLOC
00263
00264 n->file=file;
00265 n->func="frag. from fm_malloc";
00266 n->line=line;
00267 n->check=ST_CHECK_PATTERN;
00268 #endif
00269
00270 fm_insert_free(qm, n);
00271 }else{
00272
00273 }
00274 }
00275
00276
00283 struct fm_block* fm_malloc_init(char* address, unsigned long size)
00284 {
00285 char* start;
00286 char* end;
00287 struct fm_block* qm;
00288 unsigned long init_overhead;
00289
00290
00291 start=(char*)ROUNDUP((unsigned long) address);
00292 DBG("fm_malloc_init: F_OPTIMIZE=%lu, /ROUNDTO=%lu\n",
00293 F_MALLOC_OPTIMIZE, F_MALLOC_OPTIMIZE/ROUNDTO);
00294 DBG("fm_malloc_init: F_HASH_SIZE=%lu, fm_block size=%lu\n",
00295 F_HASH_SIZE, (long)sizeof(struct fm_block));
00296 DBG("fm_malloc_init(%p, %lu), start=%p\n", address, size, start);
00297
00298 if (size<start-address) return 0;
00299 size-=(start-address);
00300 if (size <(MIN_FRAG_SIZE+FRAG_OVERHEAD)) return 0;
00301 size=ROUNDDOWN(size);
00302
00303 init_overhead=INIT_OVERHEAD;
00304
00305
00306 if (size < init_overhead)
00307 {
00308
00309 return 0;
00310 }
00311 end=start+size;
00312 qm=(struct fm_block*)start;
00313 memset(qm, 0, sizeof(struct fm_block));
00314 qm->size=size;
00315 #if defined(DBG_F_MALLOC) || defined(MALLOC_STATS)
00316 qm->real_used=init_overhead;
00317 qm->max_real_used=qm->real_used;
00318 #endif
00319 size-=init_overhead;
00320
00321 qm->first_frag=(struct fm_frag*)(start+ROUNDUP(sizeof(struct fm_block)));
00322 qm->last_frag=(struct fm_frag*)(end-sizeof(struct fm_frag));
00323
00324 qm->first_frag->size=size;
00325 qm->last_frag->size=0;
00326
00327 #ifdef DBG_F_MALLOC
00328 qm->first_frag->check=ST_CHECK_PATTERN;
00329 qm->last_frag->check=END_CHECK_PATTERN1;
00330 #endif
00331
00332
00333
00334 fm_insert_free(qm, qm->first_frag);
00335
00336
00337 return qm;
00338 }
00339
00340
00349 #ifdef DBG_F_MALLOC
00350 void* fm_malloc(struct fm_block* qm, unsigned long size,
00351 const char* file, const char* func, unsigned int line)
00352 #else
00353 void* fm_malloc(struct fm_block* qm, unsigned long size)
00354 #endif
00355 {
00356 struct fm_frag** f;
00357 struct fm_frag* frag;
00358 int hash;
00359
00360 #ifdef DBG_F_MALLOC
00361 MDBG("fm_malloc(%p, %lu) called from %s: %s(%d)\n", qm, size, file, func,
00362 line);
00363 #endif
00364
00365 size=ROUNDUP(size);
00366
00367
00368
00369
00370
00371 #ifdef F_MALLOC_HASH_BITMAP
00372 hash=fm_bmp_first_set(qm, GET_HASH(size));
00373 if (likely(hash>=0)){
00374 if (likely(hash<=F_MALLOC_OPTIMIZE/ROUNDTO)) {
00375 f=&(qm->free_hash[hash].first);
00376 goto found;
00377 }
00378
00379
00380
00381
00382
00383
00384
00385 do {
00386 for(f=&(qm->free_hash[hash].first);(*f); f=&((*f)->u.nxt_free))
00387 if ((*f)->size>=size) goto found;
00388 hash++;
00389 }while((hash < F_HASH_SIZE) &&
00390 ((hash=fm_bmp_first_set(qm, hash)) >= 0));
00391 }
00392 #else
00393 for(hash=GET_HASH(size);hash<F_HASH_SIZE;hash++){
00394 f=&(qm->free_hash[hash].first);
00395 #if 0
00396 if (likely(hash<=F_MALLOC_OPTIMIZE/ROUNDTO))
00397 goto found;
00398 #endif
00399 for(;(*f); f=&((*f)->u.nxt_free))
00400 if ((*f)->size>=size) goto found;
00401
00402 }
00403 #endif
00404
00405 return 0;
00406
00407 found:
00408
00409
00410 frag=*f;
00411 *f=frag->u.nxt_free;
00412 frag->u.nxt_free=0;
00413 qm->free_hash[hash].no--;
00414 #ifdef F_MALLOC_HASH_BITMAP
00415 if (qm->free_hash[hash].no==0)
00416 fm_bmp_reset(qm, hash);
00417 #endif
00418
00419
00420
00421 #ifdef DBG_F_MALLOC
00422 fm_split_frag(qm, frag, size, file, func, line);
00423
00424 frag->file=file;
00425 frag->func=func;
00426 frag->line=line;
00427 frag->check=ST_CHECK_PATTERN;
00428 MDBG("fm_malloc(%p, %lu) returns address %p \n", qm, size,
00429 (char*)frag+sizeof(struct fm_frag));
00430 #else
00431 fm_split_frag(qm, frag, size);
00432 #endif
00433 #if defined(DBG_F_MALLOC) || defined(MALLOC_STATS)
00434 qm->real_used+=frag->size;
00435 qm->used+=frag->size;
00436 if (qm->max_real_used<qm->real_used)
00437 qm->max_real_used=qm->real_used;
00438 #ifdef MALLOC_STATS
00439 sr_event_exec(SREV_PKG_SET_USED, (void*)qm->used);
00440 sr_event_exec(SREV_PKG_SET_REAL_USED, (void*)qm->real_used);
00441 #endif
00442 #endif
00443 FRAG_MARK_USED(frag);
00444 return (char*)frag+sizeof(struct fm_frag);
00445 }
00446
00447
00448 #ifdef MEM_JOIN_FREE
00449
00452 static void fm_join_frag(struct fm_block* qm, struct fm_frag* f)
00453 {
00454 int hash;
00455 struct fm_frag **pf;
00456 struct fm_frag* n;
00457
00458 n=FRAG_NEXT(f);
00459
00460 if (((char*)n >= (char*)qm->last_frag) || (n->u.nxt_free==NULL))
00461 return;
00462
00463
00464 hash=GET_HASH(n->size);
00465 pf=&(qm->free_hash[hash].first);
00466
00467 for(;(*pf)&&(*pf!=n); pf=&((*pf)->u.nxt_free));
00468 if (*pf==0){
00469
00470 LM_WARN("could not find %p in free list (hash=%ld)\n", n, GET_HASH(n->size));
00471 return;
00472 }
00473
00474 *pf=n->u.nxt_free;
00475 qm->free_hash[hash].no--;
00476 #ifdef F_MALLOC_HASH_BITMAP
00477 if (qm->free_hash[hash].no==0)
00478 fm_bmp_reset(qm, hash);
00479 #endif
00480
00481 f->size+=n->size+FRAG_OVERHEAD;
00482 #if defined(DBG_F_MALLOC) || defined(MALLOC_STATS)
00483 qm->real_used-=FRAG_OVERHEAD;
00484 #ifdef MALLOC_STATS
00485 sr_event_exec(SREV_PKG_SET_REAL_USED, (void*)qm->real_used);
00486 #endif
00487 #endif
00488 }
00489 #endif
00490
00498 #ifdef DBG_F_MALLOC
00499 void fm_free(struct fm_block* qm, void* p, const char* file, const char* func,
00500 unsigned int line)
00501 #else
00502 void fm_free(struct fm_block* qm, void* p)
00503 #endif
00504 {
00505 struct fm_frag* f;
00506 unsigned long size;
00507
00508 #ifdef DBG_F_MALLOC
00509 MDBG("fm_free(%p, %p), called from %s: %s(%d)\n", qm, p, file, func, line);
00510 if (p>(void*)qm->last_frag || p<(void*)qm->first_frag){
00511 LOG(L_CRIT, "BUG: fm_free: bad pointer %p (out of memory block!),"
00512 " called from %s: %s(%d) - aborting\n", p,
00513 file, func, line);
00514 if(likely(cfg_get(core, core_cfg, mem_safety)==0))
00515 abort();
00516 }
00517 #endif
00518 if (p==0) {
00519 LOG(L_WARN, "WARNING:fm_free: free(0) called\n");
00520 return;
00521 }
00522 f=(struct fm_frag*) ((char*)p-sizeof(struct fm_frag));
00523 #ifdef DBG_F_MALLOC
00524 MDBG("fm_free: freeing block alloc'ed from %s: %s(%ld)\n",
00525 f->file, f->func, f->line);
00526 #endif
00527 if(unlikely(f->u.nxt_free!=NULL)) {
00528 LM_INFO("freeing a free fragment (%p/%p) - ignore\n",
00529 f, p);
00530 return;
00531 }
00532 size=f->size;
00533 #if defined(DBG_F_MALLOC) || defined(MALLOC_STATS)
00534 qm->used-=size;
00535 qm->real_used-=size;
00536 #ifdef MALLOC_STATS
00537 sr_event_exec(SREV_PKG_SET_USED, (void*)qm->used);
00538 sr_event_exec(SREV_PKG_SET_REAL_USED, (void*)qm->real_used);
00539 #endif
00540 #endif
00541 #ifdef DBG_F_MALLOC
00542 f->file=file;
00543 f->func=func;
00544 f->line=line;
00545 #endif
00546 #ifdef MEM_JOIN_FREE
00547 if(unlikely(cfg_get(core, core_cfg, mem_join)!=0))
00548 fm_join_frag(qm, f);
00549 #endif
00550 fm_insert_free(qm, f);
00551 }
00552
00553
00563 #ifdef DBG_F_MALLOC
00564 void* fm_realloc(struct fm_block* qm, void* p, unsigned long size,
00565 const char* file, const char* func, unsigned int line)
00566 #else
00567 void* fm_realloc(struct fm_block* qm, void* p, unsigned long size)
00568 #endif
00569 {
00570 struct fm_frag *f;
00571 struct fm_frag **pf;
00572 unsigned long diff;
00573 unsigned long orig_size;
00574 struct fm_frag *n;
00575 void *ptr;
00576 int hash;
00577
00578 #ifdef DBG_F_MALLOC
00579 MDBG("fm_realloc(%p, %p, %lu) called from %s: %s(%d)\n", qm, p, size,
00580 file, func, line);
00581 if ((p)&&(p>(void*)qm->last_frag || p<(void*)qm->first_frag)){
00582 LOG(L_CRIT, "BUG: fm_free: bad pointer %p (out of memory block!) - "
00583 "aborting\n", p);
00584 abort();
00585 }
00586 #endif
00587 if (size==0) {
00588 if (p)
00589 #ifdef DBG_F_MALLOC
00590 fm_free(qm, p, file, func, line);
00591 #else
00592 fm_free(qm, p);
00593 #endif
00594 return 0;
00595 }
00596 if (p==0)
00597 #ifdef DBG_F_MALLOC
00598 return fm_malloc(qm, size, file, func, line);
00599 #else
00600 return fm_malloc(qm, size);
00601 #endif
00602 f=(struct fm_frag*) ((char*)p-sizeof(struct fm_frag));
00603 #ifdef DBG_F_MALLOC
00604 MDBG("fm_realloc: realloc'ing frag %p alloc'ed from %s: %s(%ld)\n",
00605 f, f->file, f->func, f->line);
00606 #endif
00607 size=ROUNDUP(size);
00608 orig_size=f->size;
00609 if (f->size > size){
00610
00611 #ifdef DBG_F_MALLOC
00612 MDBG("fm_realloc: shrinking from %lu to %lu\n", f->size, size);
00613 fm_split_frag(qm, f, size, file, "frag. from fm_realloc", line);
00614 #else
00615 fm_split_frag(qm, f, size);
00616 #endif
00617 #if defined(DBG_F_MALLOC) || defined(MALLOC_STATS)
00618
00619
00620 qm->real_used-=(orig_size-f->size);
00621 qm->used-=(orig_size-f->size);
00622 #ifdef MALLOC_STATS
00623 sr_event_exec(SREV_PKG_SET_USED, (void*)qm->used);
00624 sr_event_exec(SREV_PKG_SET_REAL_USED, (void*)qm->real_used);
00625 #endif
00626 #endif
00627 }else if (f->size<size){
00628
00629 #ifdef DBG_F_MALLOC
00630 MDBG("fm_realloc: growing from %lu to %lu\n", f->size, size);
00631 #endif
00632 diff=size-f->size;
00633 n=FRAG_NEXT(f);
00634 if (((char*)n < (char*)qm->last_frag) &&
00635 (n->u.nxt_free)&&((n->size+FRAG_OVERHEAD)>=diff)){
00636
00637
00638 hash=GET_HASH(n->size);
00639 pf=&(qm->free_hash[hash].first);
00640
00641 for(;(*pf)&&(*pf!=n); pf=&((*pf)->u.nxt_free));
00642 if (*pf==0){
00643
00644 LOG(L_CRIT, "BUG: fm_realloc: could not find %p in free "
00645 "list (hash=%ld)\n", n, GET_HASH(n->size));
00646 abort();
00647 }
00648
00649 *pf=n->u.nxt_free;
00650 qm->free_hash[hash].no--;
00651 #ifdef F_MALLOC_HASH_BITMAP
00652 if (qm->free_hash[hash].no==0)
00653 fm_bmp_reset(qm, hash);
00654 #endif
00655
00656 f->size+=n->size+FRAG_OVERHEAD;
00657 #if defined(DBG_F_MALLOC) || defined(MALLOC_STATS)
00658 qm->real_used-=FRAG_OVERHEAD;
00659 #ifdef MALLOC_STATS
00660 sr_event_exec(SREV_PKG_SET_REAL_USED, (void*)qm->real_used);
00661 #endif
00662 #endif
00663
00664 if (f->size > size){
00665 #ifdef DBG_F_MALLOC
00666 fm_split_frag(qm, f, size, file, "fragm. from fm_realloc",
00667 line);
00668 #else
00669 fm_split_frag(qm, f, size);
00670 #endif
00671 }
00672 #if defined(DBG_F_MALLOC) || defined(MALLOC_STATS)
00673 qm->real_used+=(f->size-orig_size);
00674 qm->used+=(f->size-orig_size);
00675 #ifdef MALLOC_STATS
00676 sr_event_exec(SREV_PKG_SET_USED, (void*)qm->used);
00677 sr_event_exec(SREV_PKG_SET_REAL_USED, (void*)qm->real_used);
00678 #endif
00679 #endif
00680 }else{
00681
00682 #ifdef DBG_F_MALLOC
00683 ptr=fm_malloc(qm, size, file, func, line);
00684 #else
00685 ptr=fm_malloc(qm, size);
00686 #endif
00687 if (ptr){
00688
00689 memcpy(ptr, p, orig_size);
00690 #ifdef DBG_F_MALLOC
00691 fm_free(qm, p, file, func, line);
00692 #else
00693 fm_free(qm, p);
00694 #endif
00695 }
00696 p=ptr;
00697 }
00698 }else{
00699
00700 #ifdef DBG_F_MALLOC
00701 MDBG("fm_realloc: doing nothing, same size: %lu - %lu\n",
00702 f->size, size);
00703 #endif
00704 }
00705 #ifdef DBG_F_MALLOC
00706 MDBG("fm_realloc: returning %p\n", p);
00707 #endif
00708 return p;
00709 }
00710
00711
00716 void fm_status(struct fm_block* qm)
00717 {
00718 struct fm_frag* f;
00719 int i,j;
00720 int h;
00721 int unused;
00722 unsigned long size;
00723 int memlog;
00724 int mem_summary;
00725
00726 memlog=cfg_get(core, core_cfg, memlog);
00727 mem_summary=cfg_get(core, core_cfg, mem_summary);
00728 LOG_(DEFAULT_FACILITY, memlog, "fm_status: ", "fm_status (%p):\n", qm);
00729 if (!qm) return;
00730
00731 LOG_(DEFAULT_FACILITY, memlog, "fm_status: ", " heap size= %ld\n",
00732 qm->size);
00733 #if defined(DBG_F_MALLOC) || defined(MALLOC_STATS)
00734 LOG_(DEFAULT_FACILITY, memlog, "fm_status: ",
00735 " used= %lu, used+overhead=%lu, free=%lu\n",
00736 qm->used, qm->real_used, qm->size-qm->real_used);
00737 LOG_(DEFAULT_FACILITY, memlog, "fm_status: ",
00738 " max used (+overhead)= %lu\n", qm->max_real_used);
00739 #endif
00740
00741 if (mem_summary & 16) return;
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758 LOG_(DEFAULT_FACILITY, memlog, "fm_status: ", "dumping free list:\n");
00759 for(h=0,i=0,size=0;h<F_HASH_SIZE;h++){
00760 unused=0;
00761 for (f=qm->free_hash[h].first,j=0; f;
00762 size+=f->size,f=f->u.nxt_free,i++,j++){
00763 if (!FRAG_WAS_USED(f)){
00764 unused++;
00765 #ifdef DBG_F_MALLOC
00766 LOG_(DEFAULT_FACILITY, memlog, "fm_status: ",
00767 "unused fragm.: hash = %3d, fragment %p,"
00768 " address %p size %lu, created from %s: %s(%ld)\n",
00769 h, f, (char*)f+sizeof(struct fm_frag), f->size,
00770 f->file, f->func, f->line);
00771 #endif
00772 };
00773 }
00774 if (j) LOG_(DEFAULT_FACILITY, memlog, "fm_status: ",
00775 "hash = %3d fragments no.: %5d, unused: %5d\n\t\t"
00776 " bucket size: %9lu - %9lu (first %9lu)\n",
00777 h, j, unused, UN_HASH(h),
00778 ((h<=F_MALLOC_OPTIMIZE/ROUNDTO)?1:2)* UN_HASH(h),
00779 qm->free_hash[h].first->size
00780 );
00781 if (j!=qm->free_hash[h].no){
00782 LOG(L_CRIT, "BUG: fm_status: different free frag. count: %d!=%ld"
00783 " for hash %3d\n", j, qm->free_hash[h].no, h);
00784 }
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798 }
00799 LOG_(DEFAULT_FACILITY, memlog, "fm_status: ",
00800 "TOTAL: %6d free fragments = %6lu free bytes\n", i, size);
00801 LOG_(DEFAULT_FACILITY, memlog, "fm_status: ",
00802 "-----------------------------\n");
00803 }
00804
00805
00814 void fm_info(struct fm_block* qm, struct mem_info* info)
00815 {
00816 int r;
00817 long total_frags;
00818 #if !defined(DBG_F_MALLOC) && !defined(MALLOC_STATS)
00819 struct fm_frag* f;
00820 #endif
00821
00822 memset(info,0, sizeof(*info));
00823 total_frags=0;
00824 info->total_size=qm->size;
00825 info->min_frag=MIN_FRAG_SIZE;
00826 #if defined(DBG_F_MALLOC) || defined(MALLOC_STATS)
00827 info->free=qm->size-qm->real_used;
00828 info->used=qm->used;
00829 info->real_used=qm->real_used;
00830 info->max_used=qm->max_real_used;
00831 for(r=0;r<F_HASH_SIZE; r++){
00832 total_frags+=qm->free_hash[r].no;
00833 }
00834 #else
00835
00836 for (r=0; r<=F_MALLOC_OPTIMIZE/ROUNDTO; r++){
00837 info->free+=qm->free_hash[r].no*UN_HASH(r);
00838 total_frags+=qm->free_hash[r].no;
00839 }
00840 for(;r<F_HASH_SIZE; r++){
00841 total_frags+=qm->free_hash[r].no;
00842 for(f=qm->free_hash[r].first;f;f=f->u.nxt_free){
00843 info->free+=f->size;
00844 }
00845 }
00846 info->real_used=info->total_size-info->free;
00847 info->used=0;
00848 info->used=info->real_used-total_frags*FRAG_OVERHEAD-INIT_OVERHEAD-
00849 FRAG_OVERHEAD;
00850 info->max_used=0;
00851 #endif
00852 info->total_frags=total_frags;
00853 }
00854
00855
00862 unsigned long fm_available(struct fm_block* qm)
00863 {
00864
00865 #if defined(DBG_F_MALLOC) || defined(MALLOC_STATS)
00866 return qm->size-qm->real_used;
00867 #else
00868
00869
00870 return ((unsigned long)-1);
00871 #endif
00872 }
00873
00874
00875 #ifdef DBG_F_MALLOC
00876
00877 typedef struct _mem_counter{
00878 const char *file;
00879 const char *func;
00880 unsigned long line;
00881
00882 unsigned long size;
00883 int count;
00884
00885 struct _mem_counter *next;
00886 } mem_counter;
00887
00888 static mem_counter* get_mem_counter(mem_counter **root,struct fm_frag* f)
00889 {
00890 mem_counter *x;
00891
00892 if (!*root) goto make_new;
00893 for(x=*root;x;x=x->next)
00894 if (x->file == f->file && x->func == f->func && x->line == f->line)
00895 return x;
00896 make_new:
00897 x = malloc(sizeof(mem_counter));
00898 x->file = f->file;
00899 x->func = f->func;
00900 x->line = f->line;
00901 x->count = 0;
00902 x->size = 0;
00903 x->next = *root;
00904 *root = x;
00905 return x;
00906 }
00907
00908
00913 void fm_sums(struct fm_block* qm)
00914 {
00915 struct fm_frag* f;
00916 struct fm_frag* free_frag;
00917 int i, hash;
00918 int memlog;
00919 mem_counter *root,*x;
00920
00921 root=0;
00922 if (!qm) return;
00923
00924 memlog=cfg_get(core, core_cfg, memlog);
00925 LOG_(DEFAULT_FACILITY, memlog, "fm_status: ",
00926 "summarizing all alloc'ed. fragments:\n");
00927
00928 for (f=qm->first_frag, i=0; (char*)f<(char*)qm->last_frag;
00929 f=FRAG_NEXT(f), i++){
00930 if (f->u.nxt_free==0){
00931
00932
00933
00934 hash=GET_HASH(f->size);
00935 for(free_frag=qm->free_hash[hash].first;
00936 free_frag && (free_frag!=f);
00937 free_frag=free_frag->u.nxt_free);
00938 if (free_frag==0){
00939 x = get_mem_counter(&root,f);
00940 x->count++;
00941 x->size+=f->size;
00942 }
00943 }
00944 }
00945 x = root;
00946 while(x){
00947 LOG_(DEFAULT_FACILITY, memlog, "fm_status: ",
00948 " count=%6d size=%10lu bytes from %s: %s(%ld)\n",
00949 x->count,x->size,
00950 x->file, x->func, x->line
00951 );
00952 root = x->next;
00953 free(x);
00954 x = root;
00955 }
00956 LOG_(DEFAULT_FACILITY, memlog, "fm_status: ",
00957 "-----------------------------\n");
00958 }
00959 #endif
00960
00961
00962
00963 #endif