00001
00002
00003
00004
00005
00006
00007 #if vxworks
00008 #include <sys/types.h>
00009 #else
00010 #include <sys/types.h>
00011 #include <sys/times.h>
00012 #endif
00013
00014 #include "eus.h"
00015 #include <synch.h>
00016 #include <thread.h>
00017
00018 #define nextbuddy(p) ((bpointer)((int)p+(buddy[p->h.bix].size<<2)))
00019 #define marked(p) (p->h.mark)
00020 #define markon(p) p->h.mark=1
00021 #define markoff(p) p->h.mark=0
00022
00023 extern _end();
00024
00025 char *maxmemory=(char *)0x100000;
00026 long freeheap=0,totalheap=0;
00027 struct chunk *chunklist=NULL;
00028
00029 long gccount,marktime,sweeptime;
00030 long alloccount[MAXBUDDY];
00031
00032 mutex_t alloc_lock;
00033
00034 newchunk(k)
00035 register int k;
00036 { register int s;
00037 register struct chunk *cp;
00038 if (k<DEFAULTCHUNKINDEX) k=DEFAULTCHUNKINDEX;
00039 if (QDEBUG && debug) fprintf(stderr,";; newchunk: k=%d\n",k);
00040 s=buddy[k].size;
00041 cp=(struct chunk *)(malloc((s+2)*sizeof(pointer)+3) & ~3);
00042 maxmemory=(char *)sbrk(0);
00043 if (cp==NULL) return(ERR);
00044 cp->nextchunk=chunklist;
00045 chunklist=cp;
00046 cp->chunkbix=k;
00047 cp->rootcell.h.mark=0;
00048 cp->rootcell.h.b=1;
00049 cp->rootcell.h.m=0;
00050 cp->rootcell.h.bix=k;
00051 cp->rootcell.b.nextbcell=0;
00052 buddy[k].bp= &cp->rootcell;
00053 totalheap += s; freeheap += s;
00054 return(k);
00055 }
00056
00057 static void splitheap(k)
00058 register int k;
00059 { register bpointer b1,b2,bnext;
00060 b1= buddy[k].bp;
00061 bnext=b1->b.nextbcell;
00062 buddy[k].bp= bnext;
00063 b2= (bpointer)((long)b1+buddy[k-1].size*sizeof(pointer));
00064 if (k==2) {
00065 b1->b.nextbcell=b2;
00066 b2->b.nextbcell=buddy[k-1].bp;
00067 buddy[k-1].bp=b1;
00068 b2->h.bix= 1;}
00069 else {
00070 b1->b.nextbcell= buddy[k-1].bp;
00071 buddy[k-1].bp=b1;
00072 b2->b.nextbcell=buddy[k-2].bp;
00073 buddy[k-2].bp=b2;
00074 b2->h.bix= k-2;}
00075 b2->h.m=b1->h.m;
00076 b1->h.m=b1->h.b;
00077 b1->h.b=0; b1->h.bix= k-1; b2->h.b=1;
00078 b2->h.mark=b2->h.smark=b2->h.pmark=0;}
00079
00080 pointer halloc(req,e,cid)
00081 register int req;
00082 int e;
00083 int cid;
00084 { register int k=req;
00085 register struct buddybase *bbreq= &buddy[req];
00086 register bpointer b;
00087 register pointer p;
00088 numunion nu;
00089
00090 mutex_lock(&alloc_lock);
00091 while (buddy[k].bp==0) k++;
00092 if (k>=MAXBUDDY) {
00093 if (bbreq->size<totalheap/8) {
00094 gc();
00095 while (freeheap<(totalheap*min(5.0,fltval(spevalof(GCMARGIN)))))
00096 newchunk(req);
00097 for (k=req; buddy[k].bp==0; ) k++;}
00098 if (k>=MAXBUDDY) {
00099 k=newchunk(req);
00100 if (k==ERR) { mutex_unlock(&alloc_lock); error(E_ALLOCATION);}}}
00101 while (req<k) { splitheap(k--); if (k>req) k--;}
00102 b=bbreq->bp;
00103 b->h.elmtype=e;
00104 b->h.cix=cid;
00105 bbreq->bp=b->b.nextbcell;
00106 freeheap -= bbreq->size;
00107 alloccount[k]++;
00108 p=makepointer(b);
00109 euscontexts[thr_self()]->lastalloc=p;
00110 mutex_unlock(&alloc_lock);
00111 return(p);}
00112
00113 pointer alloc(s,e,cid,nils)
00114 register int s,nils;
00115 int e,cid;
00116 { register int i=1,ss;
00117 register cell *c;
00118 register pointer *v;
00119 ss=max(3,s+1);
00120 while (buddy[i].size<ss) i++;
00121 if (i>=MAXBUDDY) return(NULL);
00122 c=halloc(i,e,cid);
00123 i=buddy[i].size-1;
00124 v=c->c.obj.iv;
00125 while (nils<s) v[nils++]=NIL;
00126 while (s<i) v[s++]=NULL;
00127 return(c);}
00128
00129
00130
00131
00132
00133 context *markctx;
00134
00135 mark(p)
00136 register pointer p;
00137 { register int s;
00138 register bpointer bp;
00139
00140 if ((int)p<(int)_end || (pointer)0x20000000<p) return(NULL);
00141 markagain:
00142 bp=bpointerof(p);
00143 if (marked(bp)) return;
00144 markon(bp);
00145 if (pisclosure(p)) return;
00146 if (bp->h.elmtype==ELM_FIXED) {
00147 if (bp->h.cix==conscp.cix) {
00148 p=bp->b.c[0];
00149 if ((int)p>(int)_end && (int)p<0x20000000 && ispointer(p)) mark(p);
00150 p=bp->b.c[1];
00151 if ((int)p>(int)_end && (int)p<0x20000000 && ispointer(p)) goto markagain;
00152 }
00153 else {
00154 s=buddy[bp->h.bix].size-1;
00155 while (s>0) {
00156 p=bp->b.c[--s];
00157 if (ispointer(p)) mark(p);}}}
00158 else if (bp->h.elmtype==ELM_POINTER) {
00159 s=buddy[bp->h.bix].size-1;
00160 while (--s>0) {
00161 p=bp->b.c[s];
00162 if (ispointer(p)) mark(p);}
00163 }
00164 }
00165
00166 markall()
00167 { register pointer *p,*spsave;
00168 register int i,j;
00169 register context *ctx;
00170 markctx=euscontexts[thr_self()];
00171 mark(sysobj);
00172 mark(pkglist);
00173 for (i=0; i<MAXTHREAD; i++) {
00174
00175 if (ctx=euscontexts[i]) {
00176 markctx=ctx;
00177 for (p=ctx->stack; p<ctx->vsp; p++)
00178 if (ispointer(*p) && ((ctx->stack>(pointer *)*p)
00179 || ((pointer *)*p>ctx->stacklimit))) { mark(*p); } ;
00180 mark(ctx->lastalloc);}}
00181 for (i=0; i<MAXCLASS; i++) {
00182 markctx=euscontexts[thr_self()];
00183 if (ispointer(classtab[i].def)) mark(classtab[i].def); }
00184 }
00185
00186 reclaim(p)
00187 register bpointer p;
00188 { register int rbix,stat;
00189 register pointer s;
00190 s=makepointer(p);
00191 if (pisfilestream(s)) {
00192 if (!isint(s->c.fstream.fname) && s->c.fstream.direction!=NIL) {
00193 if (s->c.fstream.fd==makeint(0) || s->c.fstream.fd==makeint(1)) {
00194 fprintf(stderr,";; gc! bogus stream at %x fd=%d\n",
00195 (int)s,intval(s->c.fstream.fd));}
00196 else if ((closestream(s)==0) && debug)
00197 fprintf(stderr,";; gc: dangling stream(address=%x fd=%d) is closed\n",
00198 (int)s,intval(s->c.fstream.fd)); } }
00199 p->h.cix= -1;
00200 rbix=p->h.bix;
00201 p->b.nextbcell=buddy[rbix].bp;
00202 buddy[rbix].bp=p;
00203 freeheap+=buddy[rbix].size;}
00204
00205 static bpointer mergecell(p,cbix)
00206 register bpointer p;
00207 int cbix;
00208
00209
00210 { register bpointer np,p2;
00211 np=nextbuddy(p);
00212 while (p->h.b==0 && (int)p->h.bix<cbix) {
00213 if (marked(np)) return(np);
00214 p2=mergecell(np,cbix);
00215 if (np->h.b==1) {
00216 p->h.b=p->h.m;
00217 p->h.m=np->h.m;
00218 p->h.bix++;
00219 np=p2;}
00220 else {
00221 reclaim(np);
00222 return(p2);}}
00223 return(np);}
00224
00225 static void sweep(cp)
00226 struct chunk *cp;
00227 { register int s,gcmerge;
00228 register bpointer p,np,tail;
00229 numunion nu;
00230
00231 gcmerge=totalheap * min(1.0,fltval(spevalof(GCMARGIN)))
00232 * max(0.1,fltval(spevalof(GCMERGE)));
00233 s=buddy[cp->chunkbix].size;
00234 p= &cp->rootcell;
00235 tail=(bpointer)((int)p+(s<<2));
00236 while (p<tail) {
00237 if (marked(p)) { markoff(p); p=nextbuddy(p);}
00238 else if (gcmerge<freeheap) {
00239 np=nextbuddy(p);
00240 reclaim(p);
00241 p=np;}
00242 else {
00243 np=mergecell(p,cp->chunkbix);
00244 reclaim(p);
00245 p=np;} }
00246 }
00247
00248 void sweepall()
00249 {
00250 register struct chunk *chp;
00251 register int i;
00252 for (i=0; i<MAXBUDDY-1; i++) buddy[i].bp=0;
00253 freeheap=0;
00254 for (chp=chunklist; chp!=0; chp=chp->nextchunk) sweep(chp);
00255 }
00256
00257 #if vxworks
00258 gc()
00259 { if (debug) fprintf(stderr,"\n;; gc:");
00260 breakck;
00261 gccount++;
00262 markall();
00263 sweepall();
00264 if (debug) {
00265 fprintf(stderr," free/total=%d/%d stack=%d ",
00266 freeheap,totalheap,markctx->vsp-markctx->stack);
00267 }
00268 breakck;
00269 }
00270 #else
00271 gc()
00272 { struct tms tbuf1,tbuf2,tbuf3;
00273
00274 if (debug) fprintf(stderr,"\n;; gc:");
00275 breakck;
00276 mutex_lock(&mark_lock);
00277 gccount++;
00278 times(&tbuf1);
00279 markall();
00280 times(&tbuf2);
00281 marktime+=(tbuf2.tms_utime-tbuf1.tms_utime);
00282 sweepall();
00283 times(&tbuf3);
00284 sweeptime+=(tbuf3.tms_utime-tbuf2.tms_utime);
00285 if (debug) {
00286 fprintf(stderr," thread=%d free/total=%d/%d stack=%d ",
00287 thr_self(),
00288 freeheap,totalheap,markctx->vsp - markctx->stack);
00289 fprintf(stderr," mark=%d sweep=%d\n", marktime,sweeptime);}
00290 mutex_unlock(&mark_lock);
00291 breakck;
00292 }
00293 #endif
00294