[gclist] Possbile compatibilty problem with B-W GC and Win2000

wink wink@saville.com
Wed, 16 Jan 2002 20:14:27 -0800


Hello all,

I'd like to report a possible compatibility problem with the B-W GC
and Windows 2000. The problem occurs after a 256K block was coalesced
with a 1MB block in GC_freehblk and then when GC_remove_protection is
called the invocation of UNPROTECT causes an abort.

I was using gc_cpp and creating objects that were slightly larger
than 1mb with incremental mode enabled. The problem appears to be
that blocks allocated by VirtualAlloc can't have VirtualProtect
called when coalescing has occurred. A quick and dirty solution was
to change GC_freehblk as below, this causes GC_freehblk to never
coalesce blocks. This is probably not a good solution, but it appears
to work.

Who is current "maintaining" B-W GC for windows, I'd like to be sure
this information gets to them and hopefully we can create a proper
solution.


Thanks,

Wink Saville


/*
 * Free a heap block.
 *
 * Coalesce the block with its neighbors if possible.
 *
 * All mark words are assumed to be cleared.
 */
void
GC_freehblk(hbp)
struct hblk *hbp;
{
struct hblk *next, *prev;
hdr *hhdr, *prevhdr, *nexthdr;
signed_word size;


    GET_HDR(hbp, hhdr);
    size = hhdr->hb_sz;
    size = HBLKSIZE * OBJ_SZ_TO_BLOCKS(size);
    GC_remove_counts(hbp, (word)size);
    hhdr->hb_sz = size;
    
    /* Check for duplicate deallocation in the easy case */
      if (HBLK_IS_FREE(hhdr)) {
        GC_printf1("Duplicate large block deallocation of 0x%lx\n",
        	   (unsigned long) hbp);
	ABORT("Duplicate large block deallocation");
      }

    GC_ASSERT(IS_MAPPED(hhdr));
    GC_invalidate_map(hhdr);
    next = (struct hblk *)((word)hbp + size);
    GET_HDR(next, nexthdr);

#ifndef MSWIN32
    prev = GC_free_block_ending_at(hbp);
    /* Coalesce with successor, if possible */
      if(0 != nexthdr && HBLK_IS_FREE(nexthdr) && IS_MAPPED(nexthdr))
{
	GC_remove_from_fl(nexthdr, FL_UNKNOWN);
	hhdr -> hb_sz += nexthdr -> hb_sz; 
	GC_remove_header(next);
      }
    /* Coalesce with predecessor, if possible. */
      if (0 != prev) {
	prevhdr = HDR(prev);
	if (IS_MAPPED(prevhdr)) {
	  GC_remove_from_fl(prevhdr, FL_UNKNOWN);
	  prevhdr -> hb_sz += hhdr -> hb_sz;
	  GC_remove_header(hbp);
	  hbp = prev;
	  hhdr = prevhdr;
	}
      }
#endif
    GC_large_free_bytes += size;
    GC_add_to_fl(hbp, hhdr);    
}