/** * @internal * * FUNCTION: pcsl_end_memory() * TYPE: private operation * OVERVIEW: Finalize the PCSL memory pool * INTERFACE: * parameters: count address to store memory leak count * size address to store totol bytes of memory leaked * returns: the number of memory leaks detected * */ static int pcsl_end_memory(int* count, int* size) { _PcslMemHdrPtr pcslMemoryHdr; char* pcslMemoryPtr; *count = 0; *size = 0; for (pcslMemoryPtr = PcslMemoryStart; pcslMemoryPtr < PcslMemoryEnd; pcslMemoryPtr += pcslMemoryHdr->size + sizeof(_PcslMemHdr)) { pcslMemoryHdr = (_PcslMemHdrPtr)pcslMemoryPtr; if (pcslMemoryHdr->magic != MAGIC) { REPORT1("ERROR: Corrupted start of memory header: 0x%p\n", pcslMemoryPtr); return -1; } #ifdef PCSL_DEBUG if (pcslMemoryHdr->guard != GUARD_WORD) { report("ERROR: Corrupted end of memory header: 0x%p\n", pcslMemoryPtr); return -1; } /* The memory block header is valid, now check the guard data */ if (verify_tail_guard_data(pcslMemoryHdr)) { report("ERROR: Memory overrun: 0x%p\n", pcslMemoryPtr); print_alloc("allocated", pcslMemoryHdr->filename, pcslMemoryHdr->lineno); } #endif if (pcslMemoryHdr->free != 1) { #ifdef PCSL_DEBUG report("WARNING: memory leak: size= %d address= 0x%p\n", pcslMemoryHdr->size, (void*)((char*)pcslMemoryHdr + sizeof(_PcslMemHdr))); print_alloc("allocated", pcslMemoryHdr->filename, pcslMemoryHdr->lineno); #endif pcsl_mem_free((void*)((char*)pcslMemoryHdr + sizeof(_PcslMemHdr))); *count += 1; *size += pcslMemoryHdr->size; } } return *count; }
PTR Agc_refill_cache(ALLOC_CACHE *cache) { int elsize = (int)(cache-Agc_1alloc_cache+1) * WORDSIZE; REPORT1(7,"Agc_refill_cache(size=%d)\n",elsize); #ifdef A_DEBUG Agc_allocstat[elsize].refills++; #endif cache->free_elems = CACHE_SLOTS(elsize)-1; return (cache->area = Agc_nalloc(elsize,CACHE_SLOTS(elsize))); }
/* Set countMemoryLeaksOnly = 0 in order to get more verbose information */ int pcsl_mem_malloc_dump_impl0(int countMemoryLeaksOnly) { char *localpcslMallocMemPtr = NULL; char *localpcslMallocMemStart = PcslMemoryStart; char *localpcslMallocMemEnd = PcslMemoryEnd; _PcslMemHdrPtr localpcslMallocMemHdr = NULL; int numberOfAllocatedBlocks = 0; REPORT3("PcslMemory=0x%p PcslMemoryStart=0x%p PcslMemoryEnd=0x%p\n", PcslMemory, PcslMemoryStart, PcslMemoryEnd); for (localpcslMallocMemPtr = localpcslMallocMemStart; localpcslMallocMemPtr < localpcslMallocMemEnd; localpcslMallocMemPtr += localpcslMallocMemHdr->size + sizeof(_PcslMemHdr)) { localpcslMallocMemHdr = (_PcslMemHdrPtr) localpcslMallocMemPtr; if (localpcslMallocMemHdr->magic != MAGIC) { REPORT1("ERROR: memory corruption at 0x%p\n", localpcslMallocMemPtr); return -1; } else { if (countMemoryLeaksOnly == 0) { REPORT4("hdr 0x%p free=%d size=%d address=0x%p\n", localpcslMallocMemHdr, localpcslMallocMemHdr->free, localpcslMallocMemHdr->size, (void *)(((char *)localpcslMallocMemHdr) + sizeof(_PcslMemHdr))); } if (localpcslMallocMemHdr->free != 1) { numberOfAllocatedBlocks += 1; #ifdef PCSL_DEBUG report("WARNING: memory leak: size=%d address=0x%p\n", localpcslMallocMemHdr->size, (void*)((char*)localpcslMallocMemHdr + sizeof(_PcslMemHdr))); print_alloc("allocated", localpcslMallocMemHdr->filename, localpcslMallocMemHdr->lineno); #endif } } } return numberOfAllocatedBlocks; }
void Agc_sweep(SEGCTLPTR *heap_segments) { SEGCTLPTR segctlp, *segctlpp; ELPTR elp; CODEDPTR *elpp; GC_SWEEP(); for ( segctlpp = heap_segments; (segctlp = *segctlpp) != NIL; ) /* At end of loop so it can be skipped by continue: segctlpp = &((segctlp)->next ) */ { PTR elstart, elend; BITMAPPTR bitmap = segctlp->bitmap; PTR old_elend; ASSERT_DECL( PTR last_freestart ) REPORT6(5,"Agc_collect{free list reconstruct}: segctlp=0x%p, elsize=%d, start=0x%p, end=0x%p, size=%d,els=%d\n", (void *)segctlp,SEGELSIZE(segctlp),(void *)SEGSTART(segctlp),(void *)SEGEND(segctlp),SEGSIZE(segctlp),SEGELS(segctlp)); /* ** First, clear bitmap (to indicate unused) from free list. ** This is essential for the freelist reconstruction algorithm to work. ** It ensures that all free list elements are enclosed in an unused heap area ** as identified by the bitmap. */ /* ** Note that sweeping algorithm relies on the fact that the free list elements are ** in ascending address order, and there is some allocated space between elements. */ ASSERT(bitmap == segctlp->bitmap,Agc_collect,'bitmap' out of sync); ASSERT(TSTMARK(bitmap,SEGELS(segctlp)+0),Agc_collect,bitmap trailer clear); ASSERT(!TSTMARK(bitmap,SEGELS(segctlp)+1),Agc_collect,bitmap trailer set); ASSERT(TSTMARK(bitmap,SEGELS(segctlp)+2),Agc_collect,bitmap trailer clear); elpp = &segctlp->free; elp = DECODEPTR(*elpp); old_elend = SEGSTART( segctlp ); ASSERT_INIT( last_freestart = SEGSTART(segctlp) - 1 ); if ( elp != NIL ) { elstart = (PTR)elp; elend = (PTR)ELEND( elp, segctlp ); CHECK_EL( segctlp, elp, elend ); } else { elstart = elend = (char *)(SEGEND( segctlp )) + 1; /* well beyond any free space */ } for (;;) { PTR freestart, freeend; SIZE freed_bytes; ASSERT(elp == DECODEPTR(*elpp),Agc_collect,elpp and elp out of step); ASSERT(elp == NIL || ((PTR)elp >= (PTR)SEGSTART(segctlp) && (PTR)elp < (PTR)SEGEND(segctlp)) ,Agc_collect,elp not within segment); ASSERT(elp == NIL || ((PTR)ELEND(elp,segctlp) <= (PTR)SEGEND(segctlp)) ,Agc_collect,elp end not within segment); ASSERT(elp == NIL || elend > elstart,Agc_collect,empty free list element); /* ** First, set 'freestart' to be the start of either the next: ** ** free space starting outside a free list element ** or ** free space starting at the start of a free list element ** but finishing beyond the end of that element ** or ** an adress beyond the end of the segment */ SCAN_TO_CLR( freestart, segctlp, bitmap, old_elend, elstart ); ASSERT( freestart > last_freestart,Agc_collect,not progressing in sweep); ASSERT_INIT( last_freestart = freestart ); if ( freestart >= SEGEND( segctlp ) ) break; while ( freestart == elstart && TSTMARK( bitmap, ELNUM( elend, segctlp ) ) ) { /* ** Freespace is identical to free list element. ** Skip on to next free list element. */ ASSERT(freestart <= SEGEND(segctlp),Agc_collect,freestart beyond segend); /* step on to next free list element */ ASSERT(elp != NIL,Agc_collect,elp nil at elpp update); elpp = &elp->next; elp = DECODEPTR(*elpp); old_elend = elend; if ( elp != NIL ) { elstart = (PTR)elp; elend = (PTR)ELEND( elp, segctlp ); CHECK_EL( segctlp, elp, elend ); ASSERT(elend > elstart,Agc_collect,empty free list element); } else { elstart = elend = (char *)(SEGEND( segctlp )) + 1; /* well beyond any free space */ } ASSERT(old_elend < elstart,Agc_collect,free list not in order); SCAN_TO_CLR( freestart, segctlp, bitmap, old_elend, elstart ); } if ( freestart >= SEGEND( segctlp ) ) break; ASSERT(freestart == (PTR)SEGSTART( segctlp ) || freestart > old_elend,Agc_collect,freestart before old_elend); ASSERT(freestart <= elstart,Agc_collect,freestart > elstart); ASSERT(elp == NIL || elstart == (PTR)DECODEPTR(*elpp),Agc_collect,elstart != *elpp); /* ** Secondly, set 'freeend' to be the end of the freespace */ if ( freestart < elstart ) { SCAN_TO_SET( freeend, segctlp, bitmap, freestart, elstart ); freed_bytes = (char *)freeend - (char *)freestart; CLR_AT_FREE( freestart, SEGELSIZE(segctlp), freed_bytes ); } else { ASSERT(freestart == elstart,Agc_collect,freestart == elstart); freed_bytes = 0; freeend = freestart; } while ( freeend == elstart ) { /* step on to next free list element */ ASSERT(freeend <= SEGEND(segctlp),Agc_collect,freeend beyond segend); elp = DECODEPTR(elp->next); old_elend = elend; if ( elp != NIL ) { elend = (PTR)ELEND( elp, segctlp ); CLR_ELHEADER_AT_FREE( (ELPTR)elstart, SEGELSIZE(segctlp) ); elstart = (PTR)elp; CHECK_EL( segctlp, elp, elend ); ASSERT(elend > elstart,Agc_collect,empty free list element); } else { CLR_ELHEADER_AT_FREE( (ELPTR)elstart, SEGELSIZE(segctlp) ); elstart = elend = (char *)(SEGEND( segctlp )) + 1; /* well beyond any free space */ } ASSERT(old_elend < elstart,Agc_collect,free list not in order); ASSERT(freeend < elstart,Agc_collect,freeend not less than elstart); SCAN_TO_SET( freeend, segctlp, bitmap, old_elend, elstart ); ASSERT(freeend >= old_elend,Agc_collect,freeend before old_elend); ASSERT(freeend <= elstart,Agc_collect,freeend beyond elstart limit); ASSERT(freeend <= SEGEND(segctlp),Agc_collect,freeend beyond segend); if ( freeend != old_elend ) { freed_bytes += (char *)freeend - (char *)old_elend; CLR_AT_FREE( old_elend, SEGELSIZE(segctlp), (char *)freeend-(char *)old_elend ); } } ASSERT(freeend < elstart,Agc_collect,freeend beyond elstart); /* freestart -> freeend is the new element */ /* elp is freelist element beyond freeend, or NIL */ /* elpp points to el pointer before freestart */ ASSERT(freeend > freestart,Agc_collect,empty bitmap area); ASSERT(elp == NIL || (PTR)elp > freeend,Agc_collect,elp before freeend); ASSERT(freeend <= SEGEND(segctlp),Agc_collect,freeend beyond segend); ASSERT((PTR)elpp < freestart,Agc_collect,elpp beyond freestart); ASSERT(bitmap == segctlp->bitmap,Agc_collect,'bitmap' out of sync); ASSERT(TSTMARK(bitmap,SEGELS(segctlp)+0),Agc_collect,bitmap trailer clear); ASSERT(!TSTMARK(bitmap,SEGELS(segctlp)+1),Agc_collect,bitmap trailer set); ASSERT(TSTMARK(bitmap,SEGELS(segctlp)+2),Agc_collect,bitmap trailer clear); if ( freestart == SEGSTART( segctlp ) && freeend == SEGEND( segctlp ) ) { /* Whole segment is free */ /* +++ put segment at end of list rather than freeing */ REPORT1(3,"Agc_collect: freeing seg=0x%p\n",(void *)segctlp); ASSERT(bitmap == segctlp->bitmap,Agc_collect,'bitmap' out of sync); FREE_BITMAP( bitmap, SEGELS( segctlp ) + 3 ); ASSERT_INIT( segctlp->bitmap = bitmap = NIL ); *segctlpp = segctlp->next; /* remove segctlp from list */ Agc_b_allocated -= freed_bytes; Agc_s_grabbed--; Agc_b_grabbed -= SEGSIZE(segctlp); REP_DO(Agc_s_freed++); FREE_SEG( segctlp ); ASSERT_INIT( segctlp = NIL ); goto sweep_next_seg; } else if ( ELPTRENOUGH( freestart, freeend ) ) { #define freeelp ((ELPTR)freestart) /* care needed because of possible overlap between new and old element header */ REPORT5(6,"Agc_collect: adding free list element (0x%p -> 0x%p : size %d) after elpp 0x%p, before 0x%p\n", (void *)freestart,(void *)freeend,(char *)freeend-(char *)freestart,(void *)elpp,(void *)elp); ASSERT( IS_CLR(freestart,SEGELSIZE(segctlp),(char *)freeend-(char *)freestart) ,Agc_collect,recreated free list element not clear); ASSERT( ((char *)freeend - (char *)freestart) % SEGELSIZE( segctlp ) == 0,Agc_collect,space recovered not multiple of elsize); freeelp->next = ENCODEPTR( elp ); freeelp->elements = ((char *)freeend - (char *)freestart) / SEGELSIZE( segctlp ); ASSERT(DECODEPTR(*elpp) == NIL || (PTR)DECODEPTR(*elpp) >= freestart,Agc_collect,discarding space already in free list); *elpp = ENCODEPTR( freestart ); /* elp is still correct as next element, we have just inserted preceding it */ /* however elpp now needs to point at new element */ elpp = &freeelp->next; Agc_b_allocated -= freed_bytes; ASSERT( freeend == (PTR)ELEND(freeelp,segctlp) ,Agc_collect,freeend not ELEND); ASSERT( freeelp->next == CODEDNIL || DECODEPTR(freeelp->next) > ELEND(freeelp,segctlp) ,Agc_collect,free list elements overlap); ASSERT( freeelp->next == CODEDNIL || (PTR)DECODEPTR(freeelp->next) > freeend ,Agc_collect,freeelp->next not past freeend); #undef freeelp } /* else ( ! ELPTRENOUGH( freestart, freeend ) ) */ /* do nothing, forget the few bytes of free space we found */ old_elend = freeend; } #ifdef A_DEBUG if ( ELPTRENOUGH( (PTR)NIL, (char *)NIL+SEGELSIZE(segctlp) ) ) /* if ( SEGELSIZE(segctlp) >= sizeof( EL ) ) */ { SIZE i; elp = DECODEPTR( segctlp->free ); for ( i = 0; i < SEGELS(segctlp); i++ ) { if ( !TSTMARK(bitmap,i) ) { while ( i > ELNUM( ELEND( elp, segctlp ), segctlp ) ) { elp = DECODEPTR( elp->next ); ASSERT( elp != NIL,Agc_collect,free element beyond free list end at end of sweep); } ASSERT( i >= ELNUM( elp, segctlp ) && i < ELNUM( ELEND( elp, segctlp ), segctlp ),Agc_collect,free element not in free list at end of sweep); } } } #endif ASSERT(bitmap == segctlp->bitmap,Agc_collect,'bitmap' out of sync); FREE_BITMAP( bitmap, SEGELS( segctlp ) + 3 ); ASSERT_INIT( segctlp->bitmap = bitmap = NIL ); segctlpp = &((segctlp)->next); sweep_next_seg: ; } }
void Agc_trace( SEGCTLPTR *heap_segments ) { AREA heap; AREA area; /* The current area being traced */ TRACINGSTACK tstack; /* Stack of areas to be traced */ SEGCTLPTR segctlp; SEGCTLPTR *segctlpp; SIZE temp; #ifndef A_FUNNY_STEPAREAPTR /* cop-out for weird architectures */ { /* Check that STEPAREAPTR works correctly on this machine for this nastily aligned structure */ /* If C compiler does tight packing, this could be a problem for the garbage collector */ ASSERT_DECL( struct { PTR p1; char c; PTR p2; } *ass_struct = NIL ) ASSERT_INIT( ( area.addr = (PTR)&ass_struct->c , area.size = sizeof(*ass_struct) ) ); ASSERT_INIT( STEPAREA( area ) ); ASSERT(area.addr == (PTR)&ass_struct->p2,Agc_collect,STEPAREA misbehaving); } #endif heap.addr = SEGSTART( *heap_segments ); heap.size = 0 ;/* inital values to be improved in loop*/ REPORT1(3, "%s\n", "Started trace... setting up bitmaps..."); for ( segctlp = *heap_segments; segctlp != NIL; segctlp = segctlp->next ) { REPORT6(6,"Agc_collect{mark}: segctlp=0x%p, elsize=%d, start=0x%p, end=0x%p, size=%d,els=%d\n", (void *)segctlp,SEGELSIZE(segctlp),(void *)SEGSTART(segctlp),(void *)SEGEND(segctlp),SEGSIZE(segctlp),SEGELS(segctlp)); if ( ! ( SEGELSIZE( segctlp ) > 0 && (char *)SEGEND( segctlp ) > (char *)SEGSTART( segctlp ) ) ) { /* Segment control information has been corrupted. */ /* Most likely this is because of a user scope/bound error, or CTRANS bug; though possibly a collector bug. */ GC_ERROR(HEAP segments corrupt); } if ( (char *)SEGSTART( segctlp ) < (char *)(heap.addr) ) { heap.size += (SIZE)((char *)(heap.addr) - (char *)SEGSTART( segctlp )); heap.addr = SEGSTART( segctlp ); } if ( SEGEND( segctlp ) > (PTR)((char *)(heap.addr)+heap.size) ) heap.size = (SIZE)((char *)SEGEND( segctlp ) - (char*)(heap.addr)); GRAB_BITMAP( segctlp->bitmap, SEGELS( segctlp ) + 3 ); SETMARK( segctlp->bitmap, SEGELS( segctlp ) + 0 ); ASSERT(!TSTMARK(segctlp->bitmap,SEGELS(segctlp)+1),Agc_collect,bitmap trailer set at grab); SETMARK( segctlp->bitmap, SEGELS( segctlp ) + 2 ); /* create an artificial endpoint which can be scanned to */ REPORT2(6,"Agc_collect:\t\tbitmap, ptr=0x%p, size=%d\n", (void *)(segctlp->bitmap), SEGELS( segctlp )); } REPORT2(5,"Agc_collect: heap address=0x%p, heap size=%d\n",(void *)heap.addr,heap.size); INIT_STACK(tstack); ASSERT_INIT(PUSH(tstack,(PTR)Agc_collect,-42)); /* Assertion mark */ PUSH(tstack, NIL, 0); /* identifies exhausted stack */ REPORT1(3, "%s\n", "Initialising stack scan..."); INIT_AREA(area); /* set area to first area to search - could also PUSH any additional areas (or use NEXT_AREA) */ do { for ( ; !NILAREA(area); /* POP() at end of loop as it may contain statements */ ) { REPORT3(6,"Agc_collect: AREA scan, ptr=0x%p -> 0x%p, size=%d\n", (void *)area.addr,(void *)((char *)area.addr+area.size),area.size); ASSERT(area.size >= 0 && area.size < 100*1024*1024 /* 100Mb */,Agc_collect,area size not sensible); for ( ; area.size >= sizeof(PTR); STEPAREA(area) ) { SIZE els, el_in_seg; PTR p = * (PTR *) area.addr; /* View word as a pointer */ REPORT3(9,"Agc_collect: AREA scan step, ptr=0x%p, size=%d, p=0x%p\n", (void *)area.addr,area.size,(void *)p); /* Continue loop if 'p' is unlikely to be a heap pointer. */ /* Keeping the loop small may help some machines with small instruction caches. */ if ( !VALIDPTR( p ) || !PTRINAREA(p,heap) ) continue; /* p is very likely to be a heap pointer */ for ( segctlpp = heap_segments; (segctlp = *segctlpp) != NIL; segctlpp = &((segctlp)->next )) { if ( (char *)p >= (char *)SEGSTART(segctlp) && (char *)p < (char *)SEGEND(segctlp) ) { /* Segment for heap pointer */ goto found_segment; } } /* Not a valid heap pointer */ continue; /* back to STEPAREA loop */ found_segment: REPORT3(6,"Agc_collect, found_segment: ptr=0x%p, segctlp=0x%p, elsize=%d\n", (void *)p,(void *)segctlp,SEGELSIZE(segctlp)); /* ** Move segment to front of segment list, to effect a 'cacheing' as in allocation. ** We believe that there is locality in types of heap pointers, ** (consider lists and trees) so it is likely that next ** lookup will immediately succeed. ** However a fast search startegy might be better ??? ** ** Note that typical programs only have a small number of segs, ** many of which are infrequently used. ** Multics Algol68 compiler uses 12 segs; ** ELLA uses ??? segs. */ *segctlpp = segctlp->next; segctlp->next = *heap_segments; *heap_segments = segctlp; #ifdef MUST_POINT_TO_WORD /* * Ignore pointers that are not word aligned, * unless in a segment of objects of size that is not a multiple of word. */ if ( (SEGELSIZE(segctlp) & (WORDSIZE-1)) == 0 && (((CODEDPTR)(p) & (WORDSIZE-1)) != 0) ) continue; /* p not to word aligned object, forget it */ #endif #ifdef MUST_POINT_TO_LWORD /* * Ignore pointers that are not long word aligned, * unless in a segment of objects of size that is not a multiple of long word. */ if ( (SEGELSIZE(segctlp) & (sizeof(long)-1)) == 0 && (((CODEDPTR)(p) & (sizeof(long)-1)) != 0) ) continue; /* p not to long aligned object, forget it */ #endif IDENTIFY_ALIGN_EL( p, el_in_seg, segctlp ); #ifdef MUST_POINT_TO_START /* Ignore pointers that point within objects */ /* This could be implemented more efficiently */ if ( p != * (PTR *) area.addr ) continue; /* p not to start of element, forget it */ #endif #ifdef NO_GCMARK els = 1; #else ANAL_DESC( els, p, area ); #endif REPORT3(6,"Agc_collect, aligned and analysed ptr: ptr=0x%p, element in seg=%d, elements=%d\n", (void *)p,el_in_seg,els); #ifdef A_GC_HALFWORD_ALIGNED /* Interpret this as half word aligned (2byte) DJS 8/12/94 */ /* +++ !!! ??? ** Crappy quick fix to keep elements word aligned for the Apollo ** (also done for Sun/68000, though it has not been proved that this is necessary). ** Apollo does not permit word objects to be aligned at any byte boundry, ** even though 68020/68030 does. This must be because C compiler generates ** strange code, or page faults for words that straddle page boundries are ** handled badly. */ if ( SEGELSIZE(segctlp) == 1 ) { if ( (long)p & 1 ) { p--; el_in_seg--; els++; } if ( els & 1 ) { els++; } if ( els <= 1 || els > SEGELS(segctlp) || p+(els*SEGELSIZE(segctlp)) > SEGEND(segctlp) ) { els = 2; } REPORT3(6,"Agc_collect, adjusted to: ptr=0x%x, element in seg=%d, elements=%d\n", p,el_in_seg,els); goto els_sensible; } #endif #ifdef A_GC_WORD_ALIGNED /* +++ !!! ??? ** Crappy quick fix to keep elements word aligned. */ if ( SEGELSIZE(segctlp) == 1 ) { if ( !WORDALIGNED(p) ) { int offset = (int)((CODEDPTR)p & (WORDSIZE-1)); p = (char *)p - offset; el_in_seg -= offset; els += offset; } if ( !WORDALIGNED(els) ) { els = (SIZE)ALIGN_NEXT(els,WORDSIZE); } if ( (els < WORDSIZE) || (els > SEGELS(segctlp)) || ((char *)p+(els*SEGELSIZE(segctlp)) > (char *)SEGEND(segctlp) )) { els = WORDSIZE; } REPORT3(6,"Agc_collect, adjusted to: ptr=0x%p, element in seg=%d, elements=%d\n", (void *)p,el_in_seg,els); goto els_sensible; } #endif /* 'els' may be a very silly number, check it is reasonable */ /* before doing arithmetic that may overflow. */ if ( els <= 1 || els > SEGELS(segctlp) || (char *)p+(els*SEGELSIZE(segctlp)) > (char *)SEGEND(segctlp) ) { /* els = 1; assumed in case array descriptor mis analysed, the ptr is still valid */ if ( !TSTMARK( segctlp->bitmap, el_in_seg ) ) { SETMARK( segctlp->bitmap, el_in_seg ); if ( SEGELSIZE(segctlp) >= PTRSIZE ) { /* need only scan elements that are large enough to hold pointer */ PUSH( tstack, p, SEGELSIZE(segctlp) ); REPORT2(6,"Agc_collect: PUSH( ptr=0x%p, size=%d )\n", (void *)p,SEGELSIZE(segctlp)); } } } else { els_sensible: CALCTSTMARKS( segctlp->bitmap, el_in_seg, els, temp ); if ( !RESTSTMARKS( segctlp->bitmap, el_in_seg, els, temp ) ) { /* ** At least one element in area has not been marked before. ** ** We could just mark and push unmarked areas, ** but this complicates logic for a fairly rare eventuality, ** mainly caused by the trimming of heap rows. */ SETMARKS( segctlp->bitmap, el_in_seg, els ); if ( SEGELSIZE(segctlp) >= PTRSIZE ) { /* need only scan elements that are large enough to hold pointer */ PUSH( tstack, p, els*SEGELSIZE(segctlp) ); REPORT2(6,"Agc_collect: PUSH( ptr=0x%p, size=%d )\n", (void *)p,els*SEGELSIZE(segctlp)); } } } } area = POP(tstack); } /* Stack is exhausted, replace end marker */ PUSH(tstack, NIL, 0); /* identifies exhausted stack */ NEXT_AREA(area); REPORT2(6,"Agc_collect: NEXT_AREA, ptr=0x%p, size=%d\n",(void *)area.addr,area.size); } while( area.addr != NIL ); area = POP(tstack); /* pop of (NIL, 0) to leave stack empty and tidy before calling FREE_STACK() */ ASSERT_INIT( area=POP(tstack) ); ASSERT(area.addr == (PTR)Agc_collect && area.size == -42,Agc_collect,tracing stack misuse); FREE_STACK(tstack); REPORT1(3, "%s\n", "End of trace"); }
void* pcsl_mem_malloc_impl0(unsigned int size, char* filename, int lineno) { #else void* pcsl_mem_malloc_impl0(unsigned int size) { #endif unsigned int numBytesToAllocate = size; void* loc = NULL; _PcslMemHdrPtr tempHdr = NULL; char* temp = NULL; char* pcslMemoryPtr; _PcslMemHdrPtr pcslMemoryHdr; #ifdef PCSL_DEBUG int guardSize = 0; void* guardPos = NULL; int i = 0; numBytesToAllocate += GUARD_SIZE; #endif while ( (numBytesToAllocate & ALIGNMENT) != 0 ) { numBytesToAllocate++; } /* find a free slot */ for (pcslMemoryPtr = PcslMemoryStart; pcslMemoryPtr < PcslMemoryEnd; pcslMemoryPtr += pcslMemoryHdr->size + sizeof(_PcslMemHdr)) { pcslMemoryHdr = (_PcslMemHdrPtr)pcslMemoryPtr; if (pcslMemoryHdr->magic != MAGIC) { REPORT1("ERROR: Memory corruption at 0x%p\n", pcslMemoryPtr); return((void *) 0); } else { while ( 1 ) { /* coalescing */ if (pcslMemoryHdr->free == 1) { /* if current block is free */ temp = (char*)pcslMemoryHdr; temp += pcslMemoryHdr->size + sizeof(_PcslMemHdr); tempHdr = (_PcslMemHdrPtr)temp; if ((temp < PcslMemoryEnd) && (tempHdr->free == 1) && (tempHdr->magic == MAGIC)) { /* and the next block is free too */ /* then coalesce */ pcslMemoryHdr->size += tempHdr->size + sizeof(_PcslMemHdr); #ifdef PCSL_DEBUG pcslMemoryHdr->guardSize = 0; #endif REPORT2("DEBUG: Coalescing blocks 0x%p and 0x%p\n", pcslMemoryHdr, tempHdr); } else { break; } } else { break; } } /* while */ /* allocating */ if ((pcslMemoryHdr->free == 1) && (pcslMemoryHdr->size >= numBytesToAllocate)) { if (pcslMemoryHdr->size > (numBytesToAllocate + sizeof(_PcslMemHdr) + 4)) { /* split block */ _PcslMemHdrPtr nextHdr; nextHdr = (_PcslMemHdrPtr)((char *)pcslMemoryPtr + numBytesToAllocate + sizeof(_PcslMemHdr)); nextHdr->magic = MAGIC; nextHdr->free = 1; nextHdr->size = pcslMemoryHdr->size - numBytesToAllocate - sizeof(_PcslMemHdr); #ifdef PCSL_DEBUG nextHdr->guard = GUARD_WORD; nextHdr->guardSize = 0; #endif pcslMemoryHdr->size = numBytesToAllocate; } pcslMemoryHdr->free = 0; loc = (void*)((char*)pcslMemoryHdr + sizeof(_PcslMemHdr)); #ifdef PCSL_DEBUG pcslMemoryHdr->guard = GUARD_WORD; /* Add head guard */ pcslMemoryHdr->filename = filename; pcslMemoryHdr->lineno = lineno; /* Add tail guard */ guardSize = pcslMemoryHdr->size - size; pcslMemoryHdr->guardSize = guardSize; guardPos = (void*)((char*)loc + pcslMemoryHdr->size - guardSize); for(i=0; i<guardSize; i++) { ((unsigned char*)guardPos)[i] = GUARD_BYTE; } PcslMemoryAllocated += numBytesToAllocate; if (PcslMemoryAllocated > PcslMemoryHighWaterMark) { PcslMemoryHighWaterMark = PcslMemoryAllocated; } report("DEBUG: Requested %d provided %d at 0x%p\n", numBytesToAllocate, pcslMemoryHdr->size, loc); print_alloc("allocated", filename, lineno); #endif return(loc); } /* end of allocating */ } /* end of else */ } /* end of for */ REPORT1("DEBUG: Unable to allocate %d bytes\n", numBytesToAllocate); return((void *)0); }
void main (int argc, string argv[]) { int code; string font_name = read_command_line (argc, argv); bitmap_font_type f = get_bitmap_font (font_name, atou (dpi)); string font_basename = basename (font_name); /* Initializing the display might involve forking a process. We wouldn't want that process to get copies of open output files, since then when it exited, random stuff might get written to the end of the file. */ init_display (f); if (logging) log_file = xfopen (concat (font_basename, ".log"), "w"); if (strlen (BITMAP_FONT_COMMENT (f)) > 0) REPORT1 ("{%s}\n", BITMAP_FONT_COMMENT (f)); if (output_name == NULL) output_name = font_basename; bzr_start_output (output_name, f); /* The main loop: for each character, find the outline of the shape, then fit the splines to it. */ for (code = starting_char; code <= ending_char; code++) { pixel_outline_list_type pixels; spline_list_array_type splines; char_info_type *c = get_char (font_name, code); if (c == NULL) continue; REPORT1 ("[%u ", code); if (logging) { LOG ("\n\n\f"); print_char (log_file, *c); } x_start_char (*c); pixels = find_outline_pixels (*c); /* `find_outline_pixels' uses corners as the coordinates, instead of the pixel centers. So we have to increase the bounding box. */ CHAR_MIN_COL (*c)--; CHAR_MAX_COL (*c)++; CHAR_MIN_ROW (*c)--; CHAR_MAX_ROW (*c)++; REPORT ("|"); splines = fitted_splines (pixels); bzr_output_char (*c, splines); /* Flush output before displaying the character, in case the user is interested in looking at it and the online version simultaneously. */ flush_log_output (); x_output_char (*c, splines); REPORT ("]\n"); /* If the character was empty, it won't have a bitmap. */ if (BITMAP_BITS (CHAR_BITMAP (*c)) != NULL) free_bitmap (&CHAR_BITMAP (*c)); free_pixel_outline_list (&pixels); free_spline_list_array (&splines); } bzr_finish_output (); close_display (); close_font (font_name); exit (0); }
void main (unsigned argc, string argv[]) { bzr_preamble_type preamble; bzr_postamble_type postamble; tfm_char_type *tfm_chars; tfm_global_info_type tfm_info; string tfm_name; unsigned this_char; unsigned char_count = 0; string font_name = read_command_line (argc, argv); string font_basename = basename (font_name); string bzr_name = concat (font_name, ".bzr"); if (!bzr_open_input_file (bzr_name)) FATAL1 ("%s: Could not find BZR file", font_name); tfm_name = find_tfm_filename (font_name); if (tfm_name == NULL || !tfm_open_input_file (tfm_name)) FATAL1 ("%s: Could not find TFM file", font_name); preamble = bzr_get_preamble (); postamble = bzr_get_postamble (); tfm_info = tfm_get_global_info (); tfm_chars = tfm_get_chars (); if (output_name == NULL) output_name = strtok (xstrdup (font_basename), "0123456789"); else if (find_suffix (output_name) != NULL && ((output[metafont] && output[pstype1]) || (output[metafont] && output[pstype3]) || (output[pstype1] && output[pstype3]))) FATAL ("You can't specify all the output files' suffices to be the same"); if (output[metafont]) metafont_start_output (output_name, preamble, tfm_info); if (output[pstype1]) pstype1_start_output (font_basename, output_name, preamble, postamble, tfm_info); if (output[pstype3]) pstype3_start_output (font_basename, output_name, preamble, postamble, tfm_info); if (output[text]) text_start_output (font_basename, preamble); for (this_char = 0; this_char <= MAX_CHARCODE; this_char++) { bzr_char_type *c = bzr_get_char (this_char); if (c != NULL) { REPORT1 ("[%u", this_char); BZR_SHAPE (*c) = oblique_splines (BZR_SHAPE (*c)); if (output[metafont]) metafont_output_char (*c); if (output[pstype1]) pstype1_output_char (*c); if (output[pstype3]) pstype3_output_char (*c); if (output[text]) text_output_char (*c); REPORT1 ("]%c", ++char_count % 8 ? ' ' : '\n'); } } if (output[metafont]) metafont_finish_output (tfm_chars); if (output[pstype1]) pstype1_finish_output (); if (output[pstype3]) pstype3_finish_output (); if (output[text]) text_finish_output (postamble); if (char_count % 8 != 0) REPORT ("\n"); bzr_close_input_file (); tfm_close_input_file (); exit (0); }