memory.mutex.c
Go to the documentation of this file.
1 /****************************************************************/
2 /* memory.c: memory manager for eulisp */
3 /* Copyright(c) Toshihiro MATSUI
4 /* Electrotechnical Laboratory,1986.
5 /****************************************************************/
6 
7 #if vxworks
8 #include <sys/types.h>
9 #else
10 #include <sys/types.h>
11 #include <sys/times.h>
12 #endif
13 
14 #include "eus.h"
15 #if Solaris2
16 #include <synch.h>
17 #include <thread.h>
18 #endif
19 
20 #define nextbuddy(p) ((bpointer)((int)p+(buddysize[p->h.bix]*sizeof(pointer))))
21 #define marked(p) (p->h.mark)
22 #define markon(p) p->h.mark=1
23 #define markoff(p) p->h.mark=0
24 #define myctx (euscontexts[thr_self()])
25 
26 #if Solaris2
27 extern _end();
28 #else
29 extern edata();
30 #endif
31 
32 extern pointer QPARAGC;
33 
34 char *maxmemory=(char *)0x100000;
35 long freeheap=0,totalheap=0; /*size of heap left and allocated*/
37 /* timers */
39 long alloccount[MAXBUDDY];
40 
41 #if Solaris2
42 mutex_t alloc_lock;
43 #endif
44 
46 register int k;
47 { register int s;
48  register struct chunk *cp;
49  if (k<DEFAULTCHUNKINDEX) k=DEFAULTCHUNKINDEX;
50  if (QDEBUG && debug) fprintf(stderr,";; newchunk: k=%d\n",k);
51  s=buddysize[k];
52  cp=(struct chunk *)(malloc((s+2)*sizeof(pointer)+3) & ~3);
53  maxmemory=(char *)sbrk(0);
54  if (cp==NULL) return(ERR); /*can't allocate new memory*/
55  cp->nextchunk=chunklist; /*link to chunk list*/
56  chunklist=cp;
57  cp->chunkbix=k;
58  cp->rootcell.h.mark=0;
59  cp->rootcell.h.b=1; /*initial buddy marks*/
60  cp->rootcell.h.m=0;
61  cp->rootcell.h.bix=k;
62  cp->rootcell.b.nextbcell=0;
63  buddy[k].bp= &cp->rootcell;
64  buddy[k].count++;
65  totalheap += s; freeheap += s;
66  return(k);
67  }
68 
69 static void splitheap(k,buddy) /*heart of the allocator*/
70 register int k;
71 register struct buddyfree *buddy;
72 { register bpointer b1,b2,bnext;
73  b1= buddy[k].bp; /*root buddy pointer*/
74  bnext=b1->b.nextbcell;
75  buddy[k].bp= bnext; /*remove first element*/
76  buddy[k].count--;
77  b2= (bpointer)((long)b1+buddysize[k-1]*sizeof(pointer));
78  if (k==2) { /*b1 and b2 are of the same size*/
79  b1->b.nextbcell=b2;
80  b2->b.nextbcell=buddy[k-1].bp;
81  buddy[k-1].bp=b1;
82  buddy[k-1].count +=2;
83  b2->h.bix= 1;}
84  else {
85  b1->b.nextbcell= buddy[k-1].bp;
86  buddy[k-1].bp=b1;
87  buddy[k-1].count++;
88  b2->b.nextbcell=buddy[k-2].bp;
89  buddy[k-2].bp=b2;
90  buddy[k-2].count++;
91  b2->h.bix= k-2;}
92  b2->h.m=b1->h.m;
93  b1->h.m=b1->h.b;
94  b1->h.b=0; b1->h.bix= k-1; b2->h.b=1;
95  b2->h.mark=b2->h.smark=b2->h.pmark=0;}
96 
98 register context *ctx;
99 register int req; /*index to buddy: must be greater than 0*/
100 { register int i, k;
101  register bpointer b,b2;
102  numunion nu;
103 
104 #if Solaris2
105  mutex_lock(&alloc_lock);
106 #endif
107 
108  ctx->alloc_big_count++;
109 
110  k=req;
111  while (buddy[k].bp==0) k++; /*find blocks of adequate size*/
112  if (k>=MAXBUDDY) { /*no bigger free cell*/
113  if (buddysize[req]<totalheap/8) { /*relatively small cell is requested;*/
114  gc(); /* then try garbage collection*/
115  while (freeheap<(totalheap*min(5.0,fltval(spevalof(GCMARGIN)))))
116  newchunk(req); /*still not enough space*/
117  for (k=req; buddy[k].bp==0; ) k++;}
118  if (k>=MAXBUDDY) {
119  k=newchunk(req);
120  if (k==ERR) {
121 #if Solaris2
122  mutex_unlock(&alloc_lock);
123 #endif
124  error(E_ALLOCATION);}}}
125 
126  while (req<k) { splitheap(k--,&buddy); if (k>req) k--;}
127  k=buddysize[req]-1;
128  b=buddy[req].bp;
129  b2=b->b.nextbcell;
130  for (i=0; i<k; i++) b->b.c[i]=0;
131  ctx->lastalloc=makepointer(b);
132  buddy[req].bp=b2;
133  buddy[req].count--;
134  freeheap -= buddysize[req];
135  alloccount[req]++;
136 #if Solaris2
137  mutex_unlock(&alloc_lock);
138 #endif
139  return(b);}
140 
142 register context *ctx;
143 register int req; /*index to buddy: must be greater than 0*/
144 { register int i, j, k,kk;
145  register bpointer b, b2;
146  register struct buddyfree *tb=ctx->thr_buddy;
147  static long buddyfill[MAXTHRBUDDY+1]={0,500,300,50,25,20,0};
148  numunion nu;
149  int collected=0;
150 
151 #if Solaris2
152  mutex_lock(&alloc_lock);
153 #endif
154 
155  ctx->alloc_small_count++;
156 
157  alloc_again:
158  for (i=1; i<MAXTHRBUDDY; i++) {
159  k=kk=buddyfill[i] - tb[i].count; /*how many cells are needed*/
160  while (buddy[i].count < k) { /*Do we have enough free in the root?*/
161 /* fprintf(stderr, "free_count=%d; k=%d\n",buddy[i].count,k); */
162  j=i+1;
163  while (buddy[j].bp==0) j++;
164  if (j>=MAXBUDDY) { /*no free cell*/
165  if (!collected) {
166  /* fprintf(stderr, "GC: free=%d total=%d, margin=%f\n",
167  freeheap, totalheap, fltval(spevalof(GCMARGIN))); */
168  gc(); collected=1;
169  goto alloc_again;}
170  while (freeheap<(totalheap*min(5.0,fltval(spevalof(GCMARGIN))))) {
171  j=newchunk(DEFAULTCHUNKINDEX); /*still not enough space*/
172  if (j==ERR) { mutex_unlock(&alloc_lock); error(E_ALLOCATION);}} }
173  if (j>=MAXBUDDY) { /*hard fragmentation seen*/
174  j=newchunk(DEFAULTCHUNKINDEX);
175  if (j==ERR) { mutex_unlock(&alloc_lock); error(E_ALLOCATION);}}
176  splitheap(j, &buddy);}
177  /*sufficient free cells collected in the root free list*/
178  if (k>0) {
179  b=buddy[i].bp;
180  while (k>0) { b2=b; b=b->b.nextbcell; k--;}
181  b2->b.nextbcell=tb[i].bp;
182  tb[i].bp=buddy[i].bp;
183  buddy[i].bp=b;
184  buddy[i].count -= kk;
185  tb[i].count=buddyfill[i];
186  freeheap -= buddysize[i]*kk;
187  alloccount[i] += kk;
188  }}
189 #if Solaris2
190  mutex_unlock(&alloc_lock);
191 #endif
192  /*return(b);*/
193  }
194 
195 pointer halloc(req,e,cid) /*heap alloc*/
196 register int req; /*index to buddy: must be greater than 0*/
197 int e; /*element type*/
198 int cid; /*class id*/
199 { register bpointer b;
200  register pointer p;
201  context *ctx=myctx;
202  register struct buddyfree *tb= ctx->thr_buddy;
203 
204  if (/*req>=MAXTHRBUDDY*/ 1) b=root_alloc_big(ctx, req);
205  else { /*small cell is requested*/
206  if (tb[req].count==0) /*find a cell in the local free list*/
207  root_alloc_small(ctx, req);
208  b=tb[req].bp;
209  ctx->lastalloc=makepointer(b);
210  tb[req].bp=b->b.nextbcell;
211  tb[req].count--;}
212  b->h.elmtype=e;
213  b->h.cix=cid;
214  p=makepointer(b);
215  return(p);}
216 
217 pointer allocx(s,e,cid,nils) /*allocate heap of 's' longwords*/
218 register int s,nils;
219 int e,cid;
220 { register int bs=1,i,ss;
221  register cell *c;
222  register pointer *v;
223  register bpointer b;
224  ss=max(3,s+1); /*one more word for the allocation information*/
225  while (buddysize[bs]<ss) bs++;
226  if (bs>=MAXBUDDY) return(NULL);
227 
228 /* c=halloc(bs,e,cid); */
229 
230  b=root_alloc_big(myctx, bs);
231  b->h.elmtype=e;
232  b->h.cix=cid;
233  c=makepointer(b);
234 
235  i=buddysize[bs]-1;
236  v=c->c.obj.iv;
237  while (nils<s) v[nils++]=NIL; /*fill NILs in user's slots*/
238  while (s<i) v[s++]=NULL; /*fill NULLs in buddy-cells extra slots*/
239  return(c);}
240 
241 pointer alloc(s,e,cid,nils) /*allocate heap of 's' longwords*/
242 register int s,nils;
243 int e,cid;
244 { register int req=1,i,ss,k;
245  register cell *c;
246  register pointer *v;
247  register bpointer b,b2;
248  register context *ctx=myctx;
249  numunion nu;
250 
251  ss=max(3,s+1); /*one more word for the allocation information*/
252  while (buddysize[req]<ss) req++;
253  if (req>=MAXBUDDY) return(NULL);
254 
255  k=req;
256  mutex_lock(&alloc_lock);
257 
258  while (buddy[k].bp==0) k++; /*find blocks of adequate size*/
259  if (k>=MAXBUDDY) { /*no bigger free cell*/
260  if (buddysize[req]<totalheap/8) { /*relatively small cell is requested;*/
261  gc(); /* then try garbage collection*/
262  while (freeheap<(totalheap*min(5.0,fltval(spevalof(GCMARGIN)))))
263  newchunk(req); /*still not enough space*/
264  for (k=req; buddy[k].bp==0; ) k++;}
265  if (k>=MAXBUDDY) {
266  k=newchunk(req);
267  if (k==ERR) { mutex_unlock(&alloc_lock); error(E_ALLOCATION);}}}
268  while (req<k) { splitheap(k--,&buddy); if (k>req) k--;}
269  k=buddysize[req]-1;
270  b=buddy[req].bp;
271  b2=b->b.nextbcell;
272  for (i=0; i<k; i++) b->b.c[i]=0;
273  b->h.elmtype=e;
274  b->h.cix=cid;
275  c=makepointer(b);
276  ctx->lastalloc=c;
277  buddy[req].bp=b2;
278  buddy[req].count--;
279  freeheap -= buddysize[req];
280  alloccount[req]++;
281  mutex_unlock(&alloc_lock);
282 
283  i=buddysize[req]-1;
284  v=c->c.obj.iv;
285  while (nils<s) v[nils++]=NIL; /*fill NILs in user's slots*/
286  return(c);}
287 
288 
289 
290 /****************************************************************/
291 /* gc: garbage collector
292 /****************************************************************/
293 
294 #define DEFAULT_MAX_GCSTACK 65536*2
296 #define gcpush(v) (*lgcsp++=((pointer)v))
297 #define gcpop() (*--lgcsp)
298 
300 
302 register pointer p;
303 { register int i,s;
304  register bpointer bp;
305  register pointer p2;
306  register pointer *lgcsp=gcstack;
307  register pointer *lgcsplimit=gcsplimit;
308 
309  mark_root=p;
310  gcpush(p);
311 markloop:
312  if (lgcsp<=gcstack) return;
313  p=gcpop();
314 markagain:
315 #if Solaris2
316  if ((int)p<(int)_end || (pointer)0x20000000<p) goto markloop;
317 #else
318  if ((int)p<(int)edata || (pointer)0x20000000<p) goto markloop;
319 #endif
320  bp=bpointerof(p);
321  if (marked(bp)) goto markloop; /*already marked*/
322  markon(bp); /*mark it first to avoid endless marking*/
323  if (pisclosure(p)) goto markloop; /*avoid marking contents of closure*/
324  marking=p;
325  if (bp->h.elmtype==ELM_FIXED) { /*contents are all pointers*/
326  s=buddysize[bp->h.bix]-1;
327  while (lgcsp+s>gcsplimit) { newgcstack(lgcsp); lgcsp=gcsp;}
328  for (i=0; i<s; i++) {
329  p2=p->c.obj.iv[i];
330  if (ispointer(p2)) /* && !marked(bpointerof(p2)))*/ gcpush(p2); }
331  goto markloop;}
332  else if (bp->h.elmtype==ELM_POINTER) { /*varing number of pointers*/
333  s=vecsize(p);
334  while (lgcsp+s>gcsplimit) { newgcstack(lgcsp); lgcsp=gcsp;}
335  for (i=0; i<s; i++) {
336  p2=p->c.vec.v[i];
337  if (ispointer(p2)) /* && !marked(bpointerof(p2)))*/ gcpush(p2); }
338  goto markloop;}
339  else goto markloop;
340  }
341 
343 register pointer *oldsp;
344 { register pointer *oldstack, *stk, *newstack, *newgcsp;
345  long top, oldsize, newsize;
346 
347  oldstack=stk=gcstack;
348  oldsize=gcsplimit-gcstack;
349  newsize=oldsize*2;
350  top=oldsp-gcstack;
351  newgcsp=newstack=(pointer *)malloc(newsize * sizeof(pointer)+16);
352  fprintf(stderr, "\n;; extending gcstack 0x%x[%d] --> 0x%x[%d] top=%x\n",
353  oldstack, oldsize, newstack, newsize, top);
354  while (stk<oldsp) *newgcsp++= *stk++;
355  gcstack=newstack;
356  gcsplimit= &gcstack[newsize-10];
357  gcsp= &gcstack[top];
358  cfree(oldstack);
359  }
360 
362 
364 { register pointer *p,*spsave;
365  register int i,j;
366  register context *ctx;
367  register bpointer q;
368 
369  mark_state=1;
370  mark(sysobj); /*mark internally reachable objects*/
371  mark_state=2;
372  mark(pkglist); /*mark all packages*/
373  for (i=0; i<MAXTHREAD; i++) {
374  /*mark everything reachable from stacks in euscontexts*/
375  if (ctx=euscontexts[i]) {
376  mark_state=ctx;
377  for (p=ctx->stack; p<ctx->vsp; p++) {
378  mark_state==(int)p;
379  if ((((int)(*p) & 3)==0) &&
380  ((ctx->stack>(pointer *)*p) || ((pointer *)*p>ctx->stacklimit)))
381  { mark(*p); } ;}
382  mark_state++;
383  mark(ctx->lastalloc);
384  mark_state=0x10000;
385  for (j=1; j<MAXTHRBUDDY; j++) {
386  q=ctx->thr_buddy[j].bp;
387  while (q) { markon(q); q=q->b.nextbcell; mark_state++;}
388  }
389  }}
390  mark_state=5;
391  for (i=0; i<MAXCLASS; i++) {
392  if (ispointer(classtab[i].def)) mark(classtab[i].def); }
393  mark_state=0;
394  }
395 
397 register bpointer p;
398 { register int rbix,stat;
399  register pointer s;
400  s=makepointer(p);
401  if (pisfilestream(s)) {
402  if (!isint(s->c.fstream.fname) && s->c.fstream.direction!=NIL) {
403  if (s->c.fstream.fd==makeint(0) || s->c.fstream.fd==makeint(1)) {
404  fprintf(stderr,";; gc! bogus stream at %x fd=%d\n",
405  (int)s,intval(s->c.fstream.fd));}
406  else if ((closestream(s)==0) && debug)
407  fprintf(stderr,";; gc: dangling stream(address=%x fd=%d) is closed\n",
408  (int)s,intval(s->c.fstream.fd)); } }
409  p->h.cix= -1;
410  rbix=p->h.bix;
411  p->b.nextbcell=buddy[rbix].bp;
412  buddy[rbix].bp=p; buddy[rbix].count++;
413  freeheap+=buddysize[rbix];}
414 
415 static bpointer mergecell(p,cbix)
416 register bpointer p;
417 int cbix;
418 /*the cell pointed by 'p' must not be marked*/
419 /*mergecell kindly returns next uncollectable cell address*/
420 { register bpointer np,p2;
421  np=nextbuddy(p);
422  while (p->h.b==0 && (int)p->h.bix<cbix) {
423  if (marked(np)) return(np);
424  p2=mergecell(np,cbix); /*merge neighbor cell*/
425  if (np->h.b==1) { /*can be merged*/
426  p->h.b=p->h.m; /*merge them into bigger cell*/
427  p->h.m=np->h.m;
428  p->h.bix++;
429  np=p2;}
430  else {
431  reclaim(np);
432  return(p2);}}
433  return(np);}
434 
435 static void sweep(cp,gcmerge)
436 register struct chunk *cp;
437 register int gcmerge;
438 { register int s;
439  register bpointer p,np,tail;
440 
441  s=buddysize[cp->chunkbix];
442  p= &cp->rootcell;
443  tail=(bpointer)((int)p+(s<<2));
444  while (p<tail) {
445  if (marked(p)) { markoff(p); p=nextbuddy(p);} /*don't collect*/
446  else if (gcmerge>freeheap) { /* no merge */
447  np=nextbuddy(p);
448  reclaim(p);
449  p=np;}
450  else {
451  np=mergecell(p,cp->chunkbix); /*update free buddy list*/
452  reclaim(p);
453  p=np;} }
454  }
455 
456 void sweepall()
457 {
458  register struct chunk *chp;
459  register int i, gcmerge;
460  numunion nu;
461  gcmerge=totalheap * min(1.0,fltval(spevalof(GCMARGIN)))
462  * max(0.1,fltval(spevalof(GCMERGE)));
463 
464  for (i=0; i<MAXBUDDY-1; i++) {
465  buddy[i].bp=0; /*purge buddies*/
466  buddy[i].count=0; /*clear free cell count*/
467  }
468  freeheap=0;
469  for (chp=chunklist; chp!=0; chp=chp->nextchunk) sweep(chp,gcmerge);
470  }
471 
472 #if vxworks
473 gc()
474 { if (debug) fprintf(stderr,"\n;; gc:");
475  breakck;
476  gccount++;
477  markall();
478  sweepall();
479  if (debug) {
480  fprintf(stderr," free/total=%d/%d stack=%d ",
482  }
483  breakck;
484  }
485 
486 #else
487 
488 gc()
489 { struct tms tbuf1,tbuf2,tbuf3;
490 
491  if (debug) fprintf(stderr,"\n;; gc: thread=%d ",thr_self());
492  breakck;
493  gccount++;
494  times(&tbuf1);
495 
496 #if Solaris2
497  mutex_unlock(&mark_lock);
498 #endif
499 
500  markall();
501 
502  times(&tbuf2);
503  marktime+=(tbuf2.tms_utime-tbuf1.tms_utime);
504  sweepall();
505  times(&tbuf3);
506  sweeptime+=(tbuf3.tms_utime-tbuf2.tms_utime);
507  if (debug) {
508  fprintf(stderr," free/total=%d/%d stack=%d ",
509  freeheap,totalheap,myctx->vsp - myctx->stack);
510  fprintf(stderr," mark=%d sweep=%d\n", marktime,sweeptime);}
511 
512 #if Solaris2
513  mutex_unlock(&mark_lock);
514 #endif
515  breakck;
516 }
517 #endif
518 
context * euscontexts[MAXTHREAD]
Definition: eus.c:105
Definition: eus.h:561
pointer GCMARGIN
Definition: eus.c:173
long sweeptime
Definition: memory.mutex.c:38
unsigned pmark
Definition: eus.h:179
pointer * stack
Definition: eus.h:523
unsigned elmtype
Definition: eus.h:180
static int bp
pointer * gcsp
Definition: memory.mutex.c:295
struct vector vec
Definition: eus.h:412
pointer * stacklimit
Definition: eus.h:523
void sweepall()
Definition: memory.mutex.c:456
static int gcmerge
Definition: collector.c:45
#define makeint(v)
Definition: sfttest.c:2
struct cell * pointer
Definition: eus.h:163
Definition: eus.h:522
pointer mark_root
Definition: memory.mutex.c:299
struct filestream fstream
Definition: eus.h:404
pointer GCMERGE
Definition: eus.c:173
pointer * vsp
Definition: eus.h:523
int closestream(pointer)
Definition: eusstream.c:53
long totalheap
Definition: memory.mutex.c:35
struct bcell * bpointer
Definition: eus.h:443
bpointer bp
Definition: eus.h:563
pointer QDEBUG
Definition: eus.c:123
long marktime
Definition: memory.mutex.c:38
_end()
#define intval(p)
Definition: sfttest.c:1
pointer alloc(int s, int e, int cid, int nils)
Definition: memory.mutex.c:241
Definition: eus.h:445
long alloccount[MAXBUDDY]
Definition: memory.mutex.c:39
newgcstack(pointer *oldsp)
Definition: memory.mutex.c:342
markall()
Definition: memory.mutex.c:363
context * markctx
Definition: memory.safe.c:133
#define min(x, y)
Definition: rmflags.c:17
pointer * gcstack
Definition: memory.mutex.c:295
mutex_t mark_lock
Definition: mthread.c:25
union cell::cellunion c
pointer iv[2]
Definition: eus.h:319
pointer QPARAGC
Definition: eus.c:125
pointer lastalloc
Definition: eus.h:534
Definition: eus.h:426
#define myctx
Definition: rgc_mem.c:9
unsigned smark
Definition: eus.h:178
newchunk(int k)
Definition: memory.mutex.c:45
Definition: eus.h:379
mark(pointer p)
Definition: memory.mutex.c:301
pointer fname
Definition: eus.h:285
struct cellheader h
Definition: eus.h:438
int chunkbix
Definition: eus.h:447
long buddysize[MAXBUDDY+1]
Definition: eus.c:103
static bpointer mergecell(bpointer p, int cbix)
Definition: memory.mutex.c:415
short s
Definition: structsize.c:2
struct bcell * nextbcell
Definition: eus.h:440
pointer * gcsplimit
Definition: memory.mutex.c:295
reclaim(bpointer p)
Definition: memory.mutex.c:396
pointer error(enum errorcode ec,...) pointer error(va_alist) va_dcl
Definition: eus.c:297
char * maxmemory
Definition: memory.mutex.c:34
pointer halloc(int req, int e, int cid)
Definition: memory.mutex.c:195
union bcell::@12 b
pointer marking
Definition: memory.mutex.c:299
struct bcell rootcell
Definition: eus.h:448
unsigned mark
Definition: eus.h:175
static void sweep(struct chunk *cp, int gcmerge)
Definition: memory.mutex.c:435
struct chunk * chunklist
Definition: memory.mutex.c:36
gc()
Definition: memory.mutex.c:473
struct buddyfree buddy[MAXBUDDY+1]
Definition: eus.c:46
float fltval()
tail(char *cp)
Definition: eustags.c:1156
unsigned bix
Definition: eus.h:183
int count
Definition: thrtest.c:11
short cix
Definition: eus.h:188
struct buddyfree * thr_buddy
Definition: eus.h:538
#define max(I1, I2)
Definition: eustags.c:134
#define NULL
Definition: transargv.c:8
struct object obj
Definition: eus.h:415
pointer fd
Definition: eus.h:284
GLfloat v[8][3]
Definition: cube.c:21
#define gcpush(v, off)
Definition: memory.mutex.c:296
unsigned b
Definition: eus.h:176
pointer direction
Definition: eus.h:280
pointer sysobj
Definition: eus.c:54
Definition: eus.h:437
edata()
int mark_state
Definition: memory.mutex.c:361
unsigned int thr_self()
Definition: eus.c:25
struct chunk * nextchunk
Definition: eus.h:446
long gccount
Definition: memory.mutex.c:38
pointer marking2
Definition: memory.mutex.c:299
unsigned m
Definition: eus.h:177
struct class_desc classtab[MAXCLASS]
Definition: eus.c:138
pointer pkglist
Definition: eus.c:109
struct cell * c[2]
Definition: eus.h:441
long freeheap
Definition: memory.mutex.c:35
bpointer root_alloc_big(context *ctx, int req)
Definition: memory.mutex.c:97
pointer NIL
Definition: eus.c:110
root_alloc_small(context *ctx, int req)
Definition: memory.mutex.c:141
int count
Definition: eus.h:562
pointer v[1]
Definition: eus.h:299
static void splitheap(int k, struct buddyfree *buddy)
Definition: memory.mutex.c:69
mutex_t alloc_lock
Definition: memory.mutex.c:42
pointer allocx(int s, int e, int cid, int nils)
Definition: memory.mutex.c:217


euslisp
Author(s): Toshihiro Matsui
autogenerated on Thu Jun 6 2019 20:00:44