00001
00002
00003
00004
00005 #include <sys/types.h>
00006 #include <sys/times.h>
00007 #include "eus.h"
00008
00009 #define myctx (euscontexts[thr_self()])
00010
00011
00012 extern long freeheap, totalheap, marked_words;
00013
00014
00015
00016 long alloccount[MAXBUDDY];
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 static int rgc_expand_heap_or_complete_gc(int req)
00027 {
00028 int idx = ERR;
00029
00030 #ifdef __HEAP_EXPANDABLE
00031
00032 mutex_unlock(&alloc_lock);
00033 lock_collector;
00034 mutex_lock(&alloc_lock);
00035
00036 idx = newchunk(req);
00037 unlock_collector;
00038 #else
00039
00040 mutex_unlock(&alloc_lock);
00041 if (gc_phase == PHASE_NOGC) {
00042 DPRINT1("\x1b[0;32mstart GC: free rate = %lf\x1b[0m", (double)freeheap / (double)totalheap);
00043 notify_gc();
00044 }
00045
00046 lock_collector;
00047 while (gc_phase != PHASE_NOGC) {
00048 do_a_little_gc_work(AM_UNIT, AS_UNIT);
00049 }
00050 unlock_collector;
00051 mutex_lock(&alloc_lock);
00052 #endif
00053
00054 return idx;
00055 }
00056
00057 static inline unsigned long net_free(int req) {
00058 unsigned long total = 0;
00059 register int idx;
00060
00061 for (idx = (req < REALTIME_ALLOC_LIMIT_IDX ? req : REALTIME_ALLOC_LIMIT_IDX);
00062 idx < MAXBUDDY; idx++)
00063 total += buddysize[idx] * buddy[idx].count;
00064
00065 return total;
00066 }
00067
00068 static int km[10] = {4096, 4800, 6000, 8192};
00069 static int ks[10] = {256, 256, 384, 512};
00070
00071 static int recalc_gc_priority(int req) {
00072
00073
00074
00075
00076
00077
00078 long estimation;
00079 int i;
00080
00081 #if 0
00082 for (i = 0; i < 4; i++) {
00083 if (gc_phase == PHASE_NOGC || gc_phase >= PHASE_MARK) {
00084 estimation = (totalheap - freeheap - marked_words) / km[i]
00085 + (totalheap >> 4) / ks[i];
00086 } else {
00087 estimation = (totalheap >> 4) / ks[i];
00088 }
00089 estimation *= 1024;
00090 if (net_free(req) > estimation)
00091 break;
00092 }
00093
00094 return i;
00095 #endif
00096
00097 {
00098 unsigned long nfree = net_free(req);
00099 for (i = 0; i < 4; i++) {
00100 if (nfree < totalheap * DEFAULT_GC_THRESHOLD)
00101 nfree *= 2;
00102 else
00103 break;
00104 }
00105 }
00106
00107 #if 0
00108 i = (net_free(req) < totalheap * DEFAULT_GC_THRESHOLD);
00109 #endif
00110
00111 return i;
00112 }
00113
00114
00115 volatile static int rem_cnt = 0;
00116 volatile static int gc_pri = 0;
00117 #define my_gc_pri ctx->my_gc_pri
00118
00119
00120 static int should_start_gc(int req) {
00121 static int gc_cushion = GC_ACTIVATE_CUSHION;
00122 register int idx;
00123
00124
00125 if (recalc_gc_priority(req) > 0)
00126 gc_cushion--;
00127
00128 return gc_cushion <= 0
00129 ? (gc_cushion = GC_ACTIVATE_CUSHION, 1) : 0;
00130 }
00131
00132
00133 bpointer rgc_root_alloc_big(register context *ctx, register int req)
00134 {
00135 register int i, k;
00136 register bpointer b, b2;
00137 numunion nu;
00138 pointer gcm;
00139
00140 mutex_lock(&alloc_lock);
00141 ctx->alloc_big_count++;
00142
00143 alloc_again:
00144
00145 for (k = req; buddy[k].bp == 0; )
00146 k++;
00147
00148 if (k >= MAXBUDDY) {
00149 if (buddysize[req] < totalheap / 8) {
00150 gcm = speval(GCMARGIN);
00151 DPRINT1("\x1b[1;31mstarved(alloc_big:1, free/total=%d/%d)\x1b[0m",
00152 freeheap, totalheap);
00153 rgc_expand_heap_or_complete_gc(req);
00154 for (k = req; buddy[k].bp == 0;) k++;
00155 }
00156 if (k >= MAXBUDDY) {
00157 DPRINT1("\x1b[1;31mstarved(alloc_big:1, free/total=%d/%d)\x1b[0m",
00158 freeheap, totalheap);
00159 rgc_expand_heap_or_complete_gc(req);
00160 for (k = req; buddy[k].bp == 0;) k++;
00161
00162 if (k == ERR) {
00163 mutex_unlock(&alloc_lock);
00164 error(E_ALLOCATION);
00165 }
00166 }
00167 }
00168 while (req < k) {
00169 splitheap(k--, buddy);
00170 if (k > req) k--;
00171 }
00172 k = buddysize[req] - 1;
00173 b = buddy[req].bp;
00174 b2 = b->b.nextbcell;
00175 for (i = 0; i < k; i++) b->b.c[i] = 0;
00176 #ifdef RGC
00177
00178 #endif
00179 ctx->lastalloc = makepointer(b);
00180 buddy[req].bp = b2;
00181 buddy[req].count--;
00182 #ifdef DEBUG
00183 printf( "root_alloc_big: alloc 1 block (%d), 0x%lx\n", req, b );
00184 #endif
00185 freeheap -= buddysize[req];
00186 alloccount[req]++;
00187
00188 #if THREADED
00189 mutex_unlock(&alloc_lock);
00190 #endif
00191
00192
00193 rem_cnt--;
00194 if (rem_cnt < 0) {
00195 lock_collector;
00196 switch(gc_phase) {
00197 case PHASE_NOGC:
00198
00199 if (should_start_gc(req)) {
00200 DPRINT2("\x1b[0;32mstart GC: free rate = %lf, frag rate[%d] = %lf\x1b[0m",
00201 (double)freeheap / (double)totalheap, req, (double)net_free(req) / (double)freeheap);
00202
00203 notify_gc();
00204 gc_pri = 1;
00205 }
00206 break;
00207 default:
00208 #ifdef __GC_ALLOC_DRIVEN
00209
00210 gc_pri = recalc_gc_priority(req);
00211 #endif
00212 }
00213
00214 rem_cnt = GC_GRANULARITY;
00215 unlock_collector;
00216 } else {
00217 #ifdef __GC_ALLOC_DRIVEN
00218
00219 if (gc_phase != PHASE_NOGC) {
00220 lock_collector;
00221 if (gc_phase != PHASE_NOGC) {
00222 if (my_gc_pri <= gc_pri) {
00223
00224 do_a_little_gc_work(AM_UNIT, AS_UNIT);
00225 }
00226 }
00227 unlock_collector;
00228 }
00229 #endif
00230 }
00231
00232 return b;
00233 }
00234
00235
00236 void rgc_root_alloc_small(register context *ctx, register int req)
00237 {
00238 register int i, j, k, kk;
00239 register bpointer b, b2;
00240 register struct buddyfree *tb = ctx->thr_buddy;
00241 static long buddyfill[MAXTHRBUDDY + 1] = {0, 500, 300, 20, 15, 10, 0};
00242 numunion nu;
00243
00244 mutex_lock(&alloc_lock);
00245 ctx->alloc_small_count++;
00246
00247 alloc_again:
00248 for (i = 1; i < MAXTHRBUDDY; i++) {
00249 k = kk = buddyfill[i] - tb[i].count;
00250 while (buddy[i].count < k) {
00251
00252 j = i + 1;
00253 while (buddy[j].bp == 0) j++;
00254
00255 if (j >= MAXBUDDY) {
00256 DPRINT1("\x1b[1;31mstarved(alloc_small:1, free/total=%d/%d)\x1b[0m",
00257 freeheap, totalheap);
00258 j = rgc_expand_heap_or_complete_gc(DEFAULT_EXPAND_SIZE_IDX);
00259
00260 if (j == ERR) {
00261 mutex_unlock(&alloc_lock);
00262 error(E_ALLOCATION);
00263 }
00264 }
00265 splitheap(j, buddy);
00266 }
00267
00268
00269 if (k > 0) {
00270 b = buddy[i].bp;
00271 while (k > 0) {
00272 b2 = b;
00273 b->h.cix = -1;
00274 b = b->b.nextbcell;
00275 k--;
00276 }
00277 b2->b.nextbcell = tb[i].bp;
00278 tb[i].bp = buddy[i].bp;
00279 buddy[i].bp = b;
00280 buddy[i].count -= kk;
00281 tb[i].count = buddyfill[i];
00282 freeheap -= buddysize[i] * kk;
00283 alloccount[i] += kk;
00284 #ifdef DEBUG
00285 printf("root_alloc_small: alloc %d block(s) (%d)\n", kk, i);
00286 #endif
00287 }
00288 }
00289
00290 #if THREADED
00291 mutex_unlock(&alloc_lock);
00292 #endif
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 rem_cnt--;
00308 if (rem_cnt < 0) {
00309 lock_collector;
00310 switch(gc_phase) {
00311 case PHASE_NOGC:
00312
00313 if (should_start_gc(req)) {
00314 DPRINT2("\x1b[0;32mstart GC: free rate = %lf, frag rate[%d] = %lf\x1b[0m",
00315 (double)freeheap / (double)totalheap, req, (double)net_free(req) / (double)freeheap);
00316 notify_gc();
00317 gc_pri = 1;
00318 }
00319 break;
00320 default:
00321 #ifdef __GC_ALLOC_DRIVEN
00322
00323 gc_pri = recalc_gc_priority(req);
00324 #endif
00325 }
00326
00327 rem_cnt = GC_GRANULARITY;
00328 unlock_collector;
00329 } else {
00330 #ifdef __GC_ALLOC_DRIVEN
00331
00332 if (gc_phase != PHASE_NOGC) {
00333 lock_collector;
00334 if (gc_phase != PHASE_NOGC) {
00335 if (my_gc_pri <= gc_pri) {
00336 do_a_little_gc_work(AM_UNIT, AS_UNIT);
00337 }
00338 }
00339 unlock_collector;
00340 }
00341 #endif
00342 }
00343
00344
00345 }
00346
00347 pointer rgc_alloc(register int s, int e, int cid, register int nils)
00348 {
00349 register int req = 1, i, ss;
00350 register pointer p;
00351 register pointer *v;
00352 register bpointer b, b2;
00353 register context *ctx = myctx;
00354 register struct buddyfree *tb = ctx->thr_buddy;
00355
00356 #if defined(DEBUG) || defined(DEBUG_COUNT)
00357 static int count = 0;
00358
00359 count++;
00360
00361 if (nils > s) {
00362 printf("alloc:%d:nils(=%d) > s(=%d)!!\n", count, nils, s);
00363 }
00364 #endif
00365 ss = max(3, s + 1);
00366 while (buddysize[req] < ss) req++;
00367 #ifdef DEBUG
00368 printf("alloc:%d:s=%d, e=%d, cid=%d, nils=%d\n",
00369 count, s, e, cid, nils);
00370 #endif
00371 if (req >= MAXTHRBUDDY)
00372 b = rgc_root_alloc_big(ctx, req);
00373 else {
00374 if (tb[req].count == 0) {
00375 rgc_root_alloc_small(ctx, req);
00376 #ifdef DEBUG
00377 printf("alloc:");
00378 dump_bcell(req,ctx->thr_buddy);
00379 #endif
00380 }
00381 ASSERT(tb[req].bp != 0);
00382 #if THREADED
00383 rw_rdlock(&gc_lock);
00384 #endif
00385 #ifdef DEBUG
00386 fflush( stdout );
00387 printf("alloc:%d:", count);
00388 dump_bcell( req, tb );
00389 #endif
00390 b = tb[req].bp;
00391 #ifdef RGC
00392
00393 #endif
00394 ctx->lastalloc=makepointer(b);
00395 ss = buddysize[req]-1;
00396 tb[req].bp = b->b.nextbcell;
00397 #if defined(DEBUG) || defined(UALLOC_DEBUG)
00398 printf("alloc:%d:allocate for user[%d(buddysize=%d)] = 0x%lx: new list top = 0x%lx\n",
00399 count, req, buddysize[req], b, tb[req].bp);
00400 #endif
00401 for (i = 0; i < ss; i++)
00402 b->b.c[i] = 0;
00403 tb[req].count--;
00404 #if THREADED
00405 rw_unlock(&gc_lock);
00406 #endif
00407 }
00408
00409 #ifdef __USE_MARK_BITMAP
00410
00411 if (gc_phase >= PHASE_SWEEP) {
00412 markon(b);
00413 } else {
00414 b->h.cix = cid;
00415 }
00416
00417 #else
00418
00419
00420 if (gc_phase >= PHASE_SWEEP) {
00421
00422 if (gc_phase >= PHASE_MARK) {
00423
00424 markon(b);
00425 b->h.cix = cid;
00426
00427 if (gc_phase < PHASE_MARK) {
00428
00429 lock_collector;
00430
00431 if (sweeping_state.p > b) {
00432 markoff(b);
00433 }
00434 unlock_collector;
00435 }
00436 } else if (gc_phase == PHASE_SWEEP) {
00437 if (b >= (bpointer)sweeping_state.chp) {
00438
00439 markon(b);
00440 b->h.cix = cid;
00441
00442 if (b <= (bpointer)sweeping_state.chp->nextchunk) {
00443 if (b < (bpointer)sweeping_state.chp)
00444 markoff(b);
00445 else {
00446 lock_collector;
00447 if (b < sweeping_state.p) {
00448 markoff(b);
00449 }
00450 unlock_collector;
00451 }
00452 }
00453 }
00454
00455 b->h.cix = cid;
00456 }
00457 } else {
00458 b->h.cix = cid;
00459 }
00460 #endif
00461
00462 b->h.elmtype = e;
00463 #ifndef RGC
00464 b->h.extra = 0;
00465 #endif
00466 b->h.nodispose = 0;
00467 p = makepointer(b);
00468 v = p->c.obj.iv;
00469 #ifdef DEBUG
00470 printf( "alloc:%d:fill NIL:nils = %d, s = %d\n",
00471 count, nils, s );
00472 #endif
00473 i = 0;
00474 while (i < nils) v[i++] = NIL;
00475
00476 i = buddysize[req] - 1;
00477 while (s < i) v[s++] = NULL;
00478 #ifdef DEBUG
00479 printf( "alloc:%d:after filling NIL:", count );
00480 dump_bcell( req, tb );
00481 #endif
00482 #ifdef RGC
00483
00484 #endif
00485 #ifdef __PROFILE_GC
00486 allocd_words += buddysize[req];
00487 #endif
00488 return(p);
00489 }
00490