示例#1
0
/**
 * @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;
}
示例#2
0
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)));
}
示例#3
0
/* 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;
}
示例#4
0
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:	;

  }

}
示例#5
0
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");
}
示例#6
0
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);
}
示例#7
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);
}
示例#8
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);
}