27 #include <sys/times.h> 29 #include <sys/param.h> 36 #include <linux/art_task.h> 43 #define MAXDISPOSE 256 63 static int gctime = 0;
70 #define gcpush(v, off) \ 72 lgcsp->addr = (pointer)v; \ 73 lgcsp->offset = off; \ 80 register ms_entry *oldstack, *stk, *newstack, *newgcsp;
81 long top, oldsize, newsize;
89 fprintf(stderr,
"\n\x1b[1;31m;; extending pgcstack 0x%x[%d] --> 0x%x[%d] top=%x\x1b[0m\n",
90 oldstack, oldsize, newstack, newsize, top);
91 while (stk<oldsp) *newgcsp++= *stk++;
92 collector_stack=newstack;
107 if (debug) fprintf(stderr,
";; (send %x :dispose)\n", p);
108 if (a!=
NIL)
csend(ctx,p,K_DISPOSE,0);
142 register int credit = m_unit;
167 if(!ispointer(p) || !p)
goto markloop;
183 if(marked(bp))
goto markloop;
203 fprintf (stderr,
"do_mark: too big object s=%d, header=%x at %x\n",
213 for(i = 0; i <
s; i++){
219 }
else if (bp->
h.
elmtype == ELM_POINTER) {
227 for (i = 0; i <
s; i++) {
277 for (i = 0; i < COLCACHE; i++) {
283 pcount = pcount + COLCACHE;
285 for(ii = 0; ii < i; ii++){
317 register int rbix, stat;
321 if(pisfilestream(s)){
325 fprintf(stderr,
";; gc! bogus stream at %x fd=%d\n",
326 (
int) s,
intval (s->c.fstream.fd));
329 ";; gc: dangling stream(address=%x fd=%d) is closed\n",
330 (
int) s,
intval (s->c.fstream.fd));
364 if (marked(np) || np->
h.
cix == -1)
return np;
391 register struct chunk *chp;
417 if (p->
h.
cix == -1) {
435 fprintf(stderr,
"no more space for disposal processing\n");
470 static void send_root_insertion_signals()
473 thread_t
self = pthread_self();
475 for (i = 0; i < MAXTHREAD; i++)
478 perror(
"pthread_kill");
486 unsigned int gc_thread;
501 #ifdef __USE_MARK_BITMAP 510 #ifdef __GC_SEPARATE_THREAD 519 static int clsidx = 0;
522 if (rgc_classtable ==
NULL) {
526 for (i = 0; i < MAXCLASS; i++)
529 rgc_classtable->
c.
vec.
v[clsidx++] = newclass;
561 if (q && ispointer(q)) {
567 #ifdef __RETURN_BARRIER 572 mutex_lock(&ctx->
rbar.lock);
577 frame_base = ctx->
stack;
579 for (p = ctx->
vsp - 1; p >= frame_base; p--) {
588 if (*p ==
NULL)
continue;
589 if (((
int)(*p) & 3))
continue;
596 ASSERT((
unsigned)(*p) >= mingcheap);
600 if (frame_base == ctx->
stack) {
603 ctx->
rbar.pointer = frame_base;
605 mutex_unlock(&ctx->
rbar.lock);
612 for (p = ctx->
vsp - 1; p >= ctx->
stack; p--) {
614 if (*p ==
NULL)
continue;
615 if (((
int)(*p) & 3))
continue;
622 ASSERT((
unsigned)(*p) >= mingcheap);
623 ASSERT((
unsigned)(*p) < maxgcheap);
629 static void scan_suspending_thread_roots()
632 for(
id = 0;
id < MAXTHREAD;
id++){
634 mutex_lock(&mut_stat_table[
id].
lock);
635 if(mut_stat_table[
id].stat == 0x3){
636 mut_stat_table[id].stat = 0x5;
637 mutex_unlock(&mut_stat_table[
id].lock);
642 }
while(
cas_int(frame_scan_sync, c, c + 1));
643 mutex_lock(&mut_stat_table[
id].lock);
644 mut_stat_table[id].stat = 0x1;
646 mutex_unlock(&mut_stat_table[
id].lock);
652 #ifdef __RETURN_BARRIER 653 #define INSERT_UNIT 4 655 static void scan_remaining_roots()
657 int i, local_root_count, inserted_root_count;
658 static char idx[MAXTHREAD];
660 local_root_count = 0;
662 for (i = 0; i < MAXTHREAD; i++) {
664 idx[local_root_count] = i;
669 inserted_root_count = local_root_count;
672 for (i = 0; i < local_root_count; i++) {
679 if ((ctx)->rbar.pointer ==
NULL)
continue;
681 mutex_lock(&((ctx)->rbar.lock));
683 p = (ctx)->rbar.pointer - 1;
684 counter = INSERT_UNIT;
687 if (p < ctx->stack)
break;
688 if ((((
int)(*p) & 3) == 0)
693 ASSERT((
unsigned)(*p) < maxgcheap);
697 if(counter == 0)
break;
699 (ctx)->rbar.pointer = p + 1;
701 if (p < ctx->stack) {
702 (ctx)->rbar.pointer =
NULL;
703 inserted_root_count--;
705 mutex_unlock(&(ctx)->rbar.lock);
708 while (inserted_root_count != 0);
712 unsigned int gs[MAXTHREAD];
750 send_root_insertion_signals();
795 for (tid = 0; tid < MAXTHREAD; tid++) {
797 mutex_lock(&mut_stat_table[tid].
lock);
800 mut_stat_table[
tid].stat =
801 (mut_stat_table[
tid].stat ^ 0x2) & 0xfffffffd;
802 mutex_unlock(&mut_stat_table[tid].lock);
860 #ifdef __USE_MARK_BITMAP 868 fprintf(stderr,
" free/total=%d/%d\n",
892 #ifdef __RETURN_BARRIER 893 scan_remaining_roots();
964 #ifdef __EAGER_GC_CONTROL 965 static int change_collector_thread_sched_policy(
int t_sect_length)
968 if(art_enter(ART_PRIO_MAX, ART_TASK_PERIODIC, t_sect_length) == -1){
969 DPRINT2(
"collector error: art_enter");
976 static int restore_collector_thread_sched_policy()
979 if(art_exit() == -1){
980 DPRINT2(
"collector error: art_exit");
990 void enter_gc_region(
int id)
993 mutex_lock(&mut_stat_table[
id].
lock);
999 mutex_unlock(&mut_stat_table[
id].lock);
1001 if (gc_request_flag) {
1013 void exit_gc_region(
int id)
1017 mutex_lock(&mut_stat_table[
id].
lock);
1022 mutex_unlock(&mut_stat_table[
id].lock);
1030 mutex_unlock(&mut_stat_table[
id].lock);
1046 for (i = 0; i < MAXTHREAD; i++) {
1047 mutex_init(&mut_stat_table[i].
lock,
NULL);
1055 #ifdef __USE_POLLING 1091 int check_gc_request()
1093 if (!gc_request_flag)
1105 void sighandler(
int x)
1108 DPRINT2(
"start root scanning");
1118 #define PMAXSTACK (MAXSTACK * 110) 1131 if (barrier !=
NULL) {
1150 mutex_destroy(&barrier->
lock);
1151 cond_destroy(&barrier->
wait_cv);
1158 mutex_lock(&barrier->
lock);
1159 my_phase = barrier->
phase;
1163 barrier->
phase = 1 - my_phase;
1164 cond_broadcast(&barrier->
wait_cv);
1166 while (barrier->
phase == my_phase) {
1169 mutex_unlock(&barrier->
lock);
1180 unsigned int rem_words = req_words;
1182 while (
buddysize[MAXBUDDY-1] <= rem_words) {
1186 for (i = MAXBUDDY - 2; i >= 20; i--) {
1192 return req_words - rem_words;
1211 extern long long values[];
1224 return makeint((buf.tms_utime + buf.tms_stime) * 1000/HZ );
1242 defun(ctx,
"RGCALLOCATED", mod, RGCALLOCATED,
NULL);
1244 pointer_update(Spevalof(
PACKAGE), p);
context * euscontexts[MAXTHREAD]
barrier_t startup_barrier
#define DEFAULT_MAX_RGCSTACK
static void scan_global_roots()
#define read_volatile_int(loc)
struct filestream fstream
static void go_on_to_sweep_phase()
static void wait_until_next_gc_cycle()
pointer findmethod(context *, pointer, pointer, pointer *)
barrier_t barrier_init(int n_clients)
pointer csend(context *,...)
defun("ADR_TO_STRING", mod, ADR_TO_STRING)
static pnewgcstack(ms_entry *oldsp)
static void scan_local_roots(int i)
static pointer dispose[MAXDISPOSE]
unsigned int gs[MAXTHREAD]
void rgcfunc(register context *ctx, pointer mod)
static int mark_a_little(int m_unit)
#define finish_access_before_read()
unsigned int do_allocate_heap(unsigned int req_words)
pointer RGC_GCTIME(register context *ctx, int n, pointer argv[])
static void init_sync_data()
pointer RGCCOUNT(register context *ctx, int n, pointer argv[])
void rgc_add_to_classtable(pointer newclass)
static int sweep_a_little(int gcmerge, int s_unit)
#define collector_stacklimit
static void do_scan_roots()
pointer pstack[PMAXSTACK]
#define ASSERT(condition)
struct callframe * callfp
long buddysize[MAXBUDDY+1]
static void reset_utime()
struct @10 thread_table[]
#define cas_int(loc, ov, nv)
int thr_create(void *, size_t, void(*)(), void *, long, int *)
struct _sweeping_state sweeping_state
pointer rgc_alloc(register int s, int e, int cid, register int nils)
int rw_rdlock(rwlock_t *)
struct buddyfree buddy[MAXBUDDY+1]
int rw_unlock(rwlock_t *)
#define active_mutator_num
struct barrier_struct * barrier_t
#define INITIAL_HEAP_SIZE
static struct _marking_state marking_state
void barrier_destroy(barrier_t barrier)
void barrier_reset(barrier_t barrier, int n_clients)
static pointer rgc_classtable
void barrier_wait(barrier_t barrier)
unsigned int allocate_heap()
static int do_gc_epilogue()
void allocate_bit_table()
void do_a_little_gc_work(int m_unit, int s_unit)
static bpointer mergecell(register bpointer p, int cbix)