C:/Users/Dennis/src/lang/russell.orig/src/gc/finalize.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 # define I_HIDE_POINTERS
00012 # include "gc.h"
00013 # include "gc_private.h"
00014 # ifdef __STDC__
00015     typedef void * void_star;
00016 # else
00017     typedef char * void_star;
00018 # endif
00019 
00020 # define LOG_TSIZE 7
00021 # define TSIZE (1 << LOG_TSIZE)
00022 # define HASH(addr) \
00023     ((((word)(addr) >> 3) ^ ((word)(addr) >> (3+LOG_TSIZE))) \
00024     & (TSIZE - 1))
00025     
00026 static struct disappearing_link {
00027     word dl_hidden_base;        /* Pointer to object base       */
00028     word dl_offset;     /* byte offset within object.   */
00029     struct disappearing_link * dl_next;
00030 } * dl_head[TSIZE] = {0};
00031 
00032 static struct finalizable_object {
00033     word fo_hidden_base;        /* Pointer to object base       */
00034     GC_finalization_proc fo_fn; /* Finalizer.                   */
00035     ptr_t fo_client_data;
00036     word fo_object_size;        /* In bytes.                    */
00037     struct finalizable_object * fo_next;
00038 } * fo_head[TSIZE] = {0};
00039 
00040 # define ALLOC(x, t) t *x = (t *)GC_malloc(sizeof (t))
00041 
00042 int GC_register_disappearing_link(link)
00043 void_star * link;
00044 {
00045     ptr_t base;
00046     unsigned long offset;
00047     struct disappearing_link *curr_dl;
00048     int index;
00049     /* Allocate before acquiring lock */
00050       ALLOC(new_dl, struct disappearing_link);
00051     DCL_LOCK_STATE;
00052       
00053     DISABLE_SIGNALS();
00054     LOCK();
00055     base = (ptr_t)GC_base((void_star)link);
00056     index = HASH(base);
00057     offset = (ptr_t)link - base;
00058     if (base == 0 || ((word)link & (ALIGNMENT-1)))
00059                 ABORT("Bad arg to GC_register_disappearing_link");
00060     curr_dl = dl_head[index];
00061     for (curr_dl = dl_head[index]; curr_dl != 0; curr_dl = curr_dl -> dl_next) {
00062         if (curr_dl -> dl_hidden_base == HIDE_POINTER(base)
00063             && curr_dl -> dl_offset == offset) {
00064             UNLOCK();
00065             ENABLE_SIGNALS();
00066             GC_free((extern_ptr_t)new_dl);
00067             return(1);
00068         }
00069     }
00070     {
00071         new_dl -> dl_hidden_base = HIDE_POINTER(base);
00072         new_dl -> dl_offset = offset;
00073         new_dl -> dl_next = dl_head[index];
00074         dl_head[index] = new_dl;
00075         UNLOCK();
00076         ENABLE_SIGNALS();
00077         return(0);
00078     }
00079 }
00080 
00081 
00082 int GC_unregister_disappearing_link(link)
00083 void_star * link;
00084 {
00085     ptr_t base;
00086     unsigned long offset;
00087     struct disappearing_link *curr_dl, *prev_dl;
00088     int index;
00089     DCL_LOCK_STATE;
00090     
00091     DISABLE_SIGNALS();
00092     LOCK();
00093     base = (ptr_t)GC_base((void_star)link);
00094     index = HASH(base);
00095     offset = (ptr_t)link - base;
00096     if (base == 0 || ((unsigned long)link & (ALIGNMENT-1)))
00097         return(0);
00098     prev_dl = 0; curr_dl = dl_head[index];
00099     while (curr_dl != 0) {
00100         if (curr_dl -> dl_hidden_base == HIDE_POINTER(base)
00101             && curr_dl -> dl_offset == offset) {
00102             if (prev_dl == 0) {
00103                 dl_head[index] = curr_dl -> dl_next;
00104             } else {
00105                prev_dl -> dl_next = curr_dl -> dl_next;
00106             }
00107             UNLOCK();
00108             ENABLE_SIGNALS();
00109             GC_free((extern_ptr_t)curr_dl);
00110             return(1);
00111         }
00112         curr_dl = curr_dl -> dl_next;
00113         prev_dl = curr_dl;
00114     }
00115     UNLOCK();
00116     ENABLE_SIGNALS();
00117     return(0);
00118 }
00119 
00120 bool GC_is_marked(p)
00121 ptr_t p;
00122 {
00123     register struct hblk *h = HBLKPTR(p);
00124     register hdr * hhdr = HDR(h);
00125     register int word_no = (word *)p - (word *)h;
00126     
00127     return(mark_bit_from_hdr(hhdr, word_no));
00128 }
00129 
00130 void GC_set_mark_bit(p)
00131 ptr_t p;
00132 {
00133     register struct hblk *h = HBLKPTR(p);
00134     register hdr * hhdr = HDR(h);
00135     register int word_no = (word *)p - (word *)h;
00136     
00137     set_mark_bit_from_hdr(hhdr, word_no);
00138 }
00139 
00140 void GC_clear_mark_bit(p)
00141 ptr_t p;
00142 {
00143     register struct hblk *h = HBLKPTR(p);
00144     register hdr * hhdr = HDR(h);
00145     register int word_no = (word *)p - (word *)h;
00146     
00147     clear_mark_bit_from_hdr(hhdr, word_no);
00148 }
00149 
00150 void GC_register_finalizer(obj, fn, cd, ofn, ocd)
00151 void_star obj;
00152 GC_finalization_proc fn;
00153 void_star cd;
00154 GC_finalization_proc * ofn;
00155 void_star * ocd;
00156 {
00157     ptr_t base;
00158     struct finalizable_object * curr_fo, * prev_fo;
00159     int index;
00160     /* Allocate before acquiring lock */
00161       ALLOC(new_fo, struct finalizable_object);
00162     DCL_LOCK_STATE;
00163     
00164     DISABLE_SIGNALS();
00165     LOCK();
00166     base = (ptr_t)GC_base((void_star)obj);
00167     index = HASH(base);
00168     if (base != obj)
00169                 ABORT("Bad arg to GC_register_finalizer");
00170     prev_fo = 0; curr_fo = fo_head[index];
00171     while (curr_fo != 0) {
00172         if (curr_fo -> fo_hidden_base == HIDE_POINTER(base)) {
00173             if (ofn) *ofn = curr_fo -> fo_fn;
00174             if (ocd) *ocd = (void_star) curr_fo -> fo_client_data;
00175             if (fn == 0) {
00176                 /* Delete the structure for base. */
00177                   if (prev_fo == 0) {
00178                     fo_head[index] = curr_fo -> fo_next;
00179                   } else {
00180                     prev_fo -> fo_next = curr_fo -> fo_next;
00181                   }
00182                   UNLOCK();
00183                   ENABLE_SIGNALS();
00184                   GC_free((extern_ptr_t)curr_fo);
00185             } else {
00186                 curr_fo -> fo_fn = fn;
00187                 curr_fo -> fo_client_data = (ptr_t)cd;
00188                 UNLOCK();
00189                 ENABLE_SIGNALS();
00190             }
00191             GC_free((extern_ptr_t)new_fo);
00192             return;
00193         }
00194         curr_fo = curr_fo -> fo_next;
00195         prev_fo = curr_fo;
00196     }
00197     {
00198         if (ofn) *ofn = 0;
00199         if (ocd) *ocd = 0;
00200         if (fn == 0) {
00201             UNLOCK();
00202             ENABLE_SIGNALS();
00203             GC_free((extern_ptr_t)new_fo);
00204             return;
00205         }
00206         new_fo -> fo_hidden_base = (word)HIDE_POINTER(base);
00207         new_fo -> fo_fn = fn;
00208         new_fo -> fo_client_data = (ptr_t)cd;
00209         new_fo -> fo_object_size = GC_size(base);
00210         new_fo -> fo_next = fo_head[index];
00211         fo_head[index] = new_fo;
00212     }
00213     UNLOCK();
00214     ENABLE_SIGNALS();
00215 }
00216 
00217 /* Called with world stopped.  Cause disappearing links to disappear,   */
00218 /* and invoke finalizers.                                               */
00219 void GC_finalize()
00220 {
00221     struct disappearing_link * curr_dl, * prev_dl, * next_dl;
00222     struct finalizable_object * curr_fo, * prev_fo, * next_fo;
00223     ptr_t real_ptr;
00224     register int i;
00225     
00226   /* Make disappearing links disappear */
00227     for (i = 0; i < TSIZE; i++) {
00228       curr_dl = dl_head[i];
00229       prev_dl = 0;
00230       while (curr_dl != 0) {
00231         real_ptr = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_base);
00232         if (!GC_is_marked(real_ptr)) {
00233             *(word *)(real_ptr + curr_dl -> dl_offset) = 0;
00234             next_dl = curr_dl -> dl_next;
00235             if (prev_dl == 0) {
00236                 dl_head[i] = next_dl;
00237             } else {
00238                 prev_dl -> dl_next = next_dl;
00239             }
00240             GC_clear_mark_bit((ptr_t)curr_dl);
00241             curr_dl = next_dl;
00242         } else {
00243             prev_dl = curr_dl;
00244             curr_dl = curr_dl -> dl_next;
00245         }
00246       }
00247     }
00248   /* Mark all objects reachable via chains of 1 or more pointers        */
00249   /* from finalizable objects.                                          */
00250     for (i = 0; i < TSIZE; i++) {
00251       for (curr_fo = fo_head[i]; curr_fo != 0; curr_fo = curr_fo -> fo_next) {
00252         real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
00253         if (!GC_is_marked(real_ptr)) {
00254             GC_mark_all(real_ptr, real_ptr + curr_fo -> fo_object_size);
00255         }
00256         /* 
00257         if (GC_is_marked(real_ptr)) {
00258             --> Report finalization cycle here, if desired
00259         }
00260         */
00261       }
00262     }
00263   /* Invoke finalization code for all objects that are still            */
00264   /* unreachable.                                                       */
00265     for (i = 0; i < TSIZE; i++) {
00266       curr_fo = fo_head[i];
00267       prev_fo = 0;
00268       while (curr_fo != 0) {
00269         real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
00270         if (!GC_is_marked(real_ptr)) {
00271             (*(curr_fo -> fo_fn))(real_ptr, curr_fo -> fo_client_data);
00272             GC_set_mark_bit(real_ptr);
00273             next_fo = curr_fo -> fo_next;
00274             if (prev_fo == 0) {
00275                 fo_head[i] = next_fo;
00276             } else {
00277                 prev_fo -> fo_next = next_fo;
00278             }
00279             if (!GC_is_marked((ptr_t)curr_fo)) {
00280                 ABORT("GC_finalize: found accessible unmarked object\n");
00281             }
00282             GC_clear_mark_bit((ptr_t)curr_fo);
00283             curr_fo = next_fo;
00284         } else {
00285             prev_fo = curr_fo;
00286             curr_fo = curr_fo -> fo_next;
00287         }
00288       }
00289     }
00290 }
00291 
00292 # ifdef __STDC__
00293     void_star GC_call_with_alloc_lock(GC_fn_type fn, void_star client_data)
00294 # else
00295     void_star GC_call_with_alloc_lock(fn, client_data)
00296     GC_fn_type fn;
00297     void_star client_data;
00298 # endif
00299 {
00300     DCL_LOCK_STATE;
00301     
00302     DISABLE_SIGNALS();
00303     LOCK();
00304     (*fn)(client_data);
00305     UNLOCK();
00306     ENABLE_SIGNALS();
00307 }
00308 

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