00001
00002
00003
00004
00005
00006
00007
00008
00009
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;
00028 word dl_offset;
00029 struct disappearing_link * dl_next;
00030 } * dl_head[TSIZE] = {0};
00031
00032 static struct finalizable_object {
00033 word fo_hidden_base;
00034 GC_finalization_proc fo_fn;
00035 ptr_t fo_client_data;
00036 word fo_object_size;
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
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
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
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
00218
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
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
00249
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
00258
00259
00260
00261 }
00262 }
00263
00264
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