00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <sys/times.h>
00028 #include "eus.h"
00029 #include <sys/param.h>
00030 #include "time.h"
00031 #include "rgc_utils.h"
00032 #include "xccmem.h"
00033
00034
00035 #ifdef __ART_LINUX
00036 #include <linux/art_task.h>
00037 #endif
00038
00039 #if Linux
00040 char *minmemory=(char *)1000000;
00041 #endif
00042 extern pointer K_DISPOSE;
00043 #define MAXDISPOSE 256
00044 static pointer dispose[MAXDISPOSE];
00045 static int gcmerge, dispose_count;
00046
00047 extern struct {
00048 char using;
00049 mutex_t *lock;
00050 thread_t tid;
00051 } thread_table[];
00052
00053 struct _gc_data gc_data;
00054 barrier_t startup_barrier;
00055
00056 #define GCDEBUG
00057
00058 #ifdef GCDEBUG
00059 static int white_cells, black_cells, free_cells;
00060 #endif
00061
00062 #ifdef __PROFILE_GC
00063 static int gctime = 0;
00064 int allocd_words = 0;
00065 #endif
00066
00067 static void do_scan_roots();
00068 static void init_sync_data();
00069
00070 #define gcpush(v, off) \
00071 { \
00072 lgcsp->addr = (pointer)v; \
00073 lgcsp->offset = off; \
00074 lgcsp++; \
00075 }
00076
00077 static pnewgcstack(oldsp)
00078 register ms_entry *oldsp;
00079 {
00080 register ms_entry *oldstack, *stk, *newstack, *newgcsp;
00081 long top, oldsize, newsize;
00082
00083 oldstack=stk=collector_stack;
00084 oldsize=collector_stacklimit-oldstack;
00085 newsize=oldsize*2;
00086 top=oldsp-collector_stack;
00087
00088 newgcsp=newstack=(ms_entry *)malloc(newsize * sizeof(ms_entry)+16);
00089 fprintf(stderr, "\n\x1b[1;31m;; extending pgcstack 0x%x[%d] --> 0x%x[%d] top=%x\x1b[0m\n",
00090 oldstack, oldsize, newstack, newsize, top);
00091 while (stk<oldsp) *newgcsp++= *stk++;
00092 collector_stack=newstack;
00093 collector_stacklimit= &(collector_stack[newsize-10]);
00094 collector_sp = &(collector_stack[top]);
00095 cfree(oldstack);
00096 }
00097
00098 static call_disposers()
00099 { int i;
00100 context *ctx=current_ctx;
00101 pointer p,a,curclass;
00102
00103 for (i=0; i<dispose_count; i++) {
00104 p=dispose[i];
00105 p->nodispose=0;
00106 a=(pointer)findmethod(ctx,K_DISPOSE,classof(p), &curclass);
00107 if (debug) fprintf(stderr, ";; (send %x :dispose)\n", p);
00108 if (a!=NIL) csend(ctx,p,K_DISPOSE,0);
00109 }}
00110
00111 static struct _marking_state {
00112 int is_checking_pstack;
00113 int cur_mut_num;
00114 } marking_state;
00115
00116 struct _sweeping_state sweeping_state;
00117
00118 static inline void go_on_to_sweep_phase()
00119 {
00120 numunion nu;
00121 DPRINT2("mark->sweep: free rate = %lf", (double)freeheap / totalheap);
00122 gcmerge = totalheap * min(1.0, fltval(speval(GCMARGIN)))
00123 * max(0.1, fltval(speval(GCMERGE)));
00124
00125
00126 dispose_count = 0;
00127
00128 sweeping_state.chp = chunklist;
00129 sweeping_state.p = &chunklist->rootcell;
00130 sweeping_state.tail =
00131 (bpointer)((int)sweeping_state.p + (buddysize[sweeping_state.chp->chunkbix] << 2));
00132 gc_phase = PHASE_SWEEP;
00133 }
00134
00135 long marked_words = 0;
00136
00137 static int mark_a_little(int m_unit)
00138 {
00139 extern _end();
00140 register ms_entry *lgcsp = collector_sp;
00141 register ms_entry *gcstack = collector_stack;
00142 register int credit = m_unit;
00143 unsigned int offset;
00144 register pointer p, p2;
00145 register bpointer bp;
00146 register int i, s;
00147 context *ctx;
00148
00149 markloop:
00150 if(credit <= 0){
00151
00152
00153 collector_sp = lgcsp;
00154 marked_words -= m_unit - credit;
00155 return 1;
00156 }
00157 if(lgcsp > gcstack){
00158
00159
00160 lgcsp--;
00161 p = lgcsp->addr;
00162 offset = lgcsp->offset;
00163
00164 start_mark:
00165 if(offset == 0){
00166
00167 if(!ispointer(p) || !p) goto markloop;
00168
00169 ASSERT((unsigned)p >= mingcheap);
00170 ASSERT((unsigned)p < maxgcheap);
00171
00172
00173
00174
00175
00176 if(maxmemory < (char *)p) goto markloop;
00177
00178 }
00179
00180
00181 bp = bpointerof(p);
00182
00183 if(marked(bp)) goto markloop;
00184
00185
00186 markon(bp);
00187
00188 if(pisclosure(p)){
00189
00190
00191
00192
00193
00194
00195
00196
00197 goto markloop;
00198 }
00199 if(bp->h.elmtype == ELM_FIXED){
00200 s = buddysize[bp->h.bix & TAGMASK] - 1;
00201
00202 if(s > 300){
00203 fprintf (stderr, "do_mark: too big object s=%d, header=%x at %x\n",
00204 s, bp->h, bp);
00205
00206 }
00207 while(lgcsp + s > collector_stacklimit){
00208 pnewgcstack(lgcsp);
00209 gcstack = collector_stack;
00210 lgcsp = collector_sp;
00211 }
00212 credit -= (s + 1);
00213 for(i = 0; i < s; i++){
00214 p2 = p->c.obj.iv[i];
00215 if(ispointer(p2))
00216 gcpush(p2, 0);
00217 }
00218 goto markloop;
00219 } else if (bp->h.elmtype == ELM_POINTER) {
00220 s = buddysize[bp->h.bix & TAGMASK] - 2;
00221 while (lgcsp + s > collector_stacklimit) {
00222 pnewgcstack(lgcsp);
00223 gcstack = collector_stack;
00224 lgcsp = collector_sp;
00225 }
00226 credit -= (s + 2);
00227 for (i = 0; i < s; i++) {
00228 p2 = p->c.vec.v[i];
00229 if (ispointer(p2))
00230 gcpush(p2, 0);
00231 }
00232 goto markloop;
00233 }
00234
00235 credit -= buddysize[bp->h.bix & TAGMASK];
00236 goto markloop;
00237
00238 } else {
00239
00240
00241 next_root:
00242 credit--;
00243 if (!marking_state.is_checking_pstack) {
00244 for (i = marking_state.cur_mut_num; i < MAXTHREAD; i++) {
00245 ctx = euscontexts[i];
00246 if (ctx) {
00247 if (ctx->gsp > ctx->gcstack) {
00248 p = *--(ctx->gsp);
00249
00250 ASSERT((unsigned)p >= mingcheap);
00251 ASSERT((unsigned)p < maxgcheap);
00252
00253 offset = 0;
00254 marking_state.cur_mut_num = i;
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 goto start_mark;
00265 }
00266 }
00267 }
00268 marking_state.is_checking_pstack = 1;
00269 goto next_root;
00270 } else {
00271 mutex_lock(&pstack_lock);
00272 if(psp > pstack) {
00273 #ifdef COLLECTCACHE
00274 #define COLCACHE 10
00275 int i, ii;
00276 pointer array[COLCACHE];
00277 for (i = 0; i < COLCACHE; i++) {
00278 pointerpop(array[i]);
00279 if(psp > pstack)
00280 continue;
00281 break;
00282 }
00283 pcount = pcount + COLCACHE;
00284 mutex_unlock(&pstack_lock);
00285 for(ii = 0; ii < i; ii++){
00286
00287 }
00288 mutex_lock(&pstack_lock);
00289 #else
00290 pointerpop(p);
00291 offset = 0;
00292 mutex_unlock(&pstack_lock);
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 goto start_mark;
00303 #endif
00304 }
00305 mutex_unlock(&pstack_lock);
00306 }
00307 }
00308
00309
00310 go_on_to_sweep_phase();
00311 return 0;
00312 }
00313
00314
00315 int reclaim(bpointer p)
00316 {
00317 register int rbix, stat;
00318 register pointer s;
00319
00320 s = makepointer(p);
00321 if(pisfilestream(s)){
00322 if(!isint (s->c.fstream.fname) && s->c.fstream.direction != NIL){
00323 if(s->c.fstream.fd == makeint (0)
00324 || s->c.fstream.fd == makeint (1)){
00325 fprintf(stderr, ";; gc! bogus stream at %x fd=%d\n",
00326 (int) s, intval (s->c.fstream.fd));
00327 }else if((closestream (s) == 0) && debug)
00328 fprintf (stderr,
00329 ";; gc: dangling stream(address=%x fd=%d) is closed\n",
00330 (int) s, intval (s->c.fstream.fd));
00331 }
00332 }
00333 p->h.cix = -1;
00334 rbix = p->h.bix & TAGMASK;
00335
00336 mutex_lock(&alloc_lock);
00337 rw_rdlock(&gc_lock);
00338
00339 p->b.nextbcell = buddy[rbix].bp;
00340 buddy[rbix].bp = p;
00341 buddy[rbix].count++;
00342
00343 freeheap += buddysize[rbix];
00344
00345
00346 rw_unlock(&gc_lock);
00347 mutex_unlock(&alloc_lock);
00348 return 0;
00349 }
00350
00351 static int rgc_credit = 0;
00352
00353
00354
00355 static bpointer mergecell(register bpointer p, int cbix)
00356 {
00357 register bpointer np, p2;
00358
00359 np = nextbuddy(p);
00360 while (p->h.b == 0 && ((int) (p->h.bix & TAGMASK)) < cbix) {
00361
00362
00363 rgc_credit--;
00364 if (marked(np) || np->h.cix == -1) return np;
00365 if (np->h.nodispose == 1) return np;
00366
00367 p2 = mergecell(np, cbix);
00368 if (np->h.b == 1 && rgc_credit >= 0) {
00369 p->h.b = p->h.m;
00370 p->h.m = np->h.m;
00371 p->h.bix++;
00372 np = p2;
00373 #ifdef GCDEBUG
00374 white_cells++;
00375 #endif
00376 } else {
00377 reclaim(np);
00378 return p2;
00379 }
00380 }
00381 return np;
00382 }
00383
00384
00385
00386
00387
00388
00389 static int sweep_a_little(int gcmerge, int s_unit)
00390 {
00391 register struct chunk *chp;
00392 register bpointer p, np, tail;
00393
00394 rgc_credit = s_unit;
00395
00396 chp = sweeping_state.chp;
00397 p = sweeping_state.p;
00398 tail = sweeping_state.tail;
00399
00400 if (p == NULL) {
00401 goto next_chunk;
00402 }
00403
00404
00405 cont_sweep:
00406
00407 while (p < tail) {
00408 if (rgc_credit <= 0) {
00409 sweeping_state.p = p;
00410 sweeping_state.tail = tail;
00411 return 1;
00412 }
00413
00414
00415
00416 rgc_credit--;
00417 if (p->h.cix == -1) {
00418 #ifdef GCDEBUG
00419 free_cells++;
00420 #endif
00421 p = nextbuddy(p);
00422 continue;
00423 }
00424 if (marked(p)) {
00425
00426 #ifdef GCDEBUG
00427 black_cells++;
00428 #endif
00429 markoff(p);
00430 p = nextbuddy(p);
00431 continue;
00432 }
00433 if (p->h.nodispose == 1) {
00434 if(dispose_count >= MAXDISPOSE)
00435 fprintf(stderr, "no more space for disposal processing\n");
00436 else
00437 dispose[dispose_count++] = makepointer(p);
00438 p = nextbuddy(p);
00439 }
00440 if (gcmerge > freeheap) {
00441 #ifdef GCDEBUG
00442 white_cells++;
00443 #endif
00444 np = nextbuddy(p);
00445 reclaim(p);
00446 p = np;
00447 } else {
00448 np = mergecell(p, chp->chunkbix);
00449 reclaim(p);
00450 p = np;
00451 }
00452 }
00453
00454 next_chunk:
00455 chp = sweeping_state.chp->nextchunk;
00456 if (chp == NULL) {
00457 DPRINT2("sweeping finished: free rate = %lf", (double)freeheap / totalheap);
00458 DPRINT2("white: %d black: %d free: %d", white_cells, black_cells, free_cells);
00459 gc_phase = PHASE_EPILOGUE;
00460 return 0;
00461 }
00462 sweeping_state.chp = chp;
00463 p = &chp->rootcell;
00464 tail = (bpointer)((int)p + (buddysize[chp->chunkbix] << 2));
00465 goto cont_sweep;
00466
00467 }
00468
00469 #ifdef __USE_SIGNAL
00470 static void send_root_insertion_signals()
00471 {
00472 int i;
00473 thread_t self = pthread_self();
00474
00475 for (i = 0; i < MAXTHREAD; i++)
00476 if (!pthread_equal(thread_table[i].tid, self) && euscontexts[i]) {
00477 if (pthread_kill(thread_table[i].tid, SIGUSR1) != 0) {
00478 perror("pthread_kill");
00479 }
00480 }
00481 }
00482 #endif
00483
00484 void init_rgc(){
00485 void collect();
00486 unsigned int gc_thread;
00487
00488 active_mutator_num = 1;
00489 gc_region_sync = 0;
00490 startup_barrier = barrier_init(2);
00491 gc_phase = PHASE_NOGC;
00492 ri_core_phase = 0;
00493 mut_stat_phase = 0x2;
00494 gc_wakeup_cnt = gc_cmp_cnt = 0;
00495 #ifdef __USE_POLLING
00496 gc_request_flag = 0;
00497 #endif
00498 init_sync_data();
00499 initmemory_rgc();
00500 init_utils();
00501 #ifdef __USE_MARK_BITMAP
00502 allocate_bit_table();
00503 clear_bit_table();
00504 #endif
00505
00506 collector_stack = collector_sp =
00507 (ms_entry *)malloc(sizeof(ms_entry) * DEFAULT_MAX_RGCSTACK);
00508 collector_stacklimit = collector_stack + DEFAULT_MAX_RGCSTACK - 10;
00509
00510 #ifdef __GC_SEPARATE_THREAD
00511 thr_create(0, 0, collect, 0, 0, &gc_thread);
00512 barrier_wait(startup_barrier);
00513 #endif
00514 }
00515
00516 static pointer rgc_classtable = NULL;
00517
00518 void rgc_add_to_classtable(pointer newclass) {
00519 static int clsidx = 0;
00520 int i;
00521
00522 if (rgc_classtable == NULL) {
00523 rgc_classtable =
00524 rgc_alloc((MAXCLASS + 1), ELM_POINTER, vectorcp.cix, MAXCLASS + 1);
00525 rgc_classtable->c.vec.size = makeint(MAXCLASS);
00526 for (i = 0; i < MAXCLASS; i++)
00527 rgc_classtable->c.vec.v[i] = NIL;
00528 }
00529 rgc_classtable->c.vec.v[clsidx++] = newclass;
00530 }
00531
00532 static void scan_global_roots()
00533 {
00534 int i;
00535 pointerpush(sysobj);
00536 pointerpush(pkglist);
00537
00538 pointerpush(rgc_classtable);
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549 }
00550
00551 static void scan_local_roots(int i)
00552 {
00553 register pointer *p;
00554 register bpointer q;
00555 register context *ctx = euscontexts[i];
00556
00557 pgcpush(ctx->threadobj);
00558 pgcpush(ctx->specials);
00559
00560 q = bpointerof(ctx->lastalloc);
00561 if (q && ispointer(q)) {
00562 pgcpush(ctx->lastalloc);
00563 ASSERT((unsigned)q >= mingcheap);
00564 ASSERT((unsigned)q < maxgcheap);
00565 }
00566
00567 #ifdef __RETURN_BARRIER
00568 {
00569 pointer *frame_base, *p;
00570
00571
00572 mutex_lock(&ctx->rbar.lock);
00573
00574 if (ctx->callfp != NULL)
00575 frame_base = (pointer *)ctx->callfp;
00576 else
00577 frame_base = ctx->stack;
00578
00579 for (p = ctx->vsp - 1; p >= frame_base; p--) {
00580
00581
00582
00583
00584
00585
00586
00587
00588 if (*p == NULL) continue;
00589 if (((int)(*p) & 3)) continue;
00590 if ((ctx->stack <= (pointer *)*p) && ((pointer *)*p <= ctx->stacklimit))
00591 continue;
00592 if ((pointer *)*p >= (pointer *)maxgcheap) continue;
00593 if ((pointer *)*p < (pointer *)mingcheap) continue;
00594
00595 pgcpush(*p);
00596 ASSERT((unsigned)(*p) >= mingcheap);
00597 ASSERT((unsigned)(*p) < maxgcheap);
00598 }
00599
00600 if (frame_base == ctx->stack) {
00601 ctx->rbar.pointer = NULL;
00602 } else {
00603 ctx->rbar.pointer = frame_base;
00604 }
00605 mutex_unlock(&ctx->rbar.lock);
00606
00607 }
00608
00609 #else
00610
00611
00612 for (p = ctx->vsp - 1; p >= ctx->stack; p--) {
00613
00614 if (*p == NULL) continue;
00615 if (((int)(*p) & 3)) continue;
00616 if ((ctx->stack <= (pointer *)*p) && ((pointer *)*p <= ctx->stacklimit))
00617 continue;
00618 if ((pointer *)*p >= (pointer *)maxgcheap) continue;
00619 if ((pointer *)*p < (pointer *)mingcheap) continue;
00620
00621 pgcpush(*p);
00622 ASSERT((unsigned)(*p) >= mingcheap);
00623 ASSERT((unsigned)(*p) < maxgcheap);
00624 }
00625 #endif
00626 }
00627
00628 #if 0
00629 static void scan_suspending_thread_roots()
00630 {
00631 int id, c;
00632 for(id = 0; id < MAXTHREAD; id++){
00633 if(thread_table[id].using){
00634 mutex_lock(&mut_stat_table[id].lock);
00635 if(mut_stat_table[id].stat == 0x3){
00636 mut_stat_table[id].stat = 0x5;
00637 mutex_unlock(&mut_stat_table[id].lock);
00638 scan_local_roots(id);
00639 finish_access_before_read();
00640 do{
00641 c = read_volatile_int(frame_scan_sync);
00642 }while(cas_int(frame_scan_sync, c, c + 1));
00643 mutex_lock(&mut_stat_table[id].lock);
00644 mut_stat_table[id].stat = 0x1;
00645 }
00646 mutex_unlock(&mut_stat_table[id].lock);
00647 }
00648 }
00649 }
00650 #endif
00651
00652 #ifdef __RETURN_BARRIER
00653 #define INSERT_UNIT 4
00654
00655 static void scan_remaining_roots()
00656 {
00657 int i, local_root_count, inserted_root_count;
00658 static char idx[MAXTHREAD];
00659
00660 local_root_count = 0;
00661
00662 for (i = 0; i < MAXTHREAD; i++) {
00663 if (euscontexts[i] && euscontexts[i]->rbar.pointer) {
00664 idx[local_root_count] = i;
00665 local_root_count++;
00666 }
00667 }
00668
00669 inserted_root_count = local_root_count;
00670
00671 do {
00672 for (i = 0; i < local_root_count; i++) {
00673 context *ctx;
00674 register pointer *p;
00675 int counter, tid;
00676
00677 tid = idx[i];
00678 ctx = euscontexts[tid];
00679 if ((ctx)->rbar.pointer == NULL) continue;
00680
00681 mutex_lock(&((ctx)->rbar.lock));
00682
00683 p = (ctx)->rbar.pointer - 1;
00684 counter = INSERT_UNIT;
00685
00686 while (1) {
00687 if (p < ctx->stack) break;
00688 if ((((int)(*p) & 3) == 0)
00689 && ((ctx->stack > (pointer *)*p) || ((pointer *)*p > ctx->stacklimit))
00690 && (((pointer *)*p >= (pointer *)mingcheap && (pointer *)*p < (pointer *)maxgcheap))) {
00691 pgcpush(*p);
00692 ASSERT((unsigned)(*p) >= mingcheap);
00693 ASSERT((unsigned)(*p) < maxgcheap);
00694 }
00695 p--;
00696 counter--;
00697 if(counter == 0) break;
00698 }
00699 (ctx)->rbar.pointer = p + 1;
00700
00701 if (p < ctx->stack) {
00702 (ctx)->rbar.pointer = NULL;
00703 inserted_root_count--;
00704 }
00705 mutex_unlock(&(ctx)->rbar.lock);
00706 }
00707 }
00708 while (inserted_root_count != 0);
00709 }
00710 #endif
00711
00712 unsigned int gs[MAXTHREAD];
00713
00714
00715
00716 void notify_gc()
00717 {
00718 int id, phase, c;
00719 unsigned int s, e;
00720
00721
00722
00723
00724
00725
00726
00727
00728 id = thr_self();
00729
00730
00731 gc_phase = PHASE_PROLOGUE;
00732 gc_point_sync = 0;
00733 phase = ri_core_phase;
00734 mut_stat_phase = mut_stat_phase ^ 0x2;
00735 #ifdef __USE_POLLING
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748 #endif
00749 #ifdef __USE_SIGNAL
00750 send_root_insertion_signals();
00751 #else
00752 gc_request_flag = 1;
00753 #endif
00754 marking_state.is_checking_pstack = 0;
00755 marking_state.cur_mut_num = 0;
00756 marked_words = 0;
00757 unlock_collector;
00758
00759 do {
00760 c = gc_point_sync;
00761 } while(cas_int(gc_point_sync, c, c + 1));
00762
00763 if (gc_point_sync + gc_region_sync < active_mutator_num) {
00764 sched_yield();
00765 } else {
00766 lock_collector;
00767 if (phase == ri_core_phase) {
00768 do_scan_roots();
00769 }
00770 unlock_collector;
00771 }
00772
00773
00774 lock_collector;
00775 while (phase == ri_core_phase)
00776 cond_wait(&ri_end_cv, &collector_lock);
00777
00778
00779
00780 }
00781
00782
00783
00784 static void do_scan_roots()
00785 {
00786 int tid;
00787 unsigned int s, e;
00788
00789
00790 scan_global_roots();
00791
00792
00793
00794 gc_phase = PHASE_ROOT_CORE;
00795 for (tid = 0; tid < MAXTHREAD; tid++) {
00796 if (euscontexts[tid]) {
00797 mutex_lock(&mut_stat_table[tid].lock);
00798 scan_local_roots(tid);
00799
00800 mut_stat_table[tid].stat =
00801 (mut_stat_table[tid].stat ^ 0x2) & 0xfffffffd;
00802 mutex_unlock(&mut_stat_table[tid].lock);
00803 }
00804 }
00805
00806
00807
00808 gc_request_flag = 0;
00809 ri_core_phase = 1 - ri_core_phase;
00810 gc_phase = PHASE_ROOT_REM;
00811 cond_broadcast(&ri_end_cv);
00812 gc_wakeup_cnt++;
00813 cond_broadcast(&gc_wakeup_cv);
00814 DPRINT2("root scan finished: free rate = %lf", (double)freeheap / totalheap);
00815 }
00816
00817
00818 static void wait_until_next_gc_cycle()
00819 {
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845 }
00846
00847
00848
00849
00850 static int do_gc_epilogue()
00851 {
00852
00853
00854
00855
00856
00857
00858
00859
00860 #ifdef __USE_MARK_BITMAP
00861 clear_bit_table();
00862 #endif
00863 if (gc_cmp_cnt < gc_wakeup_cnt)
00864 gc_cmp_cnt++;
00865 gc_phase = PHASE_NOGC;
00866
00867 if (debug) {
00868 fprintf(stderr, " free/total=%d/%d\n",
00869 freeheap, totalheap);
00870
00871 }
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882 DPRINT2("GC cycle finished: free rate = %lf", (double)freeheap / totalheap);
00883 return 0;
00884 }
00885
00886 void do_a_little_gc_work(int m_unit, int s_unit)
00887 {
00888 unsigned int s, e;
00889
00890 switch (gc_phase) {
00891 case PHASE_ROOT_REM:
00892 #ifdef __RETURN_BARRIER
00893 scan_remaining_roots();
00894 #endif
00895 gc_phase = PHASE_MARK;
00896 break;
00897 case PHASE_MARK:
00898 mark_a_little(m_unit);
00899 break;
00900 case PHASE_SWEEP:
00901 sweep_a_little(gcmerge, s_unit);
00902 break;
00903 case PHASE_EPILOGUE:
00904 do_gc_epilogue();
00905 default:
00906 ;
00907 }
00908
00909
00910
00911 }
00912
00913 void collect()
00914 {
00915 int i;
00916 unsigned s, e;
00917
00918 #ifdef __PROFILE_GC
00919 int tmp_free;
00920 reset_utime();
00921 #endif
00922
00923
00924 barrier_wait(startup_barrier);
00925
00926 #ifdef __PROFILE_GC
00927
00928 #endif
00929
00930
00931 for (;;) {
00932
00933
00934 lock_collector;
00935 while (gc_cmp_cnt == gc_wakeup_cnt) {
00936 cond_wait(&gc_wakeup_cv, &collector_lock);
00937 }
00938
00939 while (gc_phase != PHASE_NOGC) {
00940
00941 do_a_little_gc_work(M_UNIT, S_UNIT);
00942 unlock_collector;
00943
00944 lock_collector;
00945 };
00946 unlock_collector;
00947
00948 #ifdef __PROFILE_GC
00949
00950
00951
00952
00953
00954 #endif
00955
00956
00957
00958 }
00959
00960
00961 }
00962
00963
00964 #ifdef __EAGER_GC_CONTROL
00965 static int change_collector_thread_sched_policy(int t_sect_length)
00966 {
00967 #ifdef __ART_LINUX
00968 if(art_enter(ART_PRIO_MAX, ART_TASK_PERIODIC, t_sect_length) == -1){
00969 DPRINT2("collector error: art_enter");
00970 return -1;
00971 }
00972 #else
00973 #endif
00974 return 0;
00975 }
00976 static int restore_collector_thread_sched_policy()
00977 {
00978 #ifdef __ART_LINUX
00979 if(art_exit() == -1){
00980 DPRINT2("collector error: art_exit");
00981 return -1;
00982 }
00983 #else
00984 #endif
00985 return 0;
00986 }
00987 #endif
00988
00989 #ifdef __USE_POLLING
00990 void enter_gc_region(int id)
00991 {
00992 int c, phase;
00993 mutex_lock(&mut_stat_table[id].lock);
00994
00995
00996 do {
00997 c = gc_region_sync;
00998 } while (cas_int(gc_region_sync, c, c + 1));
00999 mutex_unlock(&mut_stat_table[id].lock);
01000
01001 if (gc_request_flag) {
01002 phase = ri_core_phase;
01003 if (gc_point_sync + gc_region_sync == active_mutator_num) {
01004 lock_collector;
01005 if (phase == ri_core_phase)
01006 do_scan_roots();
01007 unlock_collector;
01008 }
01009 }
01010
01011 }
01012
01013 void exit_gc_region(int id)
01014 {
01015 int c;
01016 try_exit:
01017 mutex_lock(&mut_stat_table[id].lock);
01018 if (mut_stat_table[id].stat & 0x2 == mut_stat_phase) {
01019
01020
01021
01022 mutex_unlock(&mut_stat_table[id].lock);
01023 sched_yield();
01024 goto try_exit;
01025 } else {
01026
01027 do {
01028 c = gc_region_sync;
01029 } while (cas_int(gc_region_sync, c, c - 1));
01030 mutex_unlock(&mut_stat_table[id].lock);
01031 }
01032 }
01033
01034 #endif
01035
01036 int ps_sem = 1;
01037
01038 static void init_sync_data()
01039 {
01040 int i;
01041 mutex_init(&pstack_lock, NULL);
01042 mutex_init(&collector_lock, NULL);
01043 cond_init(&gc_wakeup_cv, NULL);
01044 cond_init(&ri_end_cv, NULL);
01045 mutex_init(&gc_state_lock, NULL);
01046 for (i = 0; i < MAXTHREAD; i++) {
01047 mutex_init(&mut_stat_table[i].lock, NULL);
01048 }
01049 }
01050
01051
01052
01053
01054
01055 #ifdef __USE_POLLING
01056 void scan_roots()
01057 {
01058 int c;
01059 unsigned int e;
01060 int myid = thr_self();
01061 int phase = ri_core_phase;
01062
01063 myid = thr_self();
01064
01065
01066 do {
01067 c = gc_point_sync;
01068 } while (cas_int(gc_point_sync, c, c + 1));
01069
01070 if (gc_point_sync + gc_region_sync < active_mutator_num) {
01071 sched_yield();
01072 } else {
01073 lock_collector;
01074 if (phase == ri_core_phase)
01075 do_scan_roots();
01076 unlock_collector;
01077 }
01078
01079
01080 lock_collector;
01081 while (phase == ri_core_phase)
01082 cond_wait(&ri_end_cv, &collector_lock);
01083 unlock_collector;
01084
01085
01086
01087 return;
01088 }
01089
01090
01091 int check_gc_request()
01092 {
01093 if (!gc_request_flag)
01094 return 0;
01095 scan_roots();
01096 return 1;
01097 }
01098 #endif
01099
01100 #ifdef __USE_SIGNAL
01101
01102
01103
01104
01105 void sighandler(int x)
01106 {
01107 int idx;
01108 DPRINT2("start root scanning");
01109 notify_ri_start();
01110 idx = thr_self();
01111 scan_local_roots(thr_self());
01112 barrier_wait(end_ri_barrier);
01113 DPRINT2("mutators restart");
01114 }
01115 #endif
01116
01117
01118 #define PMAXSTACK (MAXSTACK * 110)
01119 pointer pstack[PMAXSTACK];
01120 volatile pointer *psp = pstack;
01121 pointer *pstacklimit = pstack + PMAXSTACK;
01122 mutex_t pstack_lock;
01123
01124
01125
01126
01127
01128 barrier_t barrier_init(int n_clients)
01129 {
01130 barrier_t barrier = (barrier_t)malloc(sizeof(struct barrier_struct));
01131 if (barrier != NULL) {
01132 barrier->n_clients = n_clients;
01133 barrier->n_waiting = 0;
01134 barrier->phase = 0;
01135 mutex_init(&barrier->lock, NULL);
01136 cond_init(&barrier->wait_cv, NULL);
01137 }
01138 return barrier;
01139 }
01140
01141 void barrier_reset(barrier_t barrier, int n_clients)
01142 {
01143
01144
01145 barrier->n_clients = n_clients;
01146 }
01147
01148 void barrier_destroy(barrier_t barrier)
01149 {
01150 mutex_destroy(&barrier->lock);
01151 cond_destroy(&barrier->wait_cv);
01152 free(barrier);
01153 }
01154
01155 void barrier_wait(barrier_t barrier)
01156 {
01157 int my_phase;
01158 mutex_lock(&barrier->lock);
01159 my_phase = barrier->phase;
01160 barrier->n_waiting++;
01161 if (barrier->n_waiting == barrier->n_clients) {
01162 barrier->n_waiting = 0;
01163 barrier->phase = 1 - my_phase;
01164 cond_broadcast(&barrier->wait_cv);
01165 }
01166 while (barrier->phase == my_phase) {
01167 cond_wait(&barrier->wait_cv, &barrier->lock);
01168 }
01169 mutex_unlock(&barrier->lock);
01170 }
01171
01172
01173
01174
01175
01176
01177 unsigned int do_allocate_heap(unsigned int req_words)
01178 {
01179 int i, k;
01180 unsigned int rem_words = req_words;
01181
01182 while (buddysize[MAXBUDDY-1] <= rem_words) {
01183 k = newchunk(MAXBUDDY-1);
01184 rem_words -= buddysize[k];
01185 }
01186 for (i = MAXBUDDY - 2; i >= 20; i--) {
01187 if (buddysize[i] < rem_words){
01188 k = newchunk(i);
01189 rem_words -= buddysize[k];
01190 }
01191 }
01192 return req_words - rem_words;
01193 }
01194
01195 unsigned int allocate_heap()
01196 {
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208 return do_allocate_heap(INITIAL_HEAP_SIZE * 1000);
01209 }
01210
01211 extern long long values[];
01212
01213 pointer RGCCOUNT(register context *ctx, int n, pointer argv[])
01214 {
01215 ckarg(0);
01216 return makeint(gc_cmp_cnt);
01217 }
01218
01219 pointer RGC_GCTIME(register context *ctx, int n, pointer argv[])
01220 {
01221 struct tms buf;
01222 ckarg(0);
01223 times(&buf);
01224 return makeint((buf.tms_utime + buf.tms_stime) * 1000/HZ );
01225 }
01226
01227 #ifdef __PROFILE_GC
01228 pointer RGCALLOCATED(register context *ctx, int n, pointer argv[])
01229 {
01230 ckarg(0);
01231 return makeint(allocd_words);
01232 }
01233 #endif
01234
01235 void rgcfunc(register context *ctx, pointer mod)
01236 {
01237 pointer p = Spevalof(PACKAGE);
01238 pointer_update(Spevalof(PACKAGE), syspkg);
01239 defun(ctx, "RGCCOUNT", mod, RGCCOUNT);
01240 defun(ctx, "RGCTIME", mod, RGC_GCTIME);
01241 #ifdef __PROFILE_GC
01242 defun(ctx, "RGCALLOCATED", mod, RGCALLOCATED);
01243 #endif
01244 pointer_update(Spevalof(PACKAGE), p);
01245 }