MEM_ALLOCATOR Class Reference

#include <memblk.h>

List of all members.


Detailed Description

Class for managing memory in Tesseract.

Definition at line 118 of file memblk.h.

Public Member Functions

Public Attributes

Private Member Functions


Member Function Documentation

void * MEM_ALLOCATOR::alloc ( INT32  size,
void *  caller 
)

Return a pointer to a buffer of count bytes aligned for any type.

Definition at line 543 of file memblk.cpp.

References ABORT, MEMUNION::age, biggestblock, MEMBLOCK::blockend, MEMBLOCK::blockstart, check_mem(), currblock, ERRCODE::error(), MEMBLOCK::find_chunk(), MEMBLOCK::freechunk, MEMBLOCK::lowerspace, MEMCHECKS, MEMTOOBIG, new_block(), MEMBLOCK::next, NULL, MEMUNION::owner, set_owner(), MEMUNION::size, topblock, MEMBLOCK::topchunk, totalmem, and MEMBLOCK::upperspace.

Referenced by alloc_big_mem(), alloc_big_zeros(), alloc_mem(), and alloc_p().

00546                             {
00547   MEMBLOCK *block;               //current block
00548   MEMUNION *chunk;               //current chunk
00549   INT32 chunksize;               //size of free chunk
00550   MEMUNION *chunkstart;          //start of free chunk
00551 
00552   if (count < 1 || count > biggestblock)
00553     MEMTOOBIG.error ("alloc_mem", ABORT, "%d", (int) count);
00554   //request too big
00555 
00556   count += sizeof (MEMUNION) - 1;//round up to word
00557   count /= sizeof (MEMUNION);
00558   count++;                       //and add one
00559   if (currblock == NULL) {
00560                                  //get first block
00561     currblock = new_block (count);
00562     topblock = currblock;
00563     if (currblock == NULL) {
00564       check_mem ("alloc_mem returning NULL", MEMCHECKS);
00565       return NULL;
00566     }
00567   }
00568   block = currblock;             //current block
00569   if (block->upperspace <= block->lowerspace) {
00570                                  //restart chunklist
00571     block->freechunk = block->blockstart;
00572     block->upperspace += block->lowerspace;
00573     block->lowerspace = 0;       //correct space counts
00574   }
00575   chunk = block->freechunk;      //current free chunk
00576   if (chunk->size < count) {     //big enough?
00577     do {
00578                                  //search for free chunk
00579       chunk = block->find_chunk (count);
00580       if (chunk->size < count)
00581         block = block->next;     //try next block
00582     }
00583                                  //until all tried
00584     while (chunk->size < count && block != currblock);
00585     if (chunk->size < count) {   //still no good
00586                                  //get a new block
00587       currblock = new_block (count);
00588       topblock = currblock;      //set perms here too
00589       if (currblock == NULL) {
00590         check_mem ("alloc_mem returning NULL", MEMCHECKS);
00591         return NULL;
00592       }
00593       block = currblock;
00594       chunk = block->freechunk;  //bound to be big enough
00595     }
00596   }
00597   chunkstart = chunk;            //start of chunk
00598   if (chunk == block->topchunk && chunk + count != block->blockend)
00599     block->topchunk += count;    //top has moved
00600   block->upperspace -= count;    //upper part used
00601   chunksize = chunk->size;       //size of free chunk
00602   chunk->size = -count;          //mark as used
00603   chunk += count;                //next free space
00604   totalmem -= count;             //no of free elements
00605   if (chunksize > count)         //bigger than exact?
00606                                  //remaining space
00607     chunk->size = chunksize - count;
00608   else if (chunk == block->blockend) {
00609     chunk = block->blockstart;   //restart block
00610     block->upperspace = block->lowerspace;
00611     block->lowerspace = 0;       //fix space counts
00612   }
00613   block->freechunk = chunk;      //next free block
00614   if (mem_mallocdepth > 0) {
00615     set_owner(chunkstart, caller);
00616   }
00617   else {
00618     chunkstart->owner = 0;
00619     chunkstart->age = 0;
00620   }
00621   chunkstart++;                  //start of block
00622   return chunkstart;             //pointer to block
00623 }

void * MEM_ALLOCATOR::alloc_p ( INT32  count,
void *  caller 
)

Allocate permanent space which will never be returned.

This space is allocated from the top end of a memory block to avoid the fragmentation which would result from alternate use of alloc_mem for permanent and temporary blocks.

Definition at line 485 of file memblk.cpp.

References ABORT, MEMUNION::age, alloc(), biggestblock, check_mem(), currblock, ERRCODE::error(), MEMCHECKS, MEMTOOBIG, new_block(), MEMBLOCK::next, NULL, MEMUNION::owner, set_owner(), MEMUNION::size, topblock, MEMBLOCK::topchunk, and MEMBLOCK::upperspace.

Referenced by alloc_mem_p().

00488                               {
00489   MEMBLOCK *block;               //current block
00490   MEMUNION *chunk;               //current chunk
00491 
00492   if (count < 1 || count > biggestblock)
00493                                  //request too big
00494     MEMTOOBIG.error ("alloc_mem_p", ABORT, "%d", (int) count);
00495 
00496   count += sizeof (MEMUNION) - 1;//round up to word
00497   count /= sizeof (MEMUNION);
00498   count++;                       //and add one
00499   if (topblock == NULL) {
00500     topblock = new_block (count);//get first block
00501     currblock = topblock;
00502     if (topblock == NULL) {
00503       check_mem ("alloc_mem_p returning NULL", MEMCHECKS);
00504       return NULL;
00505     }
00506   }
00507   block = topblock;              //current block
00508   do {
00509     chunk = block->topchunk;
00510     if (chunk->size < count)
00511       block = block->next;       //try next block
00512   }
00513                                  //until all tried
00514   while (chunk->size < count && block != topblock);
00515   if (chunk->size < count) {     //still no good
00516     chunk = (MEMUNION *) alloc ((count - 1) * sizeof (MEMUNION), caller);
00517     //try last resort
00518     if (chunk != NULL)
00519       return chunk;
00520     check_mem ("alloc_mem_p returning NULL", MEMCHECKS);
00521     return NULL;
00522   }
00523   block->upperspace -= count;    //less above freechunk
00524   if (chunk->size > count) {
00525     chunk->size -= count;
00526     chunk += chunk->size;
00527   }
00528   chunk->size = -count;          //mark as in use
00529   if (mem_mallocdepth > 0) {
00530     set_owner(chunk, caller); 
00531   }
00532   else {
00533     chunk->owner = 0;
00534     chunk->age = 0;
00535   }
00536   return chunk + 1;              //created chunk
00537 }

void MEM_ALLOCATOR::check ( const char *  string,
INT8  level 
)

Check consistency of all memory controlled by this allocator.

Definition at line 371 of file memblk.cpp.

References ABORT, MEMUNION::age, BADMEMCHUNKS, blockcount, MEMBLOCK::blockend, MEMBLOCK::blockstart, ERRCODE::error(), FULLMEMCHECKS, MEMBLOCK::lowerspace, memblocks, MEMCHECKS, NULL, MEMUNION::owner, MEMUNION::size, MEMBLOCK::topchunk, tprintf(), and MEMBLOCK::upperspace.

Referenced by check_mem().

00374                            {
00375   MEMBLOCK *block;               //current block
00376   MEMUNION *chunk;               //current chunk
00377   MEMUNION *prevchunk;           //previous chunk
00378   INT32 chunksize;               //size of chunk
00379   INT32 usedcount;               //no of used chunks
00380   INT32 usedsize;                //size of used chunks
00381   INT32 freecount;               //no of free chunks
00382   INT32 freesize;                //size of free chunks
00383   INT32 biggest;                 //biggest free chunk
00384   INT32 totusedcount;            //no of used chunks
00385   INT32 totusedsize;             //size of used chunks
00386   INT32 totfreecount;            //no of free chunks
00387   INT32 totfreesize;             //size of free chunks
00388   INT32 totbiggest;              //biggest free chunk
00389   INT32 totblocksize;            //total size of blocks
00390   INT32 chunkindex;              //index of chunk
00391   INT32 blockindex;              //index of block
00392 
00393   if (level >= MEMCHECKS)
00394     tprintf ("\nMEM_ALLOCATOR::check:at '%s'\n", string);
00395   totusedcount = 0;              //grand totals
00396   totusedsize = 0;
00397   totfreecount = 0;
00398   totfreesize = 0;
00399   totbiggest = 0;
00400   totblocksize = 0;
00401   for (blockindex = 0; blockindex < blockcount; blockindex++) {
00402                                  //current block
00403     block = &memblocks[blockindex];
00404     if (level >= MEMCHECKS)
00405       tprintf ("Block %d:0x%x-0x%x, size=%d, top=0x%x, l=%d, u=%d\n",
00406         blockindex, block->blockstart, block->blockend,
00407         (block->blockend - block->blockstart) * sizeof (MEMUNION),
00408         block->topchunk, block->lowerspace, block->upperspace);
00409     usedcount = usedsize = 0;    //zero counters
00410     freecount = freesize = 0;    //zero counters
00411     biggest = 0;
00412                                  //scan all chunks
00413     for (chunkindex = 0, prevchunk = NULL, chunk = block->blockstart; chunk != block->blockend; chunkindex++, chunk += chunksize) {
00414       chunksize = chunk->size;   //size of chunk
00415       if (chunksize < 0)
00416         chunksize = -chunksize;  //absolute size
00417       if (level >= FULLMEMCHECKS) {
00418         tprintf ("%5d=%8d%c caller=%d, age=%d ", (int) chunkindex,
00419           chunksize * sizeof (MEMUNION),
00420           chunk->size < 0 ? 'U' : 'F', chunk->owner, chunk->age);
00421         if (chunkindex % 5 == 4)
00422           tprintf ("\n");
00423       }
00424                                  //illegal sizes
00425       if (chunksize == 0 || chunk->size == -1
00426                                  //out of bounds
00427         || chunk + chunksize - block->blockstart <= 0 || block->blockend - (chunk + chunksize) < 0)
00428         BADMEMCHUNKS.error ("check_mem", ABORT,
00429           "Block=%p, Prev chunk=%p, Chunk=%p, Size=%x",
00430           block, prevchunk, chunk,
00431           (int) chunk->size);
00432 
00433       else if (chunk->size < 0) {
00434         usedcount++;             //used block
00435         usedsize += chunksize;
00436       }
00437       else {
00438         freecount++;             //free block
00439         freesize += chunksize;
00440         if (chunksize > biggest)
00441           biggest = chunksize;
00442       }
00443       prevchunk = chunk;
00444     }
00445     if (level >= MEMCHECKS) {
00446       if (level >= FULLMEMCHECKS)
00447         tprintf ("\n");
00448       tprintf ("%d chunks in use, total size=%d bytes\n",
00449         (int) usedcount, usedsize * sizeof (MEMUNION));
00450       tprintf ("%d chunks free, total size=%d bytes\n",
00451         (int) freecount, freesize * sizeof (MEMUNION));
00452       tprintf ("Largest free fragment=%d bytes\n",
00453         biggest * sizeof (MEMUNION));
00454     }
00455     totusedcount += usedcount;   //grand totals
00456     totusedsize += usedsize;
00457     totfreecount += freecount;
00458     totfreesize += freesize;
00459     if (biggest > totbiggest)
00460       totbiggest = biggest;
00461     totblocksize += block->blockend - block->blockstart;
00462   }
00463   if (level >= MEMCHECKS) {
00464     tprintf ("%d total blocks in use, total size=%d bytes\n",
00465       blockcount, totblocksize * sizeof (MEMUNION));
00466     tprintf ("%d total chunks in use, total size=%d bytes\n",
00467       (int) totusedcount, totusedsize * sizeof (MEMUNION));
00468     tprintf ("%d total chunks free, total size=%d bytes\n",
00469       (int) totfreecount, totfreesize * sizeof (MEMUNION));
00470     tprintf ("Largest free fragment=%d bytes\n",
00471       totbiggest * sizeof (MEMUNION));
00472   }
00473   if (level >= MEMCHECKS)
00474     display_counts();
00475 }

void MEM_ALLOCATOR::dealloc ( void *  oldchunk,
void *  caller 
)

Free a block allocated by alloc (or alloc_p).

It checks that the pointer is legal and maintains counts of the amount of free memory above and below the current free pointer.

Definition at line 665 of file memblk.cpp.

References ABORT, MEMBLOCK::blockend, MEMBLOCK::blockstart, callers, MALLOC_CALL::count_freeer(), currblock, ERRCODE::error(), MEMBLOCK::freechunk, FREEFREEDBLOCK, FREEILLEGALPTR, FREENULLPTR, MEMBLOCK::lowerspace, MEMBLOCK::next, NOTMALLOCMEM, NULL, MEMUNION::owner, MEMUNION::size, totalmem, and MEMBLOCK::upperspace.

Referenced by free_big_mem(), and free_mem().

00668                              {
00669   MEMUNION *chunk;               //current chunk
00670   MEMBLOCK *block;               //current block
00671 
00672   if (oldchunk == NULL)
00673     FREENULLPTR.error ("free_mem", ABORT, NULL);
00674   chunk = (MEMUNION *) oldchunk;
00675   block = currblock;             //current block
00676   if (block == NULL)
00677     NOTMALLOCMEM.error ("free_mem", ABORT, NULL);
00678   do {
00679     block = block->next;
00680   }
00681                                  //outside the block
00682   while ((chunk - block->blockstart < 0 || block->blockend - chunk <= 0)
00683     && block != currblock);
00684 
00685   if (chunk - block->blockstart < 0 || block->blockend - chunk <= 0)
00686                                  //in no block
00687     NOTMALLOCMEM.error ("free_mem", ABORT, NULL);
00688 
00689   chunk--;                       //point to size
00690   if (chunk->size == 0)
00691                                  //zero size
00692     FREEILLEGALPTR.error ("free_mem", ABORT, NULL);
00693   else if (chunk->size > 0)
00694                                  //already free
00695     FREEFREEDBLOCK.error ("free_mem", ABORT, NULL);
00696   chunk->size = -chunk->size;    //mark it free
00697   if (mem_freedepth > 0 && callers != NULL) {
00698                                  //count calls
00699     callers[chunk->owner].count_freeer (caller);
00700   }
00701   totalmem += chunk->size;       //total free memory
00702   if (chunk - block->freechunk < 0)
00703                                  //extra below
00704     block->lowerspace += chunk->size;
00705   else
00706                                  //extra above
00707     block->upperspace += chunk->size;
00708 }

void MEM_ALLOCATOR::display_counts (  ) 

Send counts of outstanding blocks to stderr.

Definition at line 248 of file memblk.cpp.

References MEMUNION::age, blockcount, MEMBLOCK::blockend, MEMBLOCK::blockstart, callers, check_mem(), MALLOC_CALL::counts, entries, JUSTCHECKS, malloc, malloc_div_ratio, malloc_serial, memblocks, NULL, MEMUNION::owner, MEMUNION::size, MEMBLOCK::topchunk, and tprintf().

00248                                    {  //count up
00249   MEMBLOCK *block;               //current block
00250   MEMUNION *chunk;               //current chunk
00251   INT32 chunksize;               //size of chunk
00252   INT32 blockindex;              //index of block
00253   INT32 buckets;                 //required buckets
00254   INT32 bucketsize;              //no in each bucket
00255   INT32 callindex;               //index to callers
00256   INT32 freeindex;               //index to freeers
00257   INT32 freeentries;             //table size
00258   INT32 totalchunks;             //total chunk counts
00259   INT32 totalspace;              //total mem space
00260   INT32 totalpchunks;            //permanent chunks
00261   INT32 totalpspace;             //permanent space
00262   INT32 totalfrees;              //total free calls
00263 
00264   if (callers == NULL)
00265     return;                      //can't do anything
00266   check_mem ("Displaying counts", JUSTCHECKS);
00267   buckets = mem_countbuckets;
00268   bucketsize = (malloc_serial - 1) / buckets + 1;
00269   tprintf ("\nEach bucket covers %g counts.\n",
00270     (double) bucketsize * malloc_div_ratio);
00271   for (callindex = 0; callindex < entries; callindex++) {
00272     if (callers[callindex].free_list != NULL) {
00273       callers[callindex].counts =
00274         (INT32 *) malloc (buckets * 4 * sizeof (INT32));
00275       memset (callers[callindex].counts, 0,
00276         (size_t) (buckets * 4 * sizeof (INT32)));
00277     }
00278   }
00279   for (blockindex = 0; blockindex < blockcount; blockindex++) {
00280                                  //current block
00281     block = &memblocks[blockindex];
00282                                  //scan all chunks
00283     for (chunk = block->blockstart; chunk != block->topchunk; chunk += chunksize) {
00284       chunksize = chunk->size;   //size of chunk
00285       if (chunksize < 0) {
00286         chunksize = -chunksize;  //absolute size
00287         callindex = chunk->owner;
00288         if (callers[callindex].counts != NULL) {
00289           callers[callindex].counts[chunk->age / bucketsize * 4]++;
00290           callers[callindex].counts[chunk->age / bucketsize * 4 +
00291             1] += chunksize;
00292         }
00293       }
00294     }
00295                                  //scan all chunks
00296     for (; chunk != block->blockend; chunk += chunksize) {
00297       chunksize = chunk->size;   //size of chunk
00298       if (chunksize < 0) {
00299         chunksize = -chunksize;  //absolute size
00300         callindex = chunk->owner;
00301         if (callers[callindex].counts != NULL) {
00302           callers[callindex].counts[chunk->age / bucketsize * 4 +
00303             2]++;
00304           callers[callindex].counts[chunk->age / bucketsize * 4 +
00305             3] += chunksize;
00306         }
00307       }
00308     }
00309   }
00310   for (callindex = 0; callindex < entries; callindex++) {
00311     if (callers[callindex].counts != NULL) {
00312       for (totalspace = 0, totalchunks = 0, totalpspace =
00313         0, totalpchunks = 0, freeindex = 0; freeindex < buckets;
00314       freeindex++) {
00315         totalchunks += callers[callindex].counts[freeindex * 4];
00316         totalspace += callers[callindex].counts[freeindex * 4 + 1];
00317         totalpchunks += callers[callindex].counts[freeindex * 4 + 2];
00318         totalpspace += callers[callindex].counts[freeindex * 4 + 3];
00319       }
00320       freeentries = 1 << callers[callindex].free_bits;
00321       for (totalfrees = 0, freeindex = 0; freeindex < freeentries;
00322         freeindex++)
00323       totalfrees += callers[callindex].free_list[freeindex].count;
00324       if (totalspace != 0 || totalfrees != 0) {
00325         tprintf ("alloc_mem at %d : total held=%d(%d), frees=%d.\n",
00326           callers[callindex].caller,
00327           totalchunks, totalspace * sizeof (MEMUNION),
00328           totalfrees);
00329       }
00330       if (totalspace > 0) {
00331         for (freeindex = 0; freeindex < buckets; freeindex++) {
00332           tprintf ("%d(%d) ",
00333             callers[callindex].counts[freeindex * 4],
00334             callers[callindex].counts[freeindex * 4 +
00335             1] * sizeof (MEMUNION));
00336         }
00337         tprintf ("\n");
00338       }
00339       if (totalfrees != 0) {
00340         tprintf ("Calls to free : ");
00341         for (freeindex = 0; freeindex < freeentries; freeindex++) {
00342           if (callers[callindex].free_list[freeindex].count != 0)
00343             tprintf ("%d : %d ",
00344               callers[callindex].free_list[freeindex].freeer,
00345               callers[callindex].free_list[freeindex].count);
00346         }
00347         tprintf ("\n");
00348       }
00349       if (totalpspace != 0) {
00350         tprintf ("alloc_mem_p at %d : total held=%d(%d).\n",
00351           callers[callindex].caller,
00352           totalpchunks, totalpspace * sizeof (MEMUNION));
00353         for (freeindex = 0; freeindex < buckets; freeindex++) {
00354           tprintf ("%d(%d) ",
00355             callers[callindex].counts[freeindex * 4 + 2],
00356             callers[callindex].counts[freeindex * 4 +
00357             3] * sizeof (MEMUNION));
00358         }
00359         tprintf ("\n");
00360       }
00361       free (callers[callindex].counts);
00362       callers[callindex].counts = NULL;
00363     }
00364   }
00365 }

UINT16 MEM_ALLOCATOR::hash_caller ( void *  addr  ) 

Generate a hash code for a caller, setup the tables if necessary.

Definition at line 117 of file memblk.cpp.

References call_bits, MALLOC_CALL::caller, callers, entries, hash(), init_callers(), MALLOC_CALL::init_freeers(), and NULL.

Referenced by set_owner().

00119                                    {
00120   INT32 index;                   //index to table
00121   INT32 initial_hash;            //initial index
00122 
00123   if (callers == NULL)
00124     init_callers();  //setup table
00125                                  //get hash code
00126   initial_hash = hash (call_bits, &addr, sizeof (addr));
00127   if (initial_hash == 0)
00128     initial_hash = 1;
00129   index = initial_hash;
00130   if (callers[index].caller != NULL && callers[index].caller != addr) {
00131     do {
00132       index++;
00133       if (index >= entries)
00134         index = 1;
00135     }
00136     while (callers[index].caller != NULL
00137       && callers[index].caller != addr && index != initial_hash);
00138     if (index == initial_hash)
00139       index = 0;
00140   }
00141   if (callers[index].caller == NULL) {
00142     if (index != 0)
00143       callers[index].caller = addr;
00144     if (callers[index].free_list == NULL)
00145                                  //setup free table
00146       callers[index].init_freeers ();
00147   }
00148   return (UINT16) index;
00149 }

void MEM_ALLOCATOR::init ( void *(*)(INT32 ext_malloc,
void(*)(void *)  ext_free,
INT32  firstsize,
INT32  lastsize,
INT32  maxchunk 
)

Constructor for a memory allocator.

Definition at line 88 of file memblk.cpp.

References biggestblock, blockcount, call_bits, callers, currblock, entries, free, malloc, malloc_auto_count, malloc_div_ratio, malloc_minor_serial, malloc_serial, maxsize, memsize, NULL, topblock, and totalmem.

Referenced by alloc_big_mem(), alloc_big_zeros(), alloc_mem(), and alloc_mem_p().

00094   {
00095   blockcount = 0;
00096   malloc_serial = 0;
00097   topblock = NULL;
00098   currblock = NULL;
00099   callers = NULL;
00100   malloc = ext_malloc;
00101   free = ext_free;
00102   maxsize = lastsize;
00103   biggestblock = maxchunk;
00104   totalmem = 0;
00105   memsize = firstsize;
00106   malloc_div_ratio = 1;
00107   malloc_minor_serial = 0;
00108   malloc_auto_count = 0;
00109   call_bits = 0;
00110   entries = 0;
00111 }

void MEM_ALLOCATOR::init_callers (  )  [private]

Initialize the callers hash table.

Definition at line 193 of file memblk.cpp.

References call_bits, callers, and entries.

Referenced by hash_caller().

00193                                  {  //setup hash table
00194   INT32 depth = mem_mallocdepth;
00195 
00196   mem_mallocdepth.set_value (0); //can't register it
00197   call_bits = mem_mallocbits;
00198   entries = 1 << call_bits;
00199                                  //make an array
00200   callers = new MALLOC_CALL[entries];
00201   mem_mallocdepth.set_value (depth);
00202 }

MEMBLOCK * MEM_ALLOCATOR::new_block ( INT32  minsize  ) 

Gets a new big block of memory from malloc for use by alloc_mem.

Definition at line 714 of file memblk.cpp.

References MEMUNION::age, blockcount, MEMBLOCK::blockend, MEMBLOCK::blockstart, check_mem(), currblock, ERRCODE::error(), MEMBLOCK::freechunk, LOG, MEMBLOCK::lowerspace, malloc, MAXBLOCKS, maxsize, memblocks, MEMCHECKS, memsize, MEMBLOCK::next, NOMOREBLOCKS, NOMOREMEM, NULL, MEMUNION::owner, MEMUNION::size, MEMBLOCK::topchunk, totalmem, tprintf(), trace_caller(), and MEMBLOCK::upperspace.

Referenced by alloc(), and alloc_p().

00716                                     {
00717   MEMBLOCK *newblock;            //new block
00718 
00719   if (blockcount >= MAXBLOCKS) {
00720                                  //can't have another
00721     NOMOREBLOCKS.error ("mem_new_block", LOG, NULL);
00722     return NULL;
00723   }
00724   if (mem_checkfreq != 0) {
00725     tprintf ("\nGetting new block due to request size of %d",
00726       minsize * sizeof (MEMUNION));
00727     tprintf (" from %d from %d from %d from %d from %d\n",
00728       trace_caller (3), trace_caller (4), trace_caller (5),
00729       trace_caller (6), trace_caller (7));
00730     check_mem ("Getting new block", MEMCHECKS);
00731   }
00732                                  //get a new one
00733   newblock = &memblocks[blockcount++];
00734   while (memsize < minsize)
00735     memsize *= 4;                //go up in sizes
00736                                  //get a big block
00737   newblock->blockstart = (MEMUNION *)
00738     malloc (memsize * sizeof (MEMUNION));
00739   if (newblock->blockstart == NULL) {
00740     NOMOREMEM.error ("mem_new_block", LOG, NULL);
00741 
00742     #ifdef __UNIX__
00743     raise(SIGTTOU);  //hangup for js
00744     #endif
00745     return NULL;
00746   }
00747                                  //end of block
00748   newblock->blockend = newblock->blockstart + memsize;
00749                                  //first free chunk
00750   newblock->freechunk = newblock->blockstart;
00751   newblock->topchunk = newblock->blockstart;
00752   newblock->lowerspace = 0;
00753   newblock->upperspace = memsize;//amount available
00754                                  //set pointer
00755   newblock->freechunk->size = memsize;
00756   newblock->freechunk->owner = 0;
00757   newblock->freechunk->age = 0;
00758 
00759   totalmem += memsize;           //total assigned mem
00760 
00761   if (memsize < maxsize)
00762     memsize *= 4;                //successively bigger
00763   if (currblock == NULL) {
00764     newblock->next = newblock;   //first block
00765   }
00766   else {
00767                                  //insert in list
00768     newblock->next = currblock->next;
00769     currblock->next = newblock;
00770   }
00771   return newblock;               //new block
00772 }

void MEM_ALLOCATOR::reduce_counts (  ) 

Divide all ages by 2 to get a log use of counts.

Definition at line 224 of file memblk.cpp.

References MEMUNION::age, blockcount, MEMBLOCK::blockend, MEMBLOCK::blockstart, check_mem(), JUSTCHECKS, memblocks, and MEMUNION::size.

Referenced by set_owner().

00224                                   {  //divide by 2
00225   MEMBLOCK *block;               //current block
00226   MEMUNION *chunk;               //current chunk
00227   INT32 chunksize;               //size of chunk
00228   INT32 blockindex;              //index of block
00229 
00230   check_mem ("Reducing counts", JUSTCHECKS);
00231   for (blockindex = 0; blockindex < blockcount; blockindex++) {
00232                                  //current block
00233     block = &memblocks[blockindex];
00234                                  //scan all chunks
00235     for (chunk = block->blockstart; chunk != block->blockend; chunk += chunksize) {
00236       chunksize = chunk->size;   //size of chunk
00237       if (chunksize < 0)
00238         chunksize = -chunksize;  //absolute size
00239       chunk->age /= 2;           //divide ages
00240     }
00241   }
00242 }

void MEM_ALLOCATOR::set_owner ( MEMUNION chunkstart,
void *  caller 
) [private]

Set the owner and time stamp of the block and check if needed.

Definition at line 629 of file memblk.cpp.

References MEMUNION::age, check_mem(), hash_caller(), malloc_auto_count, malloc_div_ratio, malloc_minor_serial, malloc_serial, MAX_INT16, MEMCHECKS, MEMUNION::owner, and reduce_counts().

Referenced by alloc(), and alloc_p().

00632                                {
00633   UINT16 callindex;              //hash code
00634 
00635   callindex = hash_caller (caller);
00636   chunkstart->owner = callindex;
00637                                  //store evidence
00638   chunkstart->age = malloc_serial;
00639   malloc_minor_serial++;
00640   if (malloc_minor_serial >= malloc_div_ratio) {
00641     malloc_minor_serial = 0;
00642     malloc_serial++;             //count calls
00643     if (malloc_serial == 0) {
00644                                  //wrap around
00645       reduce_counts();  //fix serial numbers
00646       malloc_serial = MAX_INT16 + 1;
00647                                  //all worth double
00648       malloc_div_ratio += malloc_div_ratio;
00649     }
00650   }
00651   malloc_auto_count++;
00652   if (mem_checkfreq > 0 && malloc_auto_count >= (UINT32) mem_checkfreq) {
00653     malloc_auto_count = 0;
00654     check_mem ("Auto check", MEMCHECKS);
00655   }
00656 }


Member Data Documentation

INT32 MEM_ALLOCATOR::biggestblock

Definition at line 129 of file memblk.h.

Referenced by alloc(), alloc_big_mem(), alloc_big_zeros(), alloc_mem(), alloc_mem_p(), alloc_p(), and init().

INT16 MEM_ALLOCATOR::blockcount

Definition at line 121 of file memblk.h.

Referenced by check(), display_counts(), init(), new_block(), and reduce_counts().

INT32 MEM_ALLOCATOR::call_bits

Definition at line 135 of file memblk.h.

Referenced by hash_caller(), init(), and init_callers().

MALLOC_CALL* MEM_ALLOCATOR::callers

Definition at line 125 of file memblk.h.

Referenced by dealloc(), display_counts(), free_big_mem(), free_mem(), hash_caller(), init(), and init_callers().

MEMBLOCK* MEM_ALLOCATOR::currblock

Definition at line 124 of file memblk.h.

Referenced by alloc(), alloc_p(), dealloc(), init(), and new_block().

INT32 MEM_ALLOCATOR::entries

Definition at line 136 of file memblk.h.

Referenced by display_counts(), hash_caller(), init(), and init_callers().

void(* MEM_ALLOCATOR::free)(void *)

Referenced by init().

void*(* MEM_ALLOCATOR::malloc)(INT32)

Referenced by display_counts(), init(), and new_block().

UINT32 MEM_ALLOCATOR::malloc_auto_count

Definition at line 134 of file memblk.h.

Referenced by init(), and set_owner().

UINT32 MEM_ALLOCATOR::malloc_div_ratio

Definition at line 132 of file memblk.h.

Referenced by display_counts(), init(), and set_owner().

UINT32 MEM_ALLOCATOR::malloc_minor_serial

Definition at line 133 of file memblk.h.

Referenced by init(), and set_owner().

UINT16 MEM_ALLOCATOR::malloc_serial

Definition at line 122 of file memblk.h.

Referenced by display_counts(), init(), and set_owner().

INT32 MEM_ALLOCATOR::maxsize

Definition at line 128 of file memblk.h.

Referenced by init(), and new_block().

MEMBLOCK MEM_ALLOCATOR::memblocks[MAXBLOCKS]

Definition at line 138 of file memblk.h.

Referenced by check(), display_counts(), new_block(), and reduce_counts().

INT32 MEM_ALLOCATOR::memsize

Definition at line 131 of file memblk.h.

Referenced by init(), and new_block().

MEMBLOCK* MEM_ALLOCATOR::topblock

Definition at line 123 of file memblk.h.

Referenced by alloc(), alloc_p(), and init().

INT32 MEM_ALLOCATOR::totalmem

Definition at line 130 of file memblk.h.

Referenced by alloc(), dealloc(), init(), and new_block().


The documentation for this class was generated from the following files:
Generated on Wed Feb 28 19:49:32 2007 for Tesseract by  doxygen 1.5.1