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

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

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