00001
00002
00003
00004
00005
00006 static char *rcsid="@(#)$Id$";
00007
00008 #if vxworks
00009 #include <sys/types.h>
00010 #else
00011 #include <sys/types.h>
00012 #include <sys/times.h>
00013 #endif
00014
00015 #if alpha
00016 #include <stdlib.h>
00017 #include <unistd.h>
00018 #endif
00019
00020 #include "eus.h"
00021 #if Solaris2
00022 #include <synch.h>
00023 #include <thread.h>
00024 #endif
00025
00026 #if 0
00027 #define nextbuddy(p) ((bpointer)((eusinteger_t)p+(buddysize[p->h.bix]*sizeof(pointer))))
00028 #define marked(p) (p->h.mark)
00029 #define markon(p) p->h.mark=1
00030 #define markoff(p) p->h.mark=0
00031 #endif
00032 #define myctx (euscontexts[thr_self()])
00033
00034
00035 #if Solaris2 || Linux
00036 extern eusinteger_t _end();
00037 #elif SunOS4_1
00038 extern edata;
00039 #else
00040 extern edata(),_end();
00041 #endif
00042
00043 #if alpha
00044 static eusinteger_t top_addr, bottom_addr;
00045 #endif
00046
00047 extern pointer QPARAGC;
00048 extern pointer K_DISPOSE;
00049
00050 char *maxmemory=(char *)0x0;
00051 #if (WORD_SIZE == 64)
00052 char *minmemory=(char *)0xffffffffffffffff;
00053 #else
00054 char *minmemory=(char *)0xffffffff;
00055 #endif
00056 long freeheap=0,totalheap=0;
00057 struct chunk *chunklist=NULL;
00058
00059 long gccount,marktime,sweeptime;
00060 long alloccount[MAXBUDDY];
00061
00062
00063 #define MAXDISPOSE 256
00064 static pointer dispose[MAXDISPOSE];
00065 static int dispose_count;
00066
00067 int newchunk(k)
00068 register int k;
00069 { register int s;
00070 register struct chunk *cp;
00071 eusinteger_t tail;
00072 #if defined(BIX_DEBUG) || defined(DEBUG_COUNT)
00073 static int count = 0;
00074
00075 count++;
00076 #endif
00077
00078 if (k<DEFAULTCHUNKINDEX) k=DEFAULTCHUNKINDEX;
00079 if (QDEBUG && debug) fprintf(stderr,";; newchunk: k=%d\n",k);
00080 s=buddysize[k];
00081 cp=(struct chunk *)((long)malloc((s+2)*sizeof(pointer)+(sizeof(pointer)-1)) & ~(sizeof(pointer)-1));
00082 #if defined(RGC)
00083 set_heap_range((unsigned int)cp,
00084 (unsigned int)cp + (s+2)*sizeof(pointer)+(sizeof(pointer)-1));
00085 #endif
00086 #if Linux || Cygwin || Darwin
00087 if (minmemory > (char *)cp) minmemory = (char *)cp;
00088 if (maxmemory < (char *)sbrk(0)) maxmemory = (char *)sbrk(0);
00089 if (maxmemory < (char *)cp+(s+2)*sizeof(pointer)+(sizeof(pointer)-1)) maxmemory = ((char *)cp+(s+2)*sizeof(pointer)+(sizeof(pointer)-1));
00090 #else
00091 maxmemory=(char *)sbrk(0);
00092 #endif
00093 if (QDEBUG && debug) fprintf(stderr,";; maxmemory=%p\n",maxmemory);
00094 if (cp==NULL) return(ERR);
00095 #if alpha
00096 if( chunklist == NULL ) {
00097 top_addr = (eusinteger_t)cp;
00098
00099 }
00100 if( (eusinteger_t)cp < top_addr ) {
00101 top_addr = (eusinteger_t)chunklist;
00102
00103 }
00104 #endif
00105
00106 #if defined(RGC)// && !defined(__USE_MARK_BITMAP)
00107
00108 if (chunklist == NULL) {
00109 cp->nextchunk = NULL;
00110 chunklist = cp;
00111 } else {
00112 struct chunk *ccp;
00113 for (ccp = chunklist; ccp->nextchunk < cp && ccp->nextchunk != NULL;
00114 ccp = ccp->nextchunk);
00115 cp->nextchunk = ccp->nextchunk;
00116 ccp->nextchunk = cp;
00117 }
00118 #else
00119 cp->nextchunk=chunklist;
00120 chunklist=cp;
00121 #endif
00122
00123 cp->chunkbix=k;
00124 cp->rootcell.h.mark=0;
00125 cp->rootcell.h.smark=0;
00126 cp->rootcell.h.pmark=0;
00127 cp->rootcell.h.b=1;
00128 cp->rootcell.h.m=0;
00129 cp->rootcell.h.nodispose=0;
00130 cp->rootcell.h.bix=k;
00131 #ifndef RGC
00132 cp->rootcell.b.nextbcell=0;
00133 #else
00134 cp->rootcell.b.nextbcell = buddy[k].bp;
00135 #endif
00136 #if alpha
00137 tail = (eusinteger_t)cp + (s+2)*sizeof(pointer);
00138 if( tail > bottom_addr ) {
00139 bottom_addr = tail;
00140
00141 }
00142 #endif
00143 #ifdef RGC
00144
00145 cp->rootcell.h.bix |= FREETAG;
00146 cp->rootcell.h.cix = -1;
00147 if((char *)cp < minmemory)
00148 minmemory = (char *)cp;
00149 #endif
00150 cp->rootcell.h.cix = -1;
00151 buddy[k].bp= &cp->rootcell;
00152 buddy[k].count++;
00153 totalheap += s; freeheap += s;
00154 return(k);
00155 }
00156
00157 void splitheap(k,buddy)
00158 register int k;
00159 register struct buddyfree *buddy;
00160 { register bpointer b1,b2,bnext;
00161 #if defined(BIX_DEBUG) || defined(DEBUG_COUNT)
00162 static int count;
00163
00164 count++;
00165 #endif
00166
00167 b1= buddy[k].bp;
00168 bnext=b1->b.nextbcell;
00169 buddy[k].bp= bnext;
00170 buddy[k].count--;
00171 b2= (bpointer)((long)b1+buddysize[k-1]*sizeof(pointer));
00172 if (k==2) {
00173 b1->b.nextbcell=b2;
00174 b2->b.nextbcell=buddy[k-1].bp;
00175 buddy[k-1].bp=b1;
00176 buddy[k-1].count +=2;
00177 #ifdef RGC
00178 b2->h.bix = 1 | FREETAG;
00179 b2->h.cix = -1;
00180 #else
00181 b2->h.bix= 1;
00182 b2->h.cix = -1;
00183 #endif
00184 } else {
00185 b1->b.nextbcell= buddy[k-1].bp;
00186 buddy[k-1].bp=b1;
00187 buddy[k-1].count++;
00188 b2->b.nextbcell=buddy[k-2].bp;
00189 buddy[k-2].bp=b2;
00190 buddy[k-2].count++;
00191 #ifdef RGC
00192 b2->h.bix = (k-2 | FREETAG);
00193 b2->h.cix = -1;
00194 #else
00195 b2->h.bix= k-2;
00196 b2->h.cix = -1;
00197 #endif
00198 }
00199 b2->h.m=b1->h.m;
00200 b1->h.m=b1->h.b;
00201 b1->h.b=0;
00202 #ifdef RGC
00203 b1->h.bix = (k-1 | FREETAG);
00204 #else
00205 b1->h.bix= k-1;
00206 #endif
00207 b2->h.b=1;
00208 b2->h.mark=b2->h.smark=b2->h.pmark=0;
00209 b1->h.nodispose=b2->h.nodispose=0;}
00210
00211 bpointer root_alloc_big(ctx, req)
00212 register context *ctx;
00213 register int req;
00214 { register int i, k;
00215 register bpointer b,b2;
00216 numunion nu;
00217 pointer gcm;
00218
00219 #if THREADED
00220 mutex_lock(&alloc_lock);
00221 #endif
00222
00223 ctx->alloc_big_count++;
00224
00225 k=req;
00226 while (buddy[k].bp==0) k++;
00227 if (k>=MAXBUDDY) {
00228 if (buddysize[req]<totalheap/8) {
00229 gc();
00230 gcm=speval(GCMARGIN);
00231 while (freeheap < (totalheap*min(5.0,fltval(gcm))))
00232 newchunk(req);
00233 for (k=req; buddy[k].bp==0; ) k++;}
00234 if (k>=MAXBUDDY) {
00235 k=newchunk(req);
00236 if (k==ERR) {
00237 #if THREADED
00238 mutex_unlock(&alloc_lock);
00239 #endif
00240 error(E_ALLOCATION);}}}
00241
00242 while (req<k) { splitheap(k--,buddy); if (k>req) k--;}
00243 k=buddysize[req]-1;
00244 b=buddy[req].bp;
00245 b2=b->b.nextbcell;
00246 for (i=0; i<k; i++) b->b.c[i]=0;
00247 ctx->lastalloc=makepointer(b);
00248 buddy[req].bp=b2;
00249 buddy[req].count--;
00250 #ifdef DEBUG
00251 printf( "root_alloc_big: alloc 1 block (%d), 0x%lx\n", req, b );
00252 #endif
00253 freeheap -= buddysize[req];
00254 alloccount[req]++;
00255 #if THREADED
00256 mutex_unlock(&alloc_lock);
00257 #endif
00258 return(b);}
00259
00260 void root_alloc_small(ctx, req)
00261 register context *ctx;
00262 register int req;
00263 { register int i, j, k,kk;
00264 register bpointer b, b2;
00265 register struct buddyfree *tb=ctx->thr_buddy;
00266 static long buddyfill[MAXTHRBUDDY+1]={0,500,300,20,15,10,0};
00267 numunion nu;
00268 int collected=0;
00269
00270 #if THREADED
00271 mutex_lock(&alloc_lock);
00272 #endif
00273
00274 ctx->alloc_small_count++;
00275
00276 alloc_again:
00277 for (i=1; i<MAXTHRBUDDY; i++) {
00278 k=kk=buddyfill[i] - tb[i].count;
00279 while (buddy[i].count < k) {
00280
00281 j=i+1;
00282 while (buddy[j].bp==0) j++;
00283 if (j>=MAXBUDDY) {
00284 if (!collected) {
00285
00286
00287 gc(); collected=1;
00288 goto alloc_again;}
00289 while (freeheap<(totalheap*min(5.0,fltval(speval(GCMARGIN))))) {
00290 j=newchunk(DEFAULTCHUNKINDEX);
00291 if (j==ERR) {
00292 #if THREADED
00293 mutex_unlock(&alloc_lock);
00294 #endif
00295 error(E_ALLOCATION);}} }
00296 if (j>=MAXBUDDY) {
00297 j=newchunk(DEFAULTCHUNKINDEX);
00298 if (j==ERR) {
00299 #if THREADED
00300 mutex_unlock(&alloc_lock);
00301 #endif
00302 error(E_ALLOCATION);}}
00303 splitheap(j, buddy);}
00304
00305 if (k>0) {
00306 b=buddy[i].bp;
00307 while (k>0) { b2=b; b->h.cix=0; b=b->b.nextbcell; k--;}
00308 b2->b.nextbcell=tb[i].bp;
00309 tb[i].bp=buddy[i].bp;
00310 buddy[i].bp=b;
00311 buddy[i].count -= kk;
00312 tb[i].count=buddyfill[i];
00313 freeheap -= buddysize[i]*kk;
00314 alloccount[i] += kk;
00315 #ifdef DEBUG
00316 printf( "root_alloc_small: alloc %d block(s) (%d)\n", kk, i);
00317 #endif
00318 }}
00319 #if THREADED
00320 mutex_unlock(&alloc_lock);
00321 #endif
00322
00323 }
00324
00325 #ifndef RGC
00326 pointer gc_alloc(s,e,cid,nils)
00327 register int s,nils;
00328 int e,cid;
00329 { register int req=1,i,ss;
00330 register pointer p;
00331 register pointer *v;
00332 register bpointer b,b2;
00333 register context *ctx=myctx;
00334 register struct buddyfree *tb= ctx->thr_buddy;
00335 #if defined(DEBUG) || defined(DEBUG_COUNT)
00336 static int count=0;
00337
00338 count++;
00339
00340 if( nils > s ) {
00341 printf( "alloc:%d:nils(=%d) > s(=%d)!!\n", count, nils, s );
00342 }
00343 #endif
00344 ss=max(3,s+1);
00345 while (buddysize[req]<ss) req++;
00346 #ifdef DEBUG
00347 printf( "alloc:%d:s=%d, e=%d, cid=%d, nils=%d\n",
00348 count, s, e, cid, nils );
00349 #endif
00350 if (req>=MAXTHRBUDDY) b=root_alloc_big(ctx, req);
00351 else {
00352 if (tb[req].count==0) {
00353 root_alloc_small(ctx, req);
00354 #ifdef DEBUG
00355 printf( "alloc:" );
00356 dump_bcell(req,ctx->thr_buddy);
00357 #endif
00358 }
00359 #if THREADED
00360 rw_rdlock(&gc_lock);
00361 #endif
00362 #ifdef DEBUG
00363 fflush( stdout );
00364 printf( "alloc:%d:", count );
00365 dump_bcell( req, tb );
00366 #endif
00367 b=tb[req].bp;
00368 ctx->lastalloc=makepointer(b);
00369 ss=buddysize[req]-1;
00370 tb[req].bp=b->b.nextbcell;
00371 #if defined(DEBUG) || defined(UALLOC_DEBUG)
00372 printf( "alloc:%d:allocate for user[%d(buddysize=%d)] = 0x%lx: new list top = 0x%lx\n",
00373 count, req, buddysize[req], b, tb[req].bp );
00374 #endif
00375 for (i=0; i<ss; i++) b->b.c[i]=0;
00376 tb[req].count--;
00377 #if THREADED
00378 rw_unlock(&gc_lock);
00379 #endif
00380 }
00381 b->h.elmtype=e;
00382 b->h.cix=cid;
00383 b->h.extra=0;
00384 b->h.nodispose=0;
00385 p=makepointer(b);
00386 v=p->c.obj.iv;
00387 #ifdef DEBUG
00388 printf( "alloc:%d:fill NIL:nils = %d, s = %d\n",
00389 count, nils, s );
00390 #endif
00391 i=0;
00392 while (i<nils) v[i++]=NIL;
00393
00394 i=buddysize[req]-1;
00395 while (s<i) v[s++]=NULL;
00396 #ifdef DEBUG
00397 printf( "alloc:%d:after filling NIL:", count );
00398 dump_bcell( req, tb );
00399 #endif
00400
00401 return(p);}
00402
00403 #endif
00404
00405
00406
00407
00408
00409
00410 #define DEFAULT_MAX_GCSTACK 65536*2
00411 pointer *gcstack, *gcsplimit, *gcsp;
00412 #define gcpush(v) (*lgcsp++=((pointer)v))
00413 #define gcpop() (*--lgcsp)
00414 #if Solaris2
00415 #define out_of_heap(p) ((int)p<(int)_end || (pointer)0x20000000<p)
00416 #else
00417 #if Linux || Cygwin || Darwin
00418 #if (WORD_SIZE == 64)
00419 #define out_of_heap(p) ((unsigned long)p<(unsigned long)minmemory || (pointer)maxmemory <p)
00420 #else
00421 #define out_of_heap(p) ((unsigned int)p<(unsigned int)minmemory || (pointer)maxmemory <p)
00422 #endif
00423 #else
00424 #if alpha
00425 #if THREADED
00426 #define out_of_heap(p) ((long)p<4 || bottom_addr<(long)p)
00427 #else
00428 #define out_of_heap(p) ((long)p<(long)edata || (pointer)0x000003ff00000000<p)
00429 #endif
00430 #else
00431 #if SunOS4_1
00432 #define out_of_heap(p) ((int)p<(int)edata || (pointer)0x20000000<p)
00433 #else
00434 #if (WORD_SIZE == 64)
00435 #define out_of_heap(p) ((long)p<(long)edata || (pointer)0x20000000<p)
00436 #else
00437 #define out_of_heap(p) ((int)p<(int)edata || (pointer)0x20000000<p)
00438 #endif
00439 #endif
00440 #endif
00441 #endif
00442 #endif
00443
00444
00445 pointer mark_root, marking, marking2;
00446
00447 void mark(p)
00448 register pointer p;
00449 { register int i,s;
00450 register bpointer bp;
00451 register pointer p2;
00452 register pointer *lgcsp=gcstack;
00453 register pointer *lgcsplimit=gcsplimit;
00454
00455 mark_root=p;
00456 gcpush(p);
00457 markloop:
00458 if (lgcsp<=gcstack) return;
00459 p=gcpop();
00460 markagain:
00461 if (out_of_heap(p)) goto markloop;
00462
00463 bp=bpointerof(p);
00464 if (marked(bp)) goto markloop;
00465 markon(bp);
00466 #ifdef MARK_DEBUG
00467 printf( "mark: markon 0x%lx\n", bp );
00468 #endif
00469 if (pisclosure(p)) goto markloop;
00470 marking=p;
00471
00472 if (bp->h.elmtype==ELM_FIXED) {
00473 s=buddysize[bp->h.bix]-1;
00474 while (lgcsp+s>gcsplimit) {
00475 newgcstack(lgcsp); lgcsp=gcsp;}
00476 for (i=0; i<s; i++) {
00477 p2=p->c.obj.iv[i];
00478 if (ispointer(p2)) gcpush(p2); }
00479 goto markloop;}
00480 else if (bp->h.elmtype==ELM_POINTER) {
00481 s=buddysize[bp->h.bix]-2;
00482 while (lgcsp+s>gcsplimit) {
00483 newgcstack(lgcsp); lgcsp=gcsp;}
00484 for (i=0; i<s; i++) {
00485 p2=p->c.vec.v[i];
00486 if (ispointer(p2)) gcpush(p2); }
00487 goto markloop;}
00488 else goto markloop;
00489 }
00490
00491
00492 void newgcstack(oldsp)
00493 register pointer *oldsp;
00494 { register pointer *oldstack, *stk, *newstack, *newgcsp;
00495 long top, oldsize, newsize;
00496
00497 oldstack=stk=gcstack;
00498 oldsize=gcsplimit-gcstack;
00499 newsize=oldsize*2;
00500 top=oldsp-gcstack;
00501 newgcsp=newstack=(pointer *)malloc(newsize * sizeof(pointer)+16);
00502 if(isatty(0)) {
00503 fprintf(stderr, "\n;; extending gcstack %p[%ld] --> %p[%ld] top=%lx\n",
00504 oldstack, oldsize, newstack, newsize, top);}
00505 while (stk<oldsp) *newgcsp++= *stk++;
00506 gcstack=newstack;
00507 gcsplimit= &gcstack[newsize-10];
00508 gcsp= &gcstack[top];
00509 cfree(oldstack);
00510 }
00511
00512 int mark_state;
00513 context *mark_ctx;
00514 long mark_stack_root;
00515 long mark_buddy_q;
00516
00517 void markall()
00518 { register pointer *p,*spsave;
00519 register int i,j;
00520 register context *ctx;
00521 register bpointer q;
00522
00523 static int count = 0;
00524
00525 count++;
00526
00527
00528 mark_state=1;
00529 #ifdef MARK_DEBUG
00530 printf( "markall:%d: mark(SYSTEM_OBJECTS)\n", count );
00531 #endif
00532 mark(sysobj);
00533 mark_state=2;
00534 #ifdef MARK_DEBUG
00535 printf( "markall:%d: mark(PACKAGE_LIST)\n", count );
00536 #endif
00537 mark(pkglist);
00538 for (i=0; i<MAXTHREAD; i++) {
00539
00540 if ((ctx=euscontexts[i])) {
00541 mark_ctx=ctx; mark_state=3;
00542 #ifdef MARK_DEBUG
00543 printf( "markall:%d: mark(threadobj %d)\n", count, i );
00544 #endif
00545 mark(ctx->threadobj);
00546 mark_state=4;
00547 mark_stack_root=(long)ctx->stack;
00548
00549
00550 for (p=ctx->stack; p<ctx->vsp; p++) {
00551 mark_state=(long)p;
00552 #if (WORD_SIZE == 64)
00553 if ((((eusinteger_t)(*p) & 7L)==0L) &&
00554 #else
00555 if ((((eusinteger_t)(*p) & 3)==0) &&
00556 #endif
00557 ((ctx->stack>(pointer *)*p) || ((pointer *)*p>ctx->stacklimit)))
00558 { mark(*p); } ;}
00559 mark_state=0x10000;
00560
00561
00562 for (j=1; j<MAXTHRBUDDY; j++) {
00563 q=ctx->thr_buddy[j].bp;
00564 mark_buddy_q=(long)q;
00565 while (q) { markon(q);
00566 #ifdef MARK_DEBUG
00567 printf( "markall:%d: markon 0x%ld\n", count, q );
00568 #endif
00569 q=q->b.nextbcell; mark_state++;}
00570 }
00571 mark_state=0x20000;
00572
00573
00574 #ifdef MARK_DEBUG
00575 printf( "markall:%d: mark(SPECIALS)\n", count );
00576 #endif
00577 mark(ctx->specials);
00578
00579 q=bpointerof(ctx->lastalloc);
00580 if (q && ispointer(q))
00581 #ifdef MARK_DEBUG
00582 printf( "markall:%d: mark(lastalloc)\n", count );
00583 #endif
00584 mark(ctx->lastalloc);
00585 }}
00586 mark_state=5;
00587 for (i=0; i<MAXCLASS; i++) {
00588 if (ispointer(classtab[i].def)) mark(classtab[i].def); }
00589 mark_state=0;
00590 }
00591
00592 #ifndef RGC
00593 void reclaim(p)
00594 register bpointer p;
00595 { register int rbix,stat;
00596 register pointer s;
00597 s=makepointer(p);
00598 if (pisfilestream(s)) {
00599 if (!isint(s->c.fstream.fname) && s->c.fstream.direction!=NIL) {
00600 if (s->c.fstream.fd==makeint(0) || s->c.fstream.fd==makeint(1)) {
00601 fprintf(stderr,";; gc! bogus stream at %lx fd=%ld\n",
00602 (unsigned long int)s,intval(s->c.fstream.fd));}
00603 #if (WORD_SIZE == 64)
00604 else if (s->c.fstream.fd == 0) {
00605
00606
00607
00608 fprintf(stderr, ";; closing fstream was failed, %p, %d\n", s, s->cix);
00609 }
00610 else if ((s->c.stream.buffer == NULL) ||
00611 ((unsigned long)(s->c.stream.buffer) & 0x7L) != 0x0L ||
00612 s->c.stream.buffer->cix == -1) {
00613
00614
00615
00616 fprintf(stderr, ";; bad stream buffer, %p\n", s->c.stream.buffer);
00617 }
00618 #endif
00619 else if ((closestream(s)==0) && debug)
00620 fprintf(stderr,";; gc: dangling stream(address=%lx fd=%ld) is closed\n",
00621 (unsigned long int)s,intval(s->c.fstream.fd)); } }
00622 p->h.cix= -1;
00623 rbix=p->h.bix;
00624 p->b.nextbcell=buddy[rbix].bp;
00625 buddy[rbix].bp=p; buddy[rbix].count++;
00626 freeheap+=buddysize[rbix];}
00627 #endif
00628
00629 static bpointer mergecell(p,cbix)
00630 register bpointer p;
00631 int cbix;
00632
00633
00634 { register bpointer np,p2;
00635 #if defined(DEBUG_COUNT) || defined(MERGE_DEBUG)
00636 static int count = 0;
00637
00638 count++;
00639 #endif
00640 np=nextbuddy(p);
00641 while (p->h.b==0 && (int)p->h.bix<cbix) {
00642 if (marked(np)) return(np);
00643 if (np->h.nodispose==1) return(np);
00644 p2=mergecell(np,cbix);
00645 if (np->h.b==1) {
00646 p->h.b=p->h.m;
00647 p->h.m=np->h.m;
00648 p->h.bix++;
00649 #ifdef MERGE_DEBUG
00650 printf( "mergecell:%d:p=0x%lx, np=0x%lx\n", count, p, np );
00651 #endif
00652 np=p2;}
00653 else {
00654 #ifdef MERGE_DEBUG
00655 printf( "mergecell:%d:call reclaim:np=0x%lx\n", count, np );
00656 #endif
00657 reclaim(np);
00658 return(p2);}}
00659 return(np);}
00660
00661 static void sweep(cp,gcmerge)
00662 register struct chunk *cp;
00663 register int gcmerge;
00664 { register int s;
00665 register bpointer p,np,tail;
00666 #if defined(DEBUG_COUNT) || defined(SWEEP_DEBUG) || defined(MARK_DEBUG)
00667 static int count = 0;
00668 int count2 = 0;
00669
00670 count++;
00671 #endif
00672 s=buddysize[cp->chunkbix];
00673 p= &cp->rootcell;
00674 tail=(bpointer)((eusinteger_t)p+(s<<WORDSHIFT));
00675 #ifdef SWEEP_DEBUG
00676 printf( "sweep:%d:top=0x%lx, tail=0x%lx\n", count, p, tail );
00677 #endif
00678 while (p<tail) {
00679 #ifdef SWEEP_DEBUG
00680 printf( "sweep:%d,%d:p=0x%lx:NIL->cix=%d\n", count, count2++, p, NIL->cix );
00681 #endif
00682 if (marked(p)) {
00683 markoff(p);
00684 #ifdef MARK_DEBUG
00685 printf( "sweep:%d,%d: markoff 0x%lx\n", count, count2, p );
00686 #endif
00687
00688 p=nextbuddy(p);}
00689 else {
00690 if (p->h.nodispose==1) {
00691
00692 if (dispose_count>=MAXDISPOSE)
00693 fprintf(stderr, "no more space for disposal processing\n");
00694 else dispose[dispose_count++]=makepointer(p);
00695 p=nextbuddy(p); }
00696 else if (gcmerge>freeheap) {
00697 np=nextbuddy(p);
00698 reclaim(p);
00699 p=np;}
00700 else {
00701 np=mergecell(p,cp->chunkbix);
00702 reclaim(p);
00703 p=np;} } }
00704 }
00705
00706 void call_disposers()
00707 { int i;
00708 context *ctx=current_ctx;
00709 pointer p,a,curclass;
00710
00711 for (i=0; i<dispose_count; i++) {
00712 p=dispose[i];
00713 p->nodispose=0;
00714 a=(pointer)findmethod(ctx,K_DISPOSE,classof(p), &curclass);
00715 if (debug) fprintf(stderr, ";; (send %p :dispose)\n", p);
00716 if (a!=NIL) csend(ctx,p,K_DISPOSE,0);
00717 }}
00718
00719 void sweepall()
00720 {
00721 context *ctx;
00722 register struct chunk *chp;
00723 register int i, gcmerge;
00724 numunion nu;
00725
00726 dispose_count=0;
00727 ctx=euscontexts[thr_self()];
00728 gcmerge=totalheap * min(1.0,fltval(speval(GCMARGIN)))
00729 * max(0.1,fltval(speval(GCMERGE)));
00730
00731 for (i=0; i<MAXBUDDY-1; i++) {
00732 buddy[i].bp=0;
00733 buddy[i].count=0;
00734 }
00735 freeheap=0;
00736 for (chp=chunklist; chp!=0; chp=chp->nextchunk) sweep(chp,gcmerge);
00737 call_disposers();
00738
00739 }
00740
00741 #if THREADED
00742 void suspend_all_threads()
00743 { register int i, self, stat;
00744
00745 self=thr_self();
00746 for (i=0; i<MAXTHREAD; i++)
00747 if (i!=self && euscontexts[i]) {
00748 stat=thr_suspend(i);
00749 if (stat) fprintf(stderr, "gc cannot suspend thread %d\n",i); }
00750 }
00751
00752 void resume_all_threads()
00753 { register int i, self, stat;
00754
00755 self=thr_self();
00756 for (i=0; i<MAXTHREAD; i++)
00757 if (i!=self && euscontexts[i]) {
00758 stat=thr_continue(i);
00759 if (stat) fprintf(stderr, "gc cannot resume thread %d\n",i); }
00760 }
00761
00762 #endif
00763
00764 #if vxworks
00765 void gc()
00766 { if (debug) fprintf(stderr,"\n;; gc:");
00767 breakck;
00768 gccount++;
00769 markall();
00770 sweepall();
00771 if (debug) {
00772 fprintf(stderr," free/total=%d/%d stack=%d ",
00773 freeheap,totalheap,markctx->vsp-markctx->stack);
00774 }
00775 breakck; }
00776 #else
00777
00778 void gc()
00779 { struct tms tbuf1,tbuf2,tbuf3;
00780 int i, r;
00781 context *ctx=euscontexts[thr_self()];
00782
00783 if (debug) fprintf(stderr,"\n;; gc: thread=%d ",thr_self());
00784 breakck;
00785 gccount++;
00786 times(&tbuf1);
00787
00788 #if THREADED
00789
00790
00791 r = mutex_trylock(&mark_lock);
00792 if ( r != 0 ) {
00793 if (debug) fprintf(stderr, ";; gc:mutex_lock %d ", r);
00794 return;
00795 }
00796 rw_wrlock(&gc_lock);
00797 suspend_all_threads();
00798 #endif
00799
00800 markall();
00801
00802 times(&tbuf2);
00803 marktime+=(tbuf2.tms_utime-tbuf1.tms_utime);
00804 sweepall();
00805 times(&tbuf3);
00806 sweeptime+=(tbuf3.tms_utime-tbuf2.tms_utime);
00807
00808 #if THREADED
00809 resume_all_threads();
00810 rw_unlock(&gc_lock);
00811 mutex_unlock(&mark_lock);
00812
00813 #endif
00814 if (debug) {
00815 fprintf(stderr," free/total=%ld/%ld stack=%d ",
00816 freeheap,totalheap,(int)(myctx->vsp - myctx->stack));
00817 fprintf(stderr," mark=%ld sweep=%ld\n", marktime,sweeptime);
00818 }
00819 if (speval(QGCHOOK)!=NIL) {
00820 pointer gchook=speval(QGCHOOK);
00821 vpush(makeint(freeheap)); vpush(makeint(totalheap));
00822 ufuncall(ctx,gchook,gchook,(pointer)(ctx->vsp-2),ctx->bindfp,2);
00823 ctx->vsp -= 2;
00824 }
00825 breakck;
00826 }
00827 #endif
00828
00829 #ifdef DEBUG
00830 dump_bcell( k, b )
00831 int k;
00832 struct buddyfree *b;
00833 {
00834 bpointer bp;
00835 int i;
00836
00837 printf( "buddy[%d] = { %d, (", k, b[k].count );
00838 bp = b[k].bp;
00839 for( i = 0; i < b[k].count; i++ ) {
00840 printf( "0x%lx ->", bp );
00841 bp = bp->b.nextbcell;
00842 }
00843 printf( ")}\n" );
00844 }
00845 #endif
00846
00847 #ifdef STACK_DEBUG
00848 pointer p_print( v, ctx )
00849 pointer v;
00850 context *ctx;
00851 {
00852 printf( "vpush:0x%lx->[0x%lx]\n", v, ctx->vsp );
00853
00854 return v;
00855 }
00856 #endif