memory.safe.c
Go to the documentation of this file.
00001 /****************************************************************/
00002 /* memory.c:    memory manager for eulisp                       */
00003 /*      Copyright(c) Toshihiro MATSUI
00004 /*                   Electrotechnical Laboratory,1986.
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;    /*size of heap left and allocated*/
00027 struct chunk *chunklist=NULL;
00028 /* timers */
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);    /*can't allocate new memory*/
00044   cp->nextchunk=chunklist;      /*link to chunk list*/
00045   chunklist=cp;
00046   cp->chunkbix=k;
00047   cp->rootcell.h.mark=0;
00048   cp->rootcell.h.b=1;           /*initial buddy marks*/
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)        /*heart of the allocator*/
00058 register int k;
00059 { register bpointer b1,b2,bnext;
00060   b1= buddy[k].bp;      /*root buddy pointer*/
00061   bnext=b1->b.nextbcell;
00062   buddy[k].bp= bnext;   /*remove first element*/
00063   b2= (bpointer)((long)b1+buddy[k-1].size*sizeof(pointer));
00064   if (k==2) {   /*b1 and b2 are of the same size*/
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;       /*index to buddy: must be greater than 0*/
00082 int e;                  /*element type*/
00083 int cid;                /*class id*/
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++;   /*find blocks of adequate size*/
00092   if (k>=MAXBUDDY) {            /*no enough room*/
00093     if (bbreq->size<totalheap/8) {      /*relatively small cell is requested;*/
00094       gc();                     /* then try garbage collection*/
00095       while (freeheap<(totalheap*min(5.0,fltval(spevalof(GCMARGIN)))))
00096         newchunk(req); /*still not enough space*/
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)     /*allocate heap of 's' longwords*/
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);         /*one more word for the allocation information*/
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; /*fill NILs in user's  slots*/
00126   while (s<i) v[s++]=NULL;      /*fill NULLs in buddy-cells extra slots*/
00127   return(c);}
00128 
00129 /****************************************************************/
00130 /* gc: garbage collector
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;       /*already marked*/
00144   markon(bp);                   /*mark it first to avoid endless marking*/
00145   if (pisclosure(p)) return;    /*avoid marking contents of closure*/
00146   if (bp->h.elmtype==ELM_FIXED) {       /*contents are all pointers*/
00147     if (bp->h.cix==conscp.cix) {        /*save stack when cons*/
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) { /*varing number of pointers*/
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);         /*mark internally reachable objects*/
00172   mark(pkglist);        /*mark all packages*/
00173   for (i=0; i<MAXTHREAD; i++) {
00174     /*mark everything reachable from stacks in euscontexts*/
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 /*the cell pointed by 'p' must not be marked*/
00209 /*mergecell kindly returns next uncollectable cell address*/
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);      /*merge neighbor cell*/
00215     if (np->h.b==1) {           /*can be merged*/
00216       p->h.b=p->h.m;            /*merge them into bigger cell*/
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);}       /*don't collect*/
00238     else if (gcmerge<freeheap) { /* no merge */
00239         np=nextbuddy(p);
00240         reclaim(p);
00241         p=np;} 
00242      else {
00243         np=mergecell(p,cp->chunkbix);   /*update free buddy list*/
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;   /*purge buddies*/
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 


euslisp
Author(s): Toshihiro Matsui
autogenerated on Thu Sep 3 2015 10:36:20