[BACK]Return to gc_priv.h CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / gc / include / private

Diff for /OpenXM_contrib2/asir2000/gc/include/private/gc_priv.h between version 1.2 and 1.3

version 1.2, 2000/04/10 08:31:36 version 1.3, 2001/04/20 07:39:26
Line 2 
Line 2 
  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers   * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.   * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
  * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.   * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.
  * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.   * Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved.
  *   *
  *   *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED   * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
Line 14 
Line 14 
  * provided the above notices are retained, and a notice that the code was   * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.   * modified is included with the above copyright notice.
  */   */
 /* Boehm, February 16, 1996 2:30 pm PST */  
   
   
 # ifndef GC_PRIVATE_H  # ifndef GC_PRIVATE_H
Line 41 
Line 40 
 #   include "gc.h"  #   include "gc.h"
 # endif  # endif
   
 typedef GC_word word;  # ifndef GC_MARK_H
 typedef GC_signed_word signed_word;  #   include "../gc_mark.h"
   # endif
   
 # ifndef CONFIG_H  # ifndef GCCONFIG_H
 #   include "gcconfig.h"  #   include "gcconfig.h"
 # endif  # endif
   
 # ifndef HEADERS_H  typedef GC_word word;
 #   include "gc_hdrs.h"  typedef GC_signed_word signed_word;
 # endif  
   
 typedef int GC_bool;  typedef int GC_bool;
 # define TRUE 1  # define TRUE 1
Line 61  typedef char * ptr_t; /* A generic pointer to which we
Line 60  typedef char * ptr_t; /* A generic pointer to which we
                         /* Preferably identical to caddr_t, if it       */                          /* Preferably identical to caddr_t, if it       */
                         /* exists.                                      */                          /* exists.                                      */
   
   # ifndef HEADERS_H
   #   include "gc_hdrs.h"
   # endif
   
 #if defined(__STDC__)  #if defined(__STDC__)
 #   include <stdlib.h>  #   include <stdlib.h>
 #   if !(defined( sony_news ) )  #   if !(defined( sony_news ) )
Line 74  typedef char * ptr_t; /* A generic pointer to which we
Line 77  typedef char * ptr_t; /* A generic pointer to which we
 #   define VOLATILE  #   define VOLATILE
 #endif  #endif
   
 #define CONST GC_CONST  #if 0 /* defined(__GNUC__) doesn't work yet */
   # define EXPECT(expr, outcome) __builtin_expect(expr,outcome)
     /* Equivalent to (expr), but predict that usually (expr)==outcome. */
   #else
   # define EXPECT(expr, outcome) (expr)
   #endif /* __GNUC__ */
   
 #if 0 /* was once defined for AMIGA */  # ifndef GC_LOCKS_H
   #   include "gc_locks.h"
   # endif
   
   # ifdef STACK_GROWS_DOWN
   #   define COOLER_THAN >
   #   define HOTTER_THAN <
   #   define MAKE_COOLER(x,y) if ((word)(x)+(y) > (word)(x)) {(x) += (y);} \
                               else {(x) = (word)ONES;}
   #   define MAKE_HOTTER(x,y) (x) -= (y)
   # else
   #   define COOLER_THAN <
   #   define HOTTER_THAN >
   #   define MAKE_COOLER(x,y) if ((word)(x)-(y) < (word)(x)) {(x) -= (y);} else {(x) = 0;}
   #   define MAKE_HOTTER(x,y) (x) += (y)
   # endif
   
   #if defined(AMIGA) && defined(__SASC)
 #   define GC_FAR __far  #   define GC_FAR __far
 #else  #else
 #   define GC_FAR  #   define GC_FAR
 #endif  #endif
   
   
 /*********************************/  /*********************************/
 /*                               */  /*                               */
 /* Definitions for conservative  */  /* Definitions for conservative  */
Line 95  typedef char * ptr_t; /* A generic pointer to which we
Line 121  typedef char * ptr_t; /* A generic pointer to which we
 /*                               */  /*                               */
 /*********************************/  /*********************************/
   
 #define STUBBORN_ALLOC  /* Define stubborn allocation primitives        */  /* #define STUBBORN_ALLOC */
 #if defined(SRC_M3) || defined(SMALL_CONFIG)                      /* Enable stubborm allocation, and thus a limited   */
 # undef STUBBORN_ALLOC                      /* form of incremental collection w/o dirty bits.   */
 #endif  
   
   
 /* #define ALL_INTERIOR_POINTERS */  /* #define ALL_INTERIOR_POINTERS */
                     /* Forces all pointers into the interior of an      */                      /* Forces all pointers into the interior of an      */
                     /* object to be considered valid.  Also causes the  */                      /* object to be considered valid.  Also causes the  */
Line 126  typedef char * ptr_t; /* A generic pointer to which we
Line 150  typedef char * ptr_t; /* A generic pointer to which we
                     /*    touched.                                      */                      /*    touched.                                      */
                     /* If you can easily avoid using this option, do.   */                      /* If you can easily avoid using this option, do.   */
                     /* If not, try to keep individual objects small.    */                      /* If not, try to keep individual objects small.    */
                       /* This is now really controlled at startup,        */
                       /* through GC_all_interior_pointers.                */
   
 #define PRINTSTATS  /* Print garbage collection statistics              */  #define PRINTSTATS  /* Print garbage collection statistics              */
                     /* For less verbose output, undefine in reclaim.c   */                      /* For less verbose output, undefine in reclaim.c   */
Line 156  typedef char * ptr_t; /* A generic pointer to which we
Line 182  typedef char * ptr_t; /* A generic pointer to which we
 #   define GATHERSTATS  #   define GATHERSTATS
 #endif  #endif
   
 #ifdef FINALIZE_ON_DEMAND  #if defined(PRINTSTATS) || !defined(SMALL_CONFIG)
 #   define GC_INVOKE_FINALIZERS()  #   define CONDPRINT  /* Print some things if GC_print_stats is set */
 #else  
 #   define GC_INVOKE_FINALIZERS() (void)GC_invoke_finalizers()  
 #endif  #endif
   
   #define GC_INVOKE_FINALIZERS() GC_notify_or_invoke_finalizers()
   
 #define MERGE_SIZES /* Round up some object sizes, so that fewer distinct */  #define MERGE_SIZES /* Round up some object sizes, so that fewer distinct */
                     /* free lists are actually maintained.  This applies  */                      /* free lists are actually maintained.  This applies  */
                     /* only to the top level routines in misc.c, not to   */                      /* only to the top level routines in misc.c, not to   */
Line 173  typedef char * ptr_t; /* A generic pointer to which we
Line 199  typedef char * ptr_t; /* A generic pointer to which we
                     /* May save significant amounts of space for obj_map  */                      /* May save significant amounts of space for obj_map  */
                     /* entries.                                           */                      /* entries.                                           */
   
 #ifndef OLD_BLOCK_ALLOC  #if defined(USE_MARK_BYTES) && !defined(ALIGN_DOUBLE)
    /* Macros controlling large block allocation strategy.       */  #  define ALIGN_DOUBLE
 #  define EXACT_FIRST   /* Make a complete pass through the large object */     /* We use one byte for every 2 words, which doesn't allow for        */
                         /* free list before splitting a block            */     /* odd numbered words to have mark bits.                             */
 #  define PRESERVE_LAST /* Do not divide last allocated heap segment     */  
                         /* unless we would otherwise need to expand the  */  
                         /* heap.                                         */  
 #endif  #endif
   
 /* ALIGN_DOUBLE requires MERGE_SIZES at present. */  /* ALIGN_DOUBLE requires MERGE_SIZES at present. */
Line 187  typedef char * ptr_t; /* A generic pointer to which we
Line 210  typedef char * ptr_t; /* A generic pointer to which we
 #   define MERGE_SIZES  #   define MERGE_SIZES
 # endif  # endif
   
 #if defined(ALL_INTERIOR_POINTERS) && !defined(DONT_ADD_BYTE_AT_END)  #if !defined(DONT_ADD_BYTE_AT_END)
 # define ADD_BYTE_AT_END  # define EXTRA_BYTES GC_all_interior_pointers
   #else
   # define EXTRA_BYTES 0
 #endif  #endif
   
   
 # ifndef LARGE_CONFIG  # ifndef LARGE_CONFIG
 #   define MINHINCR 16  /* Minimum heap increment, in blocks of HBLKSIZE  */  #   define MINHINCR 16   /* Minimum heap increment, in blocks of HBLKSIZE  */
                         /* Must be multiple of largest page size.         */                           /* Must be multiple of largest page size.         */
 #   define MAXHINCR 512 /* Maximum heap increment, in blocks              */  #   define MAXHINCR 2048 /* Maximum heap increment, in blocks              */
 # else  # else
 #   define MINHINCR 64  #   define MINHINCR 64
 #   define MAXHINCR 4096  #   define MAXHINCR 4096
Line 228  typedef char * ptr_t; /* A generic pointer to which we
Line 253  typedef char * ptr_t; /* A generic pointer to which we
  * Number of frames and arguments to save in objects allocated by   * Number of frames and arguments to save in objects allocated by
  * debugging allocator.   * debugging allocator.
  */   */
 #   define NFRAMES 6    /* Number of frames to save. Even for           */  #   ifndef SAVE_CALL_COUNT
   #     define NFRAMES 6  /* Number of frames to save. Even for           */
                         /* alignment reasons.                           */                          /* alignment reasons.                           */
   #   else
   #     define NFRAMES ((SAVE_CALL_COUNT + 1) & ~1)
   #   endif
 #   define NARGS 2      /* Mumber of arguments to save for each call.   */  #   define NARGS 2      /* Mumber of arguments to save for each call.   */
   
 #   define NEED_CALLINFO  #   define NEED_CALLINFO
   
 /* Fill in the pc and argument information for up to NFRAMES of my      */  /* Fill in the pc and argument information for up to NFRAMES of my      */
 /* callers.  Ignore my frame and my callers frame.                      */  /* callers.  Ignore my frame and my callers frame.                      */
 void GC_save_callers (/* struct callinfo info[NFRAMES] */);  struct callinfo;
   void GC_save_callers GC_PROTO((struct callinfo info[NFRAMES]));
   
   void GC_print_callers GC_PROTO((struct callinfo info[NFRAMES]));
   
 void GC_print_callers (/* struct callinfo info[NFRAMES] */);  
   
 #else  #else
   
 # ifdef GC_ADD_CALLER  # ifdef GC_ADD_CALLER
Line 252  void GC_print_callers (/* struct callinfo info[NFRAMES
Line 282  void GC_print_callers (/* struct callinfo info[NFRAMES
   
 #ifdef NEED_CALLINFO  #ifdef NEED_CALLINFO
     struct callinfo {      struct callinfo {
         word ci_pc;          word ci_pc;     /* Caller, not callee, pc       */
 #       if NARGS > 0  #       if NARGS > 0
             word ci_arg[NARGS]; /* bit-wise complement to avoid retention */              word ci_arg[NARGS]; /* bit-wise complement to avoid retention */
 #       endif  #       endif
Line 281  void GC_print_callers (/* struct callinfo info[NFRAMES
Line 311  void GC_print_callers (/* struct callinfo info[NFRAMES
 #   define MS_TIME_DIFF(a,b) ((double) (a.tv_sec - b.tv_sec) * 1000.0 \  #   define MS_TIME_DIFF(a,b) ((double) (a.tv_sec - b.tv_sec) * 1000.0 \
                                + (double) (a.tv_usec - b.tv_usec) / 1000.0)                                 + (double) (a.tv_usec - b.tv_usec) / 1000.0)
 #else /* !BSD_TIME */  #else /* !BSD_TIME */
   # if defined(MSWIN32) || defined(MSWINCE)
   #   include <windows.h>
   #   include <winbase.h>
   #   define CLOCK_TYPE DWORD
   #   define GET_TIME(x) x = GetTickCount()
   #   define MS_TIME_DIFF(a,b) ((long)((a)-(b)))
   # else /* !MSWIN32, !MSWINCE, !BSD_TIME */
 #   include <time.h>  #   include <time.h>
 #   if !defined(__STDC__) && defined(SPARC) && defined(SUNOS4)  #   if !defined(__STDC__) && defined(SPARC) && defined(SUNOS4)
       clock_t clock();  /* Not in time.h, where it belongs      */        clock_t clock();  /* Not in time.h, where it belongs      */
Line 306  void GC_print_callers (/* struct callinfo info[NFRAMES
Line 343  void GC_print_callers (/* struct callinfo info[NFRAMES
 #   define GET_TIME(x) x = clock()  #   define GET_TIME(x) x = clock()
 #   define MS_TIME_DIFF(a,b) ((unsigned long) \  #   define MS_TIME_DIFF(a,b) ((unsigned long) \
                 (1000.0*(double)((a)-(b))/(double)CLOCKS_PER_SEC))                  (1000.0*(double)((a)-(b))/(double)CLOCKS_PER_SEC))
   # endif /* !MSWIN32 */
 #endif /* !BSD_TIME */  #endif /* !BSD_TIME */
   
 /* We use bzero and bcopy internally.  They may not be available.       */  /* We use bzero and bcopy internally.  They may not be available.       */
Line 325  void GC_print_callers (/* struct callinfo info[NFRAMES
Line 363  void GC_print_callers (/* struct callinfo info[NFRAMES
 #   include <string.h>  #   include <string.h>
 #   define BCOPY_EXISTS  #   define BCOPY_EXISTS
 # endif  # endif
   # if defined(MACOSX)
   #   define BCOPY_EXISTS
   # endif
   
 # ifndef BCOPY_EXISTS  # ifndef BCOPY_EXISTS
 #   include <string.h>  #   include <string.h>
Line 342  void GC_print_callers (/* struct callinfo info[NFRAMES
Line 383  void GC_print_callers (/* struct callinfo info[NFRAMES
 /* GET_MEM is currently not assumed to retrieve 0 filled space, */  /* GET_MEM is currently not assumed to retrieve 0 filled space, */
 /* though we should perhaps take advantage of the case in which */  /* though we should perhaps take advantage of the case in which */
 /* does.                                                        */  /* does.                                                        */
   struct hblk;    /* See below.   */
 # ifdef PCR  # ifdef PCR
     char * real_malloc();      char * real_malloc();
 #   define GET_MEM(bytes) HBLKPTR(real_malloc((size_t)bytes + GC_page_size) \  #   define GET_MEM(bytes) HBLKPTR(real_malloc((size_t)bytes + GC_page_size) \
Line 353  void GC_print_callers (/* struct callinfo info[NFRAMES
Line 395  void GC_print_callers (/* struct callinfo info[NFRAMES
                                     + GC_page_size) \                                      + GC_page_size) \
                                     + GC_page_size-1)                                      + GC_page_size-1)
 #   else  #   else
 #     if defined(AMIGA) || defined(NEXT) || defined(MACOSX) || defined(DOS4GW)  #     if defined(NEXT) || defined(MACOSX) || defined(DOS4GW) || \
            (defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC))
 #       define GET_MEM(bytes) HBLKPTR((size_t) \  #       define GET_MEM(bytes) HBLKPTR((size_t) \
                                       calloc(1, (size_t)bytes + GC_page_size) \                                        calloc(1, (size_t)bytes + GC_page_size) \
                                       + GC_page_size-1)                                        + GC_page_size-1)
Line 374  void GC_print_callers (/* struct callinfo info[NFRAMES
Line 417  void GC_print_callers (/* struct callinfo info[NFRAMES
                         NewPtrClear(bytes + GC_page_size) + GC_page_size-1)                          NewPtrClear(bytes + GC_page_size) + GC_page_size-1)
 #           endif  #           endif
 #         else  #         else
               extern ptr_t GC_unix_get_mem();  #           ifdef MSWINCE
 #             define GET_MEM(bytes) (struct hblk *)GC_unix_get_mem(bytes)                extern ptr_t GC_wince_get_mem();
   #             define GET_MEM(bytes) (struct hblk *)GC_wince_get_mem(bytes)
   #           else
   #             if defined(AMIGA) && defined(GC_AMIGA_FASTALLOC)
                   extern void *GC_amiga_get_mem(size_t size);
                   define GET_MEM(bytes) HBLKPTR((size_t) \
                     GC_amiga_get_mem((size_t)bytes + GC_page_size) \
                     + GC_page_size-1)
   #             else
                   extern ptr_t GC_unix_get_mem();
   #               define GET_MEM(bytes) (struct hblk *)GC_unix_get_mem(bytes)
   #             endif
   #           endif
 #         endif  #         endif
 #       endif  #       endif
 #     endif  #     endif
 #   endif  #   endif
 # endif  # endif
   
 /*  
  * Mutual exclusion between allocator/collector routines.  
  * Needed if there is more than one allocator thread.  
  * FASTLOCK() is assumed to try to acquire the lock in a cheap and  
  * dirty way that is acceptable for a few instructions, e.g. by  
  * inhibiting preemption.  This is assumed to have succeeded only  
  * if a subsequent call to FASTLOCK_SUCCEEDED() returns TRUE.  
  * FASTUNLOCK() is called whether or not FASTLOCK_SUCCEEDED().  
  * If signals cannot be tolerated with the FASTLOCK held, then  
  * FASTLOCK should disable signals.  The code executed under  
  * FASTLOCK is otherwise immune to interruption, provided it is  
  * not restarted.  
  * DCL_LOCK_STATE declares any local variables needed by LOCK and UNLOCK  
  * and/or DISABLE_SIGNALS and ENABLE_SIGNALS and/or FASTLOCK.  
  * (There is currently no equivalent for FASTLOCK.)  
  */  
 # ifdef THREADS  
 #  ifdef PCR_OBSOLETE   /* Faster, but broken with multiple lwp's       */  
 #    include  "th/PCR_Th.h"  
 #    include  "th/PCR_ThCrSec.h"  
      extern struct PCR_Th_MLRep GC_allocate_ml;  
 #    define DCL_LOCK_STATE  PCR_sigset_t GC_old_sig_mask  
 #    define LOCK() PCR_Th_ML_Acquire(&GC_allocate_ml)  
 #    define UNLOCK() PCR_Th_ML_Release(&GC_allocate_ml)  
 #    define FASTLOCK() PCR_ThCrSec_EnterSys()  
      /* Here we cheat (a lot): */  
 #        define FASTLOCK_SUCCEEDED() (*(int *)(&GC_allocate_ml) == 0)  
                 /* TRUE if nobody currently holds the lock */  
 #    define FASTUNLOCK() PCR_ThCrSec_ExitSys()  
 #  endif  
 #  ifdef PCR  
 #    include <base/PCR_Base.h>  
 #    include <th/PCR_Th.h>  
      extern PCR_Th_ML GC_allocate_ml;  
 #    define DCL_LOCK_STATE \  
          PCR_ERes GC_fastLockRes; PCR_sigset_t GC_old_sig_mask  
 #    define LOCK() PCR_Th_ML_Acquire(&GC_allocate_ml)  
 #    define UNLOCK() PCR_Th_ML_Release(&GC_allocate_ml)  
 #    define FASTLOCK() (GC_fastLockRes = PCR_Th_ML_Try(&GC_allocate_ml))  
 #    define FASTLOCK_SUCCEEDED() (GC_fastLockRes == PCR_ERes_okay)  
 #    define FASTUNLOCK()  {\  
         if( FASTLOCK_SUCCEEDED() ) PCR_Th_ML_Release(&GC_allocate_ml); }  
 #  endif  
 #  ifdef SRC_M3  
      extern word RT0u__inCritical;  
 #    define LOCK() RT0u__inCritical++  
 #    define UNLOCK() RT0u__inCritical--  
 #  endif  
 #  ifdef SOLARIS_THREADS  
 #    include <thread.h>  
 #    include <signal.h>  
      extern mutex_t GC_allocate_ml;  
 #    define LOCK() mutex_lock(&GC_allocate_ml);  
 #    define UNLOCK() mutex_unlock(&GC_allocate_ml);  
 #  endif  
 #  ifdef LINUX_THREADS  
 #    include <pthread.h>  
 #    if defined(I386)  
        inline static int GC_test_and_set(volatile unsigned int *addr) {  
           int oldval;  
           /* Note: the "xchg" instruction does not need a "lock" prefix */  
           __asm__ __volatile__("xchgl %0, %1"  
                 : "=r"(oldval), "=m"(*(addr))  
                 : "0"(1), "m"(*(addr)));  
           return oldval;  
        }  
 #    else  
 #     if defined(POWERPC)  
        inline static int GC_test_and_set(volatile unsigned int *addr) {  
         int oldval;  
         int temp = 1; // locked value  
   
         __asm__ __volatile__(  
                "1:\tlwarx %0,0,%3\n"   // load and reserve  
                "\tcmpwi %0, 0\n"       // if load is  
                "\tbne 2f\n"            //   non-zero, return already set  
                "\tstwcx. %2,0,%1\n"    // else store conditional  
                "\tbne- 1b\n"           // retry if lost reservation  
                "2:\t\n"                // oldval is zero if we set  
               : "=&r"(oldval), "=p"(addr)  
               : "r"(temp), "1"(addr)  
               : "memory");  
         return (int)oldval;  
        }  
 #     else  
 #      ifdef ALPHA  
          inline static int GC_test_and_set(volatile unsigned int *  
 addr)  
          {  
            unsigned long oldvalue;  
            unsigned long temp;  
   
            __asm__ __volatile__(  
                                 "1:     ldl_l %0,%1\n"  
                                 "       and %0,%3,%2\n"  
                                 "       bne %2,2f\n"  
                                 "       xor %0,%3,%0\n"  
                                 "       stl_c %0,%1\n"  
                                 "       beq %0,3f\n"  
                                 "       mb\n"  
                                 "2:\n"  
                                 ".section .text2,\"ax\"\n"  
                                 "3:     br 1b\n"  
                                 ".previous"  
                                 :"=&r" (temp), "=m" (*addr), "=&r"  
 (oldvalue)  
                                 :"Ir" (1), "m" (*addr));  
   
            return oldvalue;  
          }  
 #      else  
          -- > Need implementation of GC_test_and_set()  
 #      endif  
 #     endif  
 #    endif  
      inline static void GC_clear(volatile unsigned int *addr) {  
           *(addr) = 0;  
      }  
   
      extern volatile unsigned int GC_allocate_lock;  
         /* This is not a mutex because mutexes that obey the (optional)     */  
         /* POSIX scheduling rules are subject to convoys in high contention */  
         /* applications.  This is basically a spin lock.                    */  
      extern pthread_t GC_lock_holder;  
      extern void GC_lock(void);  
         /* Allocation lock holder.  Only set if acquired by client through */  
         /* GC_call_with_alloc_lock.                                        */  
 #    define SET_LOCK_HOLDER() GC_lock_holder = pthread_self()  
 #    define NO_THREAD (pthread_t)(-1)  
 #    define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD  
 #    define I_HOLD_LOCK() (pthread_equal(GC_lock_holder, pthread_self()))  
 #    define LOCK() \  
                 { if (GC_test_and_set(&GC_allocate_lock)) GC_lock(); }  
 #    define UNLOCK() \  
                 GC_clear(&GC_allocate_lock)  
      extern GC_bool GC_collecting;  
 #    define ENTER_GC() \  
                 { \  
                     GC_collecting = 1; \  
                 }  
 #    define EXIT_GC() GC_collecting = 0;  
 #  endif /* LINUX_THREADS */  
 #  if defined(HPUX_THREADS)  
 #    include <pthread.h>  
      extern pthread_mutex_t GC_allocate_ml;  
 #    define LOCK() pthread_mutex_lock(&GC_allocate_ml)  
 #    define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)  
 #  endif  
 #  if defined(IRIX_THREADS) || defined(IRIX_JDK_THREADS)  
      /* This may also eventually be appropriate for HPUX_THREADS */  
 #    include <pthread.h>  
 #    ifndef HPUX_THREADS  
         /* This probably should never be included, but I can't test     */  
         /* on Irix anymore.                                             */  
 #       include <mutex.h>  
 #    endif  
   
 #    ifndef HPUX_THREADS  
 #      if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \  
         || !defined(_COMPILER_VERSION) || _COMPILER_VERSION < 700  
 #        define GC_test_and_set(addr, v) test_and_set(addr,v)  
 #      else  
 #        define GC_test_and_set(addr, v) __test_and_set(addr,v)  
 #      endif  
 #    else  
        /* I couldn't find a way to do this inline on HP/UX      */  
 #    endif  
      extern unsigned long GC_allocate_lock;  
         /* This is not a mutex because mutexes that obey the (optional)         */  
         /* POSIX scheduling rules are subject to convoys in high contention     */  
         /* applications.  This is basically a spin lock.                        */  
      extern pthread_t GC_lock_holder;  
      extern void GC_lock(void);  
         /* Allocation lock holder.  Only set if acquired by client through */  
         /* GC_call_with_alloc_lock.                                        */  
 #    define SET_LOCK_HOLDER() GC_lock_holder = pthread_self()  
 #    define NO_THREAD (pthread_t)(-1)  
 #    define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD  
 #    define I_HOLD_LOCK() (pthread_equal(GC_lock_holder, pthread_self()))  
 #    ifdef HPUX_THREADS  
 #      define LOCK() { if (!GC_test_and_clear(&GC_allocate_lock)) GC_lock(); }  
        /* The following is INCORRECT, since the memory model is too weak. */  
 #      define UNLOCK() { GC_noop1(&GC_allocate_lock); \  
                         *(volatile unsigned long *)(&GC_allocate_lock) = 1; }  
 #    else  
 #      define LOCK() { if (GC_test_and_set(&GC_allocate_lock, 1)) GC_lock(); }  
 #      if __mips >= 3 && (defined (_ABIN32) || defined(_ABI64)) \  
            && defined(_COMPILER_VERSION) && _COMPILER_VERSION >= 700  
 #           define UNLOCK() __lock_release(&GC_allocate_lock)  
 #      else  
             /* The function call in the following should prevent the    */  
             /* compiler from moving assignments to below the UNLOCK.    */  
             /* This is probably not necessary for ucode or gcc 2.8.     */  
             /* It may be necessary for Ragnarok and future gcc          */  
             /* versions.                                                */  
 #           define UNLOCK() { GC_noop1(&GC_allocate_lock); \  
                         *(volatile unsigned long *)(&GC_allocate_lock) = 0; }  
 #      endif  
 #    endif  
      extern GC_bool GC_collecting;  
 #    define ENTER_GC() \  
                 { \  
                     GC_collecting = 1; \  
                 }  
 #    define EXIT_GC() GC_collecting = 0;  
 #  endif /* IRIX_THREADS || IRIX_JDK_THREADS */  
 #  ifdef WIN32_THREADS  
 #    include <windows.h>  
      GC_API CRITICAL_SECTION GC_allocate_ml;  
 #    define LOCK() EnterCriticalSection(&GC_allocate_ml);  
 #    define UNLOCK() LeaveCriticalSection(&GC_allocate_ml);  
 #  endif  
 #  ifndef SET_LOCK_HOLDER  
 #      define SET_LOCK_HOLDER()  
 #      define UNSET_LOCK_HOLDER()  
 #      define I_HOLD_LOCK() FALSE  
                 /* Used on platforms were locks can be reacquired,      */  
                 /* so it doesn't matter if we lie.                      */  
 #  endif  
 # else  
 #    define LOCK()  
 #    define UNLOCK()  
 # endif  
 # ifndef SET_LOCK_HOLDER  
 #   define SET_LOCK_HOLDER()  
 #   define UNSET_LOCK_HOLDER()  
 #   define I_HOLD_LOCK() FALSE  
                 /* Used on platforms were locks can be reacquired,      */  
                 /* so it doesn't matter if we lie.                      */  
 # endif  
 # ifndef ENTER_GC  
 #   define ENTER_GC()  
 #   define EXIT_GC()  
 # endif  
   
 # ifndef DCL_LOCK_STATE  
 #   define DCL_LOCK_STATE  
 # endif  
 # ifndef FASTLOCK  
 #   define FASTLOCK() LOCK()  
 #   define FASTLOCK_SUCCEEDED() TRUE  
 #   define FASTUNLOCK() UNLOCK()  
 # endif  
   
 /* Delay any interrupts or signals that may abort this thread.  Data    */  /* Delay any interrupts or signals that may abort this thread.  Data    */
 /* structures are in a consistent state outside this pair of calls.     */  /* structures are in a consistent state outside this pair of calls.     */
 /* ANSI C allows both to be empty (though the standard isn't very       */  /* ANSI C allows both to be empty (though the standard isn't very       */
Line 639  addr)
Line 450  addr)
                 PCR_Th_SetSigMask(&GC_old_sig_mask, NIL)                  PCR_Th_SetSigMask(&GC_old_sig_mask, NIL)
 # else  # else
 #   if defined(SRC_M3) || defined(AMIGA) || defined(SOLARIS_THREADS) \  #   if defined(SRC_M3) || defined(AMIGA) || defined(SOLARIS_THREADS) \
         || defined(MSWIN32) || defined(MACOS) || defined(DJGPP) \          || defined(MSWIN32) || defined(MSWINCE) || defined(MACOS) \
         || defined(NO_SIGNALS) || defined(IRIX_THREADS) \          || defined(DJGPP) || defined(NO_SIGNALS) || defined(IRIX_THREADS) \
         || defined(IRIX_JDK_THREADS) || defined(LINUX_THREADS)          || defined(LINUX_THREADS)
                         /* Also useful for debugging.           */                          /* Also useful for debugging.           */
         /* Should probably use thr_sigsetmask for SOLARIS_THREADS. */          /* Should probably use thr_sigsetmask for SOLARIS_THREADS. */
 #     define DISABLE_SIGNALS()  #     define DISABLE_SIGNALS()
Line 670  addr)
Line 481  addr)
 # else  # else
 #   if defined(SOLARIS_THREADS) || defined(WIN32_THREADS) \  #   if defined(SOLARIS_THREADS) || defined(WIN32_THREADS) \
         || defined(IRIX_THREADS) || defined(LINUX_THREADS) \          || defined(IRIX_THREADS) || defined(LINUX_THREADS) \
         || defined(IRIX_JDK_THREADS) || defined(HPUX_THREADS)          || defined(HPUX_THREADS)
       void GC_stop_world();        void GC_stop_world();
       void GC_start_world();        void GC_start_world();
 #     define STOP_WORLD() GC_stop_world()  #     define STOP_WORLD() GC_stop_world()
Line 704  addr)
Line 515  addr)
 # define WARN(msg,arg) (*GC_current_warn_proc)(msg, (GC_word)(arg))  # define WARN(msg,arg) (*GC_current_warn_proc)(msg, (GC_word)(arg))
 extern GC_warn_proc GC_current_warn_proc;  extern GC_warn_proc GC_current_warn_proc;
   
   /* Get environment entry */
   #if !defined(NO_GETENV)
   #   define GETENV(name) getenv(name)
   #else
   #   define GETENV(name) 0
   #endif
   
 /*********************************/  /*********************************/
 /*                               */  /*                               */
 /* Word-size-dependent defines   */  /* Word-size-dependent defines   */
Line 733  extern GC_warn_proc GC_current_warn_proc;
Line 551  extern GC_warn_proc GC_current_warn_proc;
 #define WORDSZ ((word)CPP_WORDSZ)  #define WORDSZ ((word)CPP_WORDSZ)
 #define SIGNB  ((word)1 << (WORDSZ-1))  #define SIGNB  ((word)1 << (WORDSZ-1))
 #define BYTES_PER_WORD      ((word)(sizeof (word)))  #define BYTES_PER_WORD      ((word)(sizeof (word)))
 #define ONES                ((word)(-1))  #define ONES                ((word)(signed_word)(-1))
 #define divWORDSZ(n) ((n) >> LOGWL)        /* divide n by size of word      */  #define divWORDSZ(n) ((n) >> LOGWL)        /* divide n by size of word      */
   
 /*********************/  /*********************/
Line 786  extern GC_warn_proc GC_current_warn_proc;
Line 604  extern GC_warn_proc GC_current_warn_proc;
 /*  max size objects supported by freelist (larger objects may be   */  /*  max size objects supported by freelist (larger objects may be   */
 /*  allocated, but less efficiently)                                */  /*  allocated, but less efficiently)                                */
   
   #define CPP_MAXOBJBYTES (CPP_HBLKSIZE/2)
   #define MAXOBJBYTES ((word)CPP_MAXOBJBYTES)
 #define CPP_MAXOBJSZ    BYTES_TO_WORDS(CPP_HBLKSIZE/2)  #define CPP_MAXOBJSZ    BYTES_TO_WORDS(CPP_HBLKSIZE/2)
 #define MAXOBJSZ ((word)CPP_MAXOBJSZ)  #define MAXOBJSZ ((word)CPP_MAXOBJSZ)
   
Line 806  extern GC_warn_proc GC_current_warn_proc;
Line 626  extern GC_warn_proc GC_current_warn_proc;
 # define HBLKDISPL(objptr) (((word) (objptr)) & (HBLKSIZE-1))  # define HBLKDISPL(objptr) (((word) (objptr)) & (HBLKSIZE-1))
   
 /* Round up byte allocation requests to integral number of words, etc. */  /* Round up byte allocation requests to integral number of words, etc. */
 # ifdef ADD_BYTE_AT_END  # define ROUNDED_UP_WORDS(n) \
 #   define ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1))          BYTES_TO_WORDS((n) + (WORDS_TO_BYTES(1) - 1 + EXTRA_BYTES))
 #   ifdef ALIGN_DOUBLE  # ifdef ALIGN_DOUBLE
 #       define ALIGNED_WORDS(n) (BYTES_TO_WORDS((n) + WORDS_TO_BYTES(2)) & ~1)  
 #   else  
 #       define ALIGNED_WORDS(n) ROUNDED_UP_WORDS(n)  
 #   endif  
 #   define SMALL_OBJ(bytes) ((bytes) < WORDS_TO_BYTES(MAXOBJSZ))  
 #   define ADD_SLOP(bytes) ((bytes)+1)  
 # else  
 #   define ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + (WORDS_TO_BYTES(1) - 1))  
 #   ifdef ALIGN_DOUBLE  
 #       define ALIGNED_WORDS(n) \  #       define ALIGNED_WORDS(n) \
                         (BYTES_TO_WORDS((n) + WORDS_TO_BYTES(2) - 1) & ~1)              (BYTES_TO_WORDS((n) + WORDS_TO_BYTES(2) - 1 + EXTRA_BYTES) & ~1)
 #   else  # else
 #       define ALIGNED_WORDS(n) ROUNDED_UP_WORDS(n)  #       define ALIGNED_WORDS(n) ROUNDED_UP_WORDS(n)
   # endif
   # define SMALL_OBJ(bytes) ((bytes) < (MAXOBJBYTES -EXTRA_BYTES))
   # define ADD_SLOP(bytes) ((bytes) + EXTRA_BYTES)
   # ifndef MIN_WORDS
       /* MIN_WORDS is the size of the smallest allocated object.  */
       /* 1 and 2 are the only valid values.                       */
       /* 2 must be used if:                                       */
       /* - GC_gcj_malloc can be used for objects of requested     */
       /*   size  smaller than 2 words, or                         */
       /* - USE_MARK_BYTES is defined.                             */
   #   if defined(USE_MARK_BYTES) || defined(GC_GCJ_SUPPORT)
   #     define MIN_WORDS 2        /* Smallest allocated object.   */
   #   else
   #     define MIN_WORDS 1
 #   endif  #   endif
 #   define SMALL_OBJ(bytes) ((bytes) <= WORDS_TO_BYTES(MAXOBJSZ))  
 #   define ADD_SLOP(bytes) (bytes)  
 # endif  # endif
   
   
Line 835  extern GC_warn_proc GC_current_warn_proc;
Line 658  extern GC_warn_proc GC_current_warn_proc;
  */   */
   
 # ifdef LARGE_CONFIG  # ifdef LARGE_CONFIG
 #   define LOG_PHT_ENTRIES  17  #   define LOG_PHT_ENTRIES  19  /* Collisions likely at 512K blocks,    */
                                   /* which is >= 2GB.  Each table takes   */
                                   /* 64KB.                                */
 # else  # else
 #   define LOG_PHT_ENTRIES  14  /* Collisions are likely if heap grows  */  #   ifdef SMALL_CONFIG
                                 /* to more than 16K hblks = 64MB.       */  #     define LOG_PHT_ENTRIES  14 /* Collisions are likely if heap grows */
                                 /* Each hash table occupies 2K bytes.   */                                   /* to more than 16K hblks = 64MB.      */
                                    /* Each hash table occupies 2K bytes.   */
   #   else /* default "medium" configuration */
   #     define LOG_PHT_ENTRIES  16 /* Collisions are likely if heap grows */
                                    /* to more than 16K hblks >= 256MB.    */
                                    /* Each hash table occupies 8K bytes.  */
   #   endif
 # endif  # endif
 # define PHT_ENTRIES ((word)1 << LOG_PHT_ENTRIES)  # define PHT_ENTRIES ((word)1 << LOG_PHT_ENTRIES)
 # define PHT_SIZE (PHT_ENTRIES >> LOGWL)  # define PHT_SIZE (PHT_ENTRIES >> LOGWL)
Line 853  typedef word page_hash_table[PHT_SIZE];
Line 684  typedef word page_hash_table[PHT_SIZE];
                 (bl)[divWORDSZ(index)] |= (word)1 << modWORDSZ(index)                  (bl)[divWORDSZ(index)] |= (word)1 << modWORDSZ(index)
 # define clear_pht_entry_from_index(bl, index) \  # define clear_pht_entry_from_index(bl, index) \
                 (bl)[divWORDSZ(index)] &= ~((word)1 << modWORDSZ(index))                  (bl)[divWORDSZ(index)] &= ~((word)1 << modWORDSZ(index))
   /* And a dumb but thread-safe version of set_pht_entry_from_index.      */
   /* This sets (many) extra bits.                                         */
   # define set_pht_entry_from_index_safe(bl, index) \
                   (bl)[divWORDSZ(index)] = ONES
   
   
   
Line 865  typedef word page_hash_table[PHT_SIZE];
Line 700  typedef word page_hash_table[PHT_SIZE];
 /*  heap block header */  /*  heap block header */
 #define HBLKMASK   (HBLKSIZE-1)  #define HBLKMASK   (HBLKSIZE-1)
   
 #define BITS_PER_HBLK (HBLKSIZE * 8)  #define BITS_PER_HBLK (CPP_HBLKSIZE * 8)
   
 #define MARK_BITS_PER_HBLK (BITS_PER_HBLK/CPP_WORDSZ)  #define MARK_BITS_PER_HBLK (BITS_PER_HBLK/CPP_WORDSZ)
            /* upper bound                                    */             /* upper bound                                    */
            /* We allocate 1 bit/word.  Only the first word   */             /* We allocate 1 bit/word, unless USE_MARK_BYTES  */
              /* is defined.  Only the first word               */
            /* in each object is actually marked.             */             /* in each object is actually marked.             */
   
 # ifdef ALIGN_DOUBLE  # ifdef USE_MARK_BYTES
 #   define MARK_BITS_SZ (((MARK_BITS_PER_HBLK + 2*CPP_WORDSZ - 1) \  #   define MARK_BITS_SZ (MARK_BITS_PER_HBLK/2)
                           / (2*CPP_WORDSZ))*2)          /* Unlike the other case, this is in units of bytes.            */
           /* We actually allocate only every second mark bit, since we    */
           /* force all objects to be doubleword aligned.                  */
           /* However, each mark bit is allocated as a byte.               */
 # else  # else
 #   define MARK_BITS_SZ ((MARK_BITS_PER_HBLK + CPP_WORDSZ - 1)/CPP_WORDSZ)  #   define MARK_BITS_SZ (MARK_BITS_PER_HBLK/CPP_WORDSZ)
 # endif  # endif
            /* Upper bound on number of mark words per heap block  */  
   
   /* We maintain layout maps for heap blocks containing objects of a given */
   /* size.  Each entry in this map describes a byte offset and has the     */
   /* following type.                                                       */
   typedef unsigned char map_entry_type;
   
 struct hblkhdr {  struct hblkhdr {
     word hb_sz;  /* If in use, size in words, of objects in the block. */      word hb_sz;  /* If in use, size in words, of objects in the block. */
                  /* if free, the size in bytes of the whole block      */                   /* if free, the size in bytes of the whole block      */
Line 889  struct hblkhdr {
Line 732  struct hblkhdr {
     struct hblk * hb_prev;      /* Backwards link for free list.        */      struct hblk * hb_prev;      /* Backwards link for free list.        */
     word hb_descr;              /* object descriptor for marking.  See  */      word hb_descr;              /* object descriptor for marking.  See  */
                                 /* mark.h.                              */                                  /* mark.h.                              */
     char* hb_map;       /* A pointer to a pointer validity map of the block. */      map_entry_type * hb_map;
                           /* A pointer to a pointer validity map of the block. */
                         /* See GC_obj_map.                                   */                          /* See GC_obj_map.                                   */
                         /* Valid for all blocks with headers.                */                          /* Valid for all blocks with headers.                */
                         /* Free blocks point to GC_invalid_map.              */                          /* Free blocks point to GC_invalid_map.              */
Line 911  struct hblkhdr {
Line 755  struct hblkhdr {
                                 /* Value of GC_gc_no when block was     */                                  /* Value of GC_gc_no when block was     */
                                 /* last allocated or swept. May wrap.   */                                  /* last allocated or swept. May wrap.   */
                                 /* For a free block, this is maintained */                                  /* For a free block, this is maintained */
                                 /* unly for USE_MUNMAP, and indicates   */                                  /* only for USE_MUNMAP, and indicates   */
                                 /* when the header was allocated, or    */                                  /* when the header was allocated, or    */
                                 /* when the size of the block last      */                                  /* when the size of the block last      */
                                 /* changed.                             */                                  /* changed.                             */
     word hb_marks[MARK_BITS_SZ];  #   ifdef USE_MARK_BYTES
         union {
           char _hb_marks[MARK_BITS_SZ];
                               /* The i'th byte is 1 if the object         */
                               /* starting at word 2i is marked, 0 o.w.    */
           word dummy;     /* Force word alignment of mark bytes. */
         } _mark_byte_union;
   #     define hb_marks _mark_byte_union._hb_marks
   #   else
         word hb_marks[MARK_BITS_SZ];
                             /* Bit i in the array refers to the             */                              /* Bit i in the array refers to the             */
                             /* object starting at the ith word (header      */                              /* object starting at the ith word (header      */
                             /* INCLUDED) in the heap block.                 */                              /* INCLUDED) in the heap block.                 */
Line 923  struct hblkhdr {
Line 776  struct hblkhdr {
                             /* Unused bits are invalid, and are             */                              /* Unused bits are invalid, and are             */
                             /* occasionally set, e.g for uncollectable      */                              /* occasionally set, e.g for uncollectable      */
                             /* objects.                                     */                              /* objects.                                     */
   #   endif /* !USE_MARK_BYTES */
 };  };
   
 /*  heap block body */  /*  heap block body */
   
 # define DISCARD_WORDS 0  # define BODY_SZ (HBLKSIZE/sizeof(word))
         /* Number of words to be dropped at the beginning of each block */  
         /* Must be a multiple of WORDSZ.  May reasonably be nonzero     */  
         /* on machines that don't guarantee longword alignment of       */  
         /* pointers, so that the number of false hits is minimized.     */  
         /* 0 and WORDSZ are probably the only reasonable values.        */  
   
 # define BODY_SZ ((HBLKSIZE-WORDS_TO_BYTES(DISCARD_WORDS))/sizeof(word))  
   
 struct hblk {  struct hblk {
 #   if (DISCARD_WORDS != 0)  #   if 0  /* DISCARDWORDS no longer supported */
         word garbage[DISCARD_WORDS];          word garbage[DISCARD_WORDS];
 #   endif  #   endif
     word hb_body[BODY_SZ];      word hb_body[BODY_SZ];
 };  };
   
 # define HDR_WORDS ((word)DISCARD_WORDS)  
 # define HDR_BYTES ((word)WORDS_TO_BYTES(DISCARD_WORDS))  
   
 # define OBJ_SZ_TO_BLOCKS(sz) \  # define OBJ_SZ_TO_BLOCKS(sz) \
     divHBLKSZ(HDR_BYTES + WORDS_TO_BYTES(sz) + HBLKSIZE-1)      divHBLKSZ(WORDS_TO_BYTES(sz) + HBLKSIZE-1)
     /* Size of block (in units of HBLKSIZE) needed to hold objects of   */      /* Size of block (in units of HBLKSIZE) needed to hold objects of   */
     /* given sz (in words).                                             */      /* given sz (in words).                                             */
   
 /* Object free list link */  /* Object free list link */
 # define obj_link(p) (*(ptr_t *)(p))  # define obj_link(p) (*(ptr_t *)(p))
   
 /* The type of mark procedures.  This really belongs in gc_mark.h.      */  
 /* But we put it here, so that we can avoid scanning the mark proc      */  
 /* table.                                                               */  
 typedef struct ms_entry * (*mark_proc)(/* word * addr, mark_stack_ptr,  
                                           mark_stack_limit, env */);  
 # define LOG_MAX_MARK_PROCS 6  # define LOG_MAX_MARK_PROCS 6
 # define MAX_MARK_PROCS (1 << LOG_MAX_MARK_PROCS)  # define MAX_MARK_PROCS (1 << LOG_MAX_MARK_PROCS)
   
Line 972  typedef struct ms_entry * (*mark_proc)(/* word * addr,
Line 811  typedef struct ms_entry * (*mark_proc)(/* word * addr,
 #   ifdef PCR  #   ifdef PCR
 #     define MAX_ROOT_SETS 1024  #     define MAX_ROOT_SETS 1024
 #   else  #   else
 #     ifdef MSWIN32  #     if defined(MSWIN32) || defined(MSWINCE)
 #       define MAX_ROOT_SETS 512  #       define MAX_ROOT_SETS 1024
             /* Under NT, we add only written pages, which can result    */              /* Under NT, we add only written pages, which can result    */
             /* in many small root sets.                                 */              /* in many small root sets.                                 */
 #     else  #     else
 #       define MAX_ROOT_SETS 64  #       define MAX_ROOT_SETS 256
 #     endif  #     endif
 #   endif  #   endif
 # endif  # endif
Line 1000  struct exclusion {
Line 839  struct exclusion {
 struct roots {  struct roots {
         ptr_t r_start;          ptr_t r_start;
         ptr_t r_end;          ptr_t r_end;
 #       ifndef MSWIN32  #       if !defined(MSWIN32) && !defined(MSWINCE)
           struct roots * r_next;            struct roots * r_next;
 #       endif  #       endif
         GC_bool r_tmp;          GC_bool r_tmp;
                 /* Delete before registering new dynamic libraries */                  /* Delete before registering new dynamic libraries */
 };  };
   
 #ifndef MSWIN32  #if !defined(MSWIN32) && !defined(MSWINCE)
     /* Size of hash table index to roots.       */      /* Size of hash table index to roots.       */
 #   define LOG_RT_SIZE 6  #   define LOG_RT_SIZE 6
 #   define RT_SIZE (1 << LOG_RT_SIZE) /* Power of 2, may be != MAX_ROOT_SETS */  #   define RT_SIZE (1 << LOG_RT_SIZE) /* Power of 2, may be != MAX_ROOT_SETS */
Line 1035  struct roots {
Line 874  struct roots {
 struct _GC_arrays {  struct _GC_arrays {
   word _heapsize;    word _heapsize;
   word _max_heapsize;    word _max_heapsize;
     word _requested_heapsize;     /* Heap size due to explicit expansion */
   ptr_t _last_heap_addr;    ptr_t _last_heap_addr;
   ptr_t _prev_heap_addr;    ptr_t _prev_heap_addr;
   word _large_free_bytes;    word _large_free_bytes;
         /* Total bytes contained in blocks on large object free */          /* Total bytes contained in blocks on large object free */
         /* list.                                                */          /* list.                                                */
     word _large_allocd_bytes;
           /* Total number of bytes in allocated large objects blocks.     */
           /* For the purposes of this counter and the next one only, a    */
           /* large object is one that occupies a block of at least        */
           /* 2*HBLKSIZE.                                                  */
     word _max_large_allocd_bytes;
           /* Maximum number of bytes that were ever allocated in          */
           /* large object blocks.  This is used to help decide when it    */
           /* is safe to split up a large block.                           */
   word _words_allocd_before_gc;    word _words_allocd_before_gc;
                 /* Number of words allocated before this        */                  /* Number of words allocated before this        */
                 /* collection cycle.                            */                  /* collection cycle.                            */
   word _words_allocd;  # ifndef SEPARATE_GLOBALS
       word _words_allocd;
         /* Number of words allocated during this collection cycle */          /* Number of words allocated during this collection cycle */
   # endif
   word _words_wasted;    word _words_wasted;
         /* Number of words wasted due to internal fragmentation */          /* Number of words wasted due to internal fragmentation */
         /* in large objects, or due to dropping blacklisted     */          /* in large objects, or due to dropping blacklisted     */
Line 1059  struct _GC_arrays {
Line 910  struct _GC_arrays {
   word _mem_freed;    word _mem_freed;
         /* Number of explicitly deallocated words of memory     */          /* Number of explicitly deallocated words of memory     */
         /* since last collection.                               */          /* since last collection.                               */
   mark_proc _mark_procs[MAX_MARK_PROCS];    ptr_t _scratch_end_ptr;
     ptr_t _scratch_last_end_ptr;
           /* Used by headers.c, and can easily appear to point to */
           /* heap.                                                */
     GC_mark_proc _mark_procs[MAX_MARK_PROCS];
         /* Table of user-defined mark procedures.  There is     */          /* Table of user-defined mark procedures.  There is     */
         /* a small number of these, which can be referenced     */          /* a small number of these, which can be referenced     */
         /* by DS_PROC mark descriptors.  See gc_mark.h.         */          /* by DS_PROC mark descriptors.  See gc_mark.h.         */
   ptr_t _objfreelist[MAXOBJSZ+1];  
   # ifndef SEPARATE_GLOBALS
       ptr_t _objfreelist[MAXOBJSZ+1];
                           /* free list for objects */                            /* free list for objects */
   ptr_t _aobjfreelist[MAXOBJSZ+1];      ptr_t _aobjfreelist[MAXOBJSZ+1];
                           /* free list for atomic objs  */                            /* free list for atomic objs  */
   # endif
   
   ptr_t _uobjfreelist[MAXOBJSZ+1];    ptr_t _uobjfreelist[MAXOBJSZ+1];
                           /* uncollectable but traced objs      */                            /* uncollectable but traced objs      */
Line 1099  struct _GC_arrays {
Line 957  struct _GC_arrays {
     ptr_t _sobjfreelist[MAXOBJSZ+1];      ptr_t _sobjfreelist[MAXOBJSZ+1];
 # endif  # endif
                           /* free list for immutable objects    */                            /* free list for immutable objects    */
   ptr_t _obj_map[MAXOBJSZ+1];    map_entry_type * _obj_map[MAXOBJSZ+1];
                        /* If not NIL, then a pointer to a map of valid  */                         /* If not NIL, then a pointer to a map of valid  */
                        /* object addresses. _obj_map[sz][i] is j if the */                         /* object addresses. _obj_map[sz][i] is j if the */
                        /* address block_start+i is a valid pointer      */                         /* address block_start+i is a valid pointer      */
                        /* to an object at                               */                         /* to an object at block_start +                 */
                        /* block_start+i&~3 - WORDS_TO_BYTES(j).         */                         /* WORDS_TO_BYTES(BYTES_TO_WORDS(i) - j)         */
                        /* (If ALL_INTERIOR_POINTERS is defined, then    */                         /* I.e. j is a word displacement from the        */
                        /* instead ((short *)(hb_map[sz])[i] is j if     */                         /* object beginning.                             */
                        /* block_start+WORDS_TO_BYTES(i) is in the       */                         /* The entry is OBJ_INVALID if the corresponding */
                        /* interior of an object starting at             */                         /* address is not a valid pointer.  It is        */
                        /* block_start+WORDS_TO_BYTES(i-j)).             */                         /* OFFSET_TOO_BIG if the value j would be too    */
                        /* It is OBJ_INVALID if                          */                         /* large to fit in the entry.  (Note that the    */
                        /* block_start+WORDS_TO_BYTES(i) is not          */                         /* size of these entries matters, both for       */
                        /* valid as a pointer to an object.              */                         /* space consumption and for cache utilization.  */
                        /* We assume all values of j <= OBJ_INVALID.     */  #   define OFFSET_TOO_BIG 0xfe
                        /* The zeroth entry corresponds to large objects.*/  #   define OBJ_INVALID 0xff
 #   ifdef ALL_INTERIOR_POINTERS  #   define MAP_ENTRY(map, bytes) (map)[bytes]
 #       define map_entry_type short  #   define MAP_ENTRIES HBLKSIZE
 #       define OBJ_INVALID 0x7fff  #   define MAP_SIZE MAP_ENTRIES
 #       define MAP_ENTRY(map, bytes) \  #   define CPP_MAX_OFFSET (OFFSET_TOO_BIG - 1)
                 (((map_entry_type *)(map))[BYTES_TO_WORDS(bytes)])  #   define MAX_OFFSET ((word)CPP_MAX_OFFSET)
 #       define MAP_ENTRIES BYTES_TO_WORDS(HBLKSIZE)      /* The following are used only if GC_all_interior_ptrs != 0 */
 #       define MAP_SIZE (MAP_ENTRIES * sizeof(map_entry_type))  
 #       define OFFSET_VALID(displ) TRUE  
 #       define CPP_MAX_OFFSET (HBLKSIZE - HDR_BYTES - 1)  
 #       define MAX_OFFSET ((word)CPP_MAX_OFFSET)  
 #   else  
 #       define map_entry_type char  
 #       define OBJ_INVALID 0x7f  
 #       define MAP_ENTRY(map, bytes) \  
                 (map)[bytes]  
 #       define MAP_ENTRIES HBLKSIZE  
 #       define MAP_SIZE MAP_ENTRIES  
 #       define CPP_MAX_OFFSET (WORDS_TO_BYTES(OBJ_INVALID) - 1)  
 #       define MAX_OFFSET ((word)CPP_MAX_OFFSET)  
 #       define VALID_OFFSET_SZ \  #       define VALID_OFFSET_SZ \
           (CPP_MAX_OFFSET > WORDS_TO_BYTES(CPP_MAXOBJSZ)? \            (CPP_MAX_OFFSET > WORDS_TO_BYTES(CPP_MAXOBJSZ)? \
            CPP_MAX_OFFSET+1 \             CPP_MAX_OFFSET+1 \
Line 1141  struct _GC_arrays {
Line 986  struct _GC_arrays {
         char _valid_offsets[VALID_OFFSET_SZ];          char _valid_offsets[VALID_OFFSET_SZ];
                                 /* GC_valid_offsets[i] == TRUE ==> i    */                                  /* GC_valid_offsets[i] == TRUE ==> i    */
                                 /* is registered as a displacement.     */                                  /* is registered as a displacement.     */
 #       define OFFSET_VALID(displ) GC_valid_offsets[displ]  #       define OFFSET_VALID(displ) \
             (GC_all_interior_pointers || GC_valid_offsets[displ])
         char _modws_valid_offsets[sizeof(word)];          char _modws_valid_offsets[sizeof(word)];
                                 /* GC_valid_offsets[i] ==>                */                                  /* GC_valid_offsets[i] ==>                */
                                 /* GC_modws_valid_offsets[i%sizeof(word)] */                                  /* GC_modws_valid_offsets[i%sizeof(word)] */
 #   endif  
 # ifdef STUBBORN_ALLOC  # ifdef STUBBORN_ALLOC
     page_hash_table _changed_pages;      page_hash_table _changed_pages;
         /* Stubborn object pages that were changes since last call to   */          /* Stubborn object pages that were changes since last call to   */
Line 1172  struct _GC_arrays {
Line 1017  struct _GC_arrays {
 #     define MAX_HEAP_SECTS 768         /* Separately added heap sections. */  #     define MAX_HEAP_SECTS 768         /* Separately added heap sections. */
 #   endif  #   endif
 # else  # else
 #   define MAX_HEAP_SECTS 256  #   ifdef SMALL_CONFIG
   #     define MAX_HEAP_SECTS 128         /* Roughly 1GB                  */
   #   else
   #     define MAX_HEAP_SECTS 384         /* Roughly 3GB                  */
   #   endif
 # endif  # endif
   struct HeapSect {    struct HeapSect {
       ptr_t hs_start; word hs_bytes;        ptr_t hs_start; word hs_bytes;
   } _heap_sects[MAX_HEAP_SECTS];    } _heap_sects[MAX_HEAP_SECTS];
 # ifdef MSWIN32  # if defined(MSWIN32) || defined(MSWINCE)
     ptr_t _heap_bases[MAX_HEAP_SECTS];      ptr_t _heap_bases[MAX_HEAP_SECTS];
                 /* Start address of memory regions obtained from kernel. */                  /* Start address of memory regions obtained from kernel. */
 # endif  # endif
   # ifdef MSWINCE
       word _heap_lengths[MAX_HEAP_SECTS];
                   /* Commited lengths of memory regions obtained from kernel. */
   # endif
   struct roots _static_roots[MAX_ROOT_SETS];    struct roots _static_roots[MAX_ROOT_SETS];
 # ifndef MSWIN32  # if !defined(MSWIN32) && !defined(MSWINCE)
     struct roots * _root_index[RT_SIZE];      struct roots * _root_index[RT_SIZE];
 # endif  # endif
   struct exclusion _excl_table[MAX_EXCLUSIONS];    struct exclusion _excl_table[MAX_EXCLUSIONS];
Line 1201  struct _GC_arrays {
Line 1054  struct _GC_arrays {
   
 GC_API GC_FAR struct _GC_arrays GC_arrays;  GC_API GC_FAR struct _GC_arrays GC_arrays;
   
 # define GC_objfreelist GC_arrays._objfreelist  # ifndef SEPARATE_GLOBALS
 # define GC_aobjfreelist GC_arrays._aobjfreelist  #   define GC_objfreelist GC_arrays._objfreelist
   #   define GC_aobjfreelist GC_arrays._aobjfreelist
   #   define GC_words_allocd GC_arrays._words_allocd
   # endif
 # define GC_uobjfreelist GC_arrays._uobjfreelist  # define GC_uobjfreelist GC_arrays._uobjfreelist
 # ifdef ATOMIC_UNCOLLECTABLE  # ifdef ATOMIC_UNCOLLECTABLE
 #   define GC_auobjfreelist GC_arrays._auobjfreelist  #   define GC_auobjfreelist GC_arrays._auobjfreelist
Line 1217  GC_API GC_FAR struct _GC_arrays GC_arrays; 
Line 1073  GC_API GC_FAR struct _GC_arrays GC_arrays; 
 # define GC_obj_map GC_arrays._obj_map  # define GC_obj_map GC_arrays._obj_map
 # define GC_last_heap_addr GC_arrays._last_heap_addr  # define GC_last_heap_addr GC_arrays._last_heap_addr
 # define GC_prev_heap_addr GC_arrays._prev_heap_addr  # define GC_prev_heap_addr GC_arrays._prev_heap_addr
 # define GC_words_allocd GC_arrays._words_allocd  
 # define GC_words_wasted GC_arrays._words_wasted  # define GC_words_wasted GC_arrays._words_wasted
 # define GC_large_free_bytes GC_arrays._large_free_bytes  # define GC_large_free_bytes GC_arrays._large_free_bytes
   # define GC_large_allocd_bytes GC_arrays._large_allocd_bytes
   # define GC_max_large_allocd_bytes GC_arrays._max_large_allocd_bytes
 # define GC_words_finalized GC_arrays._words_finalized  # define GC_words_finalized GC_arrays._words_finalized
 # define GC_non_gc_bytes_at_gc GC_arrays._non_gc_bytes_at_gc  # define GC_non_gc_bytes_at_gc GC_arrays._non_gc_bytes_at_gc
 # define GC_mem_freed GC_arrays._mem_freed  # define GC_mem_freed GC_arrays._mem_freed
   # define GC_scratch_end_ptr GC_arrays._scratch_end_ptr
   # define GC_scratch_last_end_ptr GC_arrays._scratch_last_end_ptr
 # define GC_mark_procs GC_arrays._mark_procs  # define GC_mark_procs GC_arrays._mark_procs
 # define GC_heapsize GC_arrays._heapsize  # define GC_heapsize GC_arrays._heapsize
 # define GC_max_heapsize GC_arrays._max_heapsize  # define GC_max_heapsize GC_arrays._max_heapsize
   # define GC_requested_heapsize GC_arrays._requested_heapsize
 # define GC_words_allocd_before_gc GC_arrays._words_allocd_before_gc  # define GC_words_allocd_before_gc GC_arrays._words_allocd_before_gc
 # define GC_heap_sects GC_arrays._heap_sects  # define GC_heap_sects GC_arrays._heap_sects
 # define GC_last_stack GC_arrays._last_stack  # define GC_last_stack GC_arrays._last_stack
 # ifdef USE_MUNMAP  # ifdef USE_MUNMAP
 #   define GC_unmapped_bytes GC_arrays._unmapped_bytes  #   define GC_unmapped_bytes GC_arrays._unmapped_bytes
 # endif  # endif
 # ifdef MSWIN32  # if defined(MSWIN32) || defined(MSWINCE)
 #   define GC_heap_bases GC_arrays._heap_bases  #   define GC_heap_bases GC_arrays._heap_bases
 # endif  # endif
   # ifdef MSWINCE
   #   define GC_heap_lengths GC_arrays._heap_lengths
   # endif
 # define GC_static_roots GC_arrays._static_roots  # define GC_static_roots GC_arrays._static_roots
 # define GC_root_index GC_arrays._root_index  # define GC_root_index GC_arrays._root_index
 # define GC_excl_table GC_arrays._excl_table  # define GC_excl_table GC_arrays._excl_table
Line 1260  GC_API GC_FAR struct _GC_arrays GC_arrays; 
Line 1123  GC_API GC_FAR struct _GC_arrays GC_arrays; 
 # define beginGC_arrays ((ptr_t)(&GC_arrays))  # define beginGC_arrays ((ptr_t)(&GC_arrays))
 # define endGC_arrays (((ptr_t)(&GC_arrays)) + (sizeof GC_arrays))  # define endGC_arrays (((ptr_t)(&GC_arrays)) + (sizeof GC_arrays))
   
   #define USED_HEAP_SIZE (GC_heapsize - GC_large_free_bytes)
   
 /* Object kinds: */  /* Object kinds: */
 # define MAXOBJKINDS 16  # define MAXOBJKINDS 16
   
Line 1279  extern struct obj_kind {
Line 1144  extern struct obj_kind {
    GC_bool ok_init;   /* Clear objects before putting them on the free list. */     GC_bool ok_init;   /* Clear objects before putting them on the free list. */
 } GC_obj_kinds[MAXOBJKINDS];  } GC_obj_kinds[MAXOBJKINDS];
   
 # define endGC_obj_kinds (((ptr_t)(&GC_obj_kinds)) + (sizeof GC_obj_kinds))  # define beginGC_obj_kinds ((ptr_t)(&GC_obj_kinds))
   # define endGC_obj_kinds (beginGC_obj_kinds + (sizeof GC_obj_kinds))
   
 # define end_gc_area ((ptr_t)endGC_arrays == (ptr_t)(&GC_obj_kinds) ? \  /* Variables that used to be in GC_arrays, but need to be accessed by   */
                         endGC_obj_kinds : endGC_arrays)  /* inline allocation code.  If they were in GC_arrays, the inlined      */
   /* allocation code would include GC_arrays offsets (as it did), which   */
   /* introduce maintenance problems.                                      */
   
   #ifdef SEPARATE_GLOBALS
     word GC_words_allocd;
           /* Number of words allocated during this collection cycle */
     ptr_t GC_objfreelist[MAXOBJSZ+1];
                             /* free list for NORMAL objects */
   # define beginGC_objfreelist ((ptr_t)(&GC_objfreelist))
   # define endGC_objfreelist (beginGC_objfreelist + sizeof(GC_objfreelist))
   
     ptr_t GC_aobjfreelist[MAXOBJSZ+1];
                             /* free list for atomic (PTRFREE) objs        */
   # define beginGC_aobjfreelist ((ptr_t)(&GC_aobjfreelist))
   # define endGC_aobjfreelist (beginGC_aobjfreelist + sizeof(GC_aobjfreelist))
   #endif
   
 /* Predefined kinds: */  /* Predefined kinds: */
 # define PTRFREE 0  # define PTRFREE 0
 # define NORMAL  1  # define NORMAL  1
Line 1306  extern word GC_n_heap_sects; /* Number of separately a
Line 1188  extern word GC_n_heap_sects; /* Number of separately a
   
 extern word GC_page_size;  extern word GC_page_size;
   
 # ifdef MSWIN32  # if defined(MSWIN32) || defined(MSWINCE)
 extern word GC_n_heap_bases;    /* See GC_heap_bases.   */    struct _SYSTEM_INFO;
     extern struct _SYSTEM_INFO GC_sysinfo;
     extern word GC_n_heap_bases;  /* See GC_heap_bases.   */
 # endif  # endif
   
 extern word GC_total_stack_black_listed;  extern word GC_total_stack_black_listed;
Line 1320  extern word GC_black_list_spacing;
Line 1204  extern word GC_black_list_spacing;
                         /* "stack-blacklisted", i.e. that are           */                          /* "stack-blacklisted", i.e. that are           */
                         /* problematic in the interior of an object.    */                          /* problematic in the interior of an object.    */
   
 extern char * GC_invalid_map;  extern map_entry_type * GC_invalid_map;
                         /* Pointer to the nowhere valid hblk map */                          /* Pointer to the nowhere valid hblk map */
                         /* Blocks pointing to this map are free. */                          /* Blocks pointing to this map are free. */
   
Line 1339  extern GC_bool GC_objects_are_marked; /* There are mar
Line 1223  extern GC_bool GC_objects_are_marked; /* There are mar
   extern GC_bool GC_incremental;    extern GC_bool GC_incremental;
                         /* Using incremental/generational collection. */                          /* Using incremental/generational collection. */
 #else  #else
 # define GC_incremental TRUE  # define GC_incremental FALSE
                         /* Hopefully allow optimizer to remove some code. */                          /* Hopefully allow optimizer to remove some code. */
 #endif  #endif
   
Line 1352  extern word GC_root_size; /* Total size of registered 
Line 1236  extern word GC_root_size; /* Total size of registered 
   
 extern GC_bool GC_debugging_started;    /* GC_debug_malloc has been called. */  extern GC_bool GC_debugging_started;    /* GC_debug_malloc has been called. */
   
 extern ptr_t GC_least_plausible_heap_addr;  
 extern ptr_t GC_greatest_plausible_heap_addr;  
                         /* Bounds on the heap.  Guaranteed valid        */  
                         /* Likely to include future heap expansion.     */  
   
 /* Operations */  /* Operations */
 # ifndef abs  # ifndef abs
Line 1368  extern ptr_t GC_greatest_plausible_heap_addr;
Line 1248  extern ptr_t GC_greatest_plausible_heap_addr;
 /*  with it. Only those corresponding to the beginning of an */  /*  with it. Only those corresponding to the beginning of an */
 /*  object are used.                                         */  /*  object are used.                                         */
   
   /* Set mark bit correctly, even if mark bits may be concurrently        */
   /* accessed.                                                            */
   #ifdef PARALLEL_MARK
   # define OR_WORD(addr, bits) \
           { word old; \
             do { \
               old = *((volatile word *)addr); \
             } while (!GC_compare_and_exchange((addr), old, old | (bits))); \
           }
   # define OR_WORD_EXIT_IF_SET(addr, bits, exit_label) \
           { word old; \
             word my_bits = (bits); \
             do { \
               old = *((volatile word *)addr); \
               if (old & my_bits) goto exit_label; \
             } while (!GC_compare_and_exchange((addr), old, old | my_bits)); \
           }
   #else
   # define OR_WORD(addr, bits) *(addr) |= (bits)
   # define OR_WORD_EXIT_IF_SET(addr, bits, exit_label) \
           { \
             word old = *(addr); \
             word my_bits = (bits); \
             if (old & my_bits) goto exit_label; \
             *(addr) = (old | my_bits); \
           }
   #endif
   
 /* Mark bit operations */  /* Mark bit operations */
   
Line 1379  extern ptr_t GC_greatest_plausible_heap_addr;
Line 1286  extern ptr_t GC_greatest_plausible_heap_addr;
  * relative to the beginning of the block, including unused words)   * relative to the beginning of the block, including unused words)
  */   */
   
   #ifdef USE_MARK_BYTES
   # define mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[(n) >> 1])
   # define set_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[(n)>>1]) = 1
   # define clear_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[(n)>>1]) = 0
   #else /* !USE_MARK_BYTES */
 # define mark_bit_from_hdr(hhdr,n) (((hhdr)->hb_marks[divWORDSZ(n)] \  # define mark_bit_from_hdr(hhdr,n) (((hhdr)->hb_marks[divWORDSZ(n)] \
                             >> (modWORDSZ(n))) & (word)1)                              >> (modWORDSZ(n))) & (word)1)
 # define set_mark_bit_from_hdr(hhdr,n) (hhdr)->hb_marks[divWORDSZ(n)] \  # define set_mark_bit_from_hdr(hhdr,n) \
                                 |= (word)1 << modWORDSZ(n)                              OR_WORD((hhdr)->hb_marks+divWORDSZ(n), \
                                       (word)1 << modWORDSZ(n))
 # define clear_mark_bit_from_hdr(hhdr,n) (hhdr)->hb_marks[divWORDSZ(n)] \  # define clear_mark_bit_from_hdr(hhdr,n) (hhdr)->hb_marks[divWORDSZ(n)] \
                                 &= ~((word)1 << modWORDSZ(n))                                  &= ~((word)1 << modWORDSZ(n))
   #endif /* !USE_MARK_BYTES */
   
 /* Important internal collector routines */  /* Important internal collector routines */
   
 ptr_t GC_approx_sp();  ptr_t GC_approx_sp GC_PROTO((void));
   
 GC_bool GC_should_collect();  GC_bool GC_should_collect GC_PROTO((void));
 #ifdef PRESERVE_LAST  
     GC_bool GC_in_last_heap_sect(/* ptr_t */);  void GC_apply_to_all_blocks GC_PROTO(( \
         /* In last added heap section?  If so, avoid breaking up.       */      void (*fn) GC_PROTO((struct hblk *h, word client_data)), \
 #endif      word client_data));
 void GC_apply_to_all_blocks(/*fn, client_data*/);                          /* Invoke fn(hbp, client_data) for each         */
                         /* Invoke fn(hbp, client_data) for each         */                          /* allocated heap block.                        */
                         /* allocated heap block.                        */  struct hblk * GC_next_used_block GC_PROTO((struct hblk * h));
 struct hblk * GC_next_used_block(/* struct hblk * h */);                          /* Return first in-use block >= h       */
                         /* Return first in-use block >= h       */  struct hblk * GC_prev_block GC_PROTO((struct hblk * h));
 struct hblk * GC_prev_block(/* struct hblk * h */);                          /* Return last block <= h.  Returned block      */
                         /* Return last block <= h.  Returned block      */                          /* is managed by GC, but may or may not be in   */
                         /* is managed by GC, but may or may not be in   */  
                         /* use.                                         */                          /* use.                                         */
 void GC_mark_init();  void GC_mark_init GC_PROTO((void));
 void GC_clear_marks();  /* Clear mark bits for all heap objects. */  void GC_clear_marks GC_PROTO((void));   /* Clear mark bits for all heap objects. */
 void GC_invalidate_mark_state();        /* Tell the marker that marked     */  void GC_invalidate_mark_state GC_PROTO((void));
                                         /* objects may point to unmarked   */                                          /* Tell the marker that marked     */
                                         /* ones, and roots may point to    */                                          /* objects may point to unmarked   */
                                         /* unmarked objects.               */                                          /* ones, and roots may point to    */
                                         /* Reset mark stack.               */                                          /* unmarked objects.               */
 void GC_mark_from_mark_stack(); /* Mark from everything on the mark stack. */                                          /* Reset mark stack.               */
                                 /* Return after about one pages worth of   */  GC_bool GC_mark_stack_empty GC_PROTO((void));
                                 /* work.                                   */  GC_bool GC_mark_some GC_PROTO((ptr_t cold_gc_frame));
 GC_bool GC_mark_stack_empty();                          /* Perform about one pages worth of marking     */
 GC_bool GC_mark_some(/* cold_gc_frame */);                          /* work of whatever kind is needed.  Returns    */
                         /* Perform about one pages worth of marking     */                          /* quickly if no collection is in progress.     */
                         /* work of whatever kind is needed.  Returns    */                          /* Return TRUE if mark phase finished.          */
                         /* quickly if no collection is in progress.     */  void GC_initiate_gc GC_PROTO((void));
                         /* Return TRUE if mark phase finished.          */                                  /* initiate collection.                 */
 void GC_initiate_gc();          /* initiate collection.                 */                                  /* If the mark state is invalid, this   */
                                 /* If the mark state is invalid, this   */                                  /* becomes full colleection.  Otherwise */
                                 /* becomes full colleection.  Otherwise */                                  /* it's partial.                        */
                                 /* it's partial.                        */  void GC_push_all GC_PROTO((ptr_t bottom, ptr_t top));
 void GC_push_all(/*b,t*/);      /* Push everything in a range           */                                  /* Push everything in a range           */
                                 /* onto mark stack.                     */                                  /* onto mark stack.                     */
 void GC_push_dirty(/*b,t*/);      /* Push all possibly changed          */  void GC_push_selected GC_PROTO(( \
                                   /* subintervals of [b,t) onto         */      ptr_t bottom, \
                                   /* mark stack.                        */      ptr_t top, \
       int (*dirty_fn) GC_PROTO((struct hblk *h)), \
       void (*push_fn) GC_PROTO((ptr_t bottom, ptr_t top)) ));
                                     /* Push all pages h in [b,t) s.t.     */
                                     /* select_fn(h) != 0 onto mark stack. */
 #ifndef SMALL_CONFIG  #ifndef SMALL_CONFIG
   void GC_push_conditional(/* ptr_t b, ptr_t t, GC_bool all*/);    void GC_push_conditional GC_PROTO((ptr_t b, ptr_t t, GC_bool all));
 #else  #else
 # define GC_push_conditional(b, t, all) GC_push_all(b, t)  # define GC_push_conditional(b, t, all) GC_push_all(b, t)
 #endif  #endif
                                 /* Do either of the above, depending    */                                  /* Do either of the above, depending    */
                                 /* on the third arg.                    */                                  /* on the third arg.                    */
 void GC_push_all_stack(/*b,t*/);    /* As above, but consider           */  void GC_push_all_stack GC_PROTO((ptr_t b, ptr_t t));
                                       /* As above, but consider           */
                                     /*  interior pointers as valid      */                                      /*  interior pointers as valid      */
 void GC_push_all_eager(/*b,t*/);    /* Same as GC_push_all_stack, but   */  void GC_push_all_eager GC_PROTO((ptr_t b, ptr_t t));
                                       /* Same as GC_push_all_stack, but   */
                                     /* ensures that stack is scanned    */                                      /* ensures that stack is scanned    */
                                     /* immediately, not just scheduled  */                                      /* immediately, not just scheduled  */
                                     /* for scanning.                    */                                      /* for scanning.                    */
 #ifndef THREADS  #ifndef THREADS
   void GC_push_all_stack_partially_eager(/* bottom, top, cold_gc_frame */);    void GC_push_all_stack_partially_eager GC_PROTO(( \
         ptr_t bottom, ptr_t top, ptr_t cold_gc_frame ));
                         /* Similar to GC_push_all_eager, but only the   */                          /* Similar to GC_push_all_eager, but only the   */
                         /* part hotter than cold_gc_frame is scanned    */                          /* part hotter than cold_gc_frame is scanned    */
                         /* immediately.  Needed to endure that callee-  */                          /* immediately.  Needed to ensure that callee-  */
                         /* save registers are not missed.               */                          /* save registers are not missed.               */
 #else  #else
   /* In the threads case, we push part of the current thread stack      */    /* In the threads case, we push part of the current thread stack      */
Line 1456  void GC_push_all_eager(/*b,t*/);    /* Same as GC_push
Line 1375  void GC_push_all_eager(/*b,t*/);    /* Same as GC_push
   /* stacks are scheduled for scanning in *GC_push_other_roots, which   */    /* stacks are scheduled for scanning in *GC_push_other_roots, which   */
   /* is thread-package-specific.                                        */    /* is thread-package-specific.                                        */
 #endif  #endif
 void GC_push_current_stack(/* ptr_t cold_gc_frame */);  void GC_push_current_stack GC_PROTO((ptr_t cold_gc_frame));
                         /* Push enough of the current stack eagerly to  */                          /* Push enough of the current stack eagerly to  */
                         /* ensure that callee-save registers saved in   */                          /* ensure that callee-save registers saved in   */
                         /* GC frames are scanned.                       */                          /* GC frames are scanned.                       */
                         /* In the non-threads case, schedule entire     */                          /* In the non-threads case, schedule entire     */
                         /* stack for scanning.                          */                          /* stack for scanning.                          */
 void GC_push_roots(/* GC_bool all, ptr_t cold_gc_frame */);  void GC_push_roots GC_PROTO((GC_bool all, ptr_t cold_gc_frame));
                         /* Push all or dirty roots.     */                          /* Push all or dirty roots.     */
 extern void (*GC_push_other_roots)();  extern void (*GC_push_other_roots) GC_PROTO((void));
                         /* Push system or application specific roots    */                          /* Push system or application specific roots    */
                         /* onto the mark stack.  In some environments   */                          /* onto the mark stack.  In some environments   */
                         /* (e.g. threads environments) this is          */                          /* (e.g. threads environments) this is          */
                         /* predfined to be non-zero.  A client supplied */                          /* predfined to be non-zero.  A client supplied */
                         /* replacement should also call the original    */                          /* replacement should also call the original    */
                         /* function.                                    */                          /* function.                                    */
 extern void (*GC_start_call_back)(/* void */);  extern void GC_push_gc_structures GC_PROTO((void));
                         /* Called at start of full collections.         */                          /* Push GC internal roots.  These are normally  */
                         /* Not called if 0.  Called with allocation     */                          /* included in the static data segment, and     */
                         /* lock held.                                   */                          /* Thus implicitly pushed.  But we must do this */
                         /* 0 by default.                                */                          /* explicitly if normal root processing is      */
 void GC_push_regs();    /* Push register contents onto mark stack.      */                          /* disabled.  Calls the following:              */
                         /* If NURSERY is defined, the default push      */          extern void GC_push_finalizer_structures GC_PROTO((void));
                         /* action can be overridden with GC_push_proc   */          extern void GC_push_stubborn_structures GC_PROTO((void));
 void GC_remark();       /* Mark from all marked objects.  Used  */  #       ifdef THREADS
                         /* only if we had to drop something.    */            extern void GC_push_thread_structures GC_PROTO((void));
   #       endif
   extern void (*GC_start_call_back) GC_PROTO((void));
                           /* Called at start of full collections.         */
                           /* Not called if 0.  Called with allocation     */
                           /* lock held.                                   */
                           /* 0 by default.                                */
   # if defined(USE_GENERIC_PUSH_REGS)
     void GC_generic_push_regs GC_PROTO((ptr_t cold_gc_frame));
   # else
     void GC_push_regs GC_PROTO((void));
   # endif
                           /* Push register contents onto mark stack.      */
                           /* If NURSERY is defined, the default push      */
                           /* action can be overridden with GC_push_proc   */
   
 # ifdef NURSERY  # ifdef NURSERY
     extern void (*GC_push_proc)(ptr_t);      extern void (*GC_push_proc)(ptr_t);
 # endif  # endif
 # if defined(MSWIN32)  # if defined(MSWIN32) || defined(MSWINCE)
   void __cdecl GC_push_one();    void __cdecl GC_push_one GC_PROTO((word p));
 # else  # else
   void GC_push_one(/*p*/);    /* If p points to an object, mark it    */    void GC_push_one GC_PROTO((word p));
                                 /* If p points to an object, mark it    */
                               /* and push contents on the mark stack  */                                /* and push contents on the mark stack  */
                                 /* Pointer recognition test always      */
                                 /* accepts interior pointers, i.e. this */
                                 /* is appropriate for pointers found on */
                                 /* stack.                               */
 # endif  # endif
 void GC_push_one_checked(/*p*/); /* Ditto, omits plausibility test      */  # if defined(PRINT_BLACK_LIST) || defined(KEEP_BACK_PTRS)
 void GC_push_marked(/* struct hblk h, hdr * hhdr */);    void GC_mark_and_push_stack GC_PROTO((word p, ptr_t source));
                                   /* Ditto, omits plausibility test       */
   # else
     void GC_mark_and_push_stack GC_PROTO((word p));
   # endif
   void GC_push_marked GC_PROTO((struct hblk * h, hdr * hhdr));
                 /* Push contents of all marked objects in h onto        */                  /* Push contents of all marked objects in h onto        */
                 /* mark stack.                                          */                  /* mark stack.                                          */
 #ifdef SMALL_CONFIG  #ifdef SMALL_CONFIG
 # define GC_push_next_marked_dirty(h) GC_push_next_marked(h)  # define GC_push_next_marked_dirty(h) GC_push_next_marked(h)
 #else  #else
   struct hblk * GC_push_next_marked_dirty(/* h */);    struct hblk * GC_push_next_marked_dirty GC_PROTO((struct hblk * h));
                 /* Invoke GC_push_marked on next dirty block above h.   */                  /* Invoke GC_push_marked on next dirty block above h.   */
                 /* Return a pointer just past the end of this block.    */                  /* Return a pointer just past the end of this block.    */
 #endif /* !SMALL_CONFIG */  #endif /* !SMALL_CONFIG */
 struct hblk * GC_push_next_marked(/* h */);  struct hblk * GC_push_next_marked GC_PROTO((struct hblk * h));
                 /* Ditto, but also mark from clean pages.       */                  /* Ditto, but also mark from clean pages.       */
 struct hblk * GC_push_next_marked_uncollectable(/* h */);  struct hblk * GC_push_next_marked_uncollectable GC_PROTO((struct hblk * h));
                 /* Ditto, but mark only from uncollectable pages.       */                  /* Ditto, but mark only from uncollectable pages.       */
 GC_bool GC_stopped_mark(); /* Stop world and mark from all roots        */  GC_bool GC_stopped_mark GC_PROTO((GC_stop_func stop_func));
                         /* and rescuers.                        */                          /* Stop world and mark from all roots   */
 void GC_clear_hdr_marks(/* hhdr */);  /* Clear the mark bits in a header */                          /* and rescuers.                        */
 void GC_set_hdr_marks(/* hhdr */);  /* Set the mark bits in a header */  void GC_clear_hdr_marks GC_PROTO((hdr * hhdr));
 void GC_add_roots_inner();                                      /* Clear the mark bits in a header */
 GC_bool GC_is_static_root(/* ptr_t p */);  void GC_set_hdr_marks GC_PROTO((hdr * hhdr));
                 /* Is the address p in one of the registered static     */                                      /* Set the mark bits in a header */
   void GC_add_roots_inner GC_PROTO((char * b, char * e, GC_bool tmp));
   GC_bool GC_is_static_root GC_PROTO((ptr_t p));
                   /* Is the address p in one of the registered static     */
                   /* root sections?                                       */
   # if defined(MSWIN32) || defined(_WIN32_WCE_EMULATION)
   GC_bool GC_is_tmp_root GC_PROTO((ptr_t p));
                   /* Is the address p in one of the temporary static      */
                 /* root sections?                                       */                  /* root sections?                                       */
 void GC_register_dynamic_libraries();  # endif
                 /* Add dynamic library data sections to the root set. */  void GC_register_dynamic_libraries GC_PROTO((void));
                   /* Add dynamic library data sections to the root set. */
   
 /* Machine dependent startup routines */  /* Machine dependent startup routines */
 ptr_t GC_get_stack_base();  ptr_t GC_get_stack_base GC_PROTO((void));       /* Cold end of stack */
 void GC_register_data_segments();  #ifdef IA64
     ptr_t GC_get_register_stack_base GC_PROTO((void));
                                           /* Cold end of register stack.  */
   #endif
   void GC_register_data_segments GC_PROTO((void));
   
 /* Black listing: */  /* Black listing: */
 void GC_bl_init();  void GC_bl_init GC_PROTO((void));
 # ifndef ALL_INTERIOR_POINTERS  # ifdef PRINT_BLACK_LIST
     void GC_add_to_black_list_normal(/* bits, maybe source */);        void GC_add_to_black_list_normal GC_PROTO((word p, ptr_t source));
                         /* Register bits as a possible future false     */                          /* Register bits as a possible future false     */
                         /* reference from the heap or static data       */                          /* reference from the heap or static data       */
 #   ifdef PRINT_BLACK_LIST  
 #     define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \  #     define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \
                         GC_add_to_black_list_normal(bits, source)                  if (GC_all_interior_pointers) { \
 #   else                    GC_add_to_black_list_stack(bits, source); \
 #     define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \                  } else { \
                         GC_add_to_black_list_normal(bits)                    GC_add_to_black_list_normal(bits, source); \
 #   endif                  }
 # else  # else
 #   ifdef PRINT_BLACK_LIST        void GC_add_to_black_list_normal GC_PROTO((word p));
 #     define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \  #     define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \
                         GC_add_to_black_list_stack(bits, source)                  if (GC_all_interior_pointers) { \
 #   else                    GC_add_to_black_list_stack(bits); \
 #     define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \                  } else { \
                         GC_add_to_black_list_stack(bits)                    GC_add_to_black_list_normal(bits); \
 #   endif                  }
 # endif  # endif
   
 void GC_add_to_black_list_stack(/* bits, maybe source */);  # ifdef PRINT_BLACK_LIST
 struct hblk * GC_is_black_listed(/* h, len */);      void GC_add_to_black_list_stack GC_PROTO((word p, ptr_t source));
                         /* If there are likely to be false references   */  # else
                         /* to a block starting at h of the indicated    */      void GC_add_to_black_list_stack GC_PROTO((word p));
                         /* length, then return the next plausible       */  # endif
                         /* starting location for h that might avoid     */  struct hblk * GC_is_black_listed GC_PROTO((struct hblk * h, word len));
                         /* these false references.                      */                          /* If there are likely to be false references   */
 void GC_promote_black_lists();                          /* to a block starting at h of the indicated    */
                         /* Declare an end to a black listing phase.     */                          /* length, then return the next plausible       */
 void GC_unpromote_black_lists();                          /* starting location for h that might avoid     */
                         /* Approximately undo the effect of the above.  */                          /* these false references.                      */
                         /* This actually loses some information, but    */  void GC_promote_black_lists GC_PROTO((void));
                         /* only in a reasonably safe way.               */                          /* Declare an end to a black listing phase.     */
 word GC_number_stack_black_listed(/*struct hblk *start, struct hblk *endp1 */);  void GC_unpromote_black_lists GC_PROTO((void));
                         /* Return the number of (stack) blacklisted     */                          /* Approximately undo the effect of the above.  */
                         /* blocks in the range for statistical          */                          /* This actually loses some information, but    */
                         /* purposes.                                    */                          /* only in a reasonably safe way.               */
   word GC_number_stack_black_listed GC_PROTO(( \
 ptr_t GC_scratch_alloc(/*bytes*/);          struct hblk *start, struct hblk *endp1));
                                 /* GC internal memory allocation for    */                          /* Return the number of (stack) blacklisted     */
                                 /* small objects.  Deallocation is not  */                          /* blocks in the range for statistical          */
                                 /* possible.                            */                          /* purposes.                                    */
   
   ptr_t GC_scratch_alloc GC_PROTO((word bytes));
                                   /* GC internal memory allocation for    */
                                   /* small objects.  Deallocation is not  */
                                   /* possible.                            */
   
 /* Heap block layout maps: */  /* Heap block layout maps: */
 void GC_invalidate_map(/* hdr */);  void GC_invalidate_map GC_PROTO((hdr * hhdr));
                                 /* Remove the object map associated     */                                  /* Remove the object map associated     */
                                 /* with the block.  This identifies     */                                  /* with the block.  This identifies     */
                                 /* the block as invalid to the mark     */                                  /* the block as invalid to the mark     */
                                 /* routines.                            */                                  /* routines.                            */
 GC_bool GC_add_map_entry(/*sz*/);  GC_bool GC_add_map_entry GC_PROTO((word sz));
                                 /* Add a heap block map for objects of  */                                  /* Add a heap block map for objects of  */
                                 /* size sz to obj_map.                  */                                  /* size sz to obj_map.                  */
                                 /* Return FALSE on failure.             */                                  /* Return FALSE on failure.             */
 void GC_register_displacement_inner(/*offset*/);  void GC_register_displacement_inner GC_PROTO((word offset));
                                 /* Version of GC_register_displacement  */                                  /* Version of GC_register_displacement  */
                                 /* that assumes lock is already held    */                                  /* that assumes lock is already held    */
                                 /* and signals are already disabled.    */                                  /* and signals are already disabled.    */
   
 /*  hblk allocation: */  /*  hblk allocation: */
 void GC_new_hblk(/*size_in_words, kind*/);  void GC_new_hblk GC_PROTO((word size_in_words, int kind));
                                 /* Allocate a new heap block, and build */                                  /* Allocate a new heap block, and build */
                                 /* a free list in it.                   */                                  /* a free list in it.                   */
 struct hblk * GC_allochblk(/*size_in_words, kind*/);  
                                 /* Allocate a heap block, clear it if   */  ptr_t GC_build_fl GC_PROTO((struct hblk *h, word sz,
                                 /* for composite objects, inform        */                             GC_bool clear,  ptr_t list));
                                   /* Build a free list for objects of     */
                                   /* size sz in block h.  Append list to  */
                                   /* end of the free lists.  Possibly     */
                                   /* clear objects on the list.  Normally */
                                   /* called by GC_new_hblk, but also      */
                                   /* called explicitly without GC lock.   */
   
   struct hblk * GC_allochblk GC_PROTO(( \
           word size_in_words, int kind, unsigned flags));
                                   /* Allocate a heap block, inform        */
                                 /* the marker that block is valid       */                                  /* the marker that block is valid       */
                                 /* for objects of indicated size.       */                                  /* for objects of indicated size.       */
                                 /* sz < 0 ==> atomic.                   */  
 void GC_freehblk();             /* Deallocate a heap block and mark it  */  ptr_t GC_alloc_large GC_PROTO((word lw, int k, unsigned flags));
                                 /* as invalid.                          */                          /* Allocate a large block of size lw words.     */
                           /* The block is not cleared.                    */
                           /* Flags is 0 or IGNORE_OFF_PAGE.               */
                           /* Calls GC_allchblk to do the actual           */
                           /* allocation, but also triggers GC and/or      */
                           /* heap expansion as appropriate.               */
                           /* Does not update GC_words_allocd, but does    */
                           /* other accounting.                            */
   
   ptr_t GC_alloc_large_and_clear GC_PROTO((word lw, int k, unsigned flags));
                           /* As above, but clear block if appropriate     */
                           /* for kind k.                                  */
   
   void GC_freehblk GC_PROTO((struct hblk * p));
                                   /* Deallocate a heap block and mark it  */
                                   /* as invalid.                          */
   
 /*  Misc GC: */  /*  Misc GC: */
 void GC_init_inner();  void GC_init_inner GC_PROTO((void));
 GC_bool GC_expand_hp_inner();  GC_bool GC_expand_hp_inner GC_PROTO((word n));
 void GC_start_reclaim(/*abort_if_found*/);  void GC_start_reclaim GC_PROTO((int abort_if_found));
                                 /* Restore unmarked objects to free     */                                  /* Restore unmarked objects to free     */
                                 /* lists, or (if abort_if_found is      */                                  /* lists, or (if abort_if_found is      */
                                 /* TRUE) report them.                   */                                  /* TRUE) report them.                   */
                                 /* Sweeping of small object pages is    */                                  /* Sweeping of small object pages is    */
                                 /* largely deferred.                    */                                  /* largely deferred.                    */
 void GC_continue_reclaim(/*size, kind*/);  void GC_continue_reclaim GC_PROTO((word sz, int kind));
                                 /* Sweep pages of the given size and    */                                  /* Sweep pages of the given size and    */
                                 /* kind, as long as possible, and       */                                  /* kind, as long as possible, and       */
                                 /* as long as the corr. free list is    */                                  /* as long as the corr. free list is    */
                                 /* empty.                               */                                  /* empty.                               */
 void GC_reclaim_or_delete_all();  void GC_reclaim_or_delete_all GC_PROTO((void));
                                 /* Arrange for all reclaim lists to be  */                                  /* Arrange for all reclaim lists to be  */
                                 /* empty.  Judiciously choose between   */                                  /* empty.  Judiciously choose between   */
                                 /* sweeping and discarding each page.   */                                  /* sweeping and discarding each page.   */
 GC_bool GC_reclaim_all(/* GC_stop_func f*/);  GC_bool GC_reclaim_all GC_PROTO((GC_stop_func stop_func, GC_bool ignore_old));
                                 /* Reclaim all blocks.  Abort (in a     */                                  /* Reclaim all blocks.  Abort (in a     */
                                 /* consistent state) if f returns TRUE. */                                  /* consistent state) if f returns TRUE. */
 GC_bool GC_block_empty(/* hhdr */); /* Block completely unmarked?       */  GC_bool GC_block_empty GC_PROTO((hdr * hhdr));
 GC_bool GC_never_stop_func();   /* Returns FALSE.               */                                  /* Block completely unmarked?   */
 GC_bool GC_try_to_collect_inner(/* GC_stop_func f */);  GC_bool GC_never_stop_func GC_PROTO((void));
                                   /* Returns FALSE.               */
   GC_bool GC_try_to_collect_inner GC_PROTO((GC_stop_func f));
   
                                 /* Collect; caller must have acquired   */                                  /* Collect; caller must have acquired   */
                                 /* lock and disabled signals.           */                                  /* lock and disabled signals.           */
                                 /* Collection is aborted if f returns   */                                  /* Collection is aborted if f returns   */
Line 1626  GC_bool GC_try_to_collect_inner(/* GC_stop_func f */);
Line 1613  GC_bool GC_try_to_collect_inner(/* GC_stop_func f */);
                                 /* successfully.                        */                                  /* successfully.                        */
 # define GC_gcollect_inner() \  # define GC_gcollect_inner() \
         (void) GC_try_to_collect_inner(GC_never_stop_func)          (void) GC_try_to_collect_inner(GC_never_stop_func)
 void GC_finish_collection();    /* Finish collection.  Mark bits are    */  void GC_finish_collection GC_PROTO((void));
                                 /* consistent and lock is still held.   */                                  /* Finish collection.  Mark bits are    */
 GC_bool GC_collect_or_expand(/* needed_blocks */);                                  /* consistent and lock is still held.   */
                                 /* Collect or expand heap in an attempt */  GC_bool GC_collect_or_expand GC_PROTO(( \
                                 /* make the indicated number of free    */          word needed_blocks, GC_bool ignore_off_page));
                                 /* blocks available.  Should be called  */                                  /* Collect or expand heap in an attempt */
                                 /* until the blocks are available or    */                                  /* make the indicated number of free    */
                                 /* until it fails by returning FALSE.   */                                  /* blocks available.  Should be called  */
 GC_API void GC_init();          /* Initialize collector.                */                                  /* until the blocks are available or    */
 void GC_collect_a_little_inner(/* int n */);                                  /* until it fails by returning FALSE.   */
                                 /* Do n units worth of garbage          */  GC_API void GC_init GC_PROTO((void)); /* Initialize collector.          */
                                 /* collection work, if appropriate.     */  
                                 /* A unit is an amount appropriate for  */  #if defined(MSWIN32) || defined(MSWINCE)
                                 /* HBLKSIZE bytes of allocation.        */    void GC_deinit GC_PROTO((void));
 ptr_t GC_generic_malloc(/* bytes, kind */);                                  /* Free any resources allocated by      */
                                 /* Allocate an object of the given      */                                  /* GC_init                              */
                                 /* kind.  By default, there are only    */  #endif
                                 /* a few kinds: composite(pointerfree), */  
   void GC_collect_a_little_inner GC_PROTO((int n));
                                   /* Do n units worth of garbage          */
                                   /* collection work, if appropriate.     */
                                   /* A unit is an amount appropriate for  */
                                   /* HBLKSIZE bytes of allocation.        */
   ptr_t GC_generic_malloc GC_PROTO((word lb, int k));
                                   /* Allocate an object of the given      */
                                   /* kind.  By default, there are only    */
                                   /* a few kinds: composite(pointerfree), */
                                 /* atomic, uncollectable, etc.          */                                  /* atomic, uncollectable, etc.          */
                                 /* We claim it's possible for clever    */                                  /* We claim it's possible for clever    */
                                 /* client code that understands GC      */                                  /* client code that understands GC      */
                                 /* internals to add more, e.g. to       */                                  /* internals to add more, e.g. to       */
                                 /* communicate object layout info       */                                  /* communicate object layout info       */
                                 /* to the collector.                    */                                  /* to the collector.                    */
 ptr_t GC_generic_malloc_ignore_off_page(/* bytes, kind */);  ptr_t GC_generic_malloc_ignore_off_page GC_PROTO((size_t b, int k));
                                 /* As above, but pointers past the      */                                  /* As above, but pointers past the      */
                                 /* first page of the resulting object   */                                  /* first page of the resulting object   */
                                 /* are ignored.                         */                                  /* are ignored.                         */
 ptr_t GC_generic_malloc_inner(/* bytes, kind */);  ptr_t GC_generic_malloc_inner GC_PROTO((word lb, int k));
                                 /* Ditto, but I already hold lock, etc. */                                  /* Ditto, but I already hold lock, etc. */
 ptr_t GC_generic_malloc_words_small GC_PROTO((size_t words, int kind));  ptr_t GC_generic_malloc_words_small GC_PROTO((size_t lw, int k));
                                 /* As above, but size in units of words */                                  /* As above, but size in units of words */
                                 /* Bypasses MERGE_SIZES.  Assumes       */                                  /* Bypasses MERGE_SIZES.  Assumes       */
                                 /* words <= MAXOBJSZ.                   */                                  /* words <= MAXOBJSZ.                   */
 ptr_t GC_generic_malloc_inner_ignore_off_page(/* bytes, kind */);  ptr_t GC_generic_malloc_inner_ignore_off_page GC_PROTO((size_t lb, int k));
                                 /* Allocate an object, where            */                                  /* Allocate an object, where            */
                                 /* the client guarantees that there     */                                  /* the client guarantees that there     */
                                 /* will always be a pointer to the      */                                  /* will always be a pointer to the      */
                                 /* beginning of the object while the    */                                  /* beginning of the object while the    */
                                 /* object is live.                      */                                  /* object is live.                      */
 ptr_t GC_allocobj(/* sz_inn_words, kind */);  ptr_t GC_allocobj GC_PROTO((word sz, int kind));
                                 /* Make the indicated                   */                                  /* Make the indicated                   */
                                 /* free list nonempty, and return its   */                                  /* free list nonempty, and return its   */
                                 /* head.                                */                                  /* head.                                */
   
   void GC_init_headers GC_PROTO((void));
   struct hblkhdr * GC_install_header GC_PROTO((struct hblk *h));
                                   /* Install a header for block h.        */
                                   /* Return 0 on failure, or the header   */
                                   /* otherwise.                           */
   GC_bool GC_install_counts GC_PROTO((struct hblk * h, word sz));
                                   /* Set up forwarding counts for block   */
                                   /* h of size sz.                        */
                                   /* Return FALSE on failure.             */
   void GC_remove_header GC_PROTO((struct hblk * h));
                                   /* Remove the header for block h.       */
   void GC_remove_counts GC_PROTO((struct hblk * h, word sz));
                                   /* Remove forwarding counts for h.      */
   hdr * GC_find_header GC_PROTO((ptr_t h)); /* Debugging only.            */
   
   void GC_finalize GC_PROTO((void));
                           /* Perform all indicated finalization actions   */
                           /* on unmarked objects.                         */
                           /* Unreachable finalizable objects are enqueued */
                           /* for processing by GC_invoke_finalizers.      */
                           /* Invoked with lock.                           */
   
 void GC_init_headers();  void GC_notify_or_invoke_finalizers GC_PROTO((void));
 GC_bool GC_install_header(/*h*/);                          /* If GC_finalize_on_demand is not set, invoke  */
                                 /* Install a header for block h.        */                          /* eligible finalizers. Otherwise:              */
                                 /* Return FALSE on failure.             */                          /* Call *GC_finalizer_notifier if there are     */
 GC_bool GC_install_counts(/*h, sz*/);                          /* finalizers to be run, and we haven't called  */
                                 /* Set up forwarding counts for block   */                          /* this procedure yet this GC cycle.            */
                                 /* h of size sz.                        */  
                                 /* Return FALSE on failure.             */  void GC_add_to_heap GC_PROTO((struct hblk *p, word bytes));
 void GC_remove_header(/*h*/);                          /* Add a HBLKSIZE aligned chunk to the heap.    */
                                 /* Remove the header for block h.       */  
 void GC_remove_counts(/*h, sz*/);  void GC_print_obj GC_PROTO((ptr_t p));
                                 /* Remove forwarding counts for h.      */                          /* P points to somewhere inside an object with  */
 hdr * GC_find_header(/*p*/);    /* Debugging only.                      */                          /* debugging info.  Print a human readable      */
                           /* description of the object to stderr.         */
   extern void (*GC_check_heap) GC_PROTO((void));
                           /* Check that all objects in the heap with      */
                           /* debugging info are intact.  Print            */
                           /* descriptions of any that are not.            */
   extern void (*GC_print_heap_obj) GC_PROTO((ptr_t p));
                           /* If possible print s followed by a more       */
                           /* detailed description of the object           */
                           /* referred to by p.                            */
   
 void GC_finalize();     /* Perform all indicated finalization actions   */  extern GC_bool GC_print_stats;  /* Produce at least some logging output */
                         /* on unmarked objects.                         */                                  /* Set from environment variable.       */
                         /* Unreachable finalizable objects are enqueued */  
                         /* for processing by GC_invoke_finalizers.      */  
                         /* Invoked with lock.                           */  
   
 void GC_add_to_heap(/*p, bytes*/);  
                         /* Add a HBLKSIZE aligned chunk to the heap.    */  
   
 void GC_print_obj(/* ptr_t p */);  /* Macros used for collector internal allocation.       */
                         /* P points to somewhere inside an object with  */  /* These assume the collector lock is held.             */
                         /* debugging info.  Print a human readable      */  #ifdef DBG_HDRS_ALL
                         /* description of the object to stderr.         */      extern GC_PTR GC_debug_generic_malloc_inner(size_t lb, int k);
 extern void (*GC_check_heap)();      extern GC_PTR GC_debug_generic_malloc_inner_ignore_off_page(size_t lb,
                         /* Check that all objects in the heap with      */                                                                  int k);
                         /* debugging info are intact.  Print            */  #   define GC_INTERNAL_MALLOC GC_debug_generic_malloc_inner
                         /* descriptions of any that are not.            */  #   define GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE \
 extern void (*GC_print_heap_obj)(/* ptr_t p */);                   GC_debug_generic_malloc_inner_ignore_off_page
                         /* If possible print s followed by a more       */  #   ifdef THREADS
                         /* detailed description of the object           */  #       define GC_INTERNAL_FREE GC_debug_free_inner
                         /* referred to by p.                            */  #   else
   #       define GC_INTERNAL_FREE GC_debug_free
   #   endif
   #else
   #   define GC_INTERNAL_MALLOC GC_generic_malloc_inner
   #   define GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE \
                    GC_generic_malloc_inner_ignore_off_page
   #   ifdef THREADS
   #       define GC_INTERNAL_FREE GC_free_inner
   #   else
   #       define GC_INTERNAL_FREE GC_free
   #   endif
   #endif
   
 /* Memory unmapping: */  /* Memory unmapping: */
 #ifdef USE_MUNMAP  #ifdef USE_MUNMAP
   void GC_unmap_old(void);    void GC_unmap_old(void);
Line 1718  extern void (*GC_print_heap_obj)(/* ptr_t p */);
Line 1751  extern void (*GC_print_heap_obj)(/* ptr_t p */);
   
 /* Virtual dirty bit implementation:            */  /* Virtual dirty bit implementation:            */
 /* Each implementation exports the following:   */  /* Each implementation exports the following:   */
 void GC_read_dirty();   /* Retrieve dirty bits. */  void GC_read_dirty GC_PROTO((void));
 GC_bool GC_page_was_dirty(/* struct hblk * h  */);                          /* Retrieve dirty bits. */
                         /* Read retrieved dirty bits.   */  GC_bool GC_page_was_dirty GC_PROTO((struct hblk *h));
 GC_bool GC_page_was_ever_dirty(/* struct hblk * h  */);                          /* Read retrieved dirty bits.   */
                         /* Could the page contain valid heap pointers?  */  GC_bool GC_page_was_ever_dirty GC_PROTO((struct hblk *h));
 void GC_is_fresh(/* struct hblk * h, word number_of_blocks  */);                          /* Could the page contain valid heap pointers?  */
                         /* Assert the region currently contains no      */  void GC_is_fresh GC_PROTO((struct hblk *h, word n));
                         /* valid pointers.                              */                          /* Assert the region currently contains no      */
 void GC_write_hint(/* struct hblk * h  */);                          /* valid pointers.                              */
                         /* h is about to be written.    */  void GC_write_hint GC_PROTO((struct hblk *h));
 void GC_dirty_init();                          /* h is about to be written.    */
   void GC_dirty_init GC_PROTO((void));
   
 /* Slow/general mark bit manipulation: */  /* Slow/general mark bit manipulation: */
 GC_API GC_bool GC_is_marked();  GC_API GC_bool GC_is_marked GC_PROTO((ptr_t p));
 void GC_clear_mark_bit();  void GC_clear_mark_bit GC_PROTO((ptr_t p));
 void GC_set_mark_bit();  void GC_set_mark_bit GC_PROTO((ptr_t p));
   
 /* Stubborn objects: */  /* Stubborn objects: */
 void GC_read_changed(); /* Analogous to GC_read_dirty */  void GC_read_changed GC_PROTO((void));  /* Analogous to GC_read_dirty */
 GC_bool GC_page_was_changed(/* h */);   /* Analogous to GC_page_was_dirty */  GC_bool GC_page_was_changed GC_PROTO((struct hblk * h));
 void GC_clean_changing_list();  /* Collect obsolete changing list entries */                                  /* Analogous to GC_page_was_dirty */
 void GC_stubborn_init();  void GC_clean_changing_list GC_PROTO((void));
                                   /* Collect obsolete changing list entries */
   void GC_stubborn_init GC_PROTO((void));
   
 /* Debugging print routines: */  /* Debugging print routines: */
 void GC_print_block_list();  void GC_print_block_list GC_PROTO((void));
 void GC_print_hblkfreelist();  void GC_print_hblkfreelist GC_PROTO((void));
 void GC_print_heap_sects();  void GC_print_heap_sects GC_PROTO((void));
 void GC_print_static_roots();  void GC_print_static_roots GC_PROTO((void));
 void GC_dump();  void GC_dump GC_PROTO((void));
   
 #ifdef KEEP_BACK_PTRS  #ifdef KEEP_BACK_PTRS
    void GC_store_back_pointer(ptr_t source, ptr_t dest);     void GC_store_back_pointer(ptr_t source, ptr_t dest);
Line 1765  void GC_dump();
Line 1801  void GC_dump();
   GC_API void GC_noop();    GC_API void GC_noop();
 # endif  # endif
   
 void GC_noop1(/* word arg */);  void GC_noop1 GC_PROTO((word arg));
   
 /* Logging and diagnostic output:       */  /* Logging and diagnostic output:       */
 GC_API void GC_printf GC_PROTO((char * format, long, long, long, long, long, long));  GC_API void GC_printf GC_PROTO((GC_CONST char * format, long, long, long, long, long, long));
                         /* A version of printf that doesn't allocate,   */                          /* A version of printf that doesn't allocate,   */
                         /* is restricted to long arguments, and         */                          /* is restricted to long arguments, and         */
                         /* (unfortunately) doesn't use varargs for      */                          /* (unfortunately) doesn't use varargs for      */
Line 1787  GC_API void GC_printf GC_PROTO((char * format, long, l
Line 1823  GC_API void GC_printf GC_PROTO((char * format, long, l
 # define GC_printf6(f,a,b,c,d,e,g) GC_printf(f, (long)a, (long)b, (long)c, \  # define GC_printf6(f,a,b,c,d,e,g) GC_printf(f, (long)a, (long)b, (long)c, \
                                                 (long)d, (long)e, (long)g)                                                  (long)d, (long)e, (long)g)
   
 void GC_err_printf(/* format, a, b, c, d, e, f */);  GC_API void GC_err_printf GC_PROTO((GC_CONST char * format, long, long, long, long, long, long));
 # define GC_err_printf0(f) GC_err_puts(f)  # define GC_err_printf0(f) GC_err_puts(f)
 # define GC_err_printf1(f,a) GC_err_printf(f, (long)a, 0l, 0l, 0l, 0l, 0l)  # define GC_err_printf1(f,a) GC_err_printf(f, (long)a, 0l, 0l, 0l, 0l, 0l)
 # define GC_err_printf2(f,a,b) GC_err_printf(f, (long)a, (long)b, 0l, 0l, 0l, 0l)  # define GC_err_printf2(f,a,b) GC_err_printf(f, (long)a, (long)b, 0l, 0l, 0l, 0l)
Line 1803  void GC_err_printf(/* format, a, b, c, d, e, f */);
Line 1839  void GC_err_printf(/* format, a, b, c, d, e, f */);
                                                         (long)e, (long)g)                                                          (long)e, (long)g)
                         /* Ditto, writes to stderr.                     */                          /* Ditto, writes to stderr.                     */
   
 void GC_err_puts(/* char *s */);  void GC_err_puts GC_PROTO((GC_CONST char *s));
                         /* Write s to stderr, don't buffer, don't add   */                          /* Write s to stderr, don't buffer, don't add   */
                         /* newlines, don't ...                          */                          /* newlines, don't ...                          */
   
   #if defined(LINUX) && !defined(SMALL_CONFIG)
     void GC_err_write GC_PROTO((GC_CONST char *buf, size_t len));
                           /* Write buf to stderr, don't buffer, don't add */
                           /* newlines, don't ...                          */
   #endif
   
 #   ifdef GC_ASSERTIONS  
   # ifdef GC_ASSERTIONS
 #       define GC_ASSERT(expr) if(!(expr)) {\  #       define GC_ASSERT(expr) if(!(expr)) {\
                 GC_err_printf2("Assertion failure: %s:%ld\n", \                  GC_err_printf2("Assertion failure: %s:%ld\n", \
                                 __FILE__, (unsigned long)__LINE__); \                                  __FILE__, (unsigned long)__LINE__); \
                 ABORT("assertion failure"); }                  ABORT("assertion failure"); }
 #   else  # else
 #       define GC_ASSERT(expr)  #       define GC_ASSERT(expr)
 #   endif  # endif
   
   # ifdef PARALLEL_MARK
       /* We need additional synchronization facilities from the thread    */
       /* support.  We believe these are less performance critical         */
       /* than the main garbage collector lock; standard pthreads-based    */
       /* implementations should be sufficient.                            */
   
       /* The mark lock and condition variable.  If the GC lock is also    */
       /* acquired, the GC lock must be acquired first.  The mark lock is  */
       /* used to both protect some variables used by the parallel         */
       /* marker, and to protect GC_fl_builder_count, below.               */
       /* GC_notify_all_marker() is called when                            */
       /* the state of the parallel marker changes                         */
       /* in some significant way (see gc_mark.h for details).  The        */
       /* latter set of events includes incrementing GC_mark_no.           */
       /* GC_notify_all_builder() is called when GC_fl_builder_count       */
       /* reaches 0.                                                       */
   
        extern void GC_acquire_mark_lock();
        extern void GC_release_mark_lock();
        extern void GC_notify_all_marker();
        extern void GC_notify_all_builder();
        extern void GC_wait_marker();
        /* extern void GC_wait_builder(); */
        extern void GC_wait_for_reclaim();
   
        extern word GC_fl_builder_count;   /* Protected by mark lock.      */
        extern word GC_mark_no;            /* Protected by mark lock.      */
   
        extern void GC_help_marker(word my_mark_no);
                   /* Try to help out parallel marker for mark cycle       */
                   /* my_mark_no.  Returns if the mark cycle finishes or   */
                   /* was already done, or there was nothing to do for     */
                   /* some other reason.                                   */
   # endif /* PARALLEL_MARK */
   
 # endif /* GC_PRIVATE_H */  # endif /* GC_PRIVATE_H */

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.3

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>