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

Annotation of OpenXM_contrib2/asir2000/gc/stubborn.c, Revision 1.1.1.1

1.1       noro        1: /*
                      2:  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
                      3:  * Copyright (c) 1991-1994 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, July 31, 1995 5:02 pm PDT */
                     15:
                     16:
                     17: #include "gc_priv.h"
                     18:
                     19: # ifdef STUBBORN_ALLOC
                     20: /* Stubborn object (hard to change, nearly immutable) allocation. */
                     21:
                     22: extern ptr_t GC_clear_stack(); /* in misc.c, behaves like identity */
                     23:
                     24: #define GENERAL_MALLOC(lb,k) \
                     25:     (GC_PTR)GC_clear_stack(GC_generic_malloc((word)lb, k))
                     26:
                     27: /* Data structure representing immutable objects that  */
                     28: /* are still being initialized.                                */
                     29: /* This is a bit baroque in order to avoid acquiring   */
                     30: /* the lock twice for a typical allocation.            */
                     31:
                     32: GC_PTR * GC_changing_list_start;
                     33:
                     34: # ifdef THREADS
                     35:   VOLATILE GC_PTR * VOLATILE GC_changing_list_current;
                     36: # else
                     37:   GC_PTR * GC_changing_list_current;
                     38: # endif
                     39:        /* Points at last added element.  Also (ab)used for             */
                     40:        /* synchronization.  Updates and reads are assumed atomic.      */
                     41:
                     42: GC_PTR * GC_changing_list_limit;
                     43:        /* Points at the last word of the buffer, which is always 0     */
                     44:        /* All entries in (GC_changing_list_current,                    */
                     45:        /* GC_changing_list_limit] are 0                                */
                     46:
                     47:
                     48: void GC_stubborn_init()
                     49: {
                     50: #   define INIT_SIZE 10
                     51:
                     52:     GC_changing_list_start = (GC_PTR *)
                     53:                        GC_generic_malloc_inner(
                     54:                                (word)(INIT_SIZE * sizeof(GC_PTR)),
                     55:                                PTRFREE);
                     56:     BZERO(GC_changing_list_start,
                     57:          INIT_SIZE * sizeof(GC_PTR));
                     58:     if (GC_changing_list_start == 0) {
                     59:         GC_err_printf0("Insufficient space to start up\n");
                     60:         ABORT("GC_stubborn_init: put of space");
                     61:     }
                     62:     GC_changing_list_current = GC_changing_list_start;
                     63:     GC_changing_list_limit = GC_changing_list_start + INIT_SIZE - 1;
                     64:     * GC_changing_list_limit = 0;
                     65: }
                     66:
                     67: /* Compact and possibly grow GC_uninit_list.  The old copy is          */
                     68: /* left alone. Lock must be held.                                      */
                     69: /* When called GC_changing_list_current == GC_changing_list_limit      */
                     70: /* which is one past the current element.                              */
                     71: /* When we finish GC_changing_list_current again points one past last  */
                     72: /* element.                                                            */
                     73: /* Invariant while this is running: GC_changing_list_current           */
                     74: /* points at a word containing 0.                                      */
                     75: /* Returns FALSE on failure.                                           */
                     76: GC_bool GC_compact_changing_list()
                     77: {
                     78:     register GC_PTR *p, *q;
                     79:     register word count = 0;
                     80:     word old_size = (char **)GC_changing_list_limit
                     81:                    - (char **)GC_changing_list_start+1;
                     82:                    /* The casts are needed as a workaround for an Amiga bug */
                     83:     register word new_size = old_size;
                     84:     GC_PTR * new_list;
                     85:
                     86:     for (p = GC_changing_list_start; p < GC_changing_list_limit; p++) {
                     87:         if (*p != 0) count++;
                     88:     }
                     89:     if (2 * count > old_size) new_size = 2 * count;
                     90:     new_list = (GC_PTR *)
                     91:                GC_generic_malloc_inner(
                     92:                                new_size * sizeof(GC_PTR), PTRFREE);
                     93:                /* PTRFREE is a lie.  But we don't want the collector to  */
                     94:                /* consider these.  We do want the list itself to be      */
                     95:                /* collectable.                                           */
                     96:     if (new_list == 0) return(FALSE);
                     97:     BZERO(new_list, new_size * sizeof(GC_PTR));
                     98:     q = new_list;
                     99:     for (p = GC_changing_list_start; p < GC_changing_list_limit; p++) {
                    100:         if (*p != 0) *q++ = *p;
                    101:     }
                    102:     GC_changing_list_start = new_list;
                    103:     GC_changing_list_limit = new_list + new_size - 1;
                    104:     GC_changing_list_current = q;
                    105:     return(TRUE);
                    106: }
                    107:
                    108: /* Add p to changing list.  Clear p on failure.        */
                    109: # define ADD_CHANGING(p) \
                    110:        {       \
                    111:            register struct hblk * h = HBLKPTR(p);      \
                    112:            register word index = PHT_HASH(h);  \
                    113:            \
                    114:            set_pht_entry_from_index(GC_changed_pages, index);  \
                    115:        }       \
                    116:        if (*GC_changing_list_current != 0 \
                    117:            && ++GC_changing_list_current == GC_changing_list_limit) { \
                    118:            if (!GC_compact_changing_list()) (p) = 0; \
                    119:        } \
                    120:        *GC_changing_list_current = p;
                    121:
                    122: void GC_change_stubborn(p)
                    123: GC_PTR p;
                    124: {
                    125:     DCL_LOCK_STATE;
                    126:
                    127:     DISABLE_SIGNALS();
                    128:     LOCK();
                    129:     ADD_CHANGING(p);
                    130:     UNLOCK();
                    131:     ENABLE_SIGNALS();
                    132: }
                    133:
                    134: void GC_end_stubborn_change(p)
                    135: GC_PTR p;
                    136: {
                    137: #   ifdef THREADS
                    138:       register VOLATILE GC_PTR * my_current = GC_changing_list_current;
                    139: #   else
                    140:       register GC_PTR * my_current = GC_changing_list_current;
                    141: #   endif
                    142:     register GC_bool tried_quick;
                    143:     DCL_LOCK_STATE;
                    144:
                    145:     if (*my_current == p) {
                    146:         /* Hopefully the normal case.                                  */
                    147:         /* Compaction could not have been running when we started.     */
                    148:         *my_current = 0;
                    149: #      ifdef THREADS
                    150:           if (my_current == GC_changing_list_current) {
                    151:             /* Compaction can't have run in the interim.       */
                    152:             /* We got away with the quick and dirty approach.   */
                    153:             return;
                    154:           }
                    155:           tried_quick = TRUE;
                    156: #      else
                    157:          return;
                    158: #      endif
                    159:     } else {
                    160:         tried_quick = FALSE;
                    161:     }
                    162:     DISABLE_SIGNALS();
                    163:     LOCK();
                    164:     my_current = GC_changing_list_current;
                    165:     for (; my_current >= GC_changing_list_start; my_current--) {
                    166:         if (*my_current == p) {
                    167:             *my_current = 0;
                    168:             UNLOCK();
                    169:             ENABLE_SIGNALS();
                    170:             return;
                    171:         }
                    172:     }
                    173:     if (!tried_quick) {
                    174:         GC_err_printf1("Bad arg to GC_end_stubborn_change: 0x%lx\n",
                    175:                       (unsigned long)p);
                    176:         ABORT("Bad arg to GC_end_stubborn_change");
                    177:     }
                    178:     UNLOCK();
                    179:     ENABLE_SIGNALS();
                    180: }
                    181:
                    182: /* Allocate lb bytes of composite (pointerful) data    */
                    183: /* No pointer fields may be changed after a call to    */
                    184: /* GC_end_stubborn_change(p) where p is the value      */
                    185: /* returned by GC_malloc_stubborn.                     */
                    186: # ifdef __STDC__
                    187:     GC_PTR GC_malloc_stubborn(size_t lb)
                    188: # else
                    189:     GC_PTR GC_malloc_stubborn(lb)
                    190:     size_t lb;
                    191: # endif
                    192: {
                    193: register ptr_t op;
                    194: register ptr_t *opp;
                    195: register word lw;
                    196: ptr_t result;
                    197: DCL_LOCK_STATE;
                    198:
                    199:     if( SMALL_OBJ(lb) ) {
                    200: #       ifdef MERGE_SIZES
                    201:          lw = GC_size_map[lb];
                    202: #      else
                    203:          lw = ALIGNED_WORDS(lb);
                    204: #       endif
                    205:        opp = &(GC_sobjfreelist[lw]);
                    206:        FASTLOCK();
                    207:         if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) {
                    208:             FASTUNLOCK();
                    209:             result = GC_generic_malloc((word)lb, STUBBORN);
                    210:             goto record;
                    211:         }
                    212:         *opp = obj_link(op);
                    213:         obj_link(op) = 0;
                    214:         GC_words_allocd += lw;
                    215:         result = (GC_PTR) op;
                    216:         ADD_CHANGING(result);
                    217:         FASTUNLOCK();
                    218:         return((GC_PTR)result);
                    219:    } else {
                    220:        result = (GC_PTR)
                    221:                GC_generic_malloc((word)lb, STUBBORN);
                    222:    }
                    223: record:
                    224:    DISABLE_SIGNALS();
                    225:    LOCK();
                    226:    ADD_CHANGING(result);
                    227:    UNLOCK();
                    228:    ENABLE_SIGNALS();
                    229:    return((GC_PTR)GC_clear_stack(result));
                    230: }
                    231:
                    232:
                    233: /* Functions analogous to GC_read_dirty and GC_page_was_dirty. */
                    234: /* Report pages on which stubborn objects were changed.                */
                    235: void GC_read_changed()
                    236: {
                    237:     register GC_PTR * p = GC_changing_list_start;
                    238:     register GC_PTR q;
                    239:     register struct hblk * h;
                    240:     register word index;
                    241:
                    242:     if (p == 0) /* initializing */ return;
                    243:     BCOPY(GC_changed_pages, GC_prev_changed_pages,
                    244:           (sizeof GC_changed_pages));
                    245:     BZERO(GC_changed_pages, (sizeof GC_changed_pages));
                    246:     for (; p <= GC_changing_list_current; p++) {
                    247:         if ((q = *p) != 0) {
                    248:             h = HBLKPTR(q);
                    249:             index = PHT_HASH(h);
                    250:             set_pht_entry_from_index(GC_changed_pages, index);
                    251:         }
                    252:     }
                    253: }
                    254:
                    255: GC_bool GC_page_was_changed(h)
                    256: struct hblk * h;
                    257: {
                    258:     register word index = PHT_HASH(h);
                    259:
                    260:     return(get_pht_entry_from_index(GC_prev_changed_pages, index));
                    261: }
                    262:
                    263: /* Remove unreachable entries from changed list. Should only be        */
                    264: /* called with mark bits consistent and lock held.             */
                    265: void GC_clean_changing_list()
                    266: {
                    267:     register GC_PTR * p = GC_changing_list_start;
                    268:     register GC_PTR q;
                    269:     register ptr_t r;
                    270:     register unsigned long count = 0;
                    271:     register unsigned long dropped_count = 0;
                    272:
                    273:     if (p == 0) /* initializing */ return;
                    274:     for (; p <= GC_changing_list_current; p++) {
                    275:         if ((q = *p) != 0) {
                    276:             count++;
                    277:             r = (ptr_t)GC_base(q);
                    278:             if (r == 0 || !GC_is_marked(r)) {
                    279:                 *p = 0;
                    280:                 dropped_count++;
                    281:            }
                    282:         }
                    283:     }
                    284: #   ifdef PRINTSTATS
                    285:       if (count > 0) {
                    286:         GC_printf2("%lu entries in changing list: reclaimed %lu\n",
                    287:                   (unsigned long)count, (unsigned long)dropped_count);
                    288:       }
                    289: #   endif
                    290: }
                    291:
                    292: #else /* !STUBBORN_ALLOC */
                    293:
                    294: # ifdef __STDC__
                    295:     GC_PTR GC_malloc_stubborn(size_t lb)
                    296: # else
                    297:     GC_PTR GC_malloc_stubborn(lb)
                    298:     size_t lb;
                    299: # endif
                    300: {
                    301:     return(GC_malloc(lb));
                    302: }
                    303:
                    304: /*ARGSUSED*/
                    305: void GC_end_stubborn_change(p)
                    306: GC_PTR p;
                    307: {
                    308: }
                    309:
                    310: /*ARGSUSED*/
                    311: void GC_change_stubborn(p)
                    312: GC_PTR p;
                    313: {
                    314: }
                    315:
                    316:
                    317: #endif

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