Main Page | Class List | Directories | File List | Class Members | File Members

gc.h

Go to the documentation of this file.
00001 /*
00002 || This file is part of Pike. For copyright information see COPYRIGHT.
00003 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
00004 || for more information.
00005 || $Id: gc.h,v 1.119 2005/04/14 16:48:00 mast Exp $
00006 */
00007 
00008 #ifndef GC_H
00009 #define GC_H
00010 
00011 #include "global.h"
00012 #include "callback.h"
00013 #include "queue.h"
00014 #include "threads.h"
00015 #include "interpret.h"
00016 #include "pike_rusage.h"
00017 
00018 /* 1: Normal operation. 0: Disable automatic gc runs. -1: Disable
00019  * completely. */
00020 extern int gc_enabled;
00021 
00022 /* As long as the gc time is less than gc_time_ratio, aim to run the
00023  * gc approximately every time the ratio between the garbage and the
00024  * total amount of allocated things is this. */
00025 extern double gc_garbage_ratio_low;
00026 
00027 /* When more than this fraction of the cpu time is spent in the gc,
00028  * aim to minimize it as long as the garbage ratio is less than
00029  * gc_garbage_ratio_high. */
00030 extern double gc_time_ratio;
00031 
00032 /* If the garbage ratio gets up to this value, disregard gc_time_ratio
00033  * and start running the gc as often as it takes so that it doesn't
00034  * get any higher. */
00035 extern double gc_garbage_ratio_high;
00036 
00037 /* When predicting the next gc interval, use a decaying average with
00038  * this slowness factor. It should be a value less than 1.0 that
00039  * specifies the weight to give to the old average value. The
00040  * remaining weight up to 1.0 is given to the last reading. */
00041 extern double gc_average_slowness;
00042 
00043 /* The above are used to calculate the threshold on the number of
00044  * allocations since the last gc round before another is scheduled.
00045  * Put a cap on that threshold to avoid very small intervals. */
00046 #define GC_MIN_ALLOC_THRESHOLD 1000
00047 
00048 /* The upper limit on the threshold is set to avoid wrap-around only.
00049  * We need some space above it since num_allocs can go beyond the
00050  * threshold if it takes a while until the gc can run. */
00051 #define GC_MAX_ALLOC_THRESHOLD (ALLOC_COUNT_TYPE_MAX - 10000000)
00052 
00053 /* #define GC_MARK_DEBUG */
00054 
00055 /* If we only have 32 bits we need to make good use of them for the
00056  * alloc counter since it can get high, but if we have 64 it's best to
00057  * stay away from unsigned since rotten compilers like MSVC haven't
00058  * had the energy to implement conversion from that type to floating
00059  * point. :P */
00060 #ifdef INT64
00061 #define ALLOC_COUNT_TYPE INT64
00062 #define ALLOC_COUNT_TYPE_MAX MAX_INT64
00063 #define PRINT_ALLOC_COUNT_TYPE "%"PRINTINT64"d"
00064 #else
00065 #define ALLOC_COUNT_TYPE unsigned long
00066 #define ALLOC_COUNT_TYPE_MAX ULONG_MAX
00067 #define PRINT_ALLOC_COUNT_TYPE "%lu"
00068 #endif
00069 
00070 extern INT32 num_objects;
00071 extern ALLOC_COUNT_TYPE num_allocs, alloc_threshold;
00072 PMOD_EXPORT extern int Pike_in_gc;
00073 extern int gc_generation;
00074 extern int gc_trace, gc_debug;
00075 extern cpu_time_t auto_gc_time;
00076 
00077 extern struct callback *gc_evaluator_callback;
00078 #ifdef PIKE_DEBUG
00079 extern void *gc_svalue_location;
00080 #endif
00081 
00082 #ifdef DO_PIKE_CLEANUP
00083 extern int gc_destruct_everything;
00084 extern int gc_keep_markers;
00085 #else
00086 #define gc_destruct_everything 0
00087 #define gc_keep_markers 0
00088 #endif
00089 
00090 #define ADD_GC_CALLBACK() do { if(!gc_evaluator_callback)  gc_evaluator_callback=add_to_callback(&evaluator_callbacks,(callback_func)do_gc,0,0); }while(0)
00091 
00092 #define LOW_GC_ALLOC(OBJ) do {                                          \
00093  extern int d_flag;                                                     \
00094  num_objects++;                                                         \
00095  num_allocs++;                                                          \
00096  DO_IF_DEBUG(                                                           \
00097    if(d_flag) CHECK_INTERPRETER_LOCK();                                 \
00098    if(Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_FREE)        \
00099      Pike_fatal("Allocating new objects within gc is not allowed!\n");  \
00100  )                                                                      \
00101  if (Pike_in_gc) remove_marker(OBJ);                                    \
00102 } while (0)
00103 
00104 #ifdef ALWAYS_GC
00105 #define GC_ALLOC(OBJ) do{                                               \
00106   LOW_GC_ALLOC(OBJ);                                                    \
00107   ADD_GC_CALLBACK();                                                    \
00108 } while(0)
00109 #else
00110 #define GC_ALLOC(OBJ)  do{                                              \
00111   LOW_GC_ALLOC(OBJ);                                                    \
00112   if(num_allocs >= alloc_threshold)                                     \
00113     ADD_GC_CALLBACK();                                                  \
00114 } while(0)
00115 #endif
00116 
00117 #ifdef PIKE_DEBUG
00118 
00119 /* Use this when freeing blocks that you've used any gc_check or
00120  * gc_mark function on and that can't contain references. */
00121 #define GC_FREE_SIMPLE_BLOCK(PTR) do {                                  \
00122   extern int d_flag;                                                    \
00123   if(d_flag) CHECK_INTERPRETER_LOCK();                                  \
00124   if (Pike_in_gc == GC_PASS_CHECK)                                      \
00125     Pike_fatal("No free is allowed in this gc pass.\n");                \
00126   else                                                                  \
00127     remove_marker(PTR);                                                 \
00128 } while (0)
00129 
00130 /* Use this when freeing blocks that you've used any gc_check or
00131  * gc_mark function on and that can contain references. */
00132 #define GC_FREE_BLOCK(PTR) do {                                         \
00133   extern int d_flag;                                                    \
00134   if(d_flag) CHECK_INTERPRETER_LOCK();                                  \
00135   if (Pike_in_gc > GC_PASS_PREPARE && Pike_in_gc < GC_PASS_FREE)        \
00136     Pike_fatal("Freeing objects within gc is not allowed.\n");          \
00137 } while (0)
00138 
00139 #else
00140 #define GC_FREE_SIMPLE_BLOCK(PTR) do {} while (0)
00141 #define GC_FREE_BLOCK(PTR) do {} while (0)
00142 #endif
00143 
00144 #define GC_FREE(PTR) do {                                               \
00145   GC_FREE_BLOCK(PTR);                                                   \
00146   DO_IF_DEBUG(                                                          \
00147     if(num_objects < 1)                                                 \
00148       Pike_fatal("Panic!! less than zero objects!\n");                  \
00149   );                                                                    \
00150   num_objects-- ;                                                       \
00151 }while(0)
00152 
00153 struct gc_pop_frame;
00154 
00155 struct marker
00156 {
00157   struct marker *next;
00158   struct gc_pop_frame *frame;   /* Pointer to the cycle check pop frame. */
00159   void *data;
00160   INT32 refs;
00161   /* Internal references (both weak and nonweak). Increased during
00162    * check pass. */
00163   INT32 weak_refs;
00164   /* Weak (implying internal) references. Increased during check pass.
00165    * Set to -1 during check pass if it reaches the total number of
00166    * references. Set to 0 during mark pass if a nonweak reference is
00167    * found. Decreased during zap weak pass as gc_do_weak_free() is
00168    * called. */
00169 #ifdef PIKE_DEBUG
00170   INT32 xrefs;
00171   /* Known external references. Increased by gc_mark_external(). */
00172   INT32 saved_refs;
00173   /* References at beginning of gc. Set by pretouch and check passes.
00174    * Decreased by gc_do_weak_free() as weak references are removed. */
00175   unsigned INT32 flags;
00176 #else
00177   unsigned INT16 flags;
00178 #endif
00179 };
00180 
00181 #define GC_MARKED               0x0001
00182 /* The thing has less internal references than references, or has been
00183  * visited by reference from such a thing. Set in the mark pass. */
00184 #define GC_NOT_REFERENCED       0x0002
00185 /* The thing has only internal references and is not referenced from a
00186  * marked thing. Set in the check pass and cleared in the mark
00187  * pass. */
00188 #define GC_CYCLE_CHECKED        0x0004
00189 /* The thing has been pushed in the cycle check pass. */
00190 #define GC_LIVE                 0x0008
00191 /* The thing is a live object (i.e. not destructed and got a destroy
00192  * function) or is referenced from a live object. Set in the cycle
00193  * check pass. */
00194 #define GC_LIVE_OBJ             0x0010
00195 /* The thing is a live object. Set in the cycle check pass. */
00196 #define GC_LIVE_RECURSE         0x0020
00197 /* The thing is being recursed a second time to propagate GC_LIVE. */
00198 #define GC_GOT_DEAD_REF         0x0040
00199 /* 1.  The thing has lost all references but since it can't be freed
00200  *     inside the gc, it's been given an extra ref to stay around
00201  *     until the free pass. Set in the mark, cycle check or zap weak
00202  *     passes.
00203  * 2.  The thing is in a cycle and isn't GC_LIVE. It's given an
00204  *     extra ref so that the refcount garb doesn't recurse when the
00205  *     cycle is freed. Set but not cleared in the cycle check pass.
00206  *     Thus this flag is set on things that was dead but later marked
00207  *     as live, and they won't have the extra ref in that case (cf
00208  *     GC_GOT_EXTRA_REF). */
00209 #define GC_FREE_VISITED         0x0080
00210 /* The thing has been visited in the zap weak pass, which uses the
00211  * mark pass code to remove references to things that got nonweak
00212  * references but only weak external references. */
00213 #define GC_USER_1               0x0100
00214 #define GC_USER_2               0x0200
00215 /* Flags free for use in the gc callbacks for the specific data types.
00216  * E.g. multisets use these flags on the multiset_data blocks. */
00217 
00218 #define GC_PRETOUCHED           0x4000
00219 /* The thing has been visited by debug_gc_touch() in the pretouch pass. */
00220 #define GC_MIDDLETOUCHED        0x8000
00221 /* The thing has been visited by debug_gc_touch() in the middletouch pass. */
00222 
00223 #ifdef PIKE_DEBUG
00224 #define GC_IS_REFERENCED        0x00040000
00225 /* The thing has been visited by gc_is_referenced() in the mark pass. */
00226 #define GC_XREFERENCED          0x00080000
00227 /* The thing has been visited by gc_mark_external() and thus has a
00228  * known external reference. Set in the check and locate passes. */
00229 #define GC_DO_FREE              0x00100000
00230 /* The thing has been visited by gc_do_free(). Set in the free pass. */
00231 #define GC_GOT_EXTRA_REF        0x00200000
00232 /* The thing has got an extra reference by the gc. */
00233 #define GC_WEAK_FREED           0x00400000
00234 /* The thing has only weak (external) references left and will be
00235  * freed. Set in the mark and zap weak passes. */
00236 #define GC_CHECKED_AS_WEAK      0x00800000
00237 /* The thing has been visited by gc_checked_as_weak(). */
00238 #define GC_WATCHED              0x01000000
00239 /* The thing has been set under watch by gc_watch(). */
00240 #define GC_CLEANUP_FREED        0x02000000
00241 /* The thing was freed by the cleanup code under the assumption that
00242  * references were lost. */
00243 #endif
00244 
00245 #ifdef PIKE_DEBUG
00246 #define get_marker debug_get_marker
00247 #define find_marker debug_find_marker
00248 #endif
00249 
00250 #include "block_alloc_h.h"
00251 PTR_HASH_ALLOC_FIXED_FILL_PAGES(marker, n/a);
00252 
00253 #ifdef PIKE_DEBUG
00254 #undef get_marker
00255 #define get_marker(X) ((struct marker *) debug_malloc_pass(debug_get_marker(X)))
00256 #undef find_marker
00257 #define find_marker(X) ((struct marker *) debug_malloc_pass(debug_find_marker(X)))
00258 #endif
00259 
00260 extern size_t gc_ext_weak_refs;
00261 
00262 typedef void gc_cycle_check_cb (void *data, int weak);
00263 
00264 /* Prototypes begin here */
00265 struct gc_frame;
00266 struct callback *debug_add_gc_callback(callback_func call,
00267                                  void *arg,
00268                                  callback_func free_func);
00269 void dump_gc_info(void);
00270 int attempt_to_identify(void *something, void **inblock);
00271 void describe_location(void *real_memblock,
00272                        int real_type,
00273                        void *location,
00274                        int indent,
00275                        int depth,
00276                        int flags);
00277 void debug_gc_fatal(void *a, int flags, const char *fmt, ...);
00278 void low_describe_something(void *a,
00279                             int t,
00280                             int indent,
00281                             int depth,
00282                             int flags,
00283                             void *inblock);
00284 void describe_something(void *a, int t, int indent, int depth, int flags, void *inblock);
00285 PMOD_EXPORT void describe(void *x);
00286 void debug_describe_svalue(struct svalue *s);
00287 void gc_watch(void *a);
00288 void debug_gc_touch(void *a);
00289 PMOD_EXPORT int real_gc_check(void *a);
00290 int real_gc_check_weak(void *a);
00291 void exit_gc(void);
00292 void locate_references(void *a);
00293 void debug_gc_add_extra_ref(void *a);
00294 void debug_gc_free_extra_ref(void *a);
00295 int debug_gc_is_referenced(void *a);
00296 int gc_mark_external (void *a, const char *place);
00297 void debug_really_free_gc_frame(struct gc_frame *l);
00298 int gc_do_weak_free(void *a);
00299 void gc_delayed_free(void *a, int type);
00300 void debug_gc_mark_enqueue(queue_call call, void *data);
00301 int gc_mark(void *a);
00302 PMOD_EXPORT void gc_cycle_enqueue(gc_cycle_check_cb *checkfn, void *data, int weak);
00303 void gc_cycle_run_queue(void);
00304 int gc_cycle_push(void *x, struct marker *m, int weak);
00305 void do_gc_recurse_svalues(struct svalue *s, int num);
00306 void do_gc_recurse_short_svalue(union anything *u, int type);
00307 int gc_do_free(void *a);
00308 size_t do_gc(void *ignored, int explicit_call);
00309 void f__gc_status(INT32 args);
00310 void cleanup_gc(void);
00311 
00312 #if defined (PIKE_DEBUG) && defined (DEBUG_MALLOC)
00313 #define DMALLOC_TOUCH_MARKER(X, EXPR) (get_marker(X), (EXPR))
00314 #else
00315 #define DMALLOC_TOUCH_MARKER(X, EXPR) (EXPR)
00316 #endif
00317 
00318 #define gc_check(VP) \
00319   DMALLOC_TOUCH_MARKER(VP, real_gc_check(debug_malloc_pass(VP)))
00320 #define gc_check_weak(VP) \
00321   DMALLOC_TOUCH_MARKER(VP, real_gc_check_weak(debug_malloc_pass(VP)))
00322 
00323 #ifdef GC_MARK_DEBUG
00324 
00325 void gc_mark_enqueue (queue_call fn, void *data);
00326 void gc_mark_run_queue();
00327 void gc_mark_discard_queue();
00328 
00329 #else  /* !GC_MARK_DEBUG */
00330 
00331 extern struct pike_queue gc_mark_queue;
00332 #define gc_mark_enqueue(FN, DATA) enqueue (&gc_mark_queue, (FN), (DATA))
00333 #define gc_mark_run_queue() run_queue (&gc_mark_queue)
00334 #define gc_mark_discard_queue() discard_queue (&gc_mark_queue)
00335 
00336 #endif  /* !GC_MARK_DEBUG */
00337 
00338 #if defined (PIKE_DEBUG) || defined (GC_MARK_DEBUG)
00339 
00340 extern void *gc_found_in;
00341 extern int gc_found_in_type;
00342 extern const char *gc_found_place;
00343 
00344 #define GC_ENTER(THING, TYPE)                                           \
00345   do {                                                                  \
00346     void *orig_gc_found_in = gc_found_in;                               \
00347     int orig_gc_found_in_type = gc_found_in_type;                       \
00348     gc_found_in = (THING);                                              \
00349     gc_found_in_type = (TYPE);                                          \
00350     do
00351 
00352 #define GC_LEAVE                                                        \
00353     while (0);                                                          \
00354     gc_found_in = orig_gc_found_in;                                     \
00355     gc_found_in_type = orig_gc_found_in_type;                           \
00356   } while (0)
00357 
00358 static INLINE int debug_gc_check (void *a, const char *place)
00359 {
00360   int res;
00361   const char *orig_gc_found_place = gc_found_place;
00362   gc_found_place = place;
00363   res = gc_check (a);
00364   gc_found_place = orig_gc_found_place;
00365   return res;
00366 }
00367 
00368 static INLINE int debug_gc_check_weak (void *a, const char *place)
00369 {
00370   int res;
00371   const char *orig_gc_found_place = gc_found_place;
00372   gc_found_place = place;
00373   res = gc_check_weak (a);
00374   gc_found_place = orig_gc_found_place;
00375   return res;
00376 }
00377 
00378 #define debug_gc_check_svalues(S, NUM, PLACE)                           \
00379   do {                                                                  \
00380     const char *orig_gc_found_place = gc_found_place;                   \
00381     gc_found_place = (PLACE);                                           \
00382     gc_check_svalues ((S), (NUM));                                      \
00383     gc_found_place = orig_gc_found_place;                               \
00384   } while (0)
00385 
00386 #define debug_gc_check_weak_svalues(S, NUM, PLACE)                      \
00387   do {                                                                  \
00388     const char *orig_gc_found_place = gc_found_place;                   \
00389     gc_found_place = (PLACE);                                           \
00390     gc_check_weak_svalues ((S), (NUM));                                 \
00391     gc_found_place = orig_gc_found_place;                               \
00392   } while (0)
00393 
00394 #else  /* !defined (PIKE_DEBUG) && !defined (GC_MARK_DEBUG) */
00395 
00396 #define GC_ENTER(THING, TYPE) do
00397 #define GC_LEAVE while (0)
00398 #define debug_gc_check(X, PLACE) gc_check (X)
00399 #define debug_gc_check_weak(X, PLACE) gc_check_weak (X)
00400 #define debug_gc_check_svalues(S, NUM, PLACE) gc_check_svalues ((S), (NUM))
00401 #define debug_gc_check_weak_svalues(S, NUM, PLACE) gc_check_weak_svalues ((S), (NUM))
00402 
00403 #endif  /* !defined (PIKE_DEBUG) && !defined (GC_MARK_DEBUG) */
00404 
00405 #define gc_fatal \
00406   fprintf(stderr, "%s:%d: GC fatal:\n", __FILE__, __LINE__), debug_gc_fatal
00407 
00408 #ifdef PIKE_DEBUG
00409 
00410 #define gc_checked_as_weak(X) do {                                      \
00411   get_marker(X)->flags |= GC_CHECKED_AS_WEAK;                           \
00412 } while (0)
00413 #define gc_assert_checked_as_weak(X) do {                               \
00414   if (!(find_marker(X)->flags & GC_CHECKED_AS_WEAK))                    \
00415     Pike_fatal("A thing was checked as nonweak but "                    \
00416                "marked or cycle checked as weak.\n");                   \
00417 } while (0)
00418 #define gc_assert_checked_as_nonweak(X) do {                            \
00419   if (find_marker(X)->flags & GC_CHECKED_AS_WEAK)                       \
00420     Pike_fatal("A thing was checked as weak but "                       \
00421                "marked or cycle checked as nonweak.\n");                \
00422 } while (0)
00423 
00424 #else  /* !PIKE_DEBUG */
00425 
00426 #define gc_checked_as_weak(X) do {} while (0)
00427 #define gc_assert_checked_as_weak(X) do {} while (0)
00428 #define gc_assert_checked_as_nonweak(X) do {} while (0)
00429 
00430 #endif  /* !PIKE_DEBUG */
00431 
00432 #define gc_recurse_svalues(S,N)                                         \
00433   (Pike_in_gc == GC_PASS_CYCLE ?                                        \
00434    gc_cycle_check_svalues((S), (N)) : gc_mark_svalues((S), (N)))
00435 #define gc_recurse_short_svalue(U,T)                                    \
00436   (Pike_in_gc == GC_PASS_CYCLE ?                                        \
00437    gc_cycle_check_short_svalue((U), (T)) : gc_mark_short_svalue((U), (T)))
00438 #define gc_recurse_weak_svalues(S,N)                                    \
00439   (Pike_in_gc == GC_PASS_CYCLE ?                                        \
00440    gc_cycle_check_weak_svalues((S), (N)) : gc_mark_weak_svalues((S), (N)))
00441 #define gc_recurse_weak_short_svalue(U,T)                               \
00442   (Pike_in_gc == GC_PASS_CYCLE ?                                        \
00443    gc_cycle_check_weak_short_svalue((U), (T)) : gc_mark_weak_short_svalue((U), (T)))
00444 
00445 #define GC_RECURSE_THING(V, T)                                          \
00446   (DMALLOC_TOUCH_MARKER(V, Pike_in_gc == GC_PASS_CYCLE) ?               \
00447    PIKE_CONCAT(gc_cycle_check_, T)(V, 0) :                              \
00448    PIKE_CONCAT3(gc_mark_, T, _as_referenced)(V))
00449 #define gc_recurse_array(V) GC_RECURSE_THING((V), array)
00450 #define gc_recurse_mapping(V) GC_RECURSE_THING((V), mapping)
00451 #define gc_recurse_multiset(V) GC_RECURSE_THING((V), multiset)
00452 #define gc_recurse_object(V) GC_RECURSE_THING((V), object)
00453 #define gc_recurse_program(V) GC_RECURSE_THING((V), program)
00454 
00455 #ifdef PIKE_DEBUG
00456 #define gc_is_referenced(X) \
00457   DMALLOC_TOUCH_MARKER(X, debug_gc_is_referenced(debug_malloc_pass(X)))
00458 #else
00459 #define gc_is_referenced(X) !(get_marker(X)->flags & GC_NOT_REFERENCED)
00460 #endif
00461 
00462 #define add_gc_callback(X,Y,Z) \
00463   dmalloc_touch(struct callback *,debug_add_gc_callback((X),(Y),(Z)))
00464 
00465 #ifndef PIKE_DEBUG
00466 #define gc_add_extra_ref(X) (++*(INT32 *)(X))
00467 #define gc_free_extra_ref(X)
00468 #else
00469 #define gc_add_extra_ref(X) debug_gc_add_extra_ref(debug_malloc_pass(X))
00470 #define gc_free_extra_ref(X) debug_gc_free_extra_ref(debug_malloc_pass(X))
00471 #endif
00472 
00473 #define GC_PASS_PREPARE          50
00474 #define GC_PASS_PRETOUCH         90
00475 #define GC_PASS_CHECK           100
00476 #define GC_PASS_MARK            200
00477 #define GC_PASS_CYCLE           250
00478 #define GC_PASS_ZAP_WEAK        260
00479 #define GC_PASS_MIDDLETOUCH     270
00480 #define GC_PASS_FREE            300
00481 #define GC_PASS_KILL            400
00482 #define GC_PASS_DESTRUCT        500
00483 #define GC_PASS_POSTTOUCH       510
00484 
00485 #define GC_PASS_LOCATE -1
00486 #define GC_PASS_DISABLED -2
00487 
00488 #ifdef PIKE_DEBUG
00489 extern int gc_in_cycle_check;
00490 #endif
00491 
00492 /* Use WEAK < 0 for strong links. The gc makes these assumptions about
00493  * them:
00494  *
00495  * 1.  All strong links are recursed before any other links, i.e.
00496  *     strong links must be passed to gc_cycle_check_* last. This also
00497  *     means that if following a strong link causes nonstrong links to
00498  *     be followed recursively then there can only be one strong link
00499  *     in a thing.
00500  * 2.  There can never be a cycle consisting of only strong links.
00501  *
00502  * Warning: This is unusable other than internally; you'll never be
00503  * able to guarantee the second assumption since strong links are used
00504  * internally for parent object and program relations. */
00505 
00506 #define GC_CYCLE_ENTER(X, TYPE, WEAK) do {                              \
00507   void *_thing_ = (X);                                                  \
00508   struct marker *_m_ = get_marker(_thing_);                             \
00509   if (!(_m_->flags & GC_MARKED)) {                                      \
00510     DO_IF_DEBUG(                                                        \
00511       if (gc_in_cycle_check)                                            \
00512         Pike_fatal("Recursing immediately in gc cycle check.\n");       \
00513       gc_in_cycle_check = 1;                                            \
00514     );                                                                  \
00515     if (gc_cycle_push(_thing_, _m_, (WEAK))) {
00516 
00517 #define GC_CYCLE_ENTER_OBJECT(X, WEAK) do {                             \
00518   struct object *_thing_ = (X);                                         \
00519   struct marker *_m_ = get_marker(_thing_);                             \
00520   if (!(_m_->flags & GC_MARKED)) {                                      \
00521     if (_thing_->prog && FIND_LFUN(_thing_->prog, LFUN_DESTROY) != -1)  \
00522       _m_->flags |= GC_LIVE|GC_LIVE_OBJ;                                \
00523     DO_IF_DEBUG(                                                        \
00524       if (gc_in_cycle_check)                                            \
00525         Pike_fatal("Recursing immediately in gc cycle check.\n");       \
00526       gc_in_cycle_check = 1;                                            \
00527     );                                                                  \
00528     if (gc_cycle_push(_thing_, _m_, (WEAK))) {
00529 
00530 #define GC_CYCLE_LEAVE                                                  \
00531     }                                                                   \
00532     DO_IF_DEBUG(gc_in_cycle_check = 0);                                 \
00533   }                                                                     \
00534 } while (0)
00535 
00536 #endif

Generated on Fri Jul 22 23:44:24 2005 for Pike by  doxygen 1.3.9.1