[BACK]Return to misc.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / gc

Diff for /OpenXM_contrib2/asir2000/gc/misc.c between version 1.3 and 1.6

version 1.3, 2000/12/01 09:26:12 version 1.6, 2002/07/24 08:00:10
Line 1 
Line 1 
 /*  /*
  * 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) 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
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.   * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
Line 15 
Line 16 
   
   
 #include <stdio.h>  #include <stdio.h>
   #include <limits.h>
   #ifndef _WIN32_WCE
 #include <signal.h>  #include <signal.h>
   #endif
   
 #define I_HIDE_POINTERS /* To make GC_call_with_alloc_lock visible */  #define I_HIDE_POINTERS /* To make GC_call_with_alloc_lock visible */
 #include "gc_priv.h"  #include "private/gc_pmark.h"
   
 #ifdef SOLARIS_THREADS  #ifdef GC_SOLARIS_THREADS
 # include <sys/syscall.h>  # include <sys/syscall.h>
 #endif  #endif
 #ifdef MSWIN32  #if defined(MSWIN32) || defined(MSWINCE)
   # define WIN32_LEAN_AND_MEAN
   # define NOSERVICE
 # include <windows.h>  # include <windows.h>
   # include <tchar.h>
 #endif  #endif
   
 # ifdef THREADS  # ifdef THREADS
Line 36 
Line 43 
         /* Critical section counter is defined in the M3 runtime        */          /* Critical section counter is defined in the M3 runtime        */
         /* That's all we use.                                           */          /* That's all we use.                                           */
 #     else  #     else
 #       ifdef SOLARIS_THREADS  #       ifdef GC_SOLARIS_THREADS
           mutex_t GC_allocate_ml;       /* Implicitly initialized.      */            mutex_t GC_allocate_ml;       /* Implicitly initialized.      */
 #       else  #       else
 #          ifdef WIN32_THREADS  #          if defined(GC_WIN32_THREADS)
               GC_API CRITICAL_SECTION GC_allocate_ml;  #             if defined(GC_PTHREADS)
 #          else                    pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER;
 #             if defined(IRIX_THREADS) || defined(IRIX_JDK_THREADS) \  #             elif !defined(GC_NOT_DLL) && (defined(_DLL) || defined(GC_DLL))
                  || (defined(LINUX_THREADS) && defined(USE_SPIN_LOCK))                   __declspec(dllexport) CRITICAL_SECTION GC_allocate_ml;
                 pthread_t GC_lock_holder = NO_THREAD;  
 #             else  #             else
 #               if defined(HPUX_THREADS) \                   CRITICAL_SECTION GC_allocate_ml;
                    || defined(LINUX_THREADS) && !defined(USE_SPIN_LOCK)  #             endif
   #          else
   #             if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS)
   #               if defined(USE_SPIN_LOCK)
                     pthread_t GC_lock_holder = NO_THREAD;
   #               else
                   pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER;                    pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER;
 #               else                    pthread_t GC_lock_holder = NO_THREAD;
                           /* Used only for assertions, and to prevent      */
                           /* recursive reentry in the system call wrapper. */
   #               endif
   #             else
                   --> declare allocator lock here                    --> declare allocator lock here
 #               endif  
 #             endif  #             endif
 #          endif  #          endif
 #       endif  #       endif
Line 59 
Line 73 
 #   endif  #   endif
 # endif  # endif
   
   #if defined(NOSYS) || defined(ECOS)
   #undef STACKBASE
   #endif
   
 GC_FAR struct _GC_arrays GC_arrays /* = { 0 } */;  GC_FAR struct _GC_arrays GC_arrays /* = { 0 } */;
   
   
 GC_bool GC_debugging_started = FALSE;  GC_bool GC_debugging_started = FALSE;
         /* defined here so we don't have to load debug_malloc.o */          /* defined here so we don't have to load debug_malloc.o */
   
 void (*GC_check_heap)() = (void (*)())0;  void (*GC_check_heap) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0;
   void (*GC_print_all_smashed) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0;
   
 void (*GC_start_call_back)() = (void (*)())0;  void (*GC_start_call_back) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0;
   
 ptr_t GC_stackbottom = 0;  ptr_t GC_stackbottom = 0;
   
   #ifdef IA64
     ptr_t GC_register_stackbottom = 0;
   #endif
   
 GC_bool GC_dont_gc = 0;  GC_bool GC_dont_gc = 0;
   
   GC_bool GC_dont_precollect = 0;
   
 GC_bool GC_quiet = 0;  GC_bool GC_quiet = 0;
   
   GC_bool GC_print_stats = 0;
   
   GC_bool GC_print_back_height = 0;
   
 #ifdef FIND_LEAK  #ifdef FIND_LEAK
   int GC_find_leak = 1;    int GC_find_leak = 1;
 #else  #else
   int GC_find_leak = 0;    int GC_find_leak = 0;
 #endif  #endif
   
   #ifdef ALL_INTERIOR_POINTERS
     int GC_all_interior_pointers = 1;
   #else
     int GC_all_interior_pointers = 0;
   #endif
   
   long GC_large_alloc_warn_interval = 5;
           /* Interval between unsuppressed warnings.      */
   
   long GC_large_alloc_warn_suppressed = 0;
           /* Number of warnings suppressed so far.        */
   
 /*ARGSUSED*/  /*ARGSUSED*/
 GC_PTR GC_default_oom_fn GC_PROTO((size_t bytes_requested))  GC_PTR GC_default_oom_fn GC_PROTO((size_t bytes_requested))
 {  {
Line 103  extern signed_word GC_mem_found;
Line 144  extern signed_word GC_mem_found;
     {      {
         register unsigned i;          register unsigned i;
   
         /* Map size 0 to 1.  This avoids problems at lower levels. */          /* Map size 0 to something bigger.                      */
           GC_size_map[0] = 1;          /* This avoids problems at lower levels.                */
         /* One word objects don't have to be 2 word aligned.       */          /* One word objects don't have to be 2 word aligned,    */
           for (i = 1; i < sizeof(word); i++) {          /* unless we're using mark bytes.                       */
               GC_size_map[i] = 1;            for (i = 0; i < sizeof(word); i++) {
                 GC_size_map[i] = MIN_WORDS;
           }            }
           GC_size_map[sizeof(word)] = ROUNDED_UP_WORDS(sizeof(word));  #         if MIN_WORDS > 1
               GC_size_map[sizeof(word)] = MIN_WORDS;
   #         else
               GC_size_map[sizeof(word)] = ROUNDED_UP_WORDS(sizeof(word));
   #         endif
         for (i = sizeof(word) + 1; i <= 8 * sizeof(word); i++) {          for (i = sizeof(word) + 1; i <= 8 * sizeof(word); i++) {
 #           ifdef ALIGN_DOUBLE              GC_size_map[i] = ALIGNED_WORDS(i);
               GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 1) & (~1);  
 #           else  
               GC_size_map[i] = ROUNDED_UP_WORDS(i);  
 #           endif  
         }          }
         for (i = 8*sizeof(word) + 1; i <= 16 * sizeof(word); i++) {          for (i = 8*sizeof(word) + 1; i <= 16 * sizeof(word); i++) {
               GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 1) & (~1);                GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 1) & (~1);
Line 178  extern signed_word GC_mem_found;
Line 220  extern signed_word GC_mem_found;
 #           endif  #           endif
         }          }
         byte_sz = WORDS_TO_BYTES(word_sz);          byte_sz = WORDS_TO_BYTES(word_sz);
 #       ifdef ADD_BYTE_AT_END          if (GC_all_interior_pointers) {
             /* We need one extra byte; don't fill in GC_size_map[byte_sz] */              /* We need one extra byte; don't fill in GC_size_map[byte_sz] */
             byte_sz--;              byte_sz--;
 #       endif          }
   
         for (j = low_limit; j <= byte_sz; j++) GC_size_map[j] = word_sz;          for (j = low_limit; j <= byte_sz; j++) GC_size_map[j] = word_sz;
     }      }
Line 198  extern signed_word GC_mem_found;
Line 240  extern signed_word GC_mem_found;
  */   */
 word GC_stack_last_cleared = 0; /* GC_no when we last did this */  word GC_stack_last_cleared = 0; /* GC_no when we last did this */
 # ifdef THREADS  # ifdef THREADS
 #   define CLEAR_SIZE 2048  #   define BIG_CLEAR_SIZE 2048  /* Clear this much now and then.        */
 # else  #   define SMALL_CLEAR_SIZE 256 /* Clear this much every time.          */
 #   define CLEAR_SIZE 213  
 # endif  # endif
   # define CLEAR_SIZE 213  /* Granularity for GC_clear_stack_inner */
 # define DEGRADE_RATE 50  # define DEGRADE_RATE 50
   
 word GC_min_sp;         /* Coolest stack pointer value from which we've */  word GC_min_sp;         /* Coolest stack pointer value from which we've */
                         /* already cleared the stack.                   */                          /* already cleared the stack.                   */
   
 # 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  
   
 word GC_high_water;  word GC_high_water;
                         /* "hottest" stack pointer value we have seen   */                          /* "hottest" stack pointer value we have seen   */
                         /* recently.  Degrades over time.               */                          /* recently.  Degrades over time.               */
   
 word GC_words_allocd_at_reset;  word GC_words_allocd_at_reset;
   
 #if defined(ASM_CLEAR_CODE) && !defined(THREADS)  #if defined(ASM_CLEAR_CODE)
   extern ptr_t GC_clear_stack_inner();    extern ptr_t GC_clear_stack_inner();
 #endif  #else
   
 #if !defined(ASM_CLEAR_CODE) && !defined(THREADS)  
 /* Clear the stack up to about limit.  Return arg. */  /* Clear the stack up to about limit.  Return arg. */
 /*ARGSUSED*/  /*ARGSUSED*/
 ptr_t GC_clear_stack_inner(arg, limit)  ptr_t GC_clear_stack_inner(arg, limit)
Line 258  ptr_t arg;
Line 285  ptr_t arg;
 {  {
     register word sp = (word)GC_approx_sp();  /* Hotter than actual sp */      register word sp = (word)GC_approx_sp();  /* Hotter than actual sp */
 #   ifdef THREADS  #   ifdef THREADS
         word dummy[CLEAR_SIZE];          word dummy[SMALL_CLEAR_SIZE];
 #   else          static unsigned random_no = 0;
         register word limit;                                   /* Should be more random than it is ... */
                                    /* Used to occasionally clear a bigger  */
                                    /* chunk.                               */
 #   endif  #   endif
       register word limit;
   
 #   define SLOP 400  #   define SLOP 400
         /* Extra bytes we clear every time.  This clears our own        */          /* Extra bytes we clear every time.  This clears our own        */
Line 279  ptr_t arg;
Line 309  ptr_t arg;
         /* thus more junk remains accessible, thus the heap gets        */          /* thus more junk remains accessible, thus the heap gets        */
         /* larger ...                                                   */          /* larger ...                                                   */
 # ifdef THREADS  # ifdef THREADS
     BZERO(dummy, CLEAR_SIZE*sizeof(word));      if (++random_no % 13 == 0) {
           limit = sp;
           MAKE_HOTTER(limit, BIG_CLEAR_SIZE*sizeof(word));
           limit &= ~0xf;  /* Make it sufficiently aligned for assembly    */
                           /* implementations of GC_clear_stack_inner.     */
           return GC_clear_stack_inner(arg, limit);
       } else {
           BZERO(dummy, SMALL_CLEAR_SIZE*sizeof(word));
           return arg;
       }
 # else  # else
     if (GC_gc_no > GC_stack_last_cleared) {      if (GC_gc_no > GC_stack_last_cleared) {
         /* Start things over, so we clear the entire stack again */          /* Start things over, so we clear the entire stack again */
Line 309  ptr_t arg;
Line 348  ptr_t arg;
         if (GC_min_sp HOTTER_THAN GC_high_water) GC_min_sp = GC_high_water;          if (GC_min_sp HOTTER_THAN GC_high_water) GC_min_sp = GC_high_water;
         GC_words_allocd_at_reset = GC_words_allocd;          GC_words_allocd_at_reset = GC_words_allocd;
     }      }
       return(arg);
 # endif  # endif
   return(arg);  
 }  }
   
   
Line 339  ptr_t arg;
Line 378  ptr_t arg;
     /* to the beginning.                                                */      /* to the beginning.                                                */
         while (IS_FORWARDING_ADDR_OR_NIL(candidate_hdr)) {          while (IS_FORWARDING_ADDR_OR_NIL(candidate_hdr)) {
            h = FORWARDED_ADDR(h,candidate_hdr);             h = FORWARDED_ADDR(h,candidate_hdr);
            r = (word)h + HDR_BYTES;             r = (word)h;
            candidate_hdr = HDR(h);             candidate_hdr = HDR(h);
         }          }
     if (candidate_hdr -> hb_map == GC_invalid_map) return(0);      if (candidate_hdr -> hb_map == GC_invalid_map) return(0);
     /* Make sure r points to the beginning of the object */      /* Make sure r points to the beginning of the object */
         r &= ~(WORDS_TO_BYTES(1) - 1);          r &= ~(WORDS_TO_BYTES(1) - 1);
         {          {
             register int offset = (char *)r - (char *)(HBLKPTR(r));              register int offset = HBLKDISPL(r);
             register signed_word sz = candidate_hdr -> hb_sz;              register signed_word sz = candidate_hdr -> hb_sz;
               register signed_word map_entry;
 #           ifdef ALL_INTERIOR_POINTERS  
               register map_entry_type map_entry;  
   
               map_entry = MAP_ENTRY((candidate_hdr -> hb_map), offset);              map_entry = MAP_ENTRY((candidate_hdr -> hb_map), offset);
               if (map_entry == OBJ_INVALID) {              if (map_entry > CPP_MAX_OFFSET) {
                 return(0);                  map_entry = (signed_word)(BYTES_TO_WORDS(offset)) % sz;
               }              }
               r -= WORDS_TO_BYTES(map_entry);              r -= WORDS_TO_BYTES(map_entry);
               limit = r + WORDS_TO_BYTES(sz);              limit = r + WORDS_TO_BYTES(sz);
 #           else              if (limit > (word)(h + 1)
               register int correction;                  && sz <= BYTES_TO_WORDS(HBLKSIZE)) {
   
               offset = BYTES_TO_WORDS(offset - HDR_BYTES);  
               correction = offset % sz;  
               r -= (WORDS_TO_BYTES(correction));  
               limit = r + WORDS_TO_BYTES(sz);  
               if (limit > (word)(h + 1)  
                 && sz <= BYTES_TO_WORDS(HBLKSIZE) - HDR_WORDS) {  
                 return(0);                  return(0);
               }              }
 #           endif  
             if ((word)p >= limit) return(0);              if ((word)p >= limit) return(0);
         }          }
     return((GC_PTR)r);      return((GC_PTR)r);
Line 390  ptr_t arg;
Line 419  ptr_t arg;
     register hdr * hhdr = HDR(p);      register hdr * hhdr = HDR(p);
   
     sz = WORDS_TO_BYTES(hhdr -> hb_sz);      sz = WORDS_TO_BYTES(hhdr -> hb_sz);
     if (sz < 0) {      return(sz);
         return(-sz);  
     } else {  
         return(sz);  
     }  
 }  }
   
 size_t GC_get_heap_size GC_PROTO(())  size_t GC_get_heap_size GC_PROTO(())
Line 412  size_t GC_get_bytes_since_gc GC_PROTO(())
Line 437  size_t GC_get_bytes_since_gc GC_PROTO(())
     return ((size_t) WORDS_TO_BYTES(GC_words_allocd));      return ((size_t) WORDS_TO_BYTES(GC_words_allocd));
 }  }
   
   size_t GC_get_total_bytes GC_PROTO(())
   {
       return ((size_t) WORDS_TO_BYTES(GC_words_allocd+GC_words_allocd_before_gc));
   }
   
 GC_bool GC_is_initialized = FALSE;  GC_bool GC_is_initialized = FALSE;
   
 void GC_init()  void GC_init()
Line 419  void GC_init()
Line 449  void GC_init()
     DCL_LOCK_STATE;      DCL_LOCK_STATE;
   
     DISABLE_SIGNALS();      DISABLE_SIGNALS();
   
   #if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)
       if (!GC_is_initialized) InitializeCriticalSection(&GC_allocate_ml);
   #endif /* MSWIN32 */
   
     LOCK();      LOCK();
     GC_init_inner();      GC_init_inner();
     UNLOCK();      UNLOCK();
     ENABLE_SIGNALS();      ENABLE_SIGNALS();
   
   #   if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
           /* Make sure marker threads and started and thread local */
           /* allocation is initialized, in case we didn't get      */
           /* called from GC_init_parallel();                       */
           {
             extern void GC_init_parallel(void);
             GC_init_parallel();
           }
   #   endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
 }  }
   
   #if defined(MSWIN32) || defined(MSWINCE)
       CRITICAL_SECTION GC_write_cs;
   #endif
   
 #ifdef MSWIN32  #ifdef MSWIN32
     extern void GC_init_win32();      extern void GC_init_win32 GC_PROTO((void));
 #endif  #endif
   
 extern void GC_setpagesize();  extern void GC_setpagesize();
   
   #ifdef UNIX_LIKE
   
   extern void GC_set_and_save_fault_handler GC_PROTO((void (*handler)(int)));
   
   static void looping_handler(sig)
   int sig;
   {
       GC_err_printf1("Caught signal %d: looping in handler\n", sig);
       for(;;);
   }
   #endif
   
   #ifdef MSWIN32
   extern GC_bool GC_no_win32_dlls;
   #else
   # define GC_no_win32_dlls FALSE
   #endif
   
 void GC_init_inner()  void GC_init_inner()
 {  {
 #   ifndef THREADS  #   if !defined(THREADS) && defined(GC_ASSERTIONS)
         word dummy;          word dummy;
 #   endif  #   endif
       word initial_heap_sz = (word)MINHINCR;
   
     if (GC_is_initialized) return;      if (GC_is_initialized) return;
     GC_setpagesize();  
     GC_exclude_static_roots(beginGC_arrays, end_gc_area);  
 #   ifdef PRINTSTATS  #   ifdef PRINTSTATS
         if ((ptr_t)endGC_arrays != (ptr_t)(&GC_obj_kinds)) {        GC_print_stats = 1;
             GC_printf0("Reordering linker, didn't exclude obj_kinds\n");  
         }  
 #   endif  #   endif
   #   if defined(MSWIN32) || defined(MSWINCE)
         InitializeCriticalSection(&GC_write_cs);
   #   endif
       if (0 != GETENV("GC_PRINT_STATS")) {
         GC_print_stats = 1;
       }
       if (0 != GETENV("GC_FIND_LEAK")) {
         GC_find_leak = 1;
       }
       if (0 != GETENV("GC_ALL_INTERIOR_POINTERS")) {
         GC_all_interior_pointers = 1;
       }
       if (0 != GETENV("GC_DONT_GC")) {
         GC_dont_gc = 1;
       }
       if (0 != GETENV("GC_PRINT_BACK_HEIGHT")) {
         GC_print_back_height = 1;
       }
       if (0 != GETENV("GC_NO_BLACKLIST_WARNING")) {
         GC_large_alloc_warn_interval = LONG_MAX;
       }
       {
         char * time_limit_string = GETENV("GC_PAUSE_TIME_TARGET");
         if (0 != time_limit_string) {
           long time_limit = atol(time_limit_string);
           if (time_limit < 5) {
             WARN("GC_PAUSE_TIME_TARGET environment variable value too small "
                  "or bad syntax: Ignoring\n", 0);
           } else {
             GC_time_limit = time_limit;
           }
         }
       }
       {
         char * interval_string = GETENV("GC_LARGE_ALLOC_WARN_INTERVAL");
         if (0 != interval_string) {
           long interval = atol(interval_string);
           if (interval <= 0) {
             WARN("GC_LARGE_ALLOC_WARN_INTERVAL environment variable has "
                  "bad value: Ignoring\n", 0);
           } else {
             GC_large_alloc_warn_interval = interval;
           }
         }
       }
   #   ifdef UNIX_LIKE
         if (0 != GETENV("GC_LOOP_ON_ABORT")) {
           GC_set_and_save_fault_handler(looping_handler);
         }
   #   endif
       /* Adjust normal object descriptor for extra allocation.    */
       if (ALIGNMENT > GC_DS_TAGS && EXTRA_BYTES != 0) {
         GC_obj_kinds[NORMAL].ok_descriptor = ((word)(-ALIGNMENT) | GC_DS_LENGTH);
       }
       GC_setpagesize();
       GC_exclude_static_roots(beginGC_arrays, endGC_arrays);
       GC_exclude_static_roots(beginGC_obj_kinds, endGC_obj_kinds);
   #   ifdef SEPARATE_GLOBALS
         GC_exclude_static_roots(beginGC_objfreelist, endGC_objfreelist);
         GC_exclude_static_roots(beginGC_aobjfreelist, endGC_aobjfreelist);
   #   endif
 #   ifdef MSWIN32  #   ifdef MSWIN32
         GC_init_win32();          GC_init_win32();
 #   endif  #   endif
 #   if defined(SEARCH_FOR_DATA_START)  #   if defined(SEARCH_FOR_DATA_START)
         /* This doesn't really work if the collector is in a shared library. */  
         GC_init_linux_data_start();          GC_init_linux_data_start();
 #   endif  #   endif
 #   ifdef SOLARIS_THREADS  #   if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__)
         GC_thr_init();          GC_init_netbsd_elf();
         /* We need dirty bits in order to find live stack sections.     */  
         GC_dirty_init();  
 #   endif  #   endif
 #   if defined(IRIX_THREADS) || defined(LINUX_THREADS) \  #   if defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS)
        || defined(IRIX_JDK_THREADS) || defined(HPUX_THREADS)  
         GC_thr_init();          GC_thr_init();
 #   endif  #   endif
 #   if !defined(THREADS) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) \  #   ifdef GC_SOLARIS_THREADS
        || defined(IRIX_THREADS) || defined(LINUX_THREADS) \          /* We need dirty bits in order to find live stack sections.     */
        || defined(HPUX_THREADS)          GC_dirty_init();
   #   endif
   #   if !defined(THREADS) || defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) \
           || defined(GC_SOLARIS_THREADS)
       if (GC_stackbottom == 0) {        if (GC_stackbottom == 0) {
         GC_stackbottom = GC_get_stack_base();          GC_stackbottom = GC_get_stack_base();
   #       if defined(LINUX) && defined(IA64)
             GC_register_stackbottom = GC_get_register_stack_base();
   #       endif
       }        }
 #   endif  #   endif
     if  (sizeof (ptr_t) != sizeof(word)) {      GC_ASSERT(sizeof (ptr_t) == sizeof(word));
         ABORT("sizeof (ptr_t) != sizeof(word)\n");      GC_ASSERT(sizeof (signed_word) == sizeof(word));
     }      GC_ASSERT(sizeof (struct hblk) == HBLKSIZE);
     if  (sizeof (signed_word) != sizeof(word)) {  
         ABORT("sizeof (signed_word) != sizeof(word)\n");  
     }  
     if  (sizeof (struct hblk) != HBLKSIZE) {  
         ABORT("sizeof (struct hblk) != HBLKSIZE\n");  
     }  
 #   ifndef THREADS  #   ifndef THREADS
 #     if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN)  #     if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN)
         ABORT(          ABORT(
Line 488  void GC_init_inner()
Line 608  void GC_init_inner()
           "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");            "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
 #     endif  #     endif
 #     ifdef STACK_GROWS_DOWN  #     ifdef STACK_GROWS_DOWN
         if ((word)(&dummy) > (word)GC_stackbottom) {          GC_ASSERT((word)(&dummy) <= (word)GC_stackbottom);
           GC_err_printf0(  
                 "STACK_GROWS_DOWN is defd, but stack appears to grow up\n");  
 #         ifndef UTS4  /* Compiler bug workaround */  
             GC_err_printf2("sp = 0x%lx, GC_stackbottom = 0x%lx\n",  
                            (unsigned long) (&dummy),  
                            (unsigned long) GC_stackbottom);  
 #         endif  
           ABORT("stack direction 3\n");  
         }  
 #     else  #     else
         if ((word)(&dummy) < (word)GC_stackbottom) {          GC_ASSERT((word)(&dummy) >= (word)GC_stackbottom);
           GC_err_printf0(  
                 "STACK_GROWS_UP is defd, but stack appears to grow down\n");  
           GC_err_printf2("sp = 0x%lx, GC_stackbottom = 0x%lx\n",  
                          (unsigned long) (&dummy),  
                          (unsigned long) GC_stackbottom);  
           ABORT("stack direction 4");  
         }  
 #     endif  #     endif
 #   endif  #   endif
 #   if !defined(_AUX_SOURCE) || defined(__GNUC__)  #   if !defined(_AUX_SOURCE) || defined(__GNUC__)
       if ((word)(-1) < (word)0) {        GC_ASSERT((word)(-1) > (word)0);
         GC_err_printf0("The type word should be an unsigned integer type\n");        /* word should be unsigned */
         GC_err_printf0("It appears to be signed\n");  
         ABORT("word");  
       }  
 #   endif  #   endif
     if ((signed_word)(-1) >= (signed_word)0) {      GC_ASSERT((signed_word)(-1) < (signed_word)0);
         GC_err_printf0(  
                 "The type signed_word should be a signed integer type\n");  
         GC_err_printf0("It appears to be unsigned\n");  
         ABORT("signed_word");  
     }  
   
     /* Add initial guess of root sets.  Do this first, since sbrk(0)    */      /* Add initial guess of root sets.  Do this first, since sbrk(0)    */
     /* might be used.                                                   */      /* might be used.                                                   */
Line 529  void GC_init_inner()
Line 625  void GC_init_inner()
     GC_init_headers();      GC_init_headers();
     GC_bl_init();      GC_bl_init();
     GC_mark_init();      GC_mark_init();
     if (!GC_expand_hp_inner((word)MINHINCR)) {      {
           char * sz_str = GETENV("GC_INITIAL_HEAP_SIZE");
           if (sz_str != NULL) {
             initial_heap_sz = atoi(sz_str);
             if (initial_heap_sz <= MINHINCR * HBLKSIZE) {
               WARN("Bad initial heap size %s - ignoring it.\n",
                    sz_str);
             }
             initial_heap_sz = divHBLKSZ(initial_heap_sz);
           }
       }
       if (!GC_expand_hp_inner(initial_heap_sz)) {
         GC_err_printf0("Can't start up: not enough memory\n");          GC_err_printf0("Can't start up: not enough memory\n");
         EXIT();          EXIT();
     }      }
Line 553  void GC_init_inner()
Line 660  void GC_init_inner()
       PCR_IL_Unlock();        PCR_IL_Unlock();
       GC_pcr_install();        GC_pcr_install();
 #   endif  #   endif
     /* Get black list set up */  #   if !defined(SMALL_CONFIG)
       GC_gcollect_inner();        if (!GC_no_win32_dlls && 0 != GETENV("GC_ENABLE_INCREMENTAL")) {
           GC_ASSERT(!GC_incremental);
           GC_setpagesize();
   #       ifndef GC_SOLARIS_THREADS
             GC_dirty_init();
   #       endif
           GC_ASSERT(GC_words_allocd == 0)
           GC_incremental = TRUE;
         }
   #   endif /* !SMALL_CONFIG */
       /* Get black list set up and/or incrmental GC started */
         if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner();
       GC_is_initialized = TRUE;
 #   ifdef STUBBORN_ALLOC  #   ifdef STUBBORN_ALLOC
         GC_stubborn_init();          GC_stubborn_init();
 #   endif  #   endif
     GC_is_initialized = TRUE;  
     /* Convince lint that some things are used */      /* Convince lint that some things are used */
 #   ifdef LINT  #   ifdef LINT
       {        {
Line 587  void GC_enable_incremental GC_PROTO(())
Line 705  void GC_enable_incremental GC_PROTO(())
     LOCK();      LOCK();
     if (GC_incremental) goto out;      if (GC_incremental) goto out;
     GC_setpagesize();      GC_setpagesize();
 #   ifdef MSWIN32      if (GC_no_win32_dlls) goto out;
       {  #   ifndef GC_SOLARIS_THREADS
         extern GC_bool GC_is_win32s();  
   
         /* VirtualProtect is not functional under win32s.       */  
         if (GC_is_win32s()) goto out;  
       }  
 #   endif /* MSWIN32 */  
 #   ifndef SOLARIS_THREADS  
         GC_dirty_init();          GC_dirty_init();
 #   endif  #   endif
     if (!GC_is_initialized) {      if (!GC_is_initialized) {
         GC_init_inner();          GC_init_inner();
     }      }
       if (GC_incremental) goto out;
     if (GC_dont_gc) {      if (GC_dont_gc) {
         /* Can't easily do it. */          /* Can't easily do it. */
         UNLOCK();          UNLOCK();
Line 623  out:
Line 735  out:
 }  }
   
   
 #ifdef MSWIN32  #if defined(MSWIN32) || defined(MSWINCE)
 # define LOG_FILE "gc.log"  # define LOG_FILE _T("gc.log")
   
   HANDLE GC_stdout = 0, GC_stderr;    HANDLE GC_stdout = 0;
   int GC_tmp;  
   DWORD GC_junk;  
   
   void GC_set_files()    void GC_deinit()
   {    {
     if (!GC_stdout) {        if (GC_is_initialized) {
         GC_stdout = CreateFile(LOG_FILE, GENERIC_WRITE,          DeleteCriticalSection(&GC_write_cs);
                                FILE_SHARE_READ | FILE_SHARE_WRITE,        }
                                NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH,  
                                NULL);  
         if (INVALID_HANDLE_VALUE == GC_stdout) ABORT("Open of log file failed");  
     }  
     if (GC_stderr == 0) {  
         GC_stderr = GC_stdout;  
     }  
   }    }
   
     int GC_write(buf, len)
     GC_CONST char * buf;
     size_t len;
     {
         BOOL tmp;
         DWORD written;
         if (len == 0)
             return 0;
         EnterCriticalSection(&GC_write_cs);
         if (GC_stdout == INVALID_HANDLE_VALUE) {
             return -1;
         } else if (GC_stdout == 0) {
             GC_stdout = CreateFile(LOG_FILE, GENERIC_WRITE,
                                    FILE_SHARE_READ | FILE_SHARE_WRITE,
                                    NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH,
                                    NULL);
             if (GC_stdout == INVALID_HANDLE_VALUE) ABORT("Open of log file failed");
         }
         tmp = WriteFile(GC_stdout, buf, len, &written, NULL);
         if (!tmp)
             DebugBreak();
         LeaveCriticalSection(&GC_write_cs);
         return tmp ? (int)written : -1;
     }
   
 #endif  #endif
   
 #if defined(OS2) || defined(MACOS)  #if defined(OS2) || defined(MACOS)
Line 662  int GC_tmp;  /* Should really be local ... */
Line 790  int GC_tmp;  /* Should really be local ... */
   }    }
 #endif  #endif
   
 #if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32)  #if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32) && !defined(MSWINCE)
   int GC_stdout = 1;    int GC_stdout = 1;
   int GC_stderr = 2;    int GC_stderr = 2;
 # if !defined(AMIGA)  # if !defined(AMIGA)
Line 670  int GC_tmp;  /* Should really be local ... */
Line 798  int GC_tmp;  /* Should really be local ... */
 # endif  # endif
 #endif  #endif
   
 #if !defined(MSWIN32)  && !defined(OS2) && !defined(MACOS)  #if !defined(MSWIN32) && !defined(MSWINCE) && !defined(OS2) \
       && !defined(MACOS)  && !defined(ECOS) && !defined(NOSYS)
 int GC_write(fd, buf, len)  int GC_write(fd, buf, len)
 int fd;  int fd;
 char *buf;  GC_CONST char *buf;
 size_t len;  size_t len;
 {  {
      register int bytes_written = 0;       register int bytes_written = 0;
      register int result;       register int result;
   
      while (bytes_written < len) {       while (bytes_written < len) {
 #       ifdef SOLARIS_THREADS  #       ifdef GC_SOLARIS_THREADS
             result = syscall(SYS_write, fd, buf + bytes_written,              result = syscall(SYS_write, fd, buf + bytes_written,
                                             len - bytes_written);                                              len - bytes_written);
 #       else  #       else
Line 693  size_t len;
Line 822  size_t len;
 }  }
 #endif /* UN*X */  #endif /* UN*X */
   
 #ifdef MSWIN32  #ifdef ECOS
 #   define WRITE(f, buf, len) (GC_set_files(), \  int GC_write(fd, buf, len)
                                GC_tmp = WriteFile((f), (buf), \  {
                                                   (len), &GC_junk, NULL),\    _Jv_diag_write (buf, len);
                                (GC_tmp? 1 : -1))    return len;
   }
   #endif
   
   #ifdef NOSYS
   int GC_write(fd, buf, len)
   {
     /* No writing.  */
     return len;
   }
   #endif
   
   
   #if defined(MSWIN32) || defined(MSWINCE)
   #   define WRITE(f, buf, len) GC_write(buf, len)
 #else  #else
 #   if defined(OS2) || defined(MACOS)  #   if defined(OS2) || defined(MACOS)
 #   define WRITE(f, buf, len) (GC_set_files(), \  #   define WRITE(f, buf, len) (GC_set_files(), \
Line 715  size_t len;
Line 858  size_t len;
 /* same size as long, and that the format conversions expect something    */  /* same size as long, and that the format conversions expect something    */
 /* of that size.                                                          */  /* of that size.                                                          */
 void GC_printf(format, a, b, c, d, e, f)  void GC_printf(format, a, b, c, d, e, f)
 char * format;  GC_CONST char * format;
 long a, b, c, d, e, f;  long a, b, c, d, e, f;
 {  {
     char buf[1025];      char buf[1025];
Line 728  long a, b, c, d, e, f;
Line 871  long a, b, c, d, e, f;
 }  }
   
 void GC_err_printf(format, a, b, c, d, e, f)  void GC_err_printf(format, a, b, c, d, e, f)
 char * format;  GC_CONST char * format;
 long a, b, c, d, e, f;  long a, b, c, d, e, f;
 {  {
     char buf[1025];      char buf[1025];
Line 740  long a, b, c, d, e, f;
Line 883  long a, b, c, d, e, f;
 }  }
   
 void GC_err_puts(s)  void GC_err_puts(s)
 char *s;  GC_CONST char *s;
 {  {
     if (WRITE(GC_stderr, s, strlen(s)) < 0) ABORT("write to stderr failed");      if (WRITE(GC_stderr, s, strlen(s)) < 0) ABORT("write to stderr failed");
 }  }
   
   #if defined(LINUX) && !defined(SMALL_CONFIG)
   void GC_err_write(buf, len)
   GC_CONST char *buf;
   size_t len;
   {
       if (WRITE(GC_stderr, buf, len) < 0) ABORT("write to stderr failed");
   }
   #endif
   
 # if defined(__STDC__) || defined(__cplusplus)  # if defined(__STDC__) || defined(__cplusplus)
     void GC_default_warn_proc(char *msg, GC_word arg)      void GC_default_warn_proc(char *msg, GC_word arg)
 # else  # else
Line 777  GC_warn_proc GC_current_warn_proc = GC_default_warn_pr
Line 929  GC_warn_proc GC_current_warn_proc = GC_default_warn_pr
   
 #ifndef PCR  #ifndef PCR
 void GC_abort(msg)  void GC_abort(msg)
 char * msg;  GC_CONST char * msg;
 {  {
     GC_err_printf1("%s\n", msg);  #   if defined(MSWIN32)
     (void) abort();        (void) MessageBoxA(NULL, msg, "Fatal error in gc", MB_ICONERROR|MB_OK);
 }        DebugBreak();
 #endif  
   
 #ifdef NEED_CALLINFO  
   
 void GC_print_callers (info)  
 struct callinfo info[NFRAMES];  
 {  
     register int i;  
   
 #   if NFRAMES == 1  
       GC_err_printf0("\tCaller at allocation:\n");  
 #   else  #   else
       GC_err_printf0("\tCall chain at allocation:\n");        GC_err_printf1("%s\n", msg);
 #   endif  #   endif
     for (i = 0; i < NFRAMES; i++) {      if (GETENV("GC_LOOP_ON_ABORT") != NULL) {
         if (info[i].ci_pc == 0) break;              /* In many cases it's easier to debug a running process.    */
 #       if NARGS > 0              /* It's arguably nicer to sleep, but that makes it harder   */
         {              /* to look at the thread if the debugger doesn't know much  */
           int j;              /* about threads.                                           */
               for(;;) {}
           GC_err_printf0("\t\targs: ");  
           for (j = 0; j < NARGS; j++) {  
             if (j != 0) GC_err_printf0(", ");  
             GC_err_printf2("%d (0x%X)", ~(info[i].ci_arg[j]),  
                                         ~(info[i].ci_arg[j]));  
           }  
           GC_err_printf0("\n");  
         }  
 #       endif  
         GC_err_printf1("\t\t##PC##= 0x%X\n", info[i].ci_pc);  
     }      }
   #   ifdef MSWIN32
           DebugBreak();
   #   else
           (void) abort();
   #   endif
 }  }
   #endif
   
 #endif /* SAVE_CALL_CHAIN */  
   
 /* Needed by SRC_M3, gcj, and should perhaps be the official interface  */  /* Needed by SRC_M3, gcj, and should perhaps be the official interface  */
 /* to GC_dont_gc.                                                       */  /* to GC_dont_gc.                                                       */
Line 843  void GC_dump()
Line 979  void GC_dump()
     GC_print_block_list();      GC_print_block_list();
 }  }
   
 # endif /* NO_DEBUGGING */  #endif /* NO_DEBUGGING */

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

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