[BACK]Return to finalize.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / gc

Annotation of OpenXM_contrib2/asir2000/gc/finalize.c, Revision 1.1

1.1     ! noro        1: /*
        !             2:  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
        !             3:  * Copyright (c) 1991-1996 by Xerox Corporation.  All rights reserved.
        !             4:
        !             5:  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
        !             6:  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
        !             7:  *
        !             8:  * Permission is hereby granted to use or copy this program
        !             9:  * for any purpose,  provided the above notices are retained on all copies.
        !            10:  * Permission to modify the code and to distribute modified code is granted,
        !            11:  * provided the above notices are retained, and a notice that the code was
        !            12:  * modified is included with the above copyright notice.
        !            13:  */
        !            14: /* Boehm, February 1, 1996 1:19 pm PST */
        !            15: # define I_HIDE_POINTERS
        !            16: # include "gc_priv.h"
        !            17: # include "gc_mark.h"
        !            18:
        !            19: /* Type of mark procedure used for marking from finalizable object.    */
        !            20: /* This procedure normally does not mark the object, only its          */
        !            21: /* descendents.                                                                */
        !            22: typedef void finalization_mark_proc(/* ptr_t finalizable_obj_ptr */);
        !            23:
        !            24: # define HASH3(addr,size,log_size) \
        !            25:     ((((word)(addr) >> 3) ^ ((word)(addr) >> (3+(log_size)))) \
        !            26:     & ((size) - 1))
        !            27: #define HASH2(addr,log_size) HASH3(addr, 1 << log_size, log_size)
        !            28:
        !            29: struct hash_chain_entry {
        !            30:     word hidden_key;
        !            31:     struct hash_chain_entry * next;
        !            32: };
        !            33:
        !            34: unsigned GC_finalization_failures = 0;
        !            35:        /* Number of finalization requests that failed for lack of memory. */
        !            36:
        !            37: static struct disappearing_link {
        !            38:     struct hash_chain_entry prolog;
        !            39: #   define dl_hidden_link prolog.hidden_key
        !            40:                                /* Field to be cleared.         */
        !            41: #   define dl_next(x) (struct disappearing_link *)((x) -> prolog.next)
        !            42: #   define dl_set_next(x,y) (x) -> prolog.next = (struct hash_chain_entry *)(y)
        !            43:
        !            44:     word dl_hidden_obj;                /* Pointer to object base       */
        !            45: } **dl_head = 0;
        !            46:
        !            47: static signed_word log_dl_table_size = -1;
        !            48:                        /* Binary log of                                */
        !            49:                        /* current size of array pointed to by dl_head. */
        !            50:                        /* -1 ==> size is 0.                            */
        !            51:
        !            52: word GC_dl_entries = 0;        /* Number of entries currently in disappearing  */
        !            53:                        /* link table.                                  */
        !            54:
        !            55: static struct finalizable_object {
        !            56:     struct hash_chain_entry prolog;
        !            57: #   define fo_hidden_base prolog.hidden_key
        !            58:                                /* Pointer to object base.      */
        !            59:                                /* No longer hidden once object */
        !            60:                                /* is on finalize_now queue.    */
        !            61: #   define fo_next(x) (struct finalizable_object *)((x) -> prolog.next)
        !            62: #   define fo_set_next(x,y) (x) -> prolog.next = (struct hash_chain_entry *)(y)
        !            63:     GC_finalization_proc fo_fn;        /* Finalizer.                   */
        !            64:     ptr_t fo_client_data;
        !            65:     word fo_object_size;       /* In bytes.                    */
        !            66:     finalization_mark_proc * fo_mark_proc;     /* Mark-through procedure */
        !            67: } **fo_head = 0;
        !            68:
        !            69: struct finalizable_object * GC_finalize_now = 0;
        !            70:        /* LIst of objects that should be finalized now.        */
        !            71:
        !            72: static signed_word log_fo_table_size = -1;
        !            73:
        !            74: word GC_fo_entries = 0;
        !            75:
        !            76: # ifdef SRC_M3
        !            77: void GC_push_finalizer_structures()
        !            78: {
        !            79:     GC_push_all((ptr_t)(&dl_head), (ptr_t)(&dl_head) + sizeof(word));
        !            80:     GC_push_all((ptr_t)(&fo_head), (ptr_t)(&fo_head) + sizeof(word));
        !            81: }
        !            82: # endif
        !            83:
        !            84: /* Double the size of a hash table. *size_ptr is the log of its current        */
        !            85: /* size.  May be a noop.                                               */
        !            86: /* *table is a pointer to an array of hash headers.  If we succeed, we */
        !            87: /* update both *table and *log_size_ptr.                               */
        !            88: /* Lock is held.  Signals are disabled.                                        */
        !            89: void GC_grow_table(table, log_size_ptr)
        !            90: struct hash_chain_entry ***table;
        !            91: signed_word * log_size_ptr;
        !            92: {
        !            93:     register word i;
        !            94:     register struct hash_chain_entry *p;
        !            95:     int log_old_size = *log_size_ptr;
        !            96:     register int log_new_size = log_old_size + 1;
        !            97:     word old_size = ((log_old_size == -1)? 0: (1 << log_old_size));
        !            98:     register word new_size = 1 << log_new_size;
        !            99:     struct hash_chain_entry **new_table = (struct hash_chain_entry **)
        !           100:        GC_generic_malloc_inner_ignore_off_page(
        !           101:                (size_t)new_size * sizeof(struct hash_chain_entry *), NORMAL);
        !           102:
        !           103:     if (new_table == 0) {
        !           104:        if (table == 0) {
        !           105:            ABORT("Insufficient space for initial table allocation");
        !           106:        } else {
        !           107:            return;
        !           108:        }
        !           109:     }
        !           110:     for (i = 0; i < old_size; i++) {
        !           111:       p = (*table)[i];
        !           112:       while (p != 0) {
        !           113:         register ptr_t real_key = (ptr_t)REVEAL_POINTER(p -> hidden_key);
        !           114:         register struct hash_chain_entry *next = p -> next;
        !           115:         register int new_hash = HASH3(real_key, new_size, log_new_size);
        !           116:
        !           117:         p -> next = new_table[new_hash];
        !           118:         new_table[new_hash] = p;
        !           119:         p = next;
        !           120:       }
        !           121:     }
        !           122:     *log_size_ptr = log_new_size;
        !           123:     *table = new_table;
        !           124: }
        !           125:
        !           126: # if defined(__STDC__) || defined(__cplusplus)
        !           127:     int GC_register_disappearing_link(GC_PTR * link)
        !           128: # else
        !           129:     int GC_register_disappearing_link(link)
        !           130:     GC_PTR * link;
        !           131: # endif
        !           132: {
        !           133:     ptr_t base;
        !           134:
        !           135:     base = (ptr_t)GC_base((GC_PTR)link);
        !           136:     if (base == 0)
        !           137:        ABORT("Bad arg to GC_register_disappearing_link");
        !           138:     return(GC_general_register_disappearing_link(link, base));
        !           139: }
        !           140:
        !           141: # if defined(__STDC__) || defined(__cplusplus)
        !           142:     int GC_general_register_disappearing_link(GC_PTR * link,
        !           143:                                              GC_PTR obj)
        !           144: # else
        !           145:     int GC_general_register_disappearing_link(link, obj)
        !           146:     GC_PTR * link;
        !           147:     GC_PTR obj;
        !           148: # endif
        !           149:
        !           150: {
        !           151:     struct disappearing_link *curr_dl;
        !           152:     int index;
        !           153:     struct disappearing_link * new_dl;
        !           154:     DCL_LOCK_STATE;
        !           155:
        !           156:     if ((word)link & (ALIGNMENT-1))
        !           157:        ABORT("Bad arg to GC_general_register_disappearing_link");
        !           158: #   ifdef THREADS
        !           159:        DISABLE_SIGNALS();
        !           160:        LOCK();
        !           161: #   endif
        !           162:     if (log_dl_table_size == -1
        !           163:         || GC_dl_entries > ((word)1 << log_dl_table_size)) {
        !           164: #      ifndef THREADS
        !           165:            DISABLE_SIGNALS();
        !           166: #      endif
        !           167:        GC_grow_table((struct hash_chain_entry ***)(&dl_head),
        !           168:                      &log_dl_table_size);
        !           169: #      ifdef PRINTSTATS
        !           170:            GC_printf1("Grew dl table to %lu entries\n",
        !           171:                        (unsigned long)(1 << log_dl_table_size));
        !           172: #      endif
        !           173: #      ifndef THREADS
        !           174:            ENABLE_SIGNALS();
        !           175: #      endif
        !           176:     }
        !           177:     index = HASH2(link, log_dl_table_size);
        !           178:     curr_dl = dl_head[index];
        !           179:     for (curr_dl = dl_head[index]; curr_dl != 0; curr_dl = dl_next(curr_dl)) {
        !           180:         if (curr_dl -> dl_hidden_link == HIDE_POINTER(link)) {
        !           181:             curr_dl -> dl_hidden_obj = HIDE_POINTER(obj);
        !           182: #          ifdef THREADS
        !           183:                 UNLOCK();
        !           184:                ENABLE_SIGNALS();
        !           185: #          endif
        !           186:             return(1);
        !           187:         }
        !           188:     }
        !           189: #   ifdef THREADS
        !           190:       new_dl = (struct disappearing_link *)
        !           191:        GC_generic_malloc_inner(sizeof(struct disappearing_link),NORMAL);
        !           192: #   else
        !           193:       new_dl = (struct disappearing_link *)
        !           194:        GC_malloc(sizeof(struct disappearing_link));
        !           195: #   endif
        !           196:     if (new_dl != 0) {
        !           197:         new_dl -> dl_hidden_obj = HIDE_POINTER(obj);
        !           198:         new_dl -> dl_hidden_link = HIDE_POINTER(link);
        !           199:         dl_set_next(new_dl, dl_head[index]);
        !           200:         dl_head[index] = new_dl;
        !           201:         GC_dl_entries++;
        !           202:     } else {
        !           203:         GC_finalization_failures++;
        !           204:     }
        !           205: #   ifdef THREADS
        !           206:         UNLOCK();
        !           207:         ENABLE_SIGNALS();
        !           208: #   endif
        !           209:     return(0);
        !           210: }
        !           211:
        !           212: # if defined(__STDC__) || defined(__cplusplus)
        !           213:     int GC_unregister_disappearing_link(GC_PTR * link)
        !           214: # else
        !           215:     int GC_unregister_disappearing_link(link)
        !           216:     GC_PTR * link;
        !           217: # endif
        !           218: {
        !           219:     struct disappearing_link *curr_dl, *prev_dl;
        !           220:     int index;
        !           221:     DCL_LOCK_STATE;
        !           222:
        !           223:     DISABLE_SIGNALS();
        !           224:     LOCK();
        !           225:     index = HASH2(link, log_dl_table_size);
        !           226:     if (((unsigned long)link & (ALIGNMENT-1))) goto out;
        !           227:     prev_dl = 0; curr_dl = dl_head[index];
        !           228:     while (curr_dl != 0) {
        !           229:         if (curr_dl -> dl_hidden_link == HIDE_POINTER(link)) {
        !           230:             if (prev_dl == 0) {
        !           231:                 dl_head[index] = dl_next(curr_dl);
        !           232:             } else {
        !           233:                 dl_set_next(prev_dl, dl_next(curr_dl));
        !           234:             }
        !           235:             GC_dl_entries--;
        !           236:             UNLOCK();
        !           237:            ENABLE_SIGNALS();
        !           238:             GC_free((GC_PTR)curr_dl);
        !           239:             return(1);
        !           240:         }
        !           241:         prev_dl = curr_dl;
        !           242:         curr_dl = dl_next(curr_dl);
        !           243:     }
        !           244: out:
        !           245:     UNLOCK();
        !           246:     ENABLE_SIGNALS();
        !           247:     return(0);
        !           248: }
        !           249:
        !           250: /* Possible finalization_marker procedures.  Note that mark stack      */
        !           251: /* overflow is handled by the caller, and is not a disaster.           */
        !           252: void GC_normal_finalize_mark_proc(p)
        !           253: ptr_t p;
        !           254: {
        !           255:     hdr * hhdr = HDR(p);
        !           256:
        !           257:     PUSH_OBJ((word *)p, hhdr, GC_mark_stack_top,
        !           258:             &(GC_mark_stack[GC_mark_stack_size]));
        !           259: }
        !           260:
        !           261: /* This only pays very partial attention to the mark descriptor.       */
        !           262: /* It does the right thing for normal and atomic objects, and treats   */
        !           263: /* most others as normal.                                              */
        !           264: void GC_ignore_self_finalize_mark_proc(p)
        !           265: ptr_t p;
        !           266: {
        !           267:     hdr * hhdr = HDR(p);
        !           268:     word descr = hhdr -> hb_descr;
        !           269:     ptr_t q, r;
        !           270:     ptr_t scan_limit;
        !           271:     ptr_t target_limit = p + WORDS_TO_BYTES(hhdr -> hb_sz) - 1;
        !           272:
        !           273:     if ((descr & DS_TAGS) == DS_LENGTH) {
        !           274:        scan_limit = p + descr - sizeof(word);
        !           275:     } else {
        !           276:        scan_limit = target_limit + 1 - sizeof(word);
        !           277:     }
        !           278:     for (q = p; q <= scan_limit; q += ALIGNMENT) {
        !           279:        r = *(ptr_t *)q;
        !           280:        if (r < p || r > target_limit) {
        !           281:            GC_PUSH_ONE_HEAP((word)r, q);
        !           282:        }
        !           283:     }
        !           284: }
        !           285:
        !           286: /*ARGSUSED*/
        !           287: void GC_null_finalize_mark_proc(p)
        !           288: ptr_t p;
        !           289: {
        !           290: }
        !           291:
        !           292:
        !           293:
        !           294: /* Register a finalization function.  See gc.h for details.    */
        !           295: /* in the nonthreads case, we try to avoid disabling signals,  */
        !           296: /* since it can be expensive.  Threads packages typically      */
        !           297: /* make it cheaper.                                            */
        !           298: void GC_register_finalizer_inner(obj, fn, cd, ofn, ocd, mp)
        !           299: GC_PTR obj;
        !           300: GC_finalization_proc fn;
        !           301: GC_PTR cd;
        !           302: GC_finalization_proc * ofn;
        !           303: GC_PTR * ocd;
        !           304: finalization_mark_proc * mp;
        !           305: {
        !           306:     ptr_t base;
        !           307:     struct finalizable_object * curr_fo, * prev_fo;
        !           308:     int index;
        !           309:     struct finalizable_object *new_fo;
        !           310:     DCL_LOCK_STATE;
        !           311:
        !           312: #   ifdef THREADS
        !           313:        DISABLE_SIGNALS();
        !           314:        LOCK();
        !           315: #   endif
        !           316:     if (log_fo_table_size == -1
        !           317:         || GC_fo_entries > ((word)1 << log_fo_table_size)) {
        !           318: #      ifndef THREADS
        !           319:            DISABLE_SIGNALS();
        !           320: #      endif
        !           321:        GC_grow_table((struct hash_chain_entry ***)(&fo_head),
        !           322:                      &log_fo_table_size);
        !           323: #      ifdef PRINTSTATS
        !           324:            GC_printf1("Grew fo table to %lu entries\n",
        !           325:                        (unsigned long)(1 << log_fo_table_size));
        !           326: #      endif
        !           327: #      ifndef THREADS
        !           328:            ENABLE_SIGNALS();
        !           329: #      endif
        !           330:     }
        !           331:     /* in the THREADS case signals are disabled and we hold allocation */
        !           332:     /* lock; otherwise neither is true.  Proceed carefully.            */
        !           333:     base = (ptr_t)obj;
        !           334:     index = HASH2(base, log_fo_table_size);
        !           335:     prev_fo = 0; curr_fo = fo_head[index];
        !           336:     while (curr_fo != 0) {
        !           337:         if (curr_fo -> fo_hidden_base == HIDE_POINTER(base)) {
        !           338:             /* Interruption by a signal in the middle of this  */
        !           339:             /* should be safe.  The client may see only *ocd   */
        !           340:             /* updated, but we'll declare that to be his       */
        !           341:             /* problem.                                                */
        !           342:             if (ocd) *ocd = (GC_PTR) curr_fo -> fo_client_data;
        !           343:             if (ofn) *ofn = curr_fo -> fo_fn;
        !           344:             /* Delete the structure for base. */
        !           345:                 if (prev_fo == 0) {
        !           346:                   fo_head[index] = fo_next(curr_fo);
        !           347:                 } else {
        !           348:                   fo_set_next(prev_fo, fo_next(curr_fo));
        !           349:                 }
        !           350:             if (fn == 0) {
        !           351:                 GC_fo_entries--;
        !           352:                   /* May not happen if we get a signal.  But a high    */
        !           353:                   /* estimate will only make the table larger than     */
        !           354:                   /* necessary.                                                */
        !           355: #              ifndef THREADS
        !           356:                   GC_free((GC_PTR)curr_fo);
        !           357: #              endif
        !           358:             } else {
        !           359:                 curr_fo -> fo_fn = fn;
        !           360:                 curr_fo -> fo_client_data = (ptr_t)cd;
        !           361:                 curr_fo -> fo_mark_proc = mp;
        !           362:                /* Reinsert it.  We deleted it first to maintain        */
        !           363:                /* consistency in the event of a signal.                */
        !           364:                if (prev_fo == 0) {
        !           365:                   fo_head[index] = curr_fo;
        !           366:                 } else {
        !           367:                   fo_set_next(prev_fo, curr_fo);
        !           368:                 }
        !           369:             }
        !           370: #          ifdef THREADS
        !           371:                 UNLOCK();
        !           372:                ENABLE_SIGNALS();
        !           373: #          endif
        !           374:             return;
        !           375:         }
        !           376:         prev_fo = curr_fo;
        !           377:         curr_fo = fo_next(curr_fo);
        !           378:     }
        !           379:     if (ofn) *ofn = 0;
        !           380:     if (ocd) *ocd = 0;
        !           381:     if (fn == 0) {
        !           382: #      ifdef THREADS
        !           383:             UNLOCK();
        !           384:            ENABLE_SIGNALS();
        !           385: #      endif
        !           386:         return;
        !           387:     }
        !           388: #   ifdef THREADS
        !           389:       new_fo = (struct finalizable_object *)
        !           390:        GC_generic_malloc_inner(sizeof(struct finalizable_object),NORMAL);
        !           391: #   else
        !           392:       new_fo = (struct finalizable_object *)
        !           393:        GC_malloc(sizeof(struct finalizable_object));
        !           394: #   endif
        !           395:     if (new_fo != 0) {
        !           396:         new_fo -> fo_hidden_base = (word)HIDE_POINTER(base);
        !           397:        new_fo -> fo_fn = fn;
        !           398:        new_fo -> fo_client_data = (ptr_t)cd;
        !           399:        new_fo -> fo_object_size = GC_size(base);
        !           400:        new_fo -> fo_mark_proc = mp;
        !           401:        fo_set_next(new_fo, fo_head[index]);
        !           402:        GC_fo_entries++;
        !           403:        fo_head[index] = new_fo;
        !           404:     } else {
        !           405:        GC_finalization_failures++;
        !           406:     }
        !           407: #   ifdef THREADS
        !           408:         UNLOCK();
        !           409:        ENABLE_SIGNALS();
        !           410: #   endif
        !           411: }
        !           412:
        !           413: # if defined(__STDC__)
        !           414:     void GC_register_finalizer(void * obj,
        !           415:                               GC_finalization_proc fn, void * cd,
        !           416:                               GC_finalization_proc *ofn, void ** ocd)
        !           417: # else
        !           418:     void GC_register_finalizer(obj, fn, cd, ofn, ocd)
        !           419:     GC_PTR obj;
        !           420:     GC_finalization_proc fn;
        !           421:     GC_PTR cd;
        !           422:     GC_finalization_proc * ofn;
        !           423:     GC_PTR * ocd;
        !           424: # endif
        !           425: {
        !           426:     GC_register_finalizer_inner(obj, fn, cd, ofn,
        !           427:                                ocd, GC_normal_finalize_mark_proc);
        !           428: }
        !           429:
        !           430: # if defined(__STDC__)
        !           431:     void GC_register_finalizer_ignore_self(void * obj,
        !           432:                               GC_finalization_proc fn, void * cd,
        !           433:                               GC_finalization_proc *ofn, void ** ocd)
        !           434: # else
        !           435:     void GC_register_finalizer_ignore_self(obj, fn, cd, ofn, ocd)
        !           436:     GC_PTR obj;
        !           437:     GC_finalization_proc fn;
        !           438:     GC_PTR cd;
        !           439:     GC_finalization_proc * ofn;
        !           440:     GC_PTR * ocd;
        !           441: # endif
        !           442: {
        !           443:     GC_register_finalizer_inner(obj, fn, cd, ofn,
        !           444:                                ocd, GC_ignore_self_finalize_mark_proc);
        !           445: }
        !           446:
        !           447: # if defined(__STDC__)
        !           448:     void GC_register_finalizer_no_order(void * obj,
        !           449:                               GC_finalization_proc fn, void * cd,
        !           450:                               GC_finalization_proc *ofn, void ** ocd)
        !           451: # else
        !           452:     void GC_register_finalizer_no_order(obj, fn, cd, ofn, ocd)
        !           453:     GC_PTR obj;
        !           454:     GC_finalization_proc fn;
        !           455:     GC_PTR cd;
        !           456:     GC_finalization_proc * ofn;
        !           457:     GC_PTR * ocd;
        !           458: # endif
        !           459: {
        !           460:     GC_register_finalizer_inner(obj, fn, cd, ofn,
        !           461:                                ocd, GC_null_finalize_mark_proc);
        !           462: }
        !           463:
        !           464: /* Called with world stopped.  Cause disappearing links to disappear,  */
        !           465: /* and invoke finalizers.                                              */
        !           466: void GC_finalize()
        !           467: {
        !           468:     struct disappearing_link * curr_dl, * prev_dl, * next_dl;
        !           469:     struct finalizable_object * curr_fo, * prev_fo, * next_fo;
        !           470:     ptr_t real_ptr, real_link;
        !           471:     register int i;
        !           472:     int dl_size = (log_dl_table_size == -1 ) ? 0 : (1 << log_dl_table_size);
        !           473:     int fo_size = (log_fo_table_size == -1 ) ? 0 : (1 << log_fo_table_size);
        !           474:
        !           475:   /* Make disappearing links disappear */
        !           476:     for (i = 0; i < dl_size; i++) {
        !           477:       curr_dl = dl_head[i];
        !           478:       prev_dl = 0;
        !           479:       while (curr_dl != 0) {
        !           480:         real_ptr = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_obj);
        !           481:         real_link = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_link);
        !           482:         if (!GC_is_marked(real_ptr)) {
        !           483:             *(word *)real_link = 0;
        !           484:             next_dl = dl_next(curr_dl);
        !           485:             if (prev_dl == 0) {
        !           486:                 dl_head[i] = next_dl;
        !           487:             } else {
        !           488:                 dl_set_next(prev_dl, next_dl);
        !           489:             }
        !           490:             GC_clear_mark_bit((ptr_t)curr_dl);
        !           491:             GC_dl_entries--;
        !           492:             curr_dl = next_dl;
        !           493:         } else {
        !           494:             prev_dl = curr_dl;
        !           495:             curr_dl = dl_next(curr_dl);
        !           496:         }
        !           497:       }
        !           498:     }
        !           499:   /* Mark all objects reachable via chains of 1 or more pointers       */
        !           500:   /* from finalizable objects.                                         */
        !           501: #   ifdef PRINTSTATS
        !           502:         if (GC_mark_state != MS_NONE) ABORT("Bad mark state");
        !           503: #   endif
        !           504:     for (i = 0; i < fo_size; i++) {
        !           505:       for (curr_fo = fo_head[i]; curr_fo != 0; curr_fo = fo_next(curr_fo)) {
        !           506:         real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
        !           507:         if (!GC_is_marked(real_ptr)) {
        !           508:            GC_MARKED_FOR_FINALIZATION(real_ptr);
        !           509:             GC_MARK_FO(real_ptr, curr_fo -> fo_mark_proc);
        !           510:             if (GC_is_marked(real_ptr)) {
        !           511:                 WARN("Finalization cycle involving %lx\n", real_ptr);
        !           512:             }
        !           513:         }
        !           514:       }
        !           515:     }
        !           516:   /* Enqueue for finalization all objects that are still               */
        !           517:   /* unreachable.                                                      */
        !           518:     GC_words_finalized = 0;
        !           519:     for (i = 0; i < fo_size; i++) {
        !           520:       curr_fo = fo_head[i];
        !           521:       prev_fo = 0;
        !           522:       while (curr_fo != 0) {
        !           523:         real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
        !           524:         if (!GC_is_marked(real_ptr)) {
        !           525: #         ifndef JAVA_FINALIZATION
        !           526:             GC_set_mark_bit(real_ptr);
        !           527: #         endif
        !           528:             /* Delete from hash table */
        !           529:               next_fo = fo_next(curr_fo);
        !           530:               if (prev_fo == 0) {
        !           531:                 fo_head[i] = next_fo;
        !           532:               } else {
        !           533:                 fo_set_next(prev_fo, next_fo);
        !           534:               }
        !           535:               GC_fo_entries--;
        !           536:             /* Add to list of objects awaiting finalization.   */
        !           537:               fo_set_next(curr_fo, GC_finalize_now);
        !           538:               GC_finalize_now = curr_fo;
        !           539:               /* unhide object pointer so any future collections will  */
        !           540:               /* see it.                                               */
        !           541:               curr_fo -> fo_hidden_base =
        !           542:                        (word) REVEAL_POINTER(curr_fo -> fo_hidden_base);
        !           543:               GC_words_finalized +=
        !           544:                        ALIGNED_WORDS(curr_fo -> fo_object_size)
        !           545:                        + ALIGNED_WORDS(sizeof(struct finalizable_object));
        !           546: #          ifdef PRINTSTATS
        !           547:               if (!GC_is_marked((ptr_t)curr_fo)) {
        !           548:                 ABORT("GC_finalize: found accessible unmarked object\n");
        !           549:               }
        !           550: #          endif
        !           551:             curr_fo = next_fo;
        !           552:         } else {
        !           553:             prev_fo = curr_fo;
        !           554:             curr_fo = fo_next(curr_fo);
        !           555:         }
        !           556:       }
        !           557:     }
        !           558:
        !           559: # ifdef JAVA_FINALIZATION
        !           560:   /* make sure we mark everything reachable from objects finalized
        !           561:      using the no_order mark_proc */
        !           562:     for (curr_fo = GC_finalize_now;
        !           563:         curr_fo != NULL; curr_fo = fo_next(curr_fo)) {
        !           564:        real_ptr = (ptr_t)curr_fo -> fo_hidden_base;
        !           565:        if (!GC_is_marked(real_ptr)) {
        !           566:            if (curr_fo -> fo_mark_proc == GC_null_finalize_mark_proc) {
        !           567:                GC_MARK_FO(real_ptr, GC_normal_finalize_mark_proc);
        !           568:            }
        !           569:            GC_set_mark_bit(real_ptr);
        !           570:        }
        !           571:     }
        !           572: # endif
        !           573:
        !           574:   /* Remove dangling disappearing links. */
        !           575:     for (i = 0; i < dl_size; i++) {
        !           576:       curr_dl = dl_head[i];
        !           577:       prev_dl = 0;
        !           578:       while (curr_dl != 0) {
        !           579:         real_link = GC_base((ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_link));
        !           580:         if (real_link != 0 && !GC_is_marked(real_link)) {
        !           581:             next_dl = dl_next(curr_dl);
        !           582:             if (prev_dl == 0) {
        !           583:                 dl_head[i] = next_dl;
        !           584:             } else {
        !           585:                 dl_set_next(prev_dl, next_dl);
        !           586:             }
        !           587:             GC_clear_mark_bit((ptr_t)curr_dl);
        !           588:             GC_dl_entries--;
        !           589:             curr_dl = next_dl;
        !           590:         } else {
        !           591:             prev_dl = curr_dl;
        !           592:             curr_dl = dl_next(curr_dl);
        !           593:         }
        !           594:       }
        !           595:     }
        !           596: }
        !           597:
        !           598: #ifdef JAVA_FINALIZATION
        !           599:
        !           600: /* Enqueue all remaining finalizers to be run - Assumes lock is
        !           601:  * held, and signals are disabled */
        !           602: void GC_enqueue_all_finalizers()
        !           603: {
        !           604:     struct finalizable_object * curr_fo, * prev_fo, * next_fo;
        !           605:     ptr_t real_ptr, real_link;
        !           606:     register int i;
        !           607:     int fo_size;
        !           608:
        !           609:     fo_size = (log_fo_table_size == -1 ) ? 0 : (1 << log_fo_table_size);
        !           610:     GC_words_finalized = 0;
        !           611:     for (i = 0; i < fo_size; i++) {
        !           612:         curr_fo = fo_head[i];
        !           613:         prev_fo = 0;
        !           614:       while (curr_fo != 0) {
        !           615:           real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
        !           616:           GC_MARK_FO(real_ptr, GC_normal_finalize_mark_proc);
        !           617:           GC_set_mark_bit(real_ptr);
        !           618:
        !           619:           /* Delete from hash table */
        !           620:           next_fo = fo_next(curr_fo);
        !           621:           if (prev_fo == 0) {
        !           622:               fo_head[i] = next_fo;
        !           623:           } else {
        !           624:               fo_set_next(prev_fo, next_fo);
        !           625:           }
        !           626:           GC_fo_entries--;
        !           627:
        !           628:           /* Add to list of objects awaiting finalization.     */
        !           629:           fo_set_next(curr_fo, GC_finalize_now);
        !           630:           GC_finalize_now = curr_fo;
        !           631:
        !           632:           /* unhide object pointer so any future collections will      */
        !           633:           /* see it.                                           */
        !           634:           curr_fo -> fo_hidden_base =
        !           635:                        (word) REVEAL_POINTER(curr_fo -> fo_hidden_base);
        !           636:
        !           637:           GC_words_finalized +=
        !           638:                ALIGNED_WORDS(curr_fo -> fo_object_size)
        !           639:                        + ALIGNED_WORDS(sizeof(struct finalizable_object));
        !           640:           curr_fo = next_fo;
        !           641:         }
        !           642:     }
        !           643:
        !           644:     return;
        !           645: }
        !           646:
        !           647: /* Invoke all remaining finalizers that haven't yet been run.
        !           648:  * This is needed for strict compliance with the Java standard,
        !           649:  * which can make the runtime guarantee that all finalizers are run.
        !           650:  * Unfortunately, the Java standard implies we have to keep running
        !           651:  * finalizers until there are no more left, a potential infinite loop.
        !           652:  * YUCK.
        !           653:  * This routine is externally callable, so is called without
        !           654:  * the allocation lock.
        !           655:  */
        !           656: void GC_finalize_all()
        !           657: {
        !           658:     DCL_LOCK_STATE;
        !           659:
        !           660:     DISABLE_SIGNALS();
        !           661:     LOCK();
        !           662:     while (GC_fo_entries > 0) {
        !           663:       GC_enqueue_all_finalizers();
        !           664:       UNLOCK();
        !           665:       ENABLE_SIGNALS();
        !           666:       GC_INVOKE_FINALIZERS();
        !           667:       DISABLE_SIGNALS();
        !           668:       LOCK();
        !           669:     }
        !           670:     UNLOCK();
        !           671:     ENABLE_SIGNALS();
        !           672: }
        !           673: #endif
        !           674:
        !           675: /* Invoke finalizers for all objects that are ready to be finalized.   */
        !           676: /* Should be called without allocation lock.                           */
        !           677: int GC_invoke_finalizers()
        !           678: {
        !           679:     register struct finalizable_object * curr_fo;
        !           680:     register int count = 0;
        !           681:     DCL_LOCK_STATE;
        !           682:
        !           683:     while (GC_finalize_now != 0) {
        !           684: #      ifdef THREADS
        !           685:            DISABLE_SIGNALS();
        !           686:            LOCK();
        !           687: #      endif
        !           688:        curr_fo = GC_finalize_now;
        !           689: #      ifdef THREADS
        !           690:            if (curr_fo != 0) GC_finalize_now = fo_next(curr_fo);
        !           691:            UNLOCK();
        !           692:            ENABLE_SIGNALS();
        !           693:            if (curr_fo == 0) break;
        !           694: #      else
        !           695:            GC_finalize_now = fo_next(curr_fo);
        !           696: #      endif
        !           697:        fo_set_next(curr_fo, 0);
        !           698:        (*(curr_fo -> fo_fn))((ptr_t)(curr_fo -> fo_hidden_base),
        !           699:                              curr_fo -> fo_client_data);
        !           700:        curr_fo -> fo_client_data = 0;
        !           701:        ++count;
        !           702: #      ifdef UNDEFINED
        !           703:            /* This is probably a bad idea.  It throws off accounting if */
        !           704:            /* nearly all objects are finalizable.  O.w. it shouldn't    */
        !           705:            /* matter.                                                   */
        !           706:            GC_free((GC_PTR)curr_fo);
        !           707: #      endif
        !           708:     }
        !           709:     return count;
        !           710: }
        !           711:
        !           712: # ifdef __STDC__
        !           713:     GC_PTR GC_call_with_alloc_lock(GC_fn_type fn,
        !           714:                                         GC_PTR client_data)
        !           715: # else
        !           716:     GC_PTR GC_call_with_alloc_lock(fn, client_data)
        !           717:     GC_fn_type fn;
        !           718:     GC_PTR client_data;
        !           719: # endif
        !           720: {
        !           721:     GC_PTR result;
        !           722:     DCL_LOCK_STATE;
        !           723:
        !           724: #   ifdef THREADS
        !           725:       DISABLE_SIGNALS();
        !           726:       LOCK();
        !           727:       SET_LOCK_HOLDER();
        !           728: #   endif
        !           729:     result = (*fn)(client_data);
        !           730: #   ifdef THREADS
        !           731:       UNSET_LOCK_HOLDER();
        !           732:       UNLOCK();
        !           733:       ENABLE_SIGNALS();
        !           734: #   endif
        !           735:     return(result);
        !           736: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>