C:/Users/Dennis/src/lang/russell.orig/src/gc/allochblk.c

Go to the documentation of this file.
00001 /* 
00002  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
00003  * Copyright (c) 1991 by Xerox Corporation.  All rights reserved.
00004  *
00005  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
00006  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
00007  *
00008  * Permission is hereby granted to copy this garbage collector for any purpose,
00009  * provided the above notices are retained on all copies.
00010  */
00011 
00012 #define DEBUG
00013 #undef DEBUG
00014 #include <stdio.h>
00015 #include "gc_private.h"
00016 
00017 
00018 
00019 /* allocate/free routines for heap blocks
00020 /* Note that everything called from outside the garbage collector
00021 /* should be prepared to abort at any point as the result of a signal.
00022 /**/
00023 
00024 /*
00025  * Free heap blocks are kept on a list sorted by address.
00026  * The hb_hdr.hbh_sz field of a free heap block contains the length
00027  * (in bytes) of the entire block.
00028  * Neighbors are coalesced.
00029  */
00030  
00031 # define MAX_BLACK_LIST_ALLOC (2*HBLKSIZE)
00032                 /* largest block we will allocate starting on a black   */
00033                 /* listed block.  Must be >= HBLKSIZE.                  */
00034 
00035 struct hblk * GC_hblkfreelist = 0;
00036 
00037 struct hblk *GC_savhbp = (struct hblk *)0;  /* heap block preceding next */
00038                                          /* block to be examined by   */
00039                                          /* GC_allochblk.                */
00040 
00041 /* Initialize hdr for a block containing the indicated size and         */
00042 /* kind of objects.                                                     */
00043 static setup_header(hhdr, sz, kind)
00044 register hdr * hhdr;
00045 word sz;        /* object size in words */
00046 int kind;
00047 {
00048     /* Set size, kind and mark proc fields */
00049       hhdr -> hb_sz = sz;
00050       hhdr -> hb_obj_kind = kind;
00051       hhdr -> hb_mark_proc = GC_obj_kinds[kind].ok_mark_proc;
00052       
00053     /* Add description of valid object pointers */
00054       GC_add_map_entry(sz);
00055       hhdr -> hb_map = GC_obj_map[sz > MAXOBJSZ? 0 : sz];
00056       
00057     /* Clear mark bits */
00058       GC_clear_hdr_marks(hhdr);
00059 }
00060 
00061 /*
00062  * Allocate (and return pointer to) a heap block
00063  *   for objects of size |sz| words.
00064  *
00065  * NOTE: We set obj_map field in header correctly.
00066  *       Caller is resposnsible for building an object freelist in block.
00067  *
00068  * We clear the block if it is destined for large objects, and if
00069  * kind requires that newly allocated objects be cleared.
00070  */
00071 struct hblk *
00072 GC_allochblk(sz, kind)
00073 word sz;
00074 int kind;
00075 {
00076     register struct hblk *thishbp;
00077     register hdr * thishdr;             /* Header corr. to thishbp */
00078     register struct hblk *hbp;
00079     register hdr * hhdr;                /* Header corr. to hbp */
00080     struct hblk *prevhbp;
00081     register hdr * phdr;                /* Header corr. to prevhbp */
00082     signed_word size_needed;    /* number of bytes in requested objects */
00083     signed_word size_avail;     /* bytes available in this block        */
00084     bool first_time = TRUE;
00085 
00086     size_needed = WORDS_TO_BYTES(sz);
00087     size_needed = (size_needed+HDR_BYTES+HBLKSIZE-1) & ~HBLKMASK;
00088 
00089     /* search for a big enough block in free list */
00090         hbp = GC_savhbp;
00091         hhdr = HDR(hbp);
00092         for(;;) {
00093 
00094             prevhbp = hbp;
00095             phdr = hhdr;
00096             hbp = (prevhbp == 0? GC_hblkfreelist : phdr->hb_next);
00097             hhdr = HDR(hbp);
00098 
00099             if( prevhbp == GC_savhbp && !first_time) {
00100                 return(0);
00101             }
00102 
00103             first_time = FALSE;
00104 
00105             if( hbp == 0 ) continue;
00106 
00107             size_avail = hhdr->hb_sz;
00108             if (size_avail < size_needed) continue;
00109             /* If the next heap block is obviously better, go on.       */
00110             /* This prevents us from disassembling a single large block */
00111             /* to get tiny blocks.                                      */
00112             {
00113               word next_size;
00114               
00115               thishbp = hhdr -> hb_next;
00116               if (thishbp == 0) thishbp = GC_hblkfreelist; 
00117               thishdr = HDR(thishbp);
00118               next_size = thishdr -> hb_sz;
00119               if (next_size < size_avail
00120                   && next_size >= size_needed
00121                   && !GC_is_black_listed(thishbp, (word)size_needed)) {
00122                   continue;
00123               }
00124             }
00125             if ( kind != PTRFREE || size_needed > MAX_BLACK_LIST_ALLOC) {
00126               struct hblk * lasthbp = hbp;
00127               
00128               while (size_avail >= size_needed
00129                      && (thishbp = GC_is_black_listed(lasthbp,
00130                                                       (word)size_needed))) {
00131                 lasthbp = thishbp;
00132               }
00133               size_avail -= (ptr_t)lasthbp - (ptr_t)hbp;
00134               thishbp = lasthbp;
00135               if (size_avail >= size_needed && thishbp != hbp) {
00136                   /* Split the block at thishbp */
00137                       GC_install_header(thishbp);
00138                       thishdr = HDR(thishbp);
00139                       /* GC_invalidate_map not needed, since we will    */
00140                       /* allocate this block.                           */
00141                       thishdr -> hb_next = hhdr -> hb_next;
00142                       thishdr -> hb_sz = size_avail;
00143                       hhdr -> hb_sz = (ptr_t)thishbp - (ptr_t)hbp;
00144                       hhdr -> hb_next = thishbp;
00145                   /* Advance to thishbp */
00146                       prevhbp = hbp;
00147                       phdr = hhdr;
00148                       hbp = thishbp;
00149                       hhdr = thishdr;
00150               } else if (size_avail == 0
00151                          && size_needed == HBLKSIZE
00152                          && prevhbp != 0) {
00153                   static unsigned count = 0;
00154                   
00155                   /* The block is completely blacklisted.  We need      */
00156                   /* to drop some such blocks, since otherwise we spend */
00157                   /* all our time traversing them if pointerfree        */
00158                   /* blocks are unpopular.                              */
00159                   /* A dropped block will be reconsidered at next GC.   */
00160                   if ((++count & 3) == 0) {
00161                     /* Allocate and drop the block */
00162                       phdr -> hb_next = hhdr -> hb_next;
00163                       GC_install_counts(hbp, hhdr->hb_sz);
00164                       setup_header(hhdr,
00165                                    BYTES_TO_WORDS(hhdr->hb_sz - HDR_BYTES),
00166                                    PTRFREE);
00167                       if (GC_savhbp == hbp) GC_savhbp = prevhbp;
00168                     /* Restore hbp to point at free block */
00169                       hbp = prevhbp;
00170                       hhdr = phdr;
00171                       if (hbp == GC_savhbp) first_time = TRUE;
00172                   }
00173               }
00174             }
00175             if( size_avail >= size_needed ) {
00176                 /* found a big enough block       */
00177                 /* let thishbp --> the block      */
00178                 /* set prevhbp, hbp to bracket it */
00179                     thishbp = hbp;
00180                     thishdr = hhdr;
00181                     if( size_avail == size_needed ) {
00182                         hbp = hhdr->hb_next;
00183                         hhdr = HDR(hbp);
00184                     } else {
00185                         hbp = (struct hblk *)
00186                             (((unsigned)thishbp) + size_needed);
00187                         GC_install_header(hbp);
00188                         hhdr = HDR(hbp);
00189                         GC_invalidate_map(hhdr);
00190                         hhdr->hb_next = thishdr->hb_next;
00191                         hhdr->hb_sz = size_avail - size_needed;
00192                     }
00193                 /* remove *thishbp from hblk freelist */
00194                     if( prevhbp == 0 ) {
00195                         GC_hblkfreelist = hbp;
00196                     } else {
00197                         phdr->hb_next = hbp;
00198                     }
00199                 /* save current list search position */
00200                     GC_savhbp = hbp;
00201                 break;
00202             }
00203         }
00204 
00205     /* Clear block if necessary */
00206         if (sz > MAXOBJSZ && GC_obj_kinds[kind].ok_init) {
00207             bzero((char *)thishbp + HDR_BYTES,  (int)(size_needed - HDR_BYTES));
00208         }
00209 
00210     /* Set up header */
00211         setup_header(thishdr, sz, kind);
00212         
00213     /* Add it to map of valid blocks */
00214         GC_install_counts(thishbp, (word)size_needed);
00215 
00216     return( thishbp );
00217 }
00218  
00219 /*
00220  * Free a heap block.
00221  *
00222  * Coalesce the block with its neighbors if possible.
00223  *
00224  * All mark words are assumed to be cleared.
00225  */
00226 void
00227 GC_freehblk(p)
00228 register struct hblk *p;
00229 {
00230 register hdr *phdr;     /* Header corresponding to p */
00231 register struct hblk *hbp, *prevhbp;
00232 register hdr *hhdr, *prevhdr;
00233 register signed_word size;
00234 
00235     /* GC_savhbp may become invalid due to coalescing.  Clear it. */
00236         GC_savhbp = (struct hblk *)0;
00237 
00238     phdr = HDR(p);
00239     size = phdr->hb_sz;
00240     size = 
00241         ((WORDS_TO_BYTES(size)+HDR_BYTES+HBLKSIZE-1)
00242                  & (~HBLKMASK));
00243     GC_remove_counts(p, (word)size);
00244     phdr->hb_sz = size;
00245     GC_invalidate_map(phdr);
00246 
00247     prevhbp = 0;
00248     hbp = GC_hblkfreelist;
00249     hhdr = HDR(hbp);
00250 
00251     while( (hbp != 0) && (hbp < p) ) {
00252         prevhbp = hbp;
00253         prevhdr = hhdr;
00254         hbp = hhdr->hb_next;
00255         hhdr = HDR(hbp);
00256     }
00257     
00258     /* Check for duplicate deallocation in the easy case */
00259       if (hbp != 0 && (ptr_t)p + size > (ptr_t)hbp
00260         || prevhbp != 0 && (ptr_t)prevhbp + prevhdr->hb_sz > (ptr_t)p) {
00261         GC_printf1("Duplicate large block deallocation of 0x%lx\n",
00262                    (unsigned long) p);
00263         GC_printf2("Surrounding free blocks are 0x%lx and 0x%lx\n",
00264                    (unsigned long) prevhbp, (unsigned long) hbp);
00265       }
00266 
00267     /* Coalesce with successor, if possible */
00268       if( (((word)p)+size) == ((word)hbp) ) {
00269         phdr->hb_next = hhdr->hb_next;
00270         phdr->hb_sz += hhdr->hb_sz;
00271         GC_remove_header(hbp);
00272       } else {
00273         phdr->hb_next = hbp;
00274       }
00275 
00276     
00277     if( prevhbp == 0 ) {
00278         GC_hblkfreelist = p;
00279     } else if( (((word)prevhbp) + prevhdr->hb_sz)
00280                == ((word)p) ) {
00281       /* Coalesce with predecessor */
00282         prevhdr->hb_next = phdr->hb_next;
00283         prevhdr->hb_sz += phdr->hb_sz;
00284         GC_remove_header(p);
00285     } else {
00286         prevhdr->hb_next = p;
00287     }
00288 }
00289 

Generated on Fri Jan 25 10:39:45 2008 for russell by  doxygen 1.5.4