00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #define DEBUG
00013 #undef DEBUG
00014 #include <stdio.h>
00015 #include "gc_private.h"
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 # define MAX_BLACK_LIST_ALLOC (2*HBLKSIZE)
00032
00033
00034
00035 struct hblk * GC_hblkfreelist = 0;
00036
00037 struct hblk *GC_savhbp = (struct hblk *)0;
00038
00039
00040
00041
00042
00043 static setup_header(hhdr, sz, kind)
00044 register hdr * hhdr;
00045 word sz;
00046 int kind;
00047 {
00048
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
00054 GC_add_map_entry(sz);
00055 hhdr -> hb_map = GC_obj_map[sz > MAXOBJSZ? 0 : sz];
00056
00057
00058 GC_clear_hdr_marks(hhdr);
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
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;
00078 register struct hblk *hbp;
00079 register hdr * hhdr;
00080 struct hblk *prevhbp;
00081 register hdr * phdr;
00082 signed_word size_needed;
00083 signed_word size_avail;
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
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
00110
00111
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
00137 GC_install_header(thishbp);
00138 thishdr = HDR(thishbp);
00139
00140
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
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
00156
00157
00158
00159
00160 if ((++count & 3) == 0) {
00161
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
00169 hbp = prevhbp;
00170 hhdr = phdr;
00171 if (hbp == GC_savhbp) first_time = TRUE;
00172 }
00173 }
00174 }
00175 if( size_avail >= size_needed ) {
00176
00177
00178
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
00194 if( prevhbp == 0 ) {
00195 GC_hblkfreelist = hbp;
00196 } else {
00197 phdr->hb_next = hbp;
00198 }
00199
00200 GC_savhbp = hbp;
00201 break;
00202 }
00203 }
00204
00205
00206 if (sz > MAXOBJSZ && GC_obj_kinds[kind].ok_init) {
00207 bzero((char *)thishbp + HDR_BYTES, (int)(size_needed - HDR_BYTES));
00208 }
00209
00210
00211 setup_header(thishdr, sz, kind);
00212
00213
00214 GC_install_counts(thishbp, (word)size_needed);
00215
00216 return( thishbp );
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226 void
00227 GC_freehblk(p)
00228 register struct hblk *p;
00229 {
00230 register hdr *phdr;
00231 register struct hblk *hbp, *prevhbp;
00232 register hdr *hhdr, *prevhdr;
00233 register signed_word size;
00234
00235
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
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
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
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