pike.git / src / gc.c

version» Context lines:

pike.git/src/gc.c:23:   #include "constants.h"   #include "interpret.h"   #include "bignum.h"      #include "gc.h"   #include "main.h"   #include <math.h>      #include "block_alloc.h"    - RCSID("$Id: gc.c,v 1.154 2003/04/15 17:00:56 mast Exp $"); + RCSID("$Id: gc.c,v 1.155 2003/09/08 15:27:57 mast Exp $");      /* Run garbage collect approximately every time    * 20 percent of all arrays, objects and programs is    * garbage.    */      #define GC_CONST 20   #define MIN_ALLOC_THRESHOLD 1000   #define MAX_ALLOC_THRESHOLD 2000000000   #define MULTIPLIER 0.9
pike.git/src/gc.c:92:   #ifdef GC_VERBOSE   #define GC_VERBOSE_DO(X) X   #else   #define GC_VERBOSE_DO(X)   #endif      INT32 num_objects = 3; /* Account for *_empty_array. */   INT32 num_allocs =0;   ptrdiff_t alloc_threshold = MIN_ALLOC_THRESHOLD;   PMOD_EXPORT int Pike_in_gc = 0; - struct pike_queue gc_mark_queue; +    time_t last_gc;   int gc_trace = 0, gc_debug = 0;      struct gc_frame   {    struct gc_frame *back; /* Previous stack frame. */    void *data;    union {    struct { /* Pop frame. */    struct gc_frame *prev; /* Previous frame in rec_list. */
pike.git/src/gc.c:195:      struct callback *debug_add_gc_callback(callback_func call,    void *arg,    callback_func free_func)   {    return add_to_callback(&gc_callbacks, call, arg, free_func);   }      static void gc_cycle_pop(void *a);    + #ifdef GC_MARK_DEBUG + #else + struct pike_queue gc_mark_queue; + #endif      #undef BLOCK_ALLOC_NEXT   #define BLOCK_ALLOC_NEXT next      #undef INIT_BLOCK   #ifdef PIKE_DEBUG   #define INIT_BLOCK(X) \    (X)->flags=(X)->refs=(X)->weak_refs=(X)->xrefs=0; \    (X)->saved_refs=-1; \    (X)->frame = 0;
pike.git/src/gc.c:220: Inside #if defined(PIKE_DEBUG)
     #ifdef PIKE_DEBUG   #undef get_marker   #define get_marker debug_get_marker   #undef find_marker   #define find_marker debug_find_marker   #endif      PTR_HASH_ALLOC(marker,MARKER_CHUNK_SIZE)    + #if defined (PIKE_DEBUG) || defined (GC_MARK_DEBUG) + static char *found_where=""; + static void *found_in=0; + static int found_in_type=0; +  + void debug_gc_set_where (TYPE_T type, void *data) + { +  found_in = data; +  found_in_type = type; + } + #endif +    #ifdef PIKE_DEBUG      #undef get_marker   #define get_marker(X) ((struct marker *) debug_malloc_pass(debug_get_marker(X)))   #undef find_marker   #define find_marker(X) ((struct marker *) debug_malloc_pass(debug_find_marker(X)))      int gc_in_cycle_check = 0;   static unsigned weak_freed, checked, marked, cycle_checked, live_ref;   static unsigned max_gc_frames, num_gc_frames = 0;
pike.git/src/gc.c:285:    if(mu==(struct multiset *)something)    return T_MULTISET;       if(safe_debug_findstring((struct pike_string *)something))    return T_STRING;       return PIKE_T_UNKNOWN;   }      void *check_for =0; - static char *found_where=""; - static void *found_in=0; - static int found_in_type=0; +    void *gc_svalue_location=0;   char *fatal_after_gc=0;      #define DESCRIBE_MEM 1   #define DESCRIBE_NO_REFS 2   #define DESCRIBE_SHORT 4   #define DESCRIBE_NO_DMALLOC 8      /* type == -1 means that memblock is a char* and should be    * really be printed..
pike.git/src/gc.c:855:    }else{    fprintf(stderr," Function name: %s\n",ID_FROM_INT(s->u.object->prog,s->subtype)->name->str);    }    }    }    describe_something(s->u.refs,s->type,0,2,0);   }      #endif /* PIKE_DEBUG */    + #ifdef GC_MARK_DEBUG +  + TYPE_FIELD debug_gc_mark_svalues (struct svalue *s, ptrdiff_t num, +  TYPE_T in_type, void *in) + { +  TYPE_FIELD res; +  found_in = in; +  found_in_type = in_type; +  res = gc_mark_svalues (s, num); +  found_in_type = PIKE_T_UNKNOWN; +  found_in = NULL; +  return res; + } +  + TYPE_FIELD debug_gc_mark_weak_svalues (struct svalue *s, ptrdiff_t num, +  TYPE_T in_type, void *in) + { +  TYPE_FIELD res; +  found_in = in; +  found_in_type = in_type; +  res = gc_mark_weak_svalues (s, num); +  found_in_type = PIKE_T_UNKNOWN; +  found_in = NULL; +  return res; + } +  + int debug_gc_mark_short_svalue (union anything *u, TYPE_T type, +  TYPE_T in_type, void *in) + { +  int res; +  found_in = in; +  found_in_type = in_type; +  res = gc_mark_short_svalue (u, type); +  found_in_type = PIKE_T_UNKNOWN; +  found_in = NULL; +  return res; + } +  + int debug_gc_mark_weak_short_svalue (union anything *u, TYPE_T type, +  TYPE_T in_type, void *in) + { +  int res; +  found_in = in; +  found_in_type = in_type; +  res = gc_mark_weak_short_svalue (u, type); +  found_in_type = PIKE_T_UNKNOWN; +  found_in = NULL; +  return res; + } +  + /* Cut'n'paste from queue.c. */ +  + struct gc_queue_entry + { +  queue_call call; +  void *data; +  TYPE_T in_type; +  void *in; + }; +  + #define GC_QUEUE_ENTRIES 8191 +  + struct gc_queue_block + { +  struct gc_queue_block *next; +  int used; +  struct gc_queue_entry entries[GC_QUEUE_ENTRIES]; + }; +  + struct gc_queue_block *gc_mark_first = NULL, *gc_mark_last = NULL; +  + void gc_mark_run_queue() + { +  struct gc_queue_block *b; +  +  while((b=gc_mark_first)) +  { +  int e; +  for(e=0;e<b->used;e++) +  { +  debug_malloc_touch(b->entries[e].data); +  b->entries[e].call(b->entries[e].data); +  } +  +  gc_mark_first=b->next; +  free((char *)b); +  } +  gc_mark_last=0; + } +  + void gc_mark_discard_queue() + { +  struct gc_queue_block *b = gc_mark_first; +  while (b) +  { +  struct gc_queue_block *next = b->next; +  free((char *) b); +  b = next; +  } +  gc_mark_first = gc_mark_last = 0; + } +  + void gc_mark_enqueue (queue_call call, void *data) + { +  struct gc_queue_block *b; +  +  b=gc_mark_last; +  if(!b || b->used >= GC_QUEUE_ENTRIES) +  { +  b = (struct gc_queue_block *) malloc (sizeof (struct gc_queue_block)); +  if (!b) fatal ("Out of memory in gc.\n"); +  b->used=0; +  b->next=0; +  if(gc_mark_first) +  gc_mark_last->next=b; +  else +  gc_mark_first=b; +  gc_mark_last=b; +  } +  +  b->entries[b->used].call=call; +  b->entries[b->used].data=debug_malloc_pass(data); +  b->entries[b->used].in_type = found_in_type; +  b->entries[b->used].in = debug_malloc_pass (found_in); +  b->used++; + } +  + #endif +    void debug_gc_touch(void *a)   {    struct marker *m;    if (!a) fatal("Got null pointer.\n");    m = find_marker(a);       switch (Pike_in_gc) {    case GC_PASS_PRETOUCH:    if (m && !(m->flags & GC_PRETOUCHED))    gc_fatal(a, 1, "Thing got an existing but untouched marker.\n");
pike.git/src/gc.c:2093:    gc_internal_array = empty_array.next;    gc_internal_multiset = first_multiset;    gc_internal_mapping = first_mapping;    gc_internal_program = first_program;    gc_internal_object = first_object;       /* Next we mark anything with external references. Note that we can    * follow the same reference several times, e.g. with shared mapping    * data blocks. */    gc_mark_all_arrays(); -  run_queue(&gc_mark_queue); +  gc_mark_run_queue();    gc_mark_all_multisets(); -  run_queue(&gc_mark_queue); +  gc_mark_run_queue();    gc_mark_all_mappings(); -  run_queue(&gc_mark_queue); +  gc_mark_run_queue();    gc_mark_all_programs(); -  run_queue(&gc_mark_queue); +  gc_mark_run_queue();    gc_mark_all_objects(); -  run_queue(&gc_mark_queue); +  gc_mark_run_queue();   #ifdef PIKE_DEBUG    if(gc_debug) gc_mark_all_strings();   #endif /* PIKE_DEBUG */       GC_VERBOSE_DO(fprintf(stderr,    "| mark: %u markers referenced, %u weak references freed,\n"    "| %d things really freed, got %lu tricky weak refs\n",    marked, weak_freed, objs - num_objects,    SIZE_T_TO_ULONG(gc_ext_weak_refs)));