[BACK]Return to allchblk.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gc

Annotation of OpenXM_contrib/gc/allchblk.c, Revision 1.1.1.1

1.1       maekawa     1: /*
                      2:  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
                      3:  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
                      4:  * Copyright (c) 1998 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, August 9, 1995 5:08 pm PDT */
                     16:
                     17: #define DEBUG
                     18: #undef DEBUG
                     19: #include <stdio.h>
                     20: #include "gc_priv.h"
                     21:
                     22:
                     23: /*
                     24:  * allocate/free routines for heap blocks
                     25:  * Note that everything called from outside the garbage collector
                     26:  * should be prepared to abort at any point as the result of a signal.
                     27:  */
                     28:
                     29: /*
                     30:  * Free heap blocks are kept on a list sorted by address.
                     31:  * The hb_hdr.hbh_sz field of a free heap block contains the length
                     32:  * (in bytes) of the entire block.
                     33:  * Neighbors are coalesced.
                     34:  */
                     35:
                     36: # define MAX_BLACK_LIST_ALLOC (2*HBLKSIZE)
                     37:                /* largest block we will allocate starting on a black   */
                     38:                /* listed block.  Must be >= HBLKSIZE.                  */
                     39:
                     40: struct hblk * GC_hblkfreelist = 0;
                     41:
                     42: struct hblk *GC_savhbp = (struct hblk *)0;  /* heap block preceding next */
                     43:                                         /* block to be examined by   */
                     44:                                         /* GC_allochblk.                */
                     45:
                     46: # if !defined(NO_DEBUGGING)
                     47: void GC_print_hblkfreelist()
                     48: {
                     49:     struct hblk * h = GC_hblkfreelist;
                     50:     word total_free = 0;
                     51:     hdr * hhdr = HDR(h);
                     52:     word sz;
                     53:
                     54:     while (h != 0) {
                     55:         sz = hhdr -> hb_sz;
                     56:        GC_printf2("0x%lx size %lu ", (unsigned long)h, (unsigned long)sz);
                     57:        total_free += sz;
                     58:         if (GC_is_black_listed(h, HBLKSIZE) != 0) {
                     59:              GC_printf0("start black listed\n");
                     60:         } else if (GC_is_black_listed(h, hhdr -> hb_sz) != 0) {
                     61:              GC_printf0("partially black listed\n");
                     62:         } else {
                     63:              GC_printf0("not black listed\n");
                     64:         }
                     65:         h = hhdr -> hb_next;
                     66:         hhdr = HDR(h);
                     67:     }
                     68:     GC_printf1("Total of %lu bytes on free list\n", (unsigned long)total_free);
                     69: }
                     70:
                     71: # endif /* NO_DEBUGGING */
                     72:
                     73: /* Initialize hdr for a block containing the indicated size and        */
                     74: /* kind of objects.                                                    */
                     75: /* Return FALSE on failure.                                            */
                     76: static GC_bool setup_header(hhdr, sz, kind, flags)
                     77: register hdr * hhdr;
                     78: word sz;       /* object size in words */
                     79: int kind;
                     80: unsigned char flags;
                     81: {
                     82:     register word descr;
                     83:
                     84:     /* Add description of valid object pointers */
                     85:       if (!GC_add_map_entry(sz)) return(FALSE);
                     86:       hhdr -> hb_map = GC_obj_map[sz > MAXOBJSZ? 0 : sz];
                     87:
                     88:     /* Set size, kind and mark proc fields */
                     89:       hhdr -> hb_sz = sz;
                     90:       hhdr -> hb_obj_kind = kind;
                     91:       hhdr -> hb_flags = flags;
                     92:       descr = GC_obj_kinds[kind].ok_descriptor;
                     93:       if (GC_obj_kinds[kind].ok_relocate_descr) descr += WORDS_TO_BYTES(sz);
                     94:       hhdr -> hb_descr = descr;
                     95:
                     96:     /* Clear mark bits */
                     97:       GC_clear_hdr_marks(hhdr);
                     98:
                     99:     hhdr -> hb_last_reclaimed = (unsigned short)GC_gc_no;
                    100:     return(TRUE);
                    101: }
                    102:
                    103: #ifdef EXACT_FIRST
                    104: #   define LAST_TRIP 2
                    105: #else
                    106: #   define LAST_TRIP 1
                    107: #endif
                    108:
                    109: word GC_max_hblk_size = HBLKSIZE;
                    110:
                    111: /*
                    112:  * Allocate (and return pointer to) a heap block
                    113:  *   for objects of size sz words.
                    114:  *
                    115:  * NOTE: We set obj_map field in header correctly.
                    116:  *       Caller is resposnsible for building an object freelist in block.
                    117:  *
                    118:  * We clear the block if it is destined for large objects, and if
                    119:  * kind requires that newly allocated objects be cleared.
                    120:  */
                    121: struct hblk *
                    122: GC_allochblk(sz, kind, flags)
                    123: word sz;
                    124: int kind;
                    125: unsigned char flags;  /* IGNORE_OFF_PAGE or 0 */
                    126: {
                    127:     register struct hblk *thishbp;
                    128:     register hdr * thishdr;            /* Header corr. to thishbp */
                    129:     register struct hblk *hbp;
                    130:     register hdr * hhdr;               /* Header corr. to hbp */
                    131:     struct hblk *prevhbp;
                    132:     register hdr * phdr;               /* Header corr. to prevhbp */
                    133:     signed_word size_needed;    /* number of bytes in requested objects */
                    134:     signed_word size_avail;    /* bytes available in this block        */
                    135:     int trip_count = 0;
                    136:
                    137:     size_needed = HBLKSIZE * OBJ_SZ_TO_BLOCKS(sz);
                    138:     if ((word)size_needed >  GC_max_hblk_size)
                    139:        GC_max_hblk_size = size_needed;
                    140:
                    141:     /* search for a big enough block in free list */
                    142:        hbp = GC_savhbp;
                    143:        hhdr = HDR(hbp);
                    144:        for(;;) {
                    145:
                    146:            prevhbp = hbp;
                    147:            phdr = hhdr;
                    148:            hbp = (prevhbp == 0? GC_hblkfreelist : phdr->hb_next);
                    149:            hhdr = HDR(hbp);
                    150:
                    151:            if( prevhbp == GC_savhbp) {
                    152:                if (trip_count == LAST_TRIP) return(0);
                    153:                ++trip_count;
                    154:            }
                    155:
                    156:            if( hbp == 0 ) continue;
                    157:
                    158:            size_avail = hhdr->hb_sz;
                    159: #          ifdef EXACT_FIRST
                    160:                if (trip_count <= 1 && size_avail != size_needed) continue;
                    161: #          endif
                    162:            if (size_avail < size_needed) continue;
                    163: #          ifdef PRESERVE_LAST
                    164:                if (size_avail != size_needed
                    165:                    && !GC_incremental
                    166:                    && (word)size_needed <= GC_max_hblk_size/2
                    167:                    && GC_in_last_heap_sect((ptr_t)hbp)
                    168:                    && GC_should_collect()) {
                    169:                    continue;
                    170:                }
                    171: #          endif
                    172:            /* If the next heap block is obviously better, go on.       */
                    173:            /* This prevents us from disassembling a single large block */
                    174:            /* to get tiny blocks.                                      */
                    175:            {
                    176:              signed_word next_size;
                    177:
                    178:              thishbp = hhdr -> hb_next;
                    179:              if (thishbp == 0) thishbp = GC_hblkfreelist;
                    180:              thishdr = HDR(thishbp);
                    181:              next_size = (signed_word)(thishdr -> hb_sz);
                    182:              if (next_size < size_avail
                    183:                  && next_size >= size_needed
                    184:                  && !GC_is_black_listed(thishbp, (word)size_needed)) {
                    185:                  continue;
                    186:              }
                    187:            }
                    188:            if ( !IS_UNCOLLECTABLE(kind) &&
                    189:                 (kind != PTRFREE || size_needed > MAX_BLACK_LIST_ALLOC)) {
                    190:              struct hblk * lasthbp = hbp;
                    191:              ptr_t search_end = (ptr_t)hbp + size_avail - size_needed;
                    192:              signed_word orig_avail = size_avail;
                    193:              signed_word eff_size_needed = ((flags & IGNORE_OFF_PAGE)?
                    194:                                                HBLKSIZE
                    195:                                                : size_needed);
                    196:
                    197:
                    198:              while ((ptr_t)lasthbp <= search_end
                    199:                     && (thishbp = GC_is_black_listed(lasthbp,
                    200:                                                      (word)eff_size_needed))) {
                    201:                lasthbp = thishbp;
                    202:              }
                    203:              size_avail -= (ptr_t)lasthbp - (ptr_t)hbp;
                    204:              thishbp = lasthbp;
                    205:              if (size_avail >= size_needed) {
                    206:                if (thishbp != hbp && GC_install_header(thishbp)) {
                    207:                  /* Split the block at thishbp */
                    208:                      thishdr = HDR(thishbp);
                    209:                      /* GC_invalidate_map not needed, since we will    */
                    210:                      /* allocate this block.                           */
                    211:                      thishdr -> hb_next = hhdr -> hb_next;
                    212:                      thishdr -> hb_sz = size_avail;
                    213:                      hhdr -> hb_sz = (ptr_t)thishbp - (ptr_t)hbp;
                    214:                      hhdr -> hb_next = thishbp;
                    215:                  /* Advance to thishbp */
                    216:                      prevhbp = hbp;
                    217:                      phdr = hhdr;
                    218:                      hbp = thishbp;
                    219:                      hhdr = thishdr;
                    220:                }
                    221:              } else if (size_needed > (signed_word)BL_LIMIT
                    222:                         && orig_avail - size_needed
                    223:                            > (signed_word)BL_LIMIT) {
                    224:                /* Punt, since anything else risks unreasonable heap growth. */
                    225:                WARN("Needed to allocate blacklisted block at 0x%lx\n",
                    226:                     (word)hbp);
                    227:                thishbp = hbp;
                    228:                size_avail = orig_avail;
                    229:              } else if (size_avail == 0
                    230:                         && size_needed == HBLKSIZE
                    231:                         && prevhbp != 0) {
                    232: #              ifndef FIND_LEAK
                    233:                  static unsigned count = 0;
                    234:
                    235:                  /* The block is completely blacklisted.  We need      */
                    236:                  /* to drop some such blocks, since otherwise we spend */
                    237:                  /* all our time traversing them if pointerfree        */
                    238:                  /* blocks are unpopular.                              */
                    239:                  /* A dropped block will be reconsidered at next GC.   */
                    240:                  if ((++count & 3) == 0) {
                    241:                    /* Allocate and drop the block in small chunks, to  */
                    242:                    /* maximize the chance that we will recover some    */
                    243:                    /* later.                                           */
                    244:                      struct hblk * limit = hbp + (hhdr->hb_sz/HBLKSIZE);
                    245:                      struct hblk * h;
                    246:
                    247:                      GC_words_wasted += hhdr->hb_sz;
                    248:                      phdr -> hb_next = hhdr -> hb_next;
                    249:                      for (h = hbp; h < limit; h++) {
                    250:                        if (h == hbp || GC_install_header(h)) {
                    251:                          hhdr = HDR(h);
                    252:                          (void) setup_header(
                    253:                                  hhdr,
                    254:                                  BYTES_TO_WORDS(HBLKSIZE - HDR_BYTES),
                    255:                                  PTRFREE, 0); /* Cant fail */
                    256:                          if (GC_debugging_started) {
                    257:                            BZERO(hbp + HDR_BYTES, HBLKSIZE - HDR_BYTES);
                    258:                          }
                    259:                        }
                    260:                      }
                    261:                    /* Restore hbp to point at free block */
                    262:                      if (GC_savhbp == hbp) GC_savhbp = prevhbp;
                    263:                      hbp = prevhbp;
                    264:                      hhdr = phdr;
                    265:                      if (hbp == GC_savhbp) --trip_count;
                    266:                  }
                    267: #              endif
                    268:              }
                    269:            }
                    270:            if( size_avail >= size_needed ) {
                    271:                /* found a big enough block       */
                    272:                /* let thishbp --> the block      */
                    273:                /* set prevhbp, hbp to bracket it */
                    274:                    thishbp = hbp;
                    275:                    thishdr = hhdr;
                    276:                    if( size_avail == size_needed ) {
                    277:                        hbp = hhdr->hb_next;
                    278:                        hhdr = HDR(hbp);
                    279:                    } else {
                    280:                        hbp = (struct hblk *)
                    281:                            (((word)thishbp) + size_needed);
                    282:                        if (!GC_install_header(hbp)) {
                    283:                            hbp = thishbp;
                    284:                            continue;
                    285:                        }
                    286:                        hhdr = HDR(hbp);
                    287:                        GC_invalidate_map(hhdr);
                    288:                        hhdr->hb_next = thishdr->hb_next;
                    289:                        hhdr->hb_sz = size_avail - size_needed;
                    290:                    }
                    291:                /* remove *thishbp from hblk freelist */
                    292:                    if( prevhbp == 0 ) {
                    293:                        GC_hblkfreelist = hbp;
                    294:                    } else {
                    295:                        phdr->hb_next = hbp;
                    296:                    }
                    297:                /* save current list search position */
                    298:                    GC_savhbp = hbp;
                    299:                break;
                    300:            }
                    301:        }
                    302:
                    303:     /* Notify virtual dirty bit implementation that we are about to write. */
                    304:        GC_write_hint(thishbp);
                    305:        /* This should deal better with large blocks.   */
                    306:
                    307:     /* Add it to map of valid blocks */
                    308:        if (!GC_install_counts(thishbp, (word)size_needed)) return(0);
                    309:        /* This leaks memory under very rare conditions. */
                    310:
                    311:     /* Set up header */
                    312:         if (!setup_header(thishdr, sz, kind, flags)) {
                    313:             GC_remove_counts(thishbp, (word)size_needed);
                    314:             return(0); /* ditto */
                    315:         }
                    316:
                    317:     /* Clear block if necessary */
                    318:        if (GC_debugging_started
                    319:            || sz > MAXOBJSZ && GC_obj_kinds[kind].ok_init) {
                    320:            BZERO(thishbp + HDR_BYTES,  size_needed - HDR_BYTES);
                    321:        }
                    322:
                    323:     /* We just successfully allocated a block.  Restart count of       */
                    324:     /* consecutive failures.                                           */
                    325:     {
                    326:        extern unsigned GC_fail_count;
                    327:
                    328:        GC_fail_count = 0;
                    329:     }
                    330:
                    331:     return( thishbp );
                    332: }
                    333:
                    334: struct hblk * GC_freehblk_ptr = 0;  /* Search position hint for GC_freehblk */
                    335:
                    336: /*
                    337:  * Free a heap block.
                    338:  *
                    339:  * Coalesce the block with its neighbors if possible.
                    340:  *
                    341:  * All mark words are assumed to be cleared.
                    342:  */
                    343: void
                    344: GC_freehblk(p)
                    345: register struct hblk *p;
                    346: {
                    347: register hdr *phdr;    /* Header corresponding to p */
                    348: register struct hblk *hbp, *prevhbp;
                    349: register hdr *hhdr, *prevhdr;
                    350: register signed_word size;
                    351:
                    352:     /* GC_savhbp may become invalid due to coalescing.  Clear it. */
                    353:        GC_savhbp = (struct hblk *)0;
                    354:
                    355:     phdr = HDR(p);
                    356:     size = phdr->hb_sz;
                    357:     size = HBLKSIZE * OBJ_SZ_TO_BLOCKS(size);
                    358:     GC_remove_counts(p, (word)size);
                    359:     phdr->hb_sz = size;
                    360:     GC_invalidate_map(phdr);
                    361:     prevhbp = 0;
                    362:
                    363:     /* The following optimization was suggested by David Detlefs.      */
                    364:     /* Note that the header cannot be NIL, since there cannot be an    */
                    365:     /* intervening  call to GC_freehblk without resetting              */
                    366:     /* GC_freehblk_ptr.                                                        */
                    367:     if (GC_freehblk_ptr != 0 &&
                    368:        HDR(GC_freehblk_ptr)->hb_map == GC_invalid_map &&
                    369:        (ptr_t)GC_freehblk_ptr < (ptr_t)p) {
                    370:       hbp = GC_freehblk_ptr;
                    371:     } else {
                    372:       hbp = GC_hblkfreelist;
                    373:     };
                    374:     hhdr = HDR(hbp);
                    375:
                    376:     while( (hbp != 0) && (hbp < p) ) {
                    377:        prevhbp = hbp;
                    378:        prevhdr = hhdr;
                    379:        hbp = hhdr->hb_next;
                    380:        hhdr = HDR(hbp);
                    381:     }
                    382:     GC_freehblk_ptr = prevhbp;
                    383:
                    384:     /* Check for duplicate deallocation in the easy case */
                    385:       if (hbp != 0 && (ptr_t)p + size > (ptr_t)hbp
                    386:         || prevhbp != 0 && (ptr_t)prevhbp + prevhdr->hb_sz > (ptr_t)p) {
                    387:         GC_printf1("Duplicate large block deallocation of 0x%lx\n",
                    388:                   (unsigned long) p);
                    389:         GC_printf2("Surrounding free blocks are 0x%lx and 0x%lx\n",
                    390:                   (unsigned long) prevhbp, (unsigned long) hbp);
                    391:       }
                    392:
                    393:     /* Coalesce with successor, if possible */
                    394:       if( (((word)p)+size) == ((word)hbp) ) {
                    395:        phdr->hb_next = hhdr->hb_next;
                    396:        phdr->hb_sz += hhdr->hb_sz;
                    397:        GC_remove_header(hbp);
                    398:       } else {
                    399:        phdr->hb_next = hbp;
                    400:       }
                    401:
                    402:
                    403:     if( prevhbp == 0 ) {
                    404:        GC_hblkfreelist = p;
                    405:     } else if( (((word)prevhbp) + prevhdr->hb_sz)
                    406:               == ((word)p) ) {
                    407:       /* Coalesce with predecessor */
                    408:        prevhdr->hb_next = phdr->hb_next;
                    409:        prevhdr->hb_sz += phdr->hb_sz;
                    410:        GC_remove_header(p);
                    411:     } else {
                    412:        prevhdr->hb_next = p;
                    413:     }
                    414: }
                    415:

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