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

Annotation of OpenXM_contrib2/asir2000/gc/mark_rts.c, Revision 1.7

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: # include <stdio.h>
1.4       noro       15: # include "private/gc_priv.h"
1.1       noro       16:
                     17: /* Data structure for list of root sets.                               */
                     18: /* We keep a hash table, so that we can filter out duplicate additions.        */
                     19: /* Under Win32, we need to do a better job of filtering overlaps, so   */
                     20: /* we resort to sequential search, and pay the price.                  */
                     21: /* This is really declared in gc_priv.h:
                     22: struct roots {
                     23:        ptr_t r_start;
                     24:        ptr_t r_end;
1.4       noro       25:  #     if !defined(MSWIN32) && !defined(MSWINCE)
1.1       noro       26:          struct roots * r_next;
                     27:  #     endif
                     28:        GC_bool r_tmp;
                     29:                -- Delete before registering new dynamic libraries
                     30: };
                     31:
                     32: struct roots GC_static_roots[MAX_ROOT_SETS];
                     33: */
                     34:
1.4       noro       35: int GC_no_dls = 0;     /* Register dynamic library data segments.      */
                     36:
1.1       noro       37: static int n_root_sets = 0;
                     38:
                     39:        /* GC_static_roots[0..n_root_sets) contains the valid root sets. */
                     40:
                     41: # if !defined(NO_DEBUGGING)
                     42: /* For debugging:      */
                     43: void GC_print_static_roots()
                     44: {
                     45:     register int i;
                     46:     size_t total = 0;
                     47:
                     48:     for (i = 0; i < n_root_sets; i++) {
                     49:         GC_printf2("From 0x%lx to 0x%lx ",
                     50:                   (unsigned long) GC_static_roots[i].r_start,
                     51:                   (unsigned long) GC_static_roots[i].r_end);
                     52:         if (GC_static_roots[i].r_tmp) {
                     53:             GC_printf0(" (temporary)\n");
                     54:         } else {
                     55:             GC_printf0("\n");
                     56:         }
                     57:         total += GC_static_roots[i].r_end - GC_static_roots[i].r_start;
                     58:     }
                     59:     GC_printf1("Total size: %ld\n", (unsigned long) total);
                     60:     if (GC_root_size != total) {
                     61:        GC_printf1("GC_root_size incorrect: %ld!!\n",
                     62:                   (unsigned long) GC_root_size);
                     63:     }
                     64: }
                     65: # endif /* NO_DEBUGGING */
                     66:
                     67: /* Primarily for debugging support:    */
                     68: /* Is the address p in one of the registered static                    */
                     69: /* root sections?                                                      */
                     70: GC_bool GC_is_static_root(p)
                     71: ptr_t p;
                     72: {
1.4       noro       73:     static int last_root_set = MAX_ROOT_SETS;
1.1       noro       74:     register int i;
                     75:
                     76:
1.4       noro       77:     if (last_root_set < n_root_sets
                     78:        && p >= GC_static_roots[last_root_set].r_start
1.1       noro       79:         && p < GC_static_roots[last_root_set].r_end) return(TRUE);
                     80:     for (i = 0; i < n_root_sets; i++) {
                     81:        if (p >= GC_static_roots[i].r_start
                     82:             && p < GC_static_roots[i].r_end) {
                     83:             last_root_set = i;
                     84:             return(TRUE);
                     85:         }
                     86:     }
                     87:     return(FALSE);
                     88: }
                     89:
1.4       noro       90: #if !defined(MSWIN32) && !defined(MSWINCE)
1.1       noro       91: /*
                     92: #   define LOG_RT_SIZE 6
                     93: #   define RT_SIZE (1 << LOG_RT_SIZE)  -- Power of 2, may be != MAX_ROOT_SETS
                     94:
                     95:     struct roots * GC_root_index[RT_SIZE];
                     96:        -- Hash table header.  Used only to check whether a range is
                     97:        -- already present.
                     98:        -- really defined in gc_priv.h
                     99: */
                    100:
                    101: static int rt_hash(addr)
                    102: char * addr;
                    103: {
                    104:     word result = (word) addr;
                    105: #   if CPP_WORDSZ > 8*LOG_RT_SIZE
                    106:        result ^= result >> 8*LOG_RT_SIZE;
                    107: #   endif
                    108: #   if CPP_WORDSZ > 4*LOG_RT_SIZE
                    109:        result ^= result >> 4*LOG_RT_SIZE;
                    110: #   endif
                    111:     result ^= result >> 2*LOG_RT_SIZE;
                    112:     result ^= result >> LOG_RT_SIZE;
                    113:     result &= (RT_SIZE-1);
                    114:     return(result);
                    115: }
                    116:
                    117: /* Is a range starting at b already in the table? If so return a       */
                    118: /* pointer to it, else NIL.                                            */
                    119: struct roots * GC_roots_present(b)
                    120: char *b;
                    121: {
                    122:     register int h = rt_hash(b);
                    123:     register struct roots *p = GC_root_index[h];
                    124:
                    125:     while (p != 0) {
                    126:         if (p -> r_start == (ptr_t)b) return(p);
                    127:         p = p -> r_next;
                    128:     }
                    129:     return(FALSE);
                    130: }
                    131:
                    132: /* Add the given root structure to the index. */
                    133: static void add_roots_to_index(p)
                    134: struct roots *p;
                    135: {
                    136:     register int h = rt_hash(p -> r_start);
                    137:
                    138:     p -> r_next = GC_root_index[h];
                    139:     GC_root_index[h] = p;
                    140: }
                    141:
1.4       noro      142: # else /* MSWIN32 || MSWINCE */
1.1       noro      143:
                    144: #   define add_roots_to_index(p)
                    145:
                    146: # endif
                    147:
                    148:
                    149:
                    150:
                    151: word GC_root_size = 0;
                    152:
                    153: void GC_add_roots(b, e)
                    154: char * b; char * e;
                    155: {
                    156:     DCL_LOCK_STATE;
                    157:
                    158:     DISABLE_SIGNALS();
                    159:     LOCK();
                    160:     GC_add_roots_inner(b, e, FALSE);
                    161:     UNLOCK();
                    162:     ENABLE_SIGNALS();
                    163: }
                    164:
                    165:
                    166: /* Add [b,e) to the root set.  Adding the same interval a second time  */
                    167: /* is a moderately fast noop, and hence benign.  We do not handle      */
                    168: /* different but overlapping intervals efficiently.  (We do handle     */
                    169: /* them correctly.)                                                    */
                    170: /* Tmp specifies that the interval may be deleted before               */
                    171: /* reregistering dynamic libraries.                                    */
                    172: void GC_add_roots_inner(b, e, tmp)
                    173: char * b; char * e;
                    174: GC_bool tmp;
                    175: {
                    176:     struct roots * old;
                    177:
1.4       noro      178: #   if defined(MSWIN32) || defined(MSWINCE)
1.1       noro      179:       /* Spend the time to ensure that there are no overlapping        */
                    180:       /* or adjacent intervals.                                        */
                    181:       /* This could be done faster with e.g. a                 */
                    182:       /* balanced tree.  But the execution time here is                */
                    183:       /* virtually guaranteed to be dominated by the time it   */
                    184:       /* takes to scan the roots.                              */
                    185:       {
                    186:         register int i;
                    187:
                    188:         for (i = 0; i < n_root_sets; i++) {
                    189:             old = GC_static_roots + i;
                    190:             if ((ptr_t)b <= old -> r_end && (ptr_t)e >= old -> r_start) {
                    191:                 if ((ptr_t)b < old -> r_start) {
                    192:                     old -> r_start = (ptr_t)b;
                    193:                     GC_root_size += (old -> r_start - (ptr_t)b);
                    194:                 }
                    195:                 if ((ptr_t)e > old -> r_end) {
                    196:                     old -> r_end = (ptr_t)e;
                    197:                     GC_root_size += ((ptr_t)e - old -> r_end);
                    198:                 }
                    199:                 old -> r_tmp &= tmp;
                    200:                 break;
                    201:             }
                    202:         }
                    203:         if (i < n_root_sets) {
                    204:           /* merge other overlapping intervals */
                    205:             struct roots *other;
                    206:
                    207:             for (i++; i < n_root_sets; i++) {
                    208:               other = GC_static_roots + i;
                    209:               b = (char *)(other -> r_start);
                    210:               e = (char *)(other -> r_end);
                    211:               if ((ptr_t)b <= old -> r_end && (ptr_t)e >= old -> r_start) {
                    212:                 if ((ptr_t)b < old -> r_start) {
                    213:                     old -> r_start = (ptr_t)b;
                    214:                     GC_root_size += (old -> r_start - (ptr_t)b);
                    215:                 }
                    216:                 if ((ptr_t)e > old -> r_end) {
                    217:                     old -> r_end = (ptr_t)e;
                    218:                     GC_root_size += ((ptr_t)e - old -> r_end);
                    219:                 }
                    220:                 old -> r_tmp &= other -> r_tmp;
                    221:                 /* Delete this entry. */
                    222:                   GC_root_size -= (other -> r_end - other -> r_start);
                    223:                   other -> r_start = GC_static_roots[n_root_sets-1].r_start;
                    224:                   other -> r_end = GC_static_roots[n_root_sets-1].r_end;
                    225:                                   n_root_sets--;
                    226:               }
                    227:             }
                    228:           return;
                    229:         }
                    230:       }
                    231: #   else
                    232:       old = GC_roots_present(b);
                    233:       if (old != 0) {
                    234:         if ((ptr_t)e <= old -> r_end) /* already there */ return;
                    235:         /* else extend */
                    236:         GC_root_size += (ptr_t)e - old -> r_end;
                    237:         old -> r_end = (ptr_t)e;
                    238:         return;
                    239:       }
                    240: #   endif
                    241:     if (n_root_sets == MAX_ROOT_SETS) {
                    242:         ABORT("Too many root sets\n");
                    243:     }
                    244:     GC_static_roots[n_root_sets].r_start = (ptr_t)b;
                    245:     GC_static_roots[n_root_sets].r_end = (ptr_t)e;
                    246:     GC_static_roots[n_root_sets].r_tmp = tmp;
1.4       noro      247: #   if !defined(MSWIN32) && !defined(MSWINCE)
1.1       noro      248:       GC_static_roots[n_root_sets].r_next = 0;
                    249: #   endif
                    250:     add_roots_to_index(GC_static_roots + n_root_sets);
                    251:     GC_root_size += (ptr_t)e - (ptr_t)b;
                    252:     n_root_sets++;
                    253: }
                    254:
1.6       noro      255: static GC_bool roots_were_cleared = FALSE;
1.4       noro      256:
1.1       noro      257: void GC_clear_roots GC_PROTO((void))
                    258: {
                    259:     DCL_LOCK_STATE;
                    260:
                    261:     DISABLE_SIGNALS();
                    262:     LOCK();
1.4       noro      263:     roots_were_cleared = TRUE;
1.1       noro      264:     n_root_sets = 0;
                    265:     GC_root_size = 0;
1.4       noro      266: #   if !defined(MSWIN32) && !defined(MSWINCE)
1.1       noro      267:     {
                    268:        register int i;
                    269:
                    270:        for (i = 0; i < RT_SIZE; i++) GC_root_index[i] = 0;
                    271:     }
                    272: #   endif
                    273:     UNLOCK();
                    274:     ENABLE_SIGNALS();
                    275: }
                    276:
                    277: /* Internal use only; lock held.       */
1.7     ! noro      278: static void GC_remove_root_at_pos(i)
        !           279: int i;
        !           280: {
        !           281:     GC_root_size -= (GC_static_roots[i].r_end - GC_static_roots[i].r_start);
        !           282:     GC_static_roots[i].r_start = GC_static_roots[n_root_sets-1].r_start;
        !           283:     GC_static_roots[i].r_end = GC_static_roots[n_root_sets-1].r_end;
        !           284:     GC_static_roots[i].r_tmp = GC_static_roots[n_root_sets-1].r_tmp;
        !           285:     n_root_sets--;
        !           286: }
        !           287:
        !           288: #if !defined(MSWIN32) && !defined(MSWINCE)
        !           289: static void GC_rebuild_root_index()
        !           290: {
        !           291:     register int i;
        !           292:
        !           293:     for (i = 0; i < RT_SIZE; i++) GC_root_index[i] = 0;
        !           294:     for (i = 0; i < n_root_sets; i++)
        !           295:        add_roots_to_index(GC_static_roots + i);
        !           296: }
        !           297: #endif
        !           298:
        !           299: /* Internal use only; lock held.       */
1.1       noro      300: void GC_remove_tmp_roots()
                    301: {
                    302:     register int i;
                    303:
                    304:     for (i = 0; i < n_root_sets; ) {
                    305:        if (GC_static_roots[i].r_tmp) {
1.7     ! noro      306:             GC_remove_root_at_pos(i);
1.1       noro      307:        } else {
                    308:            i++;
                    309:     }
                    310:     }
1.7     ! noro      311:     #if !defined(MSWIN32) && !defined(MSWINCE)
        !           312:     GC_rebuild_root_index();
        !           313:     #endif
        !           314: }
        !           315:
        !           316: #if !defined(MSWIN32) && !defined(MSWINCE)
        !           317: void GC_remove_roots(b, e)
        !           318: char * b; char * e;
        !           319: {
        !           320:     DCL_LOCK_STATE;
1.1       noro      321:
1.7     ! noro      322:     DISABLE_SIGNALS();
        !           323:     LOCK();
        !           324:     GC_remove_roots_inner(b, e);
        !           325:     UNLOCK();
        !           326:     ENABLE_SIGNALS();
        !           327: }
        !           328:
        !           329: /* Should only be called when the lock is held */
        !           330: void GC_remove_roots_inner(b,e)
        !           331: char * b; char * e;
        !           332: {
        !           333:     int i;
        !           334:     for (i = 0; i < n_root_sets; ) {
        !           335:        if (GC_static_roots[i].r_start >= (ptr_t)b && GC_static_roots[i].r_end <= (ptr_t)e) {
        !           336:             GC_remove_root_at_pos(i);
        !           337:        } else {
        !           338:            i++;
        !           339:        }
        !           340:     }
        !           341:     GC_rebuild_root_index();
1.1       noro      342: }
1.7     ! noro      343: #endif /* !defined(MSWIN32) && !defined(MSWINCE) */
1.1       noro      344:
1.4       noro      345: #if defined(MSWIN32) || defined(_WIN32_WCE_EMULATION)
                    346: /* Workaround for the OS mapping and unmapping behind our back:                */
                    347: /* Is the address p in one of the temporary static root sections?      */
                    348: GC_bool GC_is_tmp_root(p)
                    349: ptr_t p;
                    350: {
                    351:     static int last_root_set = MAX_ROOT_SETS;
                    352:     register int i;
                    353:
                    354:     if (last_root_set < n_root_sets
                    355:        && p >= GC_static_roots[last_root_set].r_start
                    356:         && p < GC_static_roots[last_root_set].r_end)
                    357:        return GC_static_roots[last_root_set].r_tmp;
                    358:     for (i = 0; i < n_root_sets; i++) {
                    359:        if (p >= GC_static_roots[i].r_start
                    360:             && p < GC_static_roots[i].r_end) {
                    361:             last_root_set = i;
                    362:             return GC_static_roots[i].r_tmp;
                    363:         }
                    364:     }
                    365:     return(FALSE);
                    366: }
                    367: #endif /* MSWIN32 || _WIN32_WCE_EMULATION */
                    368:
1.1       noro      369: ptr_t GC_approx_sp()
                    370: {
                    371:     word dummy;
1.4       noro      372:
                    373: #   ifdef _MSC_VER
                    374: #     pragma warning(disable:4172)
                    375: #   endif
1.1       noro      376:     return((ptr_t)(&dummy));
1.4       noro      377: #   ifdef _MSC_VER
                    378: #     pragma warning(default:4172)
                    379: #   endif
1.1       noro      380: }
                    381:
                    382: /*
                    383:  * Data structure for excluded static roots.
                    384:  * Real declaration is in gc_priv.h.
                    385:
                    386: struct exclusion {
                    387:     ptr_t e_start;
                    388:     ptr_t e_end;
                    389: };
                    390:
                    391: struct exclusion GC_excl_table[MAX_EXCLUSIONS];
                    392:                                        -- Array of exclusions, ascending
                    393:                                        -- address order.
                    394: */
                    395:
                    396: size_t GC_excl_table_entries = 0;      /* Number of entries in use.      */
                    397:
                    398: /* Return the first exclusion range that includes an address >= start_addr */
                    399: /* Assumes the exclusion table contains at least one entry (namely the    */
                    400: /* GC data structures).                                                           */
                    401: struct exclusion * GC_next_exclusion(start_addr)
                    402: ptr_t start_addr;
                    403: {
                    404:     size_t low = 0;
                    405:     size_t high = GC_excl_table_entries - 1;
                    406:     size_t mid;
                    407:
                    408:     while (high > low) {
                    409:        mid = (low + high) >> 1;
                    410:        /* low <= mid < high    */
                    411:        if ((word) GC_excl_table[mid].e_end <= (word) start_addr) {
                    412:            low = mid + 1;
                    413:        } else {
                    414:            high = mid;
                    415:        }
                    416:     }
                    417:     if ((word) GC_excl_table[low].e_end <= (word) start_addr) return 0;
                    418:     return GC_excl_table + low;
                    419: }
                    420:
                    421: void GC_exclude_static_roots(start, finish)
                    422: GC_PTR start;
                    423: GC_PTR finish;
                    424: {
                    425:     struct exclusion * next;
                    426:     size_t next_index, i;
                    427:
                    428:     if (0 == GC_excl_table_entries) {
                    429:        next = 0;
                    430:     } else {
                    431:        next = GC_next_exclusion(start);
                    432:     }
                    433:     if (0 != next) {
                    434:       if ((word)(next -> e_start) < (word) finish) {
                    435:        /* incomplete error check. */
                    436:        ABORT("exclusion ranges overlap");
                    437:       }
                    438:       if ((word)(next -> e_start) == (word) finish) {
                    439:         /* extend old range backwards  */
                    440:           next -> e_start = (ptr_t)start;
                    441:          return;
                    442:       }
                    443:       next_index = next - GC_excl_table;
                    444:       for (i = GC_excl_table_entries; i > next_index; --i) {
                    445:        GC_excl_table[i] = GC_excl_table[i-1];
                    446:       }
                    447:     } else {
                    448:       next_index = GC_excl_table_entries;
                    449:     }
                    450:     if (GC_excl_table_entries == MAX_EXCLUSIONS) ABORT("Too many exclusions");
                    451:     GC_excl_table[next_index].e_start = (ptr_t)start;
                    452:     GC_excl_table[next_index].e_end = (ptr_t)finish;
                    453:     ++GC_excl_table_entries;
                    454: }
                    455:
                    456: /* Invoke push_conditional on ranges that are not excluded. */
                    457: void GC_push_conditional_with_exclusions(bottom, top, all)
                    458: ptr_t bottom;
                    459: ptr_t top;
                    460: int all;
                    461: {
                    462:     struct exclusion * next;
                    463:     ptr_t excl_start;
                    464:
                    465:     while (bottom < top) {
                    466:         next = GC_next_exclusion(bottom);
                    467:        if (0 == next || (excl_start = next -> e_start) >= top) {
                    468:            GC_push_conditional(bottom, top, all);
                    469:            return;
                    470:        }
                    471:        if (excl_start > bottom) GC_push_conditional(bottom, excl_start, all);
                    472:        bottom = next -> e_end;
                    473:     }
                    474: }
                    475:
                    476: /*
                    477:  * In the absence of threads, push the stack contents.
                    478:  * In the presence of threads, push enough of the current stack
                    479:  * to ensure that callee-save registers saved in collector frames have been
                    480:  * seen.
                    481:  */
                    482: void GC_push_current_stack(cold_gc_frame)
                    483: ptr_t cold_gc_frame;
                    484: {
                    485: #   if defined(THREADS)
                    486:        if (0 == cold_gc_frame) return;
                    487: #       ifdef STACK_GROWS_DOWN
                    488:          GC_push_all_eager(GC_approx_sp(), cold_gc_frame);
1.3       noro      489:          /* For IA64, the register stack backing store is handled      */
                    490:          /* in the thread-specific code.                               */
1.1       noro      491: #       else
                    492:          GC_push_all_eager( cold_gc_frame, GC_approx_sp() );
                    493: #       endif
                    494: #   else
                    495: #      ifdef STACK_GROWS_DOWN
                    496:            GC_push_all_stack_partially_eager( GC_approx_sp(), GC_stackbottom,
                    497:                                               cold_gc_frame );
1.2       noro      498: #          ifdef IA64
                    499:              /* We also need to push the register stack backing store. */
                    500:              /* This should really be done in the same way as the      */
                    501:              /* regular stack.  For now we fudge it a bit.             */
                    502:              /* Note that the backing store grows up, so we can't use  */
                    503:              /* GC_push_all_stack_partially_eager.                     */
                    504:              {
                    505:                extern word GC_save_regs_ret_val;
                    506:                        /* Previously set to backing store pointer.     */
                    507:                ptr_t bsp = (ptr_t) GC_save_regs_ret_val;
                    508:                ptr_t cold_gc_bs_pointer;
1.4       noro      509:                if (GC_all_interior_pointers) {
1.2       noro      510:                  cold_gc_bs_pointer = bsp - 2048;
                    511:                  if (cold_gc_bs_pointer < BACKING_STORE_BASE) {
                    512:                    cold_gc_bs_pointer = BACKING_STORE_BASE;
1.6       noro      513:                  } else {
                    514:                    GC_push_all_stack(BACKING_STORE_BASE, cold_gc_bs_pointer);
1.2       noro      515:                  }
1.4       noro      516:                } else {
1.2       noro      517:                  cold_gc_bs_pointer = BACKING_STORE_BASE;
1.4       noro      518:                }
1.2       noro      519:                GC_push_all_eager(cold_gc_bs_pointer, bsp);
                    520:                /* All values should be sufficiently aligned that we    */
                    521:                /* dont have to worry about the boundary.               */
                    522:              }
                    523: #          endif
1.1       noro      524: #       else
                    525:            GC_push_all_stack_partially_eager( GC_stackbottom, GC_approx_sp(),
                    526:                                               cold_gc_frame );
                    527: #       endif
                    528: #   endif /* !THREADS */
                    529: }
                    530:
                    531: /*
1.4       noro      532:  * Push GC internal roots.  Only called if there is some reason to believe
                    533:  * these would not otherwise get registered.
                    534:  */
                    535: void GC_push_gc_structures GC_PROTO((void))
                    536: {
                    537:     GC_push_finalizer_structures();
                    538:     GC_push_stubborn_structures();
                    539: #   if defined(THREADS)
                    540:       GC_push_thread_structures();
                    541: #   endif
                    542: }
                    543:
1.6       noro      544: #ifdef THREAD_LOCAL_ALLOC
                    545:   void GC_mark_thread_local_free_lists();
                    546: #endif
                    547:
1.7     ! noro      548: void GC_cond_register_dynamic_libraries()
        !           549: {
        !           550: # if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE) \
        !           551:      || defined(PCR)) && !defined(SRC_M3)
        !           552:     GC_remove_tmp_roots();
        !           553:     if (!GC_no_dls) GC_register_dynamic_libraries();
        !           554: # else
        !           555:     GC_no_dls = TRUE;
        !           556: # endif
        !           557: }
        !           558:
1.4       noro      559: /*
1.1       noro      560:  * Call the mark routines (GC_tl_push for a single pointer, GC_push_conditional
                    561:  * on groups of pointers) on every top level accessible pointer.
                    562:  * If all is FALSE, arrange to push only possibly altered values.
                    563:  * Cold_gc_frame is an address inside a GC frame that
                    564:  * remains valid until all marking is complete.
                    565:  * A zero value indicates that it's OK to miss some
                    566:  * register values.
                    567:  */
                    568: void GC_push_roots(all, cold_gc_frame)
                    569: GC_bool all;
                    570: ptr_t cold_gc_frame;
                    571: {
1.7     ! noro      572:     int i;
        !           573:     int kind;
1.1       noro      574:
                    575:     /*
                    576:      * Next push static data.  This must happen early on, since it's
                    577:      * not robust against mark stack overflow.
                    578:      */
1.7     ! noro      579:      /* Reregister dynamic libraries, in case one got added.           */
        !           580:      /* There is some argument for doing this as late as possible,     */
        !           581:      /* especially on win32, where it can change asynchronously.       */
        !           582:      /* In those cases, we do it here.  But on other platforms, it's   */
        !           583:      /* not safe with the world stopped, so we do it earlier.          */
        !           584: #      if !defined(REGISTER_LIBRARIES_EARLY)
        !           585:          GC_cond_register_dynamic_libraries();
1.1       noro      586: #      endif
1.4       noro      587:
1.1       noro      588:      /* Mark everything in static data areas                             */
                    589:        for (i = 0; i < n_root_sets; i++) {
                    590:          GC_push_conditional_with_exclusions(
                    591:                             GC_static_roots[i].r_start,
                    592:                             GC_static_roots[i].r_end, all);
1.4       noro      593:        }
                    594:
1.7     ! noro      595:      /* Mark all free list header blocks, if those were allocated from */
        !           596:      /* the garbage collected heap.  This makes sure they don't        */
        !           597:      /* disappear if we are not marking from static data.  It also     */
        !           598:      /* saves us the trouble of scanning them, and possibly that of    */
        !           599:      /* marking the freelists.                                         */
        !           600:        for (kind = 0; kind < GC_n_kinds; kind++) {
        !           601:         GC_PTR base = GC_base(GC_obj_kinds[kind].ok_freelist);
        !           602:         if (0 != base) {
        !           603:           GC_set_mark_bit(base);
        !           604:         }
        !           605:        }
        !           606:
1.4       noro      607:      /* Mark from GC internal roots if those might otherwise have      */
                    608:      /* been excluded.                                                 */
                    609:        if (GC_no_dls || roots_were_cleared) {
                    610:           GC_push_gc_structures();
1.1       noro      611:        }
                    612:
1.6       noro      613:      /* Mark thread local free lists, even if their mark       */
                    614:      /* descriptor excludes the link field.                    */
1.7     ! noro      615:      /* If the world is not stopped, this is unsafe.  It is    */
        !           616:      /* also unnecessary, since we will do this again with the */
        !           617:      /* world stopped.                                         */
1.6       noro      618: #      ifdef THREAD_LOCAL_ALLOC
1.7     ! noro      619:          if (GC_world_stopped) GC_mark_thread_local_free_lists();
1.6       noro      620: #      endif
                    621:
1.1       noro      622:     /*
1.6       noro      623:      * Now traverse stacks, and mark from register contents.
                    624:      * These must be done last, since they can legitimately overflow
                    625:      * the mark stack.
1.1       noro      626:      */
1.6       noro      627: #   ifdef USE_GENERIC_PUSH_REGS
                    628:        GC_generic_push_regs(cold_gc_frame);
                    629:        /* Also pushes stack, so that we catch callee-save registers    */
                    630:        /* saved inside the GC_push_regs frame.                         */
                    631: #   else
                    632:        /*
                    633:         * push registers - i.e., call GC_push_one(r) for each
                    634:         * register contents r.
                    635:         */
                    636:         GC_push_regs(); /* usually defined in machine_dep.c */
1.1       noro      637:        GC_push_current_stack(cold_gc_frame);
1.6       noro      638:        /* In the threads case, this only pushes collector frames.      */
                    639:        /* In the case of linux threads on IA64, the hot section of     */
1.3       noro      640:        /* the main stack is marked here, but the register stack        */
                    641:        /* backing store is handled in the threads-specific code.       */
1.1       noro      642: #   endif
                    643:     if (GC_push_other_roots != 0) (*GC_push_other_roots)();
                    644:        /* In the threads case, this also pushes thread stacks. */
1.6       noro      645:         /* Note that without interior pointer recognition lots */
                    646:        /* of stuff may have been pushed already, and this      */
                    647:        /* should be careful about mark stack overflows.        */
1.1       noro      648: }
                    649:

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