C:/Users/Dennis/src/lang/russell.orig/src/gc/misc.c

Go to the documentation of this file.
00001 /* 
00002  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
00003  * Copyright (c) 1991,1992 by Xerox Corporation.  All rights reserved.
00004  *
00005  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
00006  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
00007  *
00008  * Permission is hereby granted to copy this garbage collector for any purpose,
00009  * provided the above notices are retained on all copies.
00010  */
00011 
00012 #define DEBUG       /* Some run-time consistency checks */
00013 #undef DEBUG
00014 #define VERBOSE
00015 #undef VERBOSE
00016 
00017 #include <stdio.h>
00018 #include <signal.h>
00019 #define I_HIDE_POINTERS /* To make GC_call_with_alloc_lock visible */
00020 #include "gc_private.h"
00021 
00022 # ifdef THREADS
00023 #   ifdef PCR
00024 #     include "pcr/il/PCR_IL.h"
00025       struct PCR_Th_MLRep GC_allocate_ml;
00026 #   else
00027         --> declare allocator lock here
00028 #   endif
00029 # endif
00030 
00031 struct _GC_arrays GC_arrays = { 0 };
00032 
00033 /* Initialize GC_obj_kinds properly and standard free lists properly.   */
00034 /* This must be done statically since they may be accessed before       */
00035 /* GC_init is called.                                                   */
00036 struct obj_kind GC_obj_kinds[MAXOBJKINDS] = {
00037 /* PTRFREE */ { &GC_aobjfreelist[0], &GC_areclaim_list[0],
00038                 GC_no_mark_proc, FALSE },
00039 /* NORMAL  */ { &GC_objfreelist[0], &GC_reclaim_list[0],
00040                 GC_normal_mark_proc, TRUE },
00041 };
00042 
00043 ptr_t GC_stackbottom = 0;
00044 
00045 word GC_hincr;
00046 
00047 int GC_n_kinds = 2;
00048 
00049 bool GC_dont_gc = 0;
00050 
00051 extern signed_word GC_mem_found;
00052 
00053 # ifdef ALL_INTERIOR_POINTERS
00054 #   define ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1))
00055 # else
00056 #   define ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1) - 1)
00057 # endif
00058 
00059 # ifdef MERGE_SIZES
00060     /* Set things up so that GC_size_map[i] >= words(i),                */
00061     /* but not too much bigger                                          */
00062     /* and so that size_map contains relatively few distinct entries    */
00063     /* This is stolen from Russ Atkinson's Cedar quantization           */
00064     /* alogrithm (but we precompute it).                                */
00065     
00066 #   if (CPP_WORDSZ != 32) 
00067         --> fix the following code
00068 #   endif
00069 
00070 
00071 
00072     void GC_init_size_map()
00073     {
00074         register unsigned i;
00075         register unsigned sz_rounded_up = 0;
00076 
00077         /* Map size 0 to 1.  This avoids problems at lower levels. */
00078           GC_size_map[0] = 1;
00079         /* One word objects don't have to be 2 word aligned.       */
00080           GC_size_map[1] = 1;
00081           GC_size_map[2] = 1;
00082           GC_size_map[3] = 1;
00083           GC_size_map[4] = ROUNDED_UP_WORDS(4);
00084         for (i = 5; i <= 32; i++) {
00085 #           ifdef ALIGN_DOUBLE
00086               GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 1) & (~1);
00087 #           else
00088               GC_size_map[i] = ROUNDED_UP_WORDS(i);
00089 #           endif
00090         }
00091         
00092         for (i = 33; i <= WORDS_TO_BYTES(MAXOBJSZ); i++) {
00093             if (sz_rounded_up < ROUNDED_UP_WORDS(i)) {
00094                 register int size = ROUNDED_UP_WORDS(i);
00095                 register unsigned m = 0;
00096             
00097                 while (size > 7) {
00098                   m += 1;
00099                   size += 1;
00100                   size >>= 1;
00101                 }
00102                 sz_rounded_up = size << m;
00103                 if (sz_rounded_up > MAXOBJSZ) {
00104                     sz_rounded_up = MAXOBJSZ;
00105                 }
00106             }
00107             GC_size_map[i] = sz_rounded_up;
00108         }
00109     }
00110 # endif
00111 
00112 # ifdef ALL_INTERIOR_POINTERS
00113 #   define SMALL_OBJ(bytes) ((bytes) < WORDS_TO_BYTES(MAXOBJSZ))
00114 #   define ADD_SLOP(bytes) ((bytes)+1)
00115 # else
00116 #   define SMALL_OBJ(bytes) ((bytes) <= WORDS_TO_BYTES(MAXOBJSZ))
00117 #   define ADD_SLOP(bytes) (bytes)
00118 # endif
00119 
00120 /*
00121  * The following is a gross hack to deal with a problem that can occur
00122  * on machines that are sloppy about stack frame sizes, notably SPARC.
00123  * Bogus pointers may be written to the stack and not cleared for
00124  * a LONG time, because they always fall into holes in stack frames
00125  * that are not written.  We partially address this by randomly clearing
00126  * sections of the stack whenever we get control.
00127  */
00128 word GC_stack_last_cleared = 0; /* GC_no when we last did this */
00129 # define CLEAR_SIZE 213
00130 # define CLEAR_THRESHOLD 10000
00131 # define DEGRADE_RATE 50
00132 
00133 ptr_t GC_min_sp;        /* Coolest stack pointer value from which we've */
00134                         /* already cleared the stack.                   */
00135                         
00136 # ifdef STACK_GROWS_DOWN
00137 #   define COOLER_THAN >
00138 #   define HOTTER_THAN <
00139 #   define MAKE_COOLER(x,y) if ((word)(x)+(y) > (word)(x)) {(x) += (y);} \
00140                             else {(x) = (ptr_t)ONES;}
00141 #   define MAKE_HOTTER(x,y) (x) -= (y)
00142 # else
00143 #   define COOLER_THAN <
00144 #   define HOTTER_THAN >
00145 #   define MAKE_COOLER(x,y) if ((word)(x)-(y) < (word)(x)) {(x) -= (y);} else {(x) = 0;}
00146 #   define MAKE_HOTTER(x,y) (x) += (y)
00147 # endif
00148 
00149 ptr_t GC_high_water;
00150                         /* "hottest" stack pointer value we have seen   */
00151                         /* recently.  Degrades over time.               */
00152 /*ARGSUSED*/
00153 void GC_clear_stack_inner(d)
00154 word *d;
00155 {
00156     word dummy[CLEAR_SIZE];
00157     
00158     bzero((char *)dummy, (int)(CLEAR_SIZE*sizeof(word)));
00159 #   ifdef THREADS
00160         GC_noop(dummy);
00161 #   else
00162         if ((ptr_t)(dummy) COOLER_THAN GC_min_sp) {
00163             GC_clear_stack_inner(dummy);
00164         }
00165 #   endif
00166 }
00167 
00168 void GC_clear_stack()
00169 {
00170     word dummy;
00171 
00172 
00173 # ifdef THREADS
00174     GC_clear_stack_inner(&dummy);
00175 # else
00176     if (GC_gc_no > GC_stack_last_cleared) {
00177         /* Start things over, so we clear the entire stack again */
00178         if (GC_stack_last_cleared == 0) GC_high_water = GC_stackbottom;
00179         GC_min_sp = GC_high_water;
00180         GC_stack_last_cleared = GC_gc_no;
00181     }
00182     /* Adjust GC_high_water */
00183         MAKE_COOLER(GC_high_water, WORDS_TO_BYTES(DEGRADE_RATE));
00184         if ((word)(&dummy) HOTTER_THAN (word)GC_high_water) {
00185             GC_high_water = (ptr_t)(&dummy);
00186         }
00187     if ((word)(&dummy) COOLER_THAN (word)GC_min_sp) {
00188         GC_clear_stack_inner(&dummy);
00189         GC_min_sp = (ptr_t)(&dummy);
00190     }
00191 # endif
00192 }
00193 
00194 /* allocate lb bytes for an object of kind k */
00195 ptr_t GC_generic_malloc(lb, k)
00196 register word lb;
00197 register int k;
00198 {
00199 register word lw;
00200 register ptr_t op;
00201 register ptr_t *opp;
00202 DCL_LOCK_STATE;
00203 
00204     DISABLE_SIGNALS();
00205     LOCK();
00206     if( SMALL_OBJ(lb) ) {
00207 #       ifdef MERGE_SIZES
00208           lw = GC_size_map[lb];
00209 #       else
00210           lw = ROUNDED_UP_WORDS(lb);
00211           if (lw == 0) lw = 1;
00212 #       endif
00213         opp = &(GC_obj_kinds[k].ok_freelist[lw]);
00214         if( (op = *opp) == 0 ) {
00215             if (!GC_is_initialized) {
00216                 GC_init_inner();
00217                 ENABLE_SIGNALS();
00218                 /* This may have fixed GC_size_map */
00219                 UNLOCK();
00220                 return(GC_generic_malloc(lb, k));
00221             }
00222             GC_clear_stack();
00223             op = GC_allocobj(lw, k);
00224             if (op == 0) goto out;
00225         }
00226         /* Here everything is in a consistent state.    */
00227         /* We assume the following assignment is        */
00228         /* atomic.  If we get aborted                   */
00229         /* after the assignment, we lose an object,     */
00230         /* but that's benign.                           */
00231         /* Volatile declarations may need to be added   */
00232         /* to prevent the compiler from breaking things.*/
00233         *opp = obj_link(op);
00234         obj_link(op) = 0;
00235     } else {
00236         register struct hblk * h;
00237         
00238         if (!GC_is_initialized) GC_init_inner();
00239         lw = ROUNDED_UP_WORDS(lb);
00240         while ((h = GC_allochblk(lw, k)) == 0) {
00241            GC_collect_or_expand(divHBLKSZ(lb) + 1);
00242         }
00243         if (h == 0) {
00244             op = 0;
00245         } else {
00246             op = (ptr_t) (h -> hb_body);
00247         }
00248     }
00249     GC_words_allocd += lw;
00250     
00251 out:
00252     UNLOCK();
00253     ENABLE_SIGNALS();
00254     return((ptr_t)op);
00255 }
00256 
00257 /* Analogous to the above, but assumes a small object size, and         */
00258 /* bypasses MERGE_SIZES mechanism.  Used by gc_inline.h.                */
00259 ptr_t GC_generic_malloc_words_small(lw, k)
00260 register word lw;
00261 register int k;
00262 {
00263 register ptr_t op;
00264 register ptr_t *opp;
00265 DCL_LOCK_STATE;
00266 
00267     LOCK();
00268     DISABLE_SIGNALS();
00269     opp = &(GC_obj_kinds[k].ok_freelist[lw]);
00270     if( (op = *opp) == 0 ) {
00271         if (!GC_is_initialized) {
00272             GC_init_inner();
00273         }
00274         GC_clear_stack();
00275         op = GC_allocobj(lw, k);
00276         if (op == 0) goto out;
00277     }
00278     *opp = obj_link(op);
00279     obj_link(op) = 0;
00280     GC_words_allocd += lw;
00281     
00282 out:
00283     UNLOCK();
00284     ENABLE_SIGNALS();
00285     return((ptr_t)op);
00286 }
00287 
00288 /* Allocate lb bytes of atomic (pointerfree) data */
00289 # ifdef __STDC__
00290     extern_ptr_t GC_malloc_atomic(size_t lb)
00291 # else
00292     extern_ptr_t GC_malloc_atomic(lb)
00293     size_t lb;
00294 # endif
00295 {
00296 register ptr_t op;
00297 register ptr_t * opp;
00298 register word lw;
00299 DCL_LOCK_STATE;
00300 
00301     if( SMALL_OBJ(lb) ) {
00302 #       ifdef MERGE_SIZES
00303           lw = GC_size_map[lb];
00304 #       else
00305           lw = ROUNDED_UP_WORDS(lb);
00306 #       endif
00307         opp = &(GC_aobjfreelist[lw]);
00308         FASTLOCK();
00309         if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) {
00310             FASTUNLOCK();
00311             return(GC_generic_malloc((word)lb, PTRFREE));
00312         }
00313         /* See above comment on signals.        */
00314         *opp = obj_link(op);
00315         GC_words_allocd += lw;
00316         FASTUNLOCK();
00317         return((extern_ptr_t) op);
00318    } else {
00319        return((extern_ptr_t)
00320                 GC_generic_malloc((word)lb, PTRFREE));
00321    }
00322 }
00323 
00324 /* Allocate lb bytes of composite (pointerful) data */
00325 # ifdef __STDC__
00326     extern_ptr_t GC_malloc(size_t lb)
00327 # else
00328     extern_ptr_t GC_malloc(lb)
00329     size_t lb;
00330 # endif
00331 {
00332 register ptr_t op;
00333 register ptr_t *opp;
00334 register word lw;
00335 DCL_LOCK_STATE;
00336 
00337     if( SMALL_OBJ(lb) ) {
00338 #       ifdef MERGE_SIZES
00339           lw = GC_size_map[lb];
00340 #       else
00341           lw = ROUNDED_UP_WORDS(lb);
00342 #       endif
00343         opp = &(GC_objfreelist[lw]);
00344         FASTLOCK();
00345         if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) {
00346             FASTUNLOCK();
00347             return(GC_generic_malloc((word)lb, NORMAL));
00348         }
00349         /* See above comment on signals.        */
00350         *opp = obj_link(op);
00351         obj_link(op) = 0;
00352         GC_words_allocd += lw;
00353         FASTUNLOCK();
00354         return((extern_ptr_t) op);
00355    } else {
00356        return((extern_ptr_t)
00357                 GC_generic_malloc((word)lb, NORMAL));
00358    }
00359 }
00360 
00361 /* Change the size of the block pointed to by p to contain at least   */
00362 /* lb bytes.  The object may be (and quite likely will be) moved.     */
00363 /* The kind (e.g. atomic) is the same as that of the old.             */
00364 /* Shrinking of large blocks is not implemented well.                 */
00365 # ifdef __STDC__
00366     extern_ptr_t GC_realloc(extern_ptr_t p, size_t lb)
00367 # else
00368     extern_ptr_t GC_realloc(p,lb)
00369     extern_ptr_t p;
00370     size_t lb;
00371 # endif
00372 {
00373 register struct hblk * h;
00374 register hdr * hhdr;
00375 register signed_word sz;         /* Current size in bytes       */
00376 register word orig_sz;   /* Original sz in bytes        */
00377 int obj_kind;
00378 
00379     if (p == 0) return(GC_malloc(lb));  /* Required by ANSI */
00380     h = HBLKPTR(p);
00381     hhdr = HDR(h);
00382     sz = hhdr -> hb_sz;
00383     obj_kind = hhdr -> hb_obj_kind;
00384     sz = WORDS_TO_BYTES(sz);
00385     orig_sz = sz;
00386 
00387     if (sz > WORDS_TO_BYTES(MAXOBJSZ)) {
00388         /* Round it up to the next whole heap block */
00389           
00390           sz = (sz+HDR_BYTES+HBLKSIZE-1)
00391                 & (~HBLKMASK);
00392           sz -= HDR_BYTES;
00393           hhdr -> hb_sz = BYTES_TO_WORDS(sz);
00394           /* Extra area is already cleared by allochblk. */
00395     }
00396     if (ADD_SLOP(lb) <= sz) {
00397         if (lb >= (sz >> 1)) {
00398             if (orig_sz > lb) {
00399               /* Clear unneeded part of object to avoid bogus pointer */
00400               /* tracing.                                             */
00401                 bzero(((char *)p) + lb, (int)(orig_sz - lb));
00402             }
00403             return(p);
00404         } else {
00405             /* shrink */
00406               extern_ptr_t result = GC_generic_malloc((word)lb, obj_kind);
00407 
00408               if (result == 0) return(0);
00409                   /* Could also return original object.  But this       */
00410                   /* gives the client warning of imminent disaster.     */
00411               bcopy(p, result, (int)lb);
00412               GC_free(p);
00413               return(result);
00414         }
00415     } else {
00416         /* grow */
00417           extern_ptr_t result = GC_generic_malloc((word)lb, obj_kind);
00418 
00419           if (result == 0) return(0);
00420           bcopy(p, result, (int)sz);
00421           GC_free(p);
00422           return(result);
00423     }
00424 }
00425 
00426 /* Return a pointer to the base address of p, given a pointer to a      */
00427 /* an address within an object.  Return 0 o.w.                          */
00428 # ifdef __STDC__
00429     extern_ptr_t GC_base(extern_ptr_t p)
00430 # else
00431     extern_ptr_t GC_base(p)
00432     extern_ptr_t p;
00433 # endif
00434 {
00435     register word r;
00436     register struct hblk *h;
00437     register hdr *candidate_hdr;
00438     
00439     r = (word)p;
00440     h = HBLKPTR(r);
00441     candidate_hdr = HDR(r);
00442     if (candidate_hdr == 0) return(0);
00443     /* If it's a pointer to the middle of a large object, move it       */
00444     /* to the beginning.                                                */
00445         while (IS_FORWARDING_ADDR_OR_NIL(candidate_hdr)) {
00446            h = h - (int)candidate_hdr;
00447            r = (word)h + HDR_BYTES;
00448            candidate_hdr = HDR(h);
00449         }
00450     if (candidate_hdr -> hb_map == GC_invalid_map) return(0);
00451     /* Make sure r points to the beginning of the object */
00452         r &= ~(WORDS_TO_BYTES(1) - 1);
00453         {
00454             register int offset =
00455                         (word *)r - (word *)(HBLKPTR(r)) - HDR_WORDS;
00456             register signed_word sz = candidate_hdr -> hb_sz;
00457             register int correction;
00458                 
00459             correction = offset % sz;
00460             r -= (WORDS_TO_BYTES(correction));
00461             if (((word *)r + sz) > (word *)(h + 1)
00462                 && sz <= MAXOBJSZ) {
00463                 return(0);
00464             }
00465         }
00466     return((extern_ptr_t)r);
00467 }
00468 
00469 /* Return the size of an object, given a pointer to its base.           */
00470 /* (For small obects this also happens to work from interior pointers,  */
00471 /* but that shouldn't be relied upon.)                                  */
00472 # ifdef __STDC__
00473     size_t GC_size(extern_ptr_t p)
00474 # else
00475     size_t GC_size(p)
00476     extern_ptr_t p;
00477 # endif
00478 {
00479     register int sz;
00480     register hdr * hhdr = HDR(p);
00481     
00482     sz = WORDS_TO_BYTES(hhdr -> hb_sz);
00483     if (sz < 0) {
00484         return(-sz);
00485     } else {
00486         return(sz);
00487     }
00488 }
00489 
00490 /* Explicitly deallocate an object p.                           */
00491 # ifdef __STDC__
00492     void GC_free(extern_ptr_t p)
00493 # else
00494     void GC_free(p)
00495     extern_ptr_t p;
00496 # endif
00497 {
00498     register struct hblk *h;
00499     register hdr *hhdr;
00500     register signed_word sz;
00501     register ptr_t * flh;
00502     register struct obj_kind * ok;
00503 
00504     if (p == 0) return;
00505         /* Required by ANSI.  It's not my fault ...     */
00506     h = HBLKPTR(p);
00507     hhdr = HDR(h);
00508     sz = hhdr -> hb_sz;
00509     GC_mem_freed += sz;
00510     ok = &GC_obj_kinds[hhdr -> hb_obj_kind];
00511   
00512     if (sz > MAXOBJSZ) {
00513         GC_freehblk(h);
00514     } else {
00515         ok = &GC_obj_kinds[hhdr -> hb_obj_kind];
00516         if (ok -> ok_init) {
00517             bzero((char *)((word *)p + 1), (int)(WORDS_TO_BYTES(sz-1)));
00518         }
00519         flh = &(ok -> ok_freelist[sz]);
00520         obj_link(p) = *flh;
00521         *flh = (ptr_t)p;
00522     }
00523 }
00524 
00525 bool GC_is_initialized = FALSE;
00526 
00527 void GC_init()
00528 {
00529     DCL_LOCK_STATE;
00530     
00531     DISABLE_SIGNALS();
00532     LOCK();
00533     GC_init_inner();
00534     UNLOCK();
00535     ENABLE_SIGNALS();
00536 
00537 }
00538 
00539 void GC_init_inner()
00540 {
00541     word dummy;
00542     
00543     if (GC_is_initialized) return;
00544     GC_is_initialized = TRUE;
00545 #   ifndef THREADS
00546       if (GC_stackbottom == 0) {
00547         GC_stackbottom = GC_get_stack_base();
00548       }
00549 #   endif
00550     if  (sizeof (ptr_t) != sizeof(word)) {
00551         GC_err_printf0("sizeof (ptr_t) != sizeof(word)\n");
00552         ABORT("sizeof (ptr_t) != sizeof(word)\n");
00553     }
00554     if  (sizeof (signed_word) != sizeof(word)) {
00555         GC_err_printf0("sizeof (signed_word) != sizeof(word)\n");
00556         ABORT("sizeof (signed_word) != sizeof(word)\n");
00557     }
00558     if  (sizeof (struct hblk) != HBLKSIZE) {
00559         GC_err_printf0("sizeof (struct hblk) != HBLKSIZE\n");
00560         ABORT("sizeof (struct hblk) != HBLKSIZE\n");
00561     }
00562 #   ifndef THREADS
00563 #     if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN)
00564         GC_err_printf0(
00565           "Only one of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
00566         ABORT("stack direction 1\n");
00567 #     endif
00568 #     if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN)
00569         GC_err_printf0(
00570           "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
00571         ABORT("stack direction 2\n");
00572 #     endif
00573 #     ifdef STACK_GROWS_DOWN
00574         if ((word)(&dummy) > (word)GC_stackbottom) {
00575           GC_err_printf0(
00576                 "STACK_GROWS_DOWN is defd, but stack appears to grow up\n");
00577           GC_err_printf2("sp = 0x%lx, GC_stackbottom = 0x%lx\n",
00578                          (unsigned long) (&dummy),
00579                          (unsigned long) GC_stackbottom);
00580           ABORT("stack direction 3\n");
00581         }
00582 #     else
00583         if ((word)(&dummy) < (word)GC_stackbottom) {
00584           GC_err_printf0(
00585                 "STACK_GROWS_UP is defd, but stack appears to grow down\n");
00586           GC_err_printf2("sp = 0x%lx, GC_stackbottom = 0x%lx\n",
00587                          (unsigned long) (&dummy),
00588                          (unsigned long) GC_stackbottom);
00589           ABORT("stack direction 4");
00590         }
00591 #     endif
00592 #   endif
00593 #   if !defined(_AUX_SOURCE) || defined(__GNUC__)
00594       if ((word)(-1) < (word)0) {
00595         GC_err_printf0("The type word should be an unsigned integer type\n");
00596         GC_err_printf0("It appears to be signed\n");
00597         ABORT("word");
00598       }
00599 #   endif
00600     if ((signed_word)(-1) >= (signed_word)0) {
00601         GC_err_printf0(
00602                 "The type signed_word should be a signed integer type\n");
00603         GC_err_printf0("It appears to be unsigned\n");
00604         ABORT("signed_word");
00605     }
00606     
00607     GC_hincr = HINCR;
00608     GC_init_headers();
00609     GC_bl_init();
00610     GC_mark_init();
00611     if (!GC_expand_hp_inner(GC_hincr)) {
00612         GC_printf0("Can't start up: no memory\n");
00613         EXIT();
00614     }
00615     GC_register_displacement_inner(0L);
00616 #   ifdef MERGE_SIZES
00617       GC_init_size_map();
00618 #   endif
00619     /* Add initial guess of root sets */
00620       GC_register_data_segments();
00621 #   ifdef PCR
00622       PCR_IL_Lock(PCR_Bool_false, PCR_allSigsBlocked, PCR_waitForever);
00623       PCR_IL_Unlock();
00624       GC_pcr_install();
00625 #   endif
00626     /* Get black list set up */
00627       GC_gcollect_inner(TRUE);
00628       GC_gcollect_inner(TRUE);
00629     /* Convince lint that some things are used */
00630       {
00631           extern char * GC_copyright[];
00632           GC_noop(GC_copyright, GC_find_header,
00633                   GC_tl_mark, GC_call_with_alloc_lock);
00634       }
00635 }
00636 
00637 /* A version of printf that is unlikely to call malloc, and is thus safer */
00638 /* to call from the collector in case malloc has been bound to GC_malloc. */
00639 /* Assumes that no more than 1023 characters are written at once.         */
00640 /* Assumes that all arguments have been converted to something of the     */
00641 /* same size as long, and that the format conversions expect something    */
00642 /* of that size.                                                          */
00643 void GC_printf(format, a, b, c, d, e, f)
00644 char * format;
00645 long a, b, c, d, e, f;
00646 {
00647     char buf[1025];
00648     
00649     buf[1024] = 0x15;
00650     (void) sprintf(buf, format, a, b, c, d, e, f);
00651     if (buf[1024] != 0x15) ABORT("GC_printf clobbered stack");
00652 #   ifdef OS2
00653       /* We hope this doesn't allocate */
00654       if (fwrite(buf, 1, strlen(buf), stdout) != strlen(buf))
00655           ABORT("write to stdout failed");
00656 #   else
00657       if (write(1, buf, strlen(buf)) < 0) ABORT("write to stdout failed");
00658 #   endif
00659 }
00660 
00661 void GC_err_printf(format, a, b, c, d, e, f)
00662 char * format;
00663 long a, b, c, d, e, f;
00664 {
00665     char buf[1025];
00666     
00667     buf[1024] = 0x15;
00668     (void) sprintf(buf, format, a, b, c, d, e, f);
00669     if (buf[1024] != 0x15) ABORT("GC_err_printf clobbered stack");
00670 #   ifdef OS2
00671       /* We hope this doesn't allocate */
00672       if (fwrite(buf, 1, strlen(buf), stderr) != strlen(buf))
00673           ABORT("write to stderr failed");
00674 #   else
00675       if (write(2, buf, strlen(buf)) < 0) ABORT("write to stderr failed");
00676 #   endif
00677 }
00678 
00679 void GC_err_puts(s)
00680 char *s;
00681 {
00682 #   ifdef OS2
00683       /* We hope this doesn't allocate */
00684       if (fwrite(s, 1, strlen(s), stderr) != strlen(s))
00685           ABORT("write to stderr failed");
00686 #   else
00687       if (write(2, s, strlen(s)) < 0) ABORT("write to stderr failed");
00688 #   endif
00689 }
00690 

Generated on Fri Jan 25 10:39:45 2008 for russell by  doxygen 1.5.4