Back to index

lightning-sunbird  0.9+nobinonly
Defines | Functions | Variables
misc.c File Reference
#include <stdio.h>
#include <signal.h>
#include "gc_priv.h"
#include <unistd.h>

Go to the source code of this file.

Defines

#define I_HIDE_POINTERS   /* To make GC_call_with_alloc_lock visible */
#define CLEAR_SIZE   213
#define DEGRADE_RATE   50
#define COOLER_THAN   >
#define HOTTER_THAN   <
#define MAKE_COOLER(x, y)
#define MAKE_HOTTER(x, y)   (x) -= (y)
#define SLOP   400
#define GC_SLOP   4000
#define CLEAR_THRESHOLD   100000
#define WRITE(f, buf, len)   GC_write((f), (buf), (len))

Functions

GC_PTR GC_default_oom_fn GC_PROTO ((size_t bytes_requested))
void GC_init_size_map ()
void GC_extend_size_map (word i)
ptr_t GC_clear_stack_inner (ptr_t arg, word limit)
ptr_t GC_clear_stack (ptr_t arg)
GC_PTR GC_base (GC_PTR p)
size_t GC_size (GC_PTR p)
size_t GC_get_heap_size GC_PROTO (())
void GC_init ()
void GC_setpagesize ()
void GC_init_inner ()
int GC_write (int fd, char *buf, size_t len)
void GC_printf (char *format, long a, long b, long c, long d, long e, long f)
void GC_err_printf (char *format, long a, long b, long c, long d, long e, long f)
void GC_err_puts (char *s)
void GC_default_warn_proc (char *msg, GC_word arg)
GC_warn_proc GC_set_warn_proc (GC_warn_proc p)
void GC_abort (char *msg)
void GC_dump ()

Variables

GC_FAR struct _GC_arrays
GC_bool GC_debugging_started = FALSE
void(* GC_check_heap )() = (void (*)())0
void(* GC_start_call_back )() = (void (*)())0
ptr_t GC_stackbottom = 0
GC_bool GC_dont_gc = 0
GC_bool GC_quiet = 0
signed_word GC_mem_found
word GC_stack_last_cleared = 0
word GC_min_sp
word GC_high_water
word GC_words_allocd_at_reset
GC_bool GC_is_initialized = FALSE
int GC_stdout = 1
int GC_stderr = 2
GC_warn_proc GC_current_warn_proc = GC_default_warn_proc

Define Documentation

#define CLEAR_SIZE   213

Definition at line 187 of file misc.c.

#define CLEAR_THRESHOLD   100000

Definition at line 195 of file misc.c.

#define DEGRADE_RATE   50

Definition at line 189 of file misc.c.

#define GC_SLOP   4000

Definition at line 196 of file misc.c.

#define I_HIDE_POINTERS   /* To make GC_call_with_alloc_lock visible */

Definition at line 20 of file misc.c.

#define MAKE_COOLER (   x,
  y 
)
Value:
if ((word)(x)+(y) > (word)(x)) {(x) += (y);} \
                         else {(x) = (word)ONES;}

Definition at line 197 of file misc.c.

#define MAKE_HOTTER (   x,
  y 
)    (x) -= (y)

Definition at line 199 of file misc.c.

#define SLOP   400
#define WRITE (   f,
  buf,
  len 
)    GC_write((f), (buf), (len))

Definition at line 692 of file misc.c.


Function Documentation

void GC_abort ( char *  msg)

Definition at line 764 of file misc.c.

{
    GC_err_printf1("%s\n", msg);
#ifdef MACOS
       debugstr(msg);
       ExitToShell();
#else    
    (void) abort();
#endif
}

Definition at line 306 of file misc.c.

{
    register word r;
    register struct hblk *h;
    register bottom_index *bi;
    register hdr *candidate_hdr;
    register word limit;
    
    r = (word)p;
    if (!GC_is_initialized) return 0;
    h = HBLKPTR(r);
    GET_BI(r, bi);
    candidate_hdr = HDR_FROM_BI(bi, r);
    if (candidate_hdr == 0) return(0);
    /* If it's a pointer to the middle of a large object, move it     */
    /* to the beginning.                                       */
       while (IS_FORWARDING_ADDR_OR_NIL(candidate_hdr)) {
          h = FORWARDED_ADDR(h,candidate_hdr);
          r = (word)h + HDR_BYTES;
          candidate_hdr = HDR(h);
       }
    if (candidate_hdr -> hb_map == GC_invalid_map) return(0);
    /* Make sure r points to the beginning of the object */
       r &= ~(WORDS_TO_BYTES(1) - 1);
        {
           register int offset = (char *)r - (char *)(HBLKPTR(r));
           register signed_word sz = candidate_hdr -> hb_sz;
           
#          ifdef ALL_INTERIOR_POINTERS
             register map_entry_type map_entry;
             
             map_entry = MAP_ENTRY((candidate_hdr -> hb_map), offset);
             if (map_entry == OBJ_INVALID) {
              return(0);
              }
              r -= WORDS_TO_BYTES(map_entry);
              limit = r + WORDS_TO_BYTES(sz);
#          else
             register int correction;
             
             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);
             }
#          endif
           if ((word)p >= limit) return(0);
       }
    return((GC_PTR)r);
}

Here is the caller graph for this function:

Definition at line 240 of file misc.c.

{
    register word sp = (word)GC_approx_sp();  /* Hotter than actual sp */
#   ifdef THREADS
        word dummy[CLEAR_SIZE];
#   else
       register word limit;
#   endif
    
#   define SLOP 400
       /* Extra bytes we clear every time.  This clears our own       */
       /* activation record, and should cause more frequent           */
       /* clearing near the cold end of the stack, a good thing.      */
#   define GC_SLOP 4000
       /* We make GC_high_water this much hotter than we really saw          */
       /* saw it, to cover for GC noise etc. above our current frame. */
#   define CLEAR_THRESHOLD 100000
       /* We restart the clearing process after this many bytes of    */
       /* allocation.  Otherwise very heavily recursive programs      */
       /* with sparse stacks may result in heaps that grow almost     */
       /* without bounds.  As the heap gets larger, collection        */
       /* frequency decreases, thus clearing frequency would decrease, */
       /* thus more junk remains accessible, thus the heap gets       */
       /* larger ...                                           */
# ifdef THREADS
    BZERO(dummy, CLEAR_SIZE*sizeof(word));
# else
    if (GC_gc_no > GC_stack_last_cleared) {
        /* Start things over, so we clear the entire stack again */
        if (GC_stack_last_cleared == 0) GC_high_water = (word) GC_stackbottom;
        GC_min_sp = GC_high_water;
        GC_stack_last_cleared = GC_gc_no;
        GC_words_allocd_at_reset = GC_words_allocd;
    }
    /* Adjust GC_high_water */
        MAKE_COOLER(GC_high_water, WORDS_TO_BYTES(DEGRADE_RATE) + GC_SLOP);
        if (sp HOTTER_THAN GC_high_water) {
            GC_high_water = sp;
        }
        MAKE_HOTTER(GC_high_water, GC_SLOP);
    limit = GC_min_sp;
    MAKE_HOTTER(limit, SLOP);
    if (sp COOLER_THAN limit) {
        limit &= ~0xf;      /* Make it sufficiently aligned for assembly     */
                     /* implementations of GC_clear_stack_inner.      */
        GC_min_sp = sp;
        return(GC_clear_stack_inner(arg, limit));
    } else if (WORDS_TO_BYTES(GC_words_allocd - GC_words_allocd_at_reset)
              > CLEAR_THRESHOLD) {
       /* Restart clearing process, but limit how much clearing we do. */
       GC_min_sp = sp;
       MAKE_HOTTER(GC_min_sp, CLEAR_THRESHOLD/4);
       if (GC_min_sp HOTTER_THAN GC_high_water) GC_min_sp = GC_high_water;
       GC_words_allocd_at_reset = GC_words_allocd;
    }  
# endif
  return(arg);
}

Here is the call graph for this function:

ptr_t GC_clear_stack_inner ( ptr_t  arg,
word  limit 
)

Definition at line 220 of file misc.c.

{
    word dummy[CLEAR_SIZE];
    
    BZERO(dummy, CLEAR_SIZE*sizeof(word));
    if ((word)(dummy) COOLER_THAN limit) {
        (void) GC_clear_stack_inner(arg, limit);
    }
    /* Make sure the recursive call is not a tail call, and the bzero */
    /* call is not recognized as dead code.                           */
    GC_noop1((word)dummy);
    return(arg);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void GC_default_warn_proc ( char *  msg,
GC_word  arg 
)

Definition at line 736 of file misc.c.

{
    GC_err_printf1(msg, (unsigned long)arg);
}

Definition at line 968 of file misc.c.

{
    GC_printf0("***Static roots:\n");
    GC_print_static_roots();
    GC_printf0("\n***Heap sections:\n");
    GC_print_heap_sects();
    GC_printf0("\n***Free blocks:\n");
    GC_print_hblkfreelist();
    GC_printf0("\n***Blocks in use:\n");
    GC_print_block_list();
}

Here is the call graph for this function:

Here is the caller graph for this function:

void GC_err_printf ( char *  format,
long  a,
long  b,
long  c,
long  d,
long  e,
long  f 
)

Definition at line 715 of file misc.c.

{
    char buf[1025];
    
    buf[1024] = 0x15;
    (void) sprintf(buf, format, a, b, c, d, e, f);
    if (buf[1024] != 0x15) ABORT("GC_err_printf clobbered stack");
    if (WRITE(GC_stderr, buf, strlen(buf)) < 0) ABORT("write to stderr failed");
}
void GC_err_puts ( char *  s)

Definition at line 727 of file misc.c.

{
    if (WRITE(GC_stderr, s, strlen(s)) < 0) ABORT("write to stderr failed");
}

Definition at line 123 of file misc.c.

    {
        word orig_word_sz = ROUNDED_UP_WORDS(i);
        word word_sz = orig_word_sz;
       register word byte_sz = WORDS_TO_BYTES(word_sz);
                            /* The size we try to preserve.           */
                            /* Close to to i, unless this would       */
                            /* introduce too many distinct sizes.     */
       word smaller_than_i = byte_sz - (byte_sz >> 3);
       word much_smaller_than_i = byte_sz - (byte_sz >> 2);
       register word low_limit;    /* The lowest indexed entry we     */
                                   /* initialize.                     */
       register word j;
       
       if (GC_size_map[smaller_than_i] == 0) {
           low_limit = much_smaller_than_i;
           while (GC_size_map[low_limit] != 0) low_limit++;
       } else {
           low_limit = smaller_than_i + 1;
           while (GC_size_map[low_limit] != 0) low_limit++;
           word_sz = ROUNDED_UP_WORDS(low_limit);
           word_sz += word_sz >> 3;
           if (word_sz < orig_word_sz) word_sz = orig_word_sz;
       }
#      ifdef ALIGN_DOUBLE
           word_sz += 1;
           word_sz &= ~1;
#      endif
       if (word_sz > MAXOBJSZ) {
           word_sz = MAXOBJSZ;
       }
       /* If we can fit the same number of larger objects in a block, */
       /* do so.                                               */ 
       {
           size_t number_of_objs = BODY_SZ/word_sz;
           word_sz = BODY_SZ/number_of_objs;
#          ifdef ALIGN_DOUBLE
              word_sz &= ~1;
#          endif
       }
       byte_sz = WORDS_TO_BYTES(word_sz);
#      ifdef ADD_BYTE_AT_END
           /* We need one extra byte; don't fill in GC_size_map[byte_sz] */
           byte_sz--;
#      endif

       for (j = low_limit; j <= byte_sz; j++) GC_size_map[j] = word_sz;  
    }

Definition at line 396 of file misc.c.

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 418 of file misc.c.

{
#   ifndef THREADS
        word dummy;
#   endif
    
    if (GC_is_initialized) return;
    GC_setpagesize();
    GC_exclude_static_roots(beginGC_arrays, end_gc_area);
#   ifdef PRINTSTATS
       if ((ptr_t)endGC_arrays != (ptr_t)(&GC_obj_kinds)) {
           GC_printf0("Reordering linker, didn't exclude obj_kinds\n");
       }
#   endif
#   ifdef MACOS
    GC_init_MacOS();
#   endif
#   ifdef MSWIN32
       GC_init_win32();
#   endif
#   if defined(LINUX) && defined(POWERPC)
       GC_init_linuxppc();
#   endif
#   if defined(LINUX) && defined(SPARC)
       GC_init_linuxsparc();
#   endif
#   ifdef SOLARIS_THREADS
       GC_thr_init();
       /* We need dirty bits in order to find live stack sections.    */
        GC_dirty_init();
#   endif
#   if defined(IRIX_THREADS) || defined(LINUX_THREADS) \
       || defined(IRIX_JDK_THREADS)
        GC_thr_init();
#   endif
#   if !defined(THREADS) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) \
       || defined(IRIX_THREADS) || defined(LINUX_THREADS) || defined(GENERIC_THREADS)
      if (GC_stackbottom == 0) {
       GC_stackbottom = GC_get_stack_base();
      }
#   endif
    if  (sizeof (ptr_t) != sizeof(word)) {
        ABORT("sizeof (ptr_t) != sizeof(word)\n");
    }
    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
#     if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN)
       ABORT(
         "Only one of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
#     endif
#     if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN)
       ABORT(
         "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
#     endif
#     ifdef STACK_GROWS_DOWN
        if ((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
        if ((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
#   if !defined(_AUX_SOURCE) || defined(__GNUC__)
      if ((word)(-1) < (word)0) {
       GC_err_printf0("The type word should be an unsigned integer type\n");
       GC_err_printf0("It appears to be signed\n");
       ABORT("word");
      }
#   endif
    if ((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)  */
    /* might be used.                                                 */
      GC_register_data_segments();
    GC_init_headers();
    GC_bl_init();
    GC_mark_init();
    if (!GC_expand_hp_inner((word)MINHINCR)) {
        GC_err_printf0("Can't start up: not enough memory\n");
        EXIT();
    }
    /* Preallocate large object map.  It's otherwise inconvenient to  */
    /* deal with failure.                                      */
      if (!GC_add_map_entry((word)0)) {
        GC_err_printf0("Can't start up: not enough memory\n");
        EXIT();
      }
    GC_register_displacement_inner(0L);
#   ifdef MERGE_SIZES
      GC_init_size_map();
#   endif
#   ifdef PCR
      if (PCR_IL_Lock(PCR_Bool_false, PCR_allSigsBlocked, PCR_waitForever)
          != PCR_ERes_okay) {
          ABORT("Can't lock load state\n");
      } else if (PCR_IL_Unlock() != PCR_ERes_okay) {
          ABORT("Can't unlock load state\n");
      }
      PCR_IL_Unlock();
      GC_pcr_install();
#   endif
    /* Get black list set up */
      GC_gcollect_inner();
#   ifdef STUBBORN_ALLOC
       GC_stubborn_init();
#   endif
    GC_is_initialized = TRUE;
    /* Convince lint that some things are used */
#   ifdef LINT
      {
          extern char * GC_copyright[];
          extern int GC_read();
          extern void GC_register_finalizer_no_order();
          
          GC_noop(GC_copyright, GC_find_header,
                  GC_push_one, GC_call_with_alloc_lock, GC_read,
                  GC_dont_expand,
#               ifndef NO_DEBUGGING
                  GC_dump,
#               endif
                  GC_register_finalizer_no_order);
      }
#   endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 95 of file misc.c.

    {
       register unsigned i;

       /* Map size 0 to 1.  This avoids problems at lower levels. */
         GC_size_map[0] = 1;
       /* One word objects don't have to be 2 word aligned.       */
         for (i = 1; i < sizeof(word); i++) {
             GC_size_map[i] = 1;
         }
         GC_size_map[sizeof(word)] = ROUNDED_UP_WORDS(sizeof(word));
       for (i = sizeof(word) + 1; i <= 8 * sizeof(word); i++) {
#           ifdef ALIGN_DOUBLE
             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++) {
             GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 1) & (~1);
       }
       /* We leave the rest of the array to be filled in on demand. */
    }

Here is the caller graph for this function:

void GC_printf ( char *  format,
long  a,
long  b,
long  c,
long  d,
long  e,
long  f 
)

Definition at line 702 of file misc.c.

{
    char buf[1025];
    
    if (GC_quiet) return;
    buf[1024] = 0x15;
    (void) sprintf(buf, format, a, b, c, d, e, f);
    if (buf[1024] != 0x15) ABORT("GC_printf clobbered stack");
    if (WRITE(GC_stdout, buf, strlen(buf)) < 0) ABORT("write to stdout failed");
}
GC_PTR GC_default_oom_fn GC_PROTO ( (size_t bytes_requested)  )

Definition at line 78 of file misc.c.

{
    return(0);
}
size_t GC_get_heap_size GC_PROTO ( ()  )

Definition at line 384 of file misc.c.

{
    return ((size_t) GC_heapsize);
}
GC_warn_proc GC_set_warn_proc ( GC_warn_proc  p)

Definition at line 749 of file misc.c.

{
    GC_warn_proc result;

    LOCK();
    result = GC_current_warn_proc;
    GC_current_warn_proc = p;
    UNLOCK();
    return(result);
}

Here is the caller graph for this function:

Definition at line 374 of file os_dep.c.

Here is the caller graph for this function:

size_t GC_size ( GC_PTR  p)

Definition at line 369 of file misc.c.

{
    register int sz;
    register hdr * hhdr = HDR(p);
    
    sz = WORDS_TO_BYTES(hhdr -> hb_sz);
    if (sz < 0) {
        return(-sz);
    } else {
        return(sz);
    }
}

Here is the caller graph for this function:

int GC_write ( int  fd,
char *  buf,
size_t  len 
)

Definition at line 659 of file misc.c.

{
     register int bytes_written = 0;
     register int result;
     
     while (bytes_written < len) {
#      ifdef SOLARIS_THREADS
           result = syscall(SYS_write, fd, buf + bytes_written,
                                       len - bytes_written);
#      else
           result = write(fd, buf + bytes_written, len - bytes_written);
#      endif
       if (-1 == result) return(result);
       bytes_written += result;
    }
    return(bytes_written);
}

Here is the call graph for this function:


Variable Documentation

Definition at line 61 of file misc.c.

void(* GC_check_heap)() = (void (*)())0

Definition at line 67 of file misc.c.

Definition at line 744 of file misc.c.

Definition at line 64 of file misc.c.

Definition at line 73 of file misc.c.

Definition at line 207 of file misc.c.

Definition at line 394 of file misc.c.

Definition at line 19 of file reclaim.c.

Definition at line 191 of file misc.c.

Definition at line 75 of file misc.c.

Definition at line 183 of file misc.c.

Definition at line 71 of file misc.c.

void(* GC_start_call_back)() = (void (*)())0

Definition at line 69 of file misc.c.

Definition at line 652 of file misc.c.

Definition at line 651 of file misc.c.

Definition at line 211 of file misc.c.