[BACK]Return to gc_pmark.h CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / gc / include / private

Annotation of OpenXM_contrib2/asir2000/gc/include/private/gc_pmark.h, Revision 1.1

1.1     ! noro        1: /*
        !             2:  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
        !             3:  * Copyright (c) 2001 by Hewlett-Packard Company. 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:  */
        !            15:
        !            16: /* Private declarations of GC marker data structures and macros */
        !            17:
        !            18: /*
        !            19:  * Declarations of mark stack.  Needed by marker and client supplied mark
        !            20:  * routines.  Transitively include gc_priv.h.
        !            21:  * (Note that gc_priv.h should not be included before this, since this
        !            22:  * includes dbg_mlc.h, which wants to include gc_priv.h AFTER defining
        !            23:  * I_HIDE_POINTERS.)
        !            24:  */
        !            25: #ifndef GC_PMARK_H
        !            26: # define GC_PMARK_H
        !            27:
        !            28: # ifdef KEEP_BACK_PTRS
        !            29: #   include "dbg_mlc.h"
        !            30: # endif
        !            31: # ifndef GC_MARK_H
        !            32: #   include "../gc_mark.h"
        !            33: # endif
        !            34: # ifndef GC_PRIVATE_H
        !            35: #   include "gc_priv.h"
        !            36: # endif
        !            37:
        !            38: /* The real declarations of the following is in gc_priv.h, so that     */
        !            39: /* we can avoid scanning the following table.                          */
        !            40: /*
        !            41: extern mark_proc GC_mark_procs[MAX_MARK_PROCS];
        !            42: */
        !            43:
        !            44: /*
        !            45:  * Mark descriptor stuff that should remain private for now, mostly
        !            46:  * because it's hard to export WORDSZ without including gcconfig.h.
        !            47:  */
        !            48: # define BITMAP_BITS (WORDSZ - GC_DS_TAG_BITS)
        !            49: # define PROC(descr) \
        !            50:        (GC_mark_procs[((descr) >> GC_DS_TAG_BITS) & (GC_MAX_MARK_PROCS-1)])
        !            51: # define ENV(descr) \
        !            52:        ((descr) >> (GC_DS_TAG_BITS + GC_LOG_MAX_MARK_PROCS))
        !            53: # define MAX_ENV \
        !            54:        (((word)1 << (WORDSZ - GC_DS_TAG_BITS - GC_LOG_MAX_MARK_PROCS)) - 1)
        !            55:
        !            56:
        !            57: extern word GC_n_mark_procs;
        !            58:
        !            59: /* Number of mark stack entries to discard on overflow.        */
        !            60: #define GC_MARK_STACK_DISCARDS (INITIAL_MARK_STACK_SIZE/8)
        !            61:
        !            62: typedef struct GC_ms_entry {
        !            63:     GC_word * mse_start;   /* First word of object */
        !            64:     GC_word mse_descr; /* Descriptor; low order two bits are tags,     */
        !            65:                        /* identifying the upper 30 bits as one of the  */
        !            66:                        /* following:                                   */
        !            67: } mse;
        !            68:
        !            69: extern word GC_mark_stack_size;
        !            70:
        !            71: extern mse * GC_mark_stack_limit;
        !            72:
        !            73: #ifdef PARALLEL_MARK
        !            74:   extern mse * VOLATILE GC_mark_stack_top;
        !            75: #else
        !            76:   extern mse * GC_mark_stack_top;
        !            77: #endif
        !            78:
        !            79: extern mse * GC_mark_stack;
        !            80:
        !            81: #ifdef PARALLEL_MARK
        !            82:     /*
        !            83:      * Allow multiple threads to participate in the marking process.
        !            84:      * This works roughly as follows:
        !            85:      *  The main mark stack never shrinks, but it can grow.
        !            86:      *
        !            87:      * The initiating threads holds the GC lock, and sets GC_help_wanted.
        !            88:      *
        !            89:      *  Other threads:
        !            90:      *     1) update helper_count (while holding mark_lock.)
        !            91:      *    2) allocate a local mark stack
        !            92:      *     repeatedly:
        !            93:      *         3) Steal a global mark stack entry by atomically replacing
        !            94:      *            its descriptor with 0.
        !            95:      *         4) Copy it to the local stack.
        !            96:      *         5) Mark on the local stack until it is empty, or
        !            97:      *            it may be profitable to copy it back.
        !            98:      *         6) If necessary, copy local stack to global one,
        !            99:      *            holding mark lock.
        !           100:      *    7) Stop when the global mark stack is empty.
        !           101:      *    8) decrement helper_count (holding mark_lock).
        !           102:      *
        !           103:      * This is an experiment to see if we can do something along the lines
        !           104:      * of the University of Tokyo SGC in a less intrusive, though probably
        !           105:      * also less performant, way.
        !           106:      */
        !           107:     void GC_do_parallel_mark();
        !           108:                /* inititate parallel marking.  */
        !           109:
        !           110:     extern GC_bool GC_help_wanted;     /* Protected by mark lock       */
        !           111:     extern unsigned GC_helper_count;   /* Number of running helpers.   */
        !           112:                                        /* Protected by mark lock       */
        !           113:     extern unsigned GC_active_count;   /* Number of active helpers.    */
        !           114:                                        /* Protected by mark lock       */
        !           115:                                        /* May increase and decrease    */
        !           116:                                        /* within each mark cycle.  But */
        !           117:                                        /* once it returns to 0, it     */
        !           118:                                        /* stays zero for the cycle.    */
        !           119:     /* GC_mark_stack_top is also protected by mark lock.       */
        !           120:     extern mse * VOLATILE GC_first_nonempty;
        !           121:                                        /* Lowest entry on mark stack   */
        !           122:                                        /* that may be nonempty.        */
        !           123:                                        /* Updated only by initiating   */
        !           124:                                        /* thread.                      */
        !           125:     /*
        !           126:      * GC_notify_all_marker() is used when GC_help_wanted is first set,
        !           127:      * when the last helper becomes inactive,
        !           128:      * when something is added to the global mark stack, and just after
        !           129:      * GC_mark_no is incremented.
        !           130:      * This could be split into multiple CVs (and probably should be to
        !           131:      * scale to really large numbers of processors.)
        !           132:      */
        !           133: #endif /* PARALLEL_MARK */
        !           134:
        !           135: ptr_t GC_find_start();
        !           136:
        !           137: mse * GC_signal_mark_stack_overflow();
        !           138:
        !           139: # ifdef GATHERSTATS
        !           140: #   define ADD_TO_ATOMIC(sz) GC_atomic_in_use += (sz)
        !           141: #   define ADD_TO_COMPOSITE(sz) GC_composite_in_use += (sz)
        !           142: # else
        !           143: #   define ADD_TO_ATOMIC(sz)
        !           144: #   define ADD_TO_COMPOSITE(sz)
        !           145: # endif
        !           146:
        !           147: /* Push the object obj with corresponding heap block header hhdr onto  */
        !           148: /* the mark stack.                                                     */
        !           149: # define PUSH_OBJ(obj, hhdr, mark_stack_top, mark_stack_limit) \
        !           150: { \
        !           151:     register word _descr = (hhdr) -> hb_descr; \
        !           152:         \
        !           153:     if (_descr == 0) { \
        !           154:        ADD_TO_ATOMIC((hhdr) -> hb_sz); \
        !           155:     } else { \
        !           156:         ADD_TO_COMPOSITE((hhdr) -> hb_sz); \
        !           157:         mark_stack_top++; \
        !           158:         if (mark_stack_top >= mark_stack_limit) { \
        !           159:           mark_stack_top = GC_signal_mark_stack_overflow(mark_stack_top); \
        !           160:         } \
        !           161:         mark_stack_top -> mse_start = (obj); \
        !           162:         mark_stack_top -> mse_descr = _descr; \
        !           163:     } \
        !           164: }
        !           165:
        !           166: #ifdef PRINT_BLACK_LIST
        !           167: #   define GC_FIND_START(current, hhdr, source) \
        !           168:        GC_find_start(current, hhdr, source)
        !           169: #else
        !           170: #   define GC_FIND_START(current, hhdr, source) \
        !           171:        GC_find_start(current, hhdr)
        !           172: #endif
        !           173:
        !           174: /* Push the contents of current onto the mark stack if it is a valid   */
        !           175: /* ptr to a currently unmarked object.  Mark it.                       */
        !           176: /* If we assumed a standard-conforming compiler, we could probably     */
        !           177: /* generate the exit_label transparently.                              */
        !           178: # define PUSH_CONTENTS(current, mark_stack_top, mark_stack_limit, \
        !           179:                       source, exit_label) \
        !           180: { \
        !           181:     hdr * my_hhdr; \
        !           182:     ptr_t my_current = current; \
        !           183:  \
        !           184:     GET_HDR(my_current, my_hhdr); \
        !           185:     if (IS_FORWARDING_ADDR_OR_NIL(my_hhdr)) { \
        !           186:          my_current = GC_FIND_START(my_current, my_hhdr, (word)source); \
        !           187:          if (my_current == 0) goto exit_label; \
        !           188:          my_hhdr = GC_find_header(my_current); \
        !           189:     } \
        !           190:     PUSH_CONTENTS_HDR(my_current, mark_stack_top, mark_stack_limit, \
        !           191:                  source, exit_label, my_hhdr); \
        !           192: exit_label: ; \
        !           193: }
        !           194:
        !           195: /* As above, but use header cache for header lookup.   */
        !           196: # define HC_PUSH_CONTENTS(current, mark_stack_top, mark_stack_limit, \
        !           197:                       source, exit_label) \
        !           198: { \
        !           199:     hdr * my_hhdr; \
        !           200:     ptr_t my_current = current; \
        !           201:  \
        !           202:     HC_GET_HDR(my_current, my_hhdr, source); \
        !           203:     PUSH_CONTENTS_HDR(my_current, mark_stack_top, mark_stack_limit, \
        !           204:                  source, exit_label, my_hhdr); \
        !           205: exit_label: ; \
        !           206: }
        !           207:
        !           208: /* As above, but deal with two pointers in interleaved fashion.        */
        !           209: # define HC_PUSH_CONTENTS2(current1, current2, mark_stack_top, \
        !           210:                           mark_stack_limit, \
        !           211:                           source1, source2, exit_label1, exit_label2) \
        !           212: { \
        !           213:     hdr * hhdr1; \
        !           214:     ptr_t my_current1 = current1; \
        !           215:     hdr * hhdr2; \
        !           216:     ptr_t my_current2 = current2; \
        !           217:  \
        !           218:     HC_GET_HDR2(my_current1, hhdr1, source1, my_current2, hhdr2, source2); \
        !           219:     PUSH_CONTENTS_HDR(my_current1, mark_stack_top, mark_stack_limit, \
        !           220:                  source1, exit_label1, hhdr1); \
        !           221: exit_label1: ; \
        !           222:     if (0 != hhdr2) { \
        !           223:       PUSH_CONTENTS_HDR(my_current2, mark_stack_top, mark_stack_limit, \
        !           224:                  source2, exit_label2, hhdr2); \
        !           225:     } \
        !           226: exit_label2: ; \
        !           227: }
        !           228:
        !           229: /* Set mark bit, exit if it was already set.   */
        !           230:
        !           231: # ifdef USE_MARK_BYTES
        !           232:     /* Unlike the mark bit case, there is a race here, and we may set  */
        !           233:     /* the bit twice in the concurrent case.  This can result in the   */
        !           234:     /* object being pushed twice.  But that's only a performance issue.        */
        !           235: #   define SET_MARK_BIT_EXIT_IF_SET(hhdr,displ,exit_label) \
        !           236:     { \
        !           237:         register VOLATILE char * mark_byte_addr = \
        !           238:                                hhdr -> hb_marks + ((displ) >> 1); \
        !           239:         register char mark_byte = *mark_byte_addr; \
        !           240:           \
        !           241:        if (mark_byte) goto exit_label; \
        !           242:        *mark_byte_addr = 1;  \
        !           243:     }
        !           244: # else
        !           245: #   define SET_MARK_BIT_EXIT_IF_SET(hhdr,displ,exit_label) \
        !           246:     { \
        !           247:         register word * mark_word_addr = hhdr -> hb_marks + divWORDSZ(displ); \
        !           248:         register word mark_word = *mark_word_addr; \
        !           249:           \
        !           250:         OR_WORD_EXIT_IF_SET(mark_word_addr, (word)1 << modWORDSZ(displ), \
        !           251:                            exit_label); \
        !           252:     }
        !           253: # endif /* USE_MARK_BYTES */
        !           254:
        !           255: /* If the mark bit corresponding to current is not set, set it, and    */
        !           256: /* push the contents of the object on the mark stack.  Since we                */
        !           257: /* already have the header, we only look at the low order bits of      */
        !           258: /* current.  (The value of current doesn't matter if hhdr =            */
        !           259: /* GC_invalid_header.)                                                 */
        !           260: # define PUSH_CONTENTS_HDR(current, mark_stack_top, mark_stack_limit, \
        !           261:                           source, exit_label, hhdr) \
        !           262: { \
        !           263:     int displ;  /* Displacement in block; first bytes, then words */ \
        !           264:     int map_entry; \
        !           265:     \
        !           266:     displ = HBLKDISPL(current); \
        !           267:     map_entry = MAP_ENTRY((hhdr -> hb_map), displ); \
        !           268:     displ = BYTES_TO_WORDS(displ); \
        !           269:     if (map_entry > CPP_MAX_OFFSET) { \
        !           270:        if (map_entry == OFFSET_TOO_BIG) { \
        !           271:          map_entry = displ % (hhdr -> hb_sz); \
        !           272:          displ -= map_entry; \
        !           273:          if (displ + (hhdr -> hb_sz) > BYTES_TO_WORDS(HBLKSIZE)) { \
        !           274:            GC_ADD_TO_BLACK_LIST_NORMAL((word)current, source); \
        !           275:            goto exit_label; \
        !           276:          } \
        !           277:        } else { \
        !           278:           GC_ADD_TO_BLACK_LIST_NORMAL((word)current, source); goto exit_label; \
        !           279:        } \
        !           280:     } else { \
        !           281:         displ -= map_entry; \
        !           282:     } \
        !           283:     GC_ASSERT(displ >= 0 && displ < MARK_BITS_PER_HBLK); \
        !           284:     SET_MARK_BIT_EXIT_IF_SET(hhdr, displ, exit_label); \
        !           285:     GC_STORE_BACK_PTR((ptr_t)source, (ptr_t)HBLKPTR(current) \
        !           286:                                      + WORDS_TO_BYTES(displ)); \
        !           287:     PUSH_OBJ(((word *)(HBLKPTR(current)) + displ), hhdr, \
        !           288:             mark_stack_top, mark_stack_limit) \
        !           289: }
        !           290:
        !           291: #if defined(PRINT_BLACK_LIST) || defined(KEEP_BACK_PTRS)
        !           292: #   define PUSH_ONE_CHECKED_STACK(p, source) \
        !           293:        GC_mark_and_push_stack(p, (ptr_t)(source))
        !           294: #else
        !           295: #   define PUSH_ONE_CHECKED_STACK(p, source) \
        !           296:        GC_mark_and_push_stack(p)
        !           297: #endif
        !           298:
        !           299: /*
        !           300:  * Push a single value onto mark stack. Mark from the object pointed to by p.
        !           301:  * P is considered valid even if it is an interior pointer.
        !           302:  * Previously marked objects are not pushed.  Hence we make progress even
        !           303:  * if the mark stack overflows.
        !           304:  */
        !           305: # define GC_PUSH_ONE_STACK(p, source) \
        !           306:     if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr      \
        !           307:         && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) {      \
        !           308:         PUSH_ONE_CHECKED_STACK(p, source);     \
        !           309:     }
        !           310:
        !           311: /*
        !           312:  * As above, but interior pointer recognition as for
        !           313:  * normal for heap pointers.
        !           314:  */
        !           315: # define GC_PUSH_ONE_HEAP(p,source) \
        !           316:     if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr      \
        !           317:         && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) {      \
        !           318:            GC_mark_stack_top = GC_mark_and_push( \
        !           319:                            (GC_PTR)(p), GC_mark_stack_top, \
        !           320:                            GC_mark_stack_limit, (GC_PTR *)(source)); \
        !           321:     }
        !           322:
        !           323: /* Mark starting at mark stack entry top (incl.) down to       */
        !           324: /* mark stack entry bottom (incl.).  Stop after performing     */
        !           325: /* about one page worth of work.  Return the new mark stack    */
        !           326: /* top entry.                                                  */
        !           327: mse * GC_mark_from GC_PROTO((mse * top, mse * bottom, mse *limit));
        !           328:
        !           329: #define MARK_FROM_MARK_STACK() \
        !           330:        GC_mark_stack_top = GC_mark_from(GC_mark_stack_top, \
        !           331:                                         GC_mark_stack, \
        !           332:                                         GC_mark_stack + GC_mark_stack_size);
        !           333:
        !           334: /*
        !           335:  * Mark from one finalizable object using the specified
        !           336:  * mark proc. May not mark the object pointed to by
        !           337:  * real_ptr. That is the job of the caller, if appropriate
        !           338:  */
        !           339: # define GC_MARK_FO(real_ptr, mark_proc) \
        !           340: { \
        !           341:     (*(mark_proc))(real_ptr); \
        !           342:     while (!GC_mark_stack_empty()) MARK_FROM_MARK_STACK(); \
        !           343:     if (GC_mark_state != MS_NONE) { \
        !           344:         GC_set_mark_bit(real_ptr); \
        !           345:         while (!GC_mark_some((ptr_t)0)); \
        !           346:     } \
        !           347: }
        !           348:
        !           349: extern GC_bool GC_mark_stack_too_small;
        !           350:                                /* We need a larger mark stack.  May be */
        !           351:                                /* set by client supplied mark routines.*/
        !           352:
        !           353: typedef int mark_state_t;      /* Current state of marking, as follows:*/
        !           354:                                /* Used to remember where we are during */
        !           355:                                /* concurrent marking.                  */
        !           356:
        !           357:                                /* We say something is dirty if it was  */
        !           358:                                /* written since the last time we       */
        !           359:                                /* retrieved dirty bits.  We say it's   */
        !           360:                                /* grungy if it was marked dirty in the */
        !           361:                                /* last set of bits we retrieved.       */
        !           362:
        !           363:                                /* Invariant I: all roots and marked    */
        !           364:                                /* objects p are either dirty, or point */
        !           365:                                /* to objects q that are either marked  */
        !           366:                                /* or a pointer to q appears in a range */
        !           367:                                /* on the mark stack.                   */
        !           368:
        !           369: # define MS_NONE 0             /* No marking in progress. I holds.     */
        !           370:                                /* Mark stack is empty.                 */
        !           371:
        !           372: # define MS_PUSH_RESCUERS 1    /* Rescuing objects are currently       */
        !           373:                                /* being pushed.  I holds, except       */
        !           374:                                /* that grungy roots may point to       */
        !           375:                                /* unmarked objects, as may marked      */
        !           376:                                /* grungy objects above scan_ptr.       */
        !           377:
        !           378: # define MS_PUSH_UNCOLLECTABLE 2
        !           379:                                /* I holds, except that marked          */
        !           380:                                /* uncollectable objects above scan_ptr */
        !           381:                                /* may point to unmarked objects.       */
        !           382:                                /* Roots may point to unmarked objects  */
        !           383:
        !           384: # define MS_ROOTS_PUSHED 3     /* I holds, mark stack may be nonempty  */
        !           385:
        !           386: # define MS_PARTIALLY_INVALID 4        /* I may not hold, e.g. because of M.S. */
        !           387:                                /* overflow.  However marked heap       */
        !           388:                                /* objects below scan_ptr point to      */
        !           389:                                /* marked or stacked objects.           */
        !           390:
        !           391: # define MS_INVALID 5          /* I may not hold.                      */
        !           392:
        !           393: extern mark_state_t GC_mark_state;
        !           394:
        !           395: #endif  /* GC_PMARK_H */
        !           396:

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