|
|
1.1 root 1: #ifndef lint
2: static char *rcsid =
3: "$Header: alloc.c,v 1.13 87/12/11 17:27:45 sklower Exp $";
4: #endif
5:
6: /*
7: * alloc.c $Locker: $
8: * storage allocator and garbage collector
9: *
10: * (c) copyright 1982, Regents of the University of California
11: */
12:
13: # include "global.h"
14: # include "structs.h"
15:
16: #include <sys/types.h>
17: #include <sys/times.h>
18: #ifdef METER
19: #include <sys/vtimes.h>
20: #endif
21:
22: # define NUMWORDS TTSIZE * 128 /* max number of words in P0 space */
23: # define BITQUADS TTSIZE * 2 /* length of bit map in quad words */
24: # define BITLONGS TTSIZE * 4 /* length of bit map in long words */
25:
26: # ifdef vax
27: # define ftstbit asm(" ashl $-2,r11,r3");\
28: asm(" bbcs r3,_bitmapi,1f");\
29: asm(" ret"); \
30: asm("1:");
31:
32: /* setbit is a fast way of setting a bit, it is like ftstbit except it
33: * always continues on to the next instruction
34: */
35: # define setbit asm(" ashl $-2,r11,r0"); \
36: asm(" bbcs r0,_bitmapi,$0");
37: # endif
38:
39: # if m_68k
40: # define ftstbit {if(Itstbt()) return;}
41: # define setbit Itstbt()
42: # endif
43:
44: # ifdef tahoe
45: # define ftstbit if( readbit(p) ) return; oksetbit;
46: # define setbit {bitmapi[(int)p>>7] |= bitmsk[((int)p >> 2)&31];}
47: # define readbit(p) ((int)bitmapi[r=(int)p>>7] & (s=bitmsk[((int)p>>2)&31]))
48: # define oksetbit {bitmapi[r] |= s;}
49: # endif
50:
51: /* Unused bit macros
52: # define lookbit(p) (bbitmap[(int)p>>5] & bitmsk[((int)p>>2) & 7])
53: # define readchk(p) ((int)bitfre[(int)p>>5] & bitmsk[((int)p>>2)&7])
54: # define setchk(p) {bitfre[(int)p>>5] |= bitmsk[((int)p >> 2) & 7];}
55: */
56:
57: # define roundup(x,l) (((x - 1) | (l - 1)) + 1)
58:
59: # define MARKVAL(v) if(((int)v) >= (int)beginsweep) markdp(v);
60: # define ATOLX(p) ((((int)p)-OFFSET)>>7)
61:
62: /* the Vax hardware only allows 2^16-1 bytes to be accessed with one
63: * movc5 instruction. We use the movc5 instruction to clear the
64: * bitmaps.
65: */
66: # define MAXCLEAR ((1<<16)-1)
67:
68: /* METER denotes something added to help meter storage allocation. */
69:
70: extern int *beginsweep; /* first sweepable data */
71: extern char purepage[];
72: extern int fakettsize;
73: extern int gcstrings;
74: int debugin = FALSE; /* temp debug flag */
75:
76: extern lispval datalim; /* end of data space */
77: int bitmapi[BITLONGS]; /* the bit map--one bit per long */
78: double zeroq; /* a quad word of zeros */
79: char *bbitmap = (char *) bitmapi; /* byte version of bit map array */
80: double *qbitmap = (double *) bitmapi; /* integer version of bit map array */
81: #ifdef METER
82: extern int gcstat;
83: extern struct vtimes
84: premark,presweep,alldone; /* actually struct tbuffer's */
85:
86: extern int mrkdpcnt;
87: extern int conssame, consdiff,consnil; /* count of cells whose cdr point
88: * to the same page and different
89: * pages respectively
90: */
91: #endif
92: int bitmsk[32]={1,2,4,8,16,32,64,128, /* used by bit-marking macros */
93: 0x100, 0x200, 0x400, 0x800,
94: 0x1000, 0x2000, 0x4000, 0x8000,
95: 0x10000, 0x20000, 0x40000, 0x80000,
96: 0x100000, 0x200000, 0x400000, 0x800000,
97: 0x1000000, 0x2000000, 0x4000000, 0x8000000,
98: 0x10000000, 0x20000000, 0x40000000, 0x80000000};
99: extern int *bind_lists; /* lisp data for compiled code */
100:
101: char *xsbrk();
102: char *gethspace();
103:
104:
105: extern struct types atom_str, strng_str, int_str, dtpr_str, doub_str,
106: array_str, sdot_str, val_str, funct_str, hunk_str[], vect_str,
107: vecti_str, other_str;
108:
109: extern struct str_x str_current[];
110:
111: lispval hunk_items[7], hunk_pages[7], hunk_name[7];
112:
113: extern int initflag; /* starts off TRUE: initially gc not allowed */
114:
115:
116: /* this is a table of pointers to all struct types objects
117: * the index is the type number.
118: */
119: static struct types *spaces[NUMSPACES] =
120: {&strng_str, &atom_str, &int_str,
121: &dtpr_str, &doub_str, &funct_str,
122: (struct types *) 0, /* port objects not allocated in this way */
123: &array_str,
124: &other_str, /* other objects not allocated in this way */
125: &sdot_str,&val_str,
126: &hunk_str[0], &hunk_str[1], &hunk_str[2],
127: &hunk_str[3], &hunk_str[4], &hunk_str[5],
128: &hunk_str[6],
129: &vect_str, &vecti_str};
130:
131:
132: /* this is a table of pointers to collectable struct types objects
133: * the index is the type number.
134: */
135: struct types *gcableptr[] = {
136: #ifndef GCSTRINGS
137: (struct types *) 0, /* strings not collectable */
138: #else
139: &strng_str,
140: #endif
141: &atom_str,
142: &int_str, &dtpr_str, &doub_str,
143: (struct types *) 0, /* binary objects not collectable */
144: (struct types *) 0, /* port objects not collectable */
145: &array_str,
146: (struct types *) 0, /* gap in the type number sequence */
147: &sdot_str,&val_str,
148: &hunk_str[0], &hunk_str[1], &hunk_str[2],
149: &hunk_str[3], &hunk_str[4], &hunk_str[5],
150: &hunk_str[6],
151: &vect_str, &vecti_str};
152:
153:
154: /*
155: * get_more_space(type_struct,purep)
156: *
157: * Allocates and structures a new page, returning 0.
158: * If no space is available, returns positive number.
159: * If purep is TRUE, then pure space is allocated.
160: */
161: get_more_space(type_struct,purep)
162: struct types *type_struct;
163: {
164: int cntr;
165: char *start;
166: int *loop, *temp;
167: lispval p;
168: extern char holend[];
169:
170: if( (int) datalim >= TTSIZE*LBPG+OFFSET ) return(2);
171:
172: /*
173: * If the hole is defined, then we allocate binary objects
174: * and strings in the hole. However we don't put strings in
175: * the hole if strings are gc'ed.
176: */
177: #ifdef HOLE
178: if( purep
179: #ifndef GCSTRINGS
180: || type_struct==&strng_str
181: #endif
182: || type_struct==&funct_str)
183: start = gethspace(LBPG,type_struct->type);
184: else
185: #endif
186: start = xsbrk(1); /* get new page */
187:
188:
189: SETTYPE(start, type_struct->type,20); /* set type of page */
190:
191: purepage[ATOX(start)] = (char)purep; /* remember if page was pure*/
192:
193: /* bump the page counter for this space if not pure */
194:
195: if(!purep) ++((*(type_struct->pages))->i);
196:
197: type_struct->space_left = type_struct->space;
198: temp = loop = (int *) start;
199: for(cntr=1; cntr < type_struct->space; cntr++)
200: loop = (int *) (*loop = (int) (loop + type_struct->type_len));
201:
202: /* attach new cells to either the pure space free list or the
203: * standard free list
204: */
205: if(purep) {
206: *loop = (int) (type_struct->next_pure_free);
207: type_struct->next_pure_free = (char *) temp;
208: }
209: else {
210: *loop = (int) (type_struct->next_free);
211: type_struct->next_free = (char *) temp;
212: }
213:
214: /* if type atom, set pnames to CNIL */
215:
216: if( type_struct == &atom_str )
217: for(cntr=0, p=(lispval) temp; cntr<atom_str.space; ++cntr)
218: {
219: p->a.pname = (char *) CNIL;
220: p = (lispval) ((int *)p + atom_str.type_len);
221: }
222: return(0); /* space was available */
223: }
224:
225:
226: /*
227: * next_one(type_struct)
228: *
229: * Allocates one new item of each kind of space, except STRNG.
230: * If there is no space, calls gc, the garbage collector.
231: * If there is still no space, allocates a new page using
232: * get_more_space
233: */
234:
235: lispval
236: next_one(type_struct)
237: struct types *type_struct;
238: {
239:
240: register char *temp;
241:
242: while(type_struct->next_free == (char *) CNIL)
243: {
244: int g;
245:
246: if(
247: (initflag == FALSE) && /* dont gc during init */
248: #ifndef GCSTRINGS
249: (type_struct->type != STRNG) && /* can't collect strings */
250: #else
251: gcstrings && /* user (sstatus gcstrings) */
252: #endif
253: (type_struct->type != BCD) && /* nor function headers */
254: gcdis->a.clb == nil ) /* gc not disabled */
255: /* not to collect during load */
256:
257: {
258: gc(type_struct); /* collect */
259: }
260:
261: if( type_struct->next_free != (char *) CNIL ) break;
262:
263: if(! (g=get_more_space(type_struct,FALSE))) break;
264:
265: space_warn(g);
266: }
267: temp = type_struct->next_free;
268: type_struct->next_free = * (char **)(type_struct->next_free);
269: (*(type_struct->items))->i ++;
270: return((lispval) temp);
271: }
272: /*
273: * Warn about exhaustion of space,
274: * shared with next_pure_free().
275: */
276: space_warn(g)
277: {
278: if( g==1 ) {
279: plimit->i += NUMSPACES; /* allow a few more pages */
280: copval(plima,plimit); /* restore to reserved reg */
281:
282: error("PAGE LIMIT EXCEEDED--EMERGENCY PAGES ALLOCATED", TRUE);
283: } else error("SORRY, ABSOLUTE PAGE LIMIT HAS BEEN REACHED", TRUE);
284: }
285:
286:
287: /* allocate an element of a pure structure. Pure structures will
288: * be ignored by the garbage collector.
289: */
290: lispval
291: next_pure_one(type_struct)
292: struct types *type_struct;
293: {
294:
295: register char *temp;
296:
297: while(type_struct->next_pure_free == (char *) CNIL)
298: {
299: int g;
300: if(! (g=get_more_space(type_struct,TRUE))) break;
301: space_warn(g);
302: }
303:
304: temp = type_struct->next_pure_free;
305: type_struct->next_pure_free = * (char **)(type_struct->next_pure_free);
306: return((lispval) temp);
307: }
308:
309: lispval
310: newint()
311: {
312: return(next_one(&int_str));
313: }
314:
315: lispval
316: pnewint()
317: {
318: return(next_pure_one(&int_str));
319: }
320:
321: lispval
322: newdot()
323: {
324: lispval temp;
325:
326: temp = next_one(&dtpr_str);
327: temp->d.car = temp->d.cdr = nil;
328: return(temp);
329: }
330:
331: lispval
332: pnewdot()
333: {
334: lispval temp;
335:
336: temp = next_pure_one(&dtpr_str);
337: temp->d.car = temp->d.cdr = nil;
338: return(temp);
339: }
340:
341: lispval
342: newdoub()
343: {
344: return(next_one(&doub_str));
345: }
346:
347: lispval
348: pnewdb()
349: {
350: return(next_pure_one(&doub_str));
351: }
352:
353: lispval
354: newsdot()
355: {
356: register lispval temp;
357: temp = next_one(&sdot_str);
358: temp->d.car = temp->d.cdr = 0;
359: return(temp);
360: }
361:
362: lispval
363: pnewsdot()
364: {
365: register lispval temp;
366: temp = next_pure_one(&sdot_str);
367: temp->d.car = temp->d.cdr = 0;
368: return(temp);
369: }
370:
371: struct atom *
372: newatom(pure) {
373: struct atom *save; char *mypname;
374:
375: mypname = newstr(pure);
376: pnameprot = ((lispval) mypname);
377: save = (struct atom *) next_one(&atom_str) ;
378: save->plist = save->fnbnd = nil;
379: save->hshlnk = (struct atom *)CNIL;
380: save->clb = CNIL;
381: save->pname = mypname;
382: return (save);
383: }
384:
385: char *
386: newstr(purep) {
387: char *save, *strcpy();
388: int atmlen;
389: register struct str_x *p = str_current + purep;
390:
391: atmlen = strlen(strbuf)+1;
392: if(atmlen > p->space_left) {
393: if(atmlen >= STRBLEN) {
394: save = (char *)csegment(OTHER, atmlen, purep);
395: SETTYPE(save,STRNG,40);
396: purepage[ATOX(save)] = (char)purep;
397: strcpy(save,strbuf);
398: return(save);
399: }
400: p->next_free = (char *) (purep ?
401: next_pure_one(&strng_str) : next_one(&strng_str)) ;
402: p->space_left = LBPG;
403: }
404: strcpy((save = p->next_free), strbuf);
405: /*while(atmlen & 3) ++atmlen; /* even up length of string */
406: p->next_free += atmlen;
407: p->space_left -= atmlen;
408: return(save);
409: }
410:
411: static char * Iinewstr(s,purep) char *s;
412: {
413: int len = strlen(s);
414: while(len > (endstrb - strbuf - 1)) atomtoolong(strbuf);
415: strcpy(strbuf,s);
416: return(newstr(purep));
417: }
418:
419:
420: char *inewstr(s) char *s;
421: {
422: Iinewstr(s,0);
423: }
424:
425: char *pinewstr(s) char *s;
426: {
427: Iinewstr(s,1);
428: }
429:
430: lispval
431: newarray()
432: {
433: register lispval temp;
434:
435: temp = next_one(&array_str);
436: temp->ar.data = (char *)nil;
437: temp->ar.accfun = nil;
438: temp->ar.aux = nil;
439: temp->ar.length = SMALL(0);
440: temp->ar.delta = SMALL(0);
441: return(temp);
442: }
443:
444: lispval
445: newfunct()
446: {
447: register lispval temp;
448: lispval Badcall();
449: temp = next_one(&funct_str);
450: temp->bcd.start = Badcall;
451: temp->bcd.discipline = nil;
452: return(temp);
453: }
454:
455: lispval
456: newval()
457: {
458: register lispval temp;
459: temp = next_one(&val_str);
460: temp->l = nil;
461: return(temp);
462: }
463:
464: lispval
465: pnewval()
466: {
467: register lispval temp;
468: temp = next_pure_one(&val_str);
469: temp->l = nil;
470: return(temp);
471: }
472:
473: lispval
474: newhunk(hunknum)
475: int hunknum;
476: {
477: register lispval temp;
478:
479: temp = next_one(&hunk_str[hunknum]); /* Get a hunk */
480: return(temp);
481: }
482:
483: lispval
484: pnewhunk(hunknum)
485: int hunknum;
486: {
487: register lispval temp;
488:
489: temp = next_pure_one(&hunk_str[hunknum]); /* Get a hunk */
490: return(temp);
491: }
492:
493: lispval
494: inewval(arg) lispval arg;
495: {
496: lispval temp;
497: temp = next_one(&val_str);
498: temp->l = arg;
499: return(temp);
500: }
501:
502: /*
503: * Vector allocators.
504: * a vector looks like:
505: * longword: N = size in bytes
506: * longword: pointer to lisp object, this is the vector property field
507: * N consecutive bytes
508: *
509: */
510: lispval getvec();
511:
512: lispval
513: newvec(size)
514: {
515: return(getvec(size,&vect_str,FALSE));
516: }
517:
518: lispval
519: pnewvec(size)
520: {
521: return(getvec(size,&vect_str,TRUE));
522: }
523:
524: lispval
525: nveci(size)
526: {
527: return(getvec(size,&vecti_str,FALSE));
528: }
529:
530: lispval
531: pnveci(size)
532: {
533: return(getvec(size,&vecti_str,TRUE));
534: }
535:
536: /*
537: * getvec
538: * get a vector of size byte, from type structure typestr and
539: * get it from pure space if purep is TRUE.
540: * vectors are stored linked through their property field. Thus
541: * when the code here refers to v.vector[0], it is the prop field
542: * and vl.vectorl[-1] is the size field. In other code,
543: * v.vector[-1] is the prop field, and vl.vectorl[-2] is the size.
544: */
545: lispval
546: getvec(size,typestr,purep)
547: register struct types *typestr;
548: {
549: register lispval back, current;
550: int sizewant, bytes, thissize, pages, pindex, triedgc = FALSE;
551:
552: /* we have to round up to a multiple of 4 bytes to determine the
553: * size of vector we want. The rounding up assures that the
554: * property pointers are longword aligned
555: */
556: sizewant = VecTotSize(size);
557: if(debugin) fprintf(stderr,"want vect %db\n",size);
558: again:
559: if(purep)
560: back = (lispval) &(typestr->next_pure_free);
561: else
562: back = (lispval) &(typestr->next_free);
563: current = back->v.vector[0];
564: while(current != CNIL)
565: {
566: if(debugin)
567: fprintf(stderr,"next free size %db; ", current->vl.vectorl[-1]);
568: if ((thissize = VecTotSize(current->vl.vectorl[-1])) == sizewant)
569: {
570: if(debugin) fprintf(stderr,"exact match of size %d at 0x%x\n",
571: 4*thissize, ¤t->v.vector[1]);
572: back->v.vector[0]
573: = current->v.vector[0];/* change free pointer*/
574: current->v.vector[0] = nil; /* put nil in property */
575: /* to the user, vector begins one after property*/
576: return((lispval)¤t->v.vector[1]);
577: }
578: else if (thissize >= sizewant + 3)
579: {
580: /* the reason that there is a `+ 3' instead of `+ 2'
581: * is that we don't want to leave a zero sized vector which
582: * isn't guaranteed to be followed by another vector
583: */
584: if(debugin)
585: fprintf(stderr,"breaking a %d vector into a ",
586: current->vl.vectorl[-1]);
587:
588: current->v.vector[1+sizewant+1]
589: = current->v.vector[0]; /* free list pointer */
590: current->vl.vectorl[1+sizewant]
591: = VecTotToByte(thissize - sizewant - 2);/*size info */
592: back->v.vector[0] = (lispval) &(current->v.vector[1+sizewant+1]);
593: current->vl.vectorl[-1] = size;
594:
595: if(debugin)fprintf(stderr," %d one and a %d one\n",
596: current->vl.vectorl[-1],current->vl.vectorl[1+sizewant]);
597: current->v.vector[0] = nil; /* put nil in property */
598: /* vector begins one after the property */
599: if(debugin) fprintf(stderr," and returning vector at 0x%x\n",
600: ¤t->v.vector[1]);
601: return((lispval)(¤t->v.vector[1]));
602: }
603: back = current;
604: current = current->v.vector[0];
605: }
606: if(!triedgc
607: && !purep
608: && (gcdis->a.clb == nil)
609: && (initflag == FALSE))
610: {
611: gc(typestr);
612: triedgc = TRUE;
613: goto again;
614: }
615:
616: /* set bytes to size needed for this vector */
617: bytes = size + 2*sizeof(long);
618:
619: /* must make sure that if the vector we are allocating doesnt
620: completely fill a page, there is room for another vector to record
621: the size left over */
622: if((bytes & (LBPG - 1)) > (LBPG - 2*sizeof(long))) bytes += LBPG;
623: bytes = roundup(bytes,LBPG);
624:
625: current = csegment(typestr->type,bytes/sizeof(long),purep);
626: current->vl.vectorl[0] = bytes - 2*sizeof(long);
627:
628: if(purep) {
629: current->v.vector[1] = (lispval)(typestr->next_pure_free);
630: typestr->next_pure_free = (char *) &(current->v.vector[1]);
631: /* make them pure */
632: pages = bytes/LBPG;
633: for(pindex = ATOX(current); pages ; pages--)
634: {
635: purepage[pindex++] = TRUE;
636: }
637: } else {
638: current->v.vector[1] = (lispval)(typestr->next_free);
639: typestr->next_free = (char *) &(current->v.vector[1]);
640: if(debugin) fprintf(stderr,"grabbed %d vec pages\n",bytes/LBPG);
641: }
642: if(debugin)
643: fprintf(stderr,"creating a new vec, size %d\n",current->v.vector[0]);
644: goto again;
645: }
646:
647: /*
648: * Ipurep :: routine to check for pureness of a data item
649: *
650: */
651: lispval
652: Ipurep(element)
653: lispval element;
654: {
655: if(purepage[ATOX(element)]) return(tatom) ; else return(nil);
656: }
657:
658: /* routines to return space to the free list. These are used by the
659: * arithmetic routines which tend to create large intermediate results
660: * which are know to be garbage after the calculation is over.
661: *
662: * There are jsb callable versions of these routines in qfuncl.s
663: */
664:
665: /* pruneb - prune bignum. A bignum is an sdot followed by a list of
666: * dtprs. The dtpr list is linked by car instead of cdr so when we
667: * put it in the free list, we have to change the links.
668: */
669: pruneb(bignum)
670: lispval bignum;
671: {
672: register lispval temp = bignum;
673:
674: if(TYPE(temp) != SDOT)
675: errorh(Vermisc,"value to pruneb not a sdot",nil,FALSE,0);
676:
677: --(sdot_items->i);
678: temp->s.I = (int) sdot_str.next_free;
679: sdot_str.next_free = (char *) temp;
680:
681: /* bignums are not terminated by nil on the dual,
682: they are terminated by (lispval) 0 */
683:
684: while(temp = temp->s.CDR)
685: {
686: if(TYPE(temp) != DTPR)
687: errorh(Vermisc,"value to pruneb not a list",
688: nil,FALSE,0);
689: --(dtpr_items->i);
690: temp->s.I = (int) dtpr_str.next_free;
691: dtpr_str.next_free = (char *) temp;
692: }
693: }
694: lispval
695: Badcall()
696: { error("BAD FUNCTION DESCRIPTOR USED IN CALL",FALSE); }
697:
698:
699:
700: /*
701: * Ngc
702: * this is the lisp function gc
703: *
704: */
705:
706: lispval
707: Ngc()
708: {
709: return(gc((struct types *)CNIL));
710: }
711:
712: /*
713: * gc(type_struct)
714: *
715: * garbage collector: Collects garbage by mark and sweep algorithm.
716: * After this is done, calls the Nlambda, gcafter.
717: * gc may also be called from LISP, as an nlambda of no arguments.
718: * type_struct is the type of lisp data that ran out causing this
719: * garbage collection
720: */
721: int printall = 0;
722: lispval
723: gc(type_struct)
724: struct types *type_struct;
725: {
726: lispval save;
727: struct tms begin, finish;
728: extern int gctime;
729:
730: /* if this was called automatically when space ran out
731: * print out a message
732: */
733: if((Vgcprint->a.clb != nil)
734: && (type_struct != (struct types *) CNIL ))
735: {
736: FILE *port = okport(Vpoport->a.clb,poport);
737: fprintf(port,"gc:");
738: fflush(port);
739: }
740:
741: if(gctime) times(&begin);
742:
743: gc1(); /* mark&sweep */
744:
745: /* Now we call gcafter--special c ase if gc called from LISP */
746:
747: if( type_struct == (struct types *) CNIL )
748: gccall1->d.cdr = nil; /* make the call "(gcafter)" */
749: else
750: {
751: gccall1->d.cdr = gccall2;
752: gccall2->d.car = *(type_struct->type_name);
753: }
754: PUSHDOWN(gcdis,gcdis); /* flag to indicate in garbage collector */
755: save = eval(gccall1); /* call gcafter */
756: POP; /* turn off flag */
757:
758: if(gctime) {
759: times(&finish);
760: gctime += (finish.tms_utime - begin.tms_utime);
761: }
762: return(save); /* return result of gcafter */
763: }
764:
765:
766:
767: /* gc1() **************************************************************/
768: /* */
769: /* Mark-and-sweep phase */
770:
771: gc1()
772: {
773: int j, k;
774: register int *start,bvalue,type_len;
775: register struct types *s;
776: int *point,i,freecnt,itemstogo,bits,bindex,type,bytestoclear;
777: int usedcnt;
778: char *pindex;
779: struct argent *loop2;
780: struct nament *loop3;
781: struct atom *symb;
782: int markdp();
783: extern int hashtop;
784:
785: pagerand();
786: /* decide whether to check LISP structure or not */
787:
788:
789: #ifdef METER
790: vtimes(&premark,0);
791: mrkdpcnt = 0;
792: conssame = consdiff = consnil = 0;
793: #endif
794:
795: /* first set all bit maps to zero */
796:
797:
798: #ifdef SLOCLEAR
799: {
800: int enddat;
801: enddat = (int)(datalim-OFFSET) >> 8;
802: for(bvalue=0; bvalue < (int)enddat ; ++bvalue)
803: {
804: qbitmap[bvalue] = zeroq;
805: }
806: }
807: #endif
808:
809: /* try the movc5 to clear the bit maps */
810: /* the maximum number of bytes we can clear in one sweep is
811: * 2^16 (or 1<<16 in the C lingo)
812: */
813: bytestoclear = ((((int)datalim)-((int)beginsweep)) >> 9) * 16;
814: for(start = bitmapi + ATOLX(beginsweep);
815: bytestoclear > 0;)
816: {
817: if(bytestoclear > MAXCLEAR)
818: blzero((int)start,MAXCLEAR);
819: else
820: blzero((int)start,bytestoclear);
821: start = (int *) (MAXCLEAR + (int) start);
822: bytestoclear -= MAXCLEAR;
823: }
824:
825: /* mark all atoms in the oblist */
826: for( bvalue=0 ; bvalue <= hashtop-1 ; bvalue++ ) /* though oblist */
827: {
828: for( symb = hasht[bvalue] ; symb != (struct atom *) CNIL ;
829: symb = symb-> hshlnk) {
830: markdp((lispval)symb);
831: }
832: }
833:
834:
835: /* Mark all the atoms and ints associated with the hunk
836: data types */
837:
838: for(i=0; i<7; i++) {
839: markdp(hunk_items[i]);
840: markdp(hunk_name[i]);
841: markdp(hunk_pages[i]);
842: }
843: /* next run up the name stack */
844: for(loop2 = np - 1; loop2 >= orgnp; --loop2) MARKVAL(loop2->val);
845:
846: /* now the bindstack (vals only, atoms are marked elsewhere ) */
847: for(loop3 = bnp - 1; loop3 >= orgbnp; --loop3)MARKVAL(loop3->val);
848:
849:
850: /* next mark all compiler linked data */
851: /* if the Vpurcopylits switch is non nil (lisp variable $purcopylits)
852: * then when compiled code is read in, it tables will not be linked
853: * into this table and thus will not be marked here. That is ok
854: * though, since that data is assumed to be pure.
855: */
856: point = bind_lists;
857: while((start = point) != (int *)CNIL) {
858: while( *start != -1 )
859: {
860: markdp((lispval)*start);
861: start++;
862: }
863: point = (int *)*(point-1);
864: }
865:
866: /* next mark all system-significant lisp data */
867:
868:
869: for(i=0; i<SIGNIF; ++i) markdp((lispsys[i]));
870:
871: #ifdef METER
872: vtimes(&presweep,0);
873: #endif
874: /* all accessible data has now been marked. */
875: /* all collectable spaces must be swept, */
876: /* and freelists constructed. */
877:
878: /* first clear the structure elements for types
879: * we will sweep
880: */
881:
882: for(k=0 ; k <= VECTORI ; k++)
883: {
884: if( s=gcableptr[k]) {
885: if(k==STRNG && !gcstrings) { /* don't do anything*/ }
886: else
887: {
888: (*(s->items))->i = 0;
889: s->space_left = 0;
890: s->next_free = (char *) CNIL;
891: }
892: }
893: }
894: #if m_68k
895: fixbits(bitmapi+ATOLX(beginsweep),bitmapi+ATOLX(datalim));
896: #endif
897:
898:
899: /* sweep up in memory looking at gcable pages */
900:
901: for(start = beginsweep, bindex = ATOLX(start),
902: pindex = &purepage[ATOX(start)];
903: start < (int *)datalim;
904: start += 128, pindex++)
905: {
906: if(!(s=gcableptr[type = TYPE(start)]) || *pindex
907: #ifdef GCSTRINGS
908: || (type==STRNG && !gcstrings)
909: #endif
910: )
911: {
912: /* ignore this page but advance pointer */
913: bindex += 4; /* and 4 words of 32 bit bitmap words */
914: continue;
915: }
916:
917: freecnt = 0; /* number of free items found */
918: usedcnt = 0; /* number of used items found */
919:
920: point = start;
921: /* sweep dtprs as a special case, since
922: * 1) there will (usually) be more dtpr pages than any other type
923: * 2) most dtpr pages will be empty so we can really win by special
924: * caseing the sweeping of massive numbers of free cells
925: */
926: /* since sdot's have the same structure as dtprs, this code will
927: work for them too
928: */
929: if((type == DTPR) || (type == SDOT))
930: {
931: int *head,*lim;
932: head = (int *) s->next_free; /* first value on free list*/
933:
934: for(i=0; i < 4; i++) /* 4 bit map words per page */
935: {
936: bvalue = bitmapi[bindex++]; /* 32 bits = 16 dtprs */
937: if(bvalue == 0) /* if all are free */
938: {
939: *point = (int)head;
940: lim = point + 32; /* 16 dtprs = 32 ints */
941: for(point += 2; point < lim ; point += 2)
942: {
943: *point = (int)(point - 2);
944: }
945: head = point - 2;
946: freecnt += 16;
947: }
948: else for(j = 0; j < 16 ; j++)
949: {
950: if(!(bvalue & 1))
951: {
952: freecnt++;
953: *point = (int)head;
954: head = point;
955: }
956: #ifdef METER
957: /* check if the page address of this cell is the
958: * same as the address of its cdr
959: */
960: else if(FALSE && gcstat && (type == DTPR))
961: {
962: if(((int)point & ~511)
963: == ((int)(*point) & ~511)) conssame++;
964: else consdiff++;
965: usedcnt++;
966: }
967: #endif
968: else usedcnt++; /* keep track of used */
969:
970: point += 2;
971: bvalue = bvalue >> 2;
972: }
973: }
974: s->next_free = (char *) head;
975: }
976: else if((type == VECTOR) || (type == VECTORI))
977: {
978: int canjoin = FALSE;
979: int *tempp;
980:
981: /* check if first item on freelist ends exactly at
982: this page
983: */
984: if(((tempp = (int *)s->next_free) != (int *)CNIL)
985: && ((VecTotSize(((lispval)tempp)->vl.vectorl[-1])
986: + 1 + tempp)
987: == point))
988: canjoin = TRUE;
989:
990: /* arbitrary sized vector sweeper */
991: /*
992: * jump past first word since that is a size fixnum
993: * and second word since that is property word
994: */
995: if(debugin)
996: fprintf(stderr,"vector sweeping, start at 0x%x\n",
997: point);
998: bits = 30;
999: bvalue = bitmapi[bindex++] >> 2;
1000: point += 2;
1001: while (TRUE) {
1002: type_len = point[VSizeOff];
1003: if(debugin) {
1004: fprintf(stderr,"point: 0x%x, type_len %d\n",
1005: point, type_len);
1006: fprintf(stderr,"bvalue: 0x%x, bits: %d, bindex: 0x%x\n",
1007: bvalue, bits, bindex);
1008: }
1009: /* get size of vector */
1010: if(!(bvalue & 1)) /* if free */
1011: {
1012: if(debugin) fprintf(stderr,"free\n");
1013: freecnt += type_len + 2*sizeof(long);
1014: if(canjoin)
1015: {
1016: /* join by adjusting size of first vector */
1017: ((lispval)(s->next_free))->vl.vectorl[-1]
1018: += type_len + 2*sizeof(long);
1019: if(debugin)
1020: fprintf(stderr,"joined size: %d\n",
1021: ((lispval)(s->next_free))->vl.vectorl[-1]);
1022: }
1023: else {
1024: /* vectors are linked at the property word */
1025: *(point - 1) = (int)(s->next_free);
1026: s->next_free = (char *) (point - 1);
1027: }
1028: canjoin = TRUE;
1029: }
1030: else {
1031: canjoin = FALSE;
1032: usedcnt += type_len + 2*sizeof(long);
1033: }
1034:
1035: point += VecTotSize(type_len);
1036: /* we stop sweeping only when we reach a page
1037: boundary since vectors can span pages
1038: */
1039: if(((int)point & 511) == 0)
1040: {
1041: /* reset the counters, we cannot predict how
1042: * many pages we have crossed over
1043: */
1044: bindex = ATOLX(point);
1045: /* these will be inced, so we must dec */
1046: pindex = &purepage[ATOX(point)] - 1;
1047: start = point - 128;
1048: if(debugin)
1049: fprintf(stderr,
1050: "out of vector sweep when point = 0x%x\n",
1051: point);
1052: break;
1053: }
1054: /* must advance to next point and next value in bitmap.
1055: * we add VecTotSize(type_len) + 2 to get us to the 0th
1056: * entry in the next vector (beyond the size fixnum)
1057: */
1058: point += 2; /* point to next 0th entry */
1059: if ( (bits -= (VecTotSize(type_len) + 2)) > 0)
1060: bvalue = bvalue >> (VecTotSize(type_len) + 2);
1061: else {
1062: bits = -bits; /* must advance to next word in map */
1063: bindex += bits / 32; /* this is tricky stuff... */
1064: bits = bits % 32;
1065: bvalue = bitmapi[bindex++] >> bits;
1066: bits = 32 - bits;
1067: }
1068: }
1069: }
1070: else {
1071: /* general sweeper, will work for all types */
1072: itemstogo = s->space; /* number of items per page */
1073: bits = 32; /* number of bits per word */
1074: type_len = s->type_len;
1075:
1076: /* printf(" s %d, itemstogo %d, len %d\n",s,itemstogo,type_len);*/
1077: bvalue = bitmapi[bindex++];
1078:
1079: while(TRUE)
1080: {
1081: if(!(bvalue & 1)) /* if data element is not marked */
1082: {
1083: freecnt++;
1084: *point = (int) (s->next_free) ;
1085: s->next_free = (char *) point;
1086: }
1087: else usedcnt++;
1088:
1089: if( --itemstogo <= 0 )
1090: { if(type_len >= 64)
1091: {
1092: bindex++;
1093: if(type_len >=128) bindex += 2;
1094: }
1095: break;
1096: }
1097:
1098: point += type_len;
1099: /* shift over mask by number of words in data type */
1100:
1101: if( (bits -= type_len) > 0)
1102: { bvalue = bvalue >> type_len;
1103: }
1104: else if( bits == 0 )
1105: { bvalue = bitmapi[bindex++];
1106: bits = 32;
1107: }
1108: else
1109: { bits = -bits;
1110: while( bits >= 32) { bindex++;
1111: bits -= 32;
1112: }
1113: bvalue = bitmapi[bindex++];
1114: bvalue = bvalue >> bits;
1115: bits = 32 - bits;;
1116: }
1117: }
1118: }
1119:
1120: s->space_left += freecnt;
1121: (*(s->items))->i += usedcnt;
1122: }
1123:
1124: #ifdef METER
1125: vtimes(&alldone,0);
1126: if(gcstat) gcdump();
1127: #endif
1128: pagenorm();
1129: }
1130:
1131: /*
1132: * alloc
1133: *
1134: * This routine tries to allocate one or more pages of the space named
1135: * by the first argument. Returns the number of pages actually allocated.
1136: *
1137: */
1138:
1139: lispval
1140: alloc(tname,npages)
1141: lispval tname; long npages;
1142: {
1143: long ii, jj;
1144: struct types *typeptr;
1145:
1146: ii = typenum(tname);
1147: typeptr = spaces[ii];
1148: if(npages <= 0) return(inewint(npages));
1149:
1150: if((ATOX(datalim)) + npages > TTSIZE)
1151: error("Space request would exceed maximum memory allocation",FALSE);
1152: if((ii == VECTOR) || (ii == VECTORI))
1153: {
1154: /* allocate in one big chunk */
1155: tname = csegment((int) ii,(int) npages*128,0);
1156: tname->vl.vectorl[0] = (npages*512 - 2*sizeof(long));
1157: tname->v.vector[1] = (lispval) typeptr->next_free;
1158: typeptr->next_free = (char *) &(tname->v.vector[1]);
1159: if(debugin) fprintf(stderr,"alloced %d vec pages\n",npages);
1160: return(inewint(npages));
1161: }
1162:
1163: for( jj=0; jj<npages; ++jj)
1164: if(get_more_space(spaces[ii],FALSE)) break;
1165: return(inewint(jj));
1166: }
1167:
1168: /*
1169: * csegment(typecode,nitems,useholeflag)
1170: * allocate nitems of type typecode. If useholeflag is true, then
1171: * allocate in the hole if there is room. This routine doesn't look
1172: * in the free lists, it always allocates space.
1173: */
1174: lispval
1175: csegment(typecode,nitems,useholeflag)
1176: {
1177: register int ii, jj;
1178: register char *charadd;
1179:
1180: ii = typecode;
1181:
1182: if(ii!=OTHER) nitems *= 4*spaces[ii]->type_len;
1183: nitems = roundup(nitems,512); /* round up to right length */
1184: #ifdef HOLE
1185: if(useholeflag)
1186: charadd = gethspace(nitems,ii);
1187: else
1188: #endif
1189: {
1190: charadd = sbrk(nitems);
1191: datalim = (lispval)(charadd+nitems);
1192: }
1193: if( (int) charadd <= 0 )
1194: error("NOT ENOUGH SPACE FOR ARRAY",FALSE);
1195: /*if(ii!=OTHER)*/ (*spaces[ii]->pages)->i += nitems/512;
1196: if(ATOX(datalim) > fakettsize) {
1197: datalim = (lispval) (OFFSET + (fakettsize << 9));
1198: if(fakettsize >= TTSIZE)
1199: {
1200: printf("There isn't room enough to continue, goodbye\n");
1201: franzexit(1);
1202: }
1203: fakettsize++;
1204: badmem(53);
1205: }
1206: for(jj=0; jj<nitems; jj=jj+512) {
1207: SETTYPE(charadd+jj, ii,30);
1208: }
1209: ii = (int) charadd;
1210: while(nitems > MAXCLEAR)
1211: {
1212: blzero(ii,MAXCLEAR);
1213: nitems -= MAXCLEAR;
1214: ii += MAXCLEAR;
1215: }
1216: blzero(ii,nitems);
1217: return((lispval)charadd);
1218: }
1219:
1220: int csizeof(tname) lispval tname;
1221: {
1222: return( spaces[typenum(tname)]->type_len * 4 );
1223: }
1224:
1225: int typenum(tname) lispval tname;
1226: {
1227: int ii;
1228:
1229: chek: for(ii=0; ii<NUMSPACES; ++ii)
1230: if(spaces[ii] && tname == *(spaces[ii]->type_name)) break;
1231: if(ii == NUMSPACES)
1232: {
1233: tname = error("BAD TYPE NAME",TRUE);
1234: goto chek;
1235: }
1236:
1237: return(ii);
1238:
1239: }
1240: char *
1241: gethspace(segsiz,type)
1242: {
1243: extern usehole; extern char holend[]; extern char *curhbeg;
1244: register char *value;
1245:
1246: if(usehole) {
1247: curhbeg = (char *) roundup(((int)curhbeg),LBPG);
1248: if((holend - curhbeg) < segsiz)
1249: {
1250: usehole = FALSE;
1251: curhbeg = holend;
1252: } else {
1253: value = curhbeg;
1254: curhbeg = curhbeg + segsiz;
1255: /*printf("start %d, finish %d, size %d\n",value, curhbeg,segsiz);*/
1256: return(value);
1257: }
1258: }
1259: value = (ysbrk(segsiz/LBPG,type));
1260: datalim = (lispval)(value + segsiz);
1261: return(value);
1262: }
1263: gcrebear()
1264: {
1265: #ifdef HOLE
1266: register int i; register struct types *p;
1267:
1268: /* this gets done upon rebirth */
1269: str_current[1].space_left = 0;
1270: #ifndef GCSTRINGS
1271: str_current[0].space_left = 0; /* both kinds of strings go in hole*/
1272: #endif
1273: funct_str.space_left = 0;
1274: funct_str.next_free = (char *) CNIL;
1275: /* clear pure space pointers */
1276: for(i = 0; i < NUMSPACES; i++)
1277: {
1278: if(p=spaces[i])
1279: p->next_pure_free = (char *) CNIL;
1280: }
1281: #endif
1282: }
1283:
1284: /** markit(p) ***********************************************************/
1285: /* just calls markdp */
1286:
1287: markit(p) lispval *p; { markdp(*p); }
1288:
1289: /*
1290: * markdp(p)
1291: *
1292: * markdp is the routine which marks each data item. If it is a
1293: * dotted pair, the car and cdr are marked also.
1294: * An iterative method is used to mark list structure, to avoid
1295: * excessive recursion.
1296: */
1297: markdp(p) register lispval p;
1298: {
1299: #ifdef tahoe
1300: register int r, s; /* (goes with non-asm readbit, oksetbit) */
1301: #endif
1302: /* register hsize, hcntr; */
1303: int hsize, hcntr;
1304:
1305: #ifdef METER
1306: mrkdpcnt++;
1307: #endif
1308: ptr_loop:
1309: if(((int)p) <= ((int)nil)) return; /* do not mark special data types or nil=0 */
1310:
1311:
1312: switch( TYPE(p) )
1313: {
1314: case ATOM:
1315: ftstbit;
1316: MARKVAL(p->a.clb);
1317: MARKVAL(p->a.plist);
1318: MARKVAL(p->a.fnbnd);
1319: #ifdef GCSTRINGS
1320: if(gcstrings) MARKVAL(((lispval)p->a.pname));
1321: return;
1322:
1323: case STRNG:
1324: p = (lispval) (((int) p) & ~ (LBPG-1));
1325: ftstbit;
1326: #endif
1327: return;
1328:
1329: case INT:
1330: case DOUB:
1331: ftstbit;
1332: return;
1333: case VALUE:
1334: ftstbit;
1335: p = p->l;
1336: goto ptr_loop;
1337: case DTPR:
1338: ftstbit;
1339: MARKVAL(p->d.car);
1340: #ifdef METER
1341: /* if we are metering , then check if the cdr is
1342: * nil, or if the cdr is on the same page, and if
1343: * it isn't one of those, then it is on a different
1344: * page
1345: */
1346: if(gcstat)
1347: {
1348: if(p->d.cdr == nil) consnil++;
1349: else if(((int)p & ~511)
1350: == (((int)(p->d.cdr)) & ~511))
1351: conssame++;
1352: else consdiff++;
1353: }
1354: #endif
1355: p = p->d.cdr;
1356: goto ptr_loop;
1357:
1358: case ARRAY:
1359: ftstbit; /* mark array itself */
1360:
1361: MARKVAL(p->ar.accfun); /* mark access function */
1362: MARKVAL(p->ar.aux); /* mark aux data */
1363: MARKVAL(p->ar.length); /* mark length */
1364: MARKVAL(p->ar.delta); /* mark delta */
1365: if(TYPE(p->ar.aux)==DTPR && p->ar.aux->d.car==Vnogbar)
1366: {
1367: /* a non garbage collected array must have its
1368: * array space marked but the value of the array
1369: * space is not marked
1370: */
1371: int l;
1372: int cnt,d;
1373: if(debugin) {
1374: printf("mark array holders len %d, del %d, start 0x%x\n",
1375: p->ar.length->i,p->ar.delta->i,p->ar.data);
1376: fflush(stdout);
1377: }
1378: l = p->ar.length->i; /* number of elements */
1379: d = p->ar.delta->i; /* bytes per element */
1380: p = (lispval) p->ar.data;/* address of first one*/
1381: if(purepage[ATOX(p)]) return;
1382:
1383: for((cnt = 0); cnt<l ;
1384: p = (lispval)(((char *) p) + d), cnt++)
1385: {
1386: setbit;
1387: }
1388: } else {
1389: /* register int i, l; int d; */
1390: /* register char *dataptr = p->ar.data; */
1391: int i,l,d;
1392: char *dataptr = p->ar.data;
1393:
1394: for(i=0, l=p->ar.length->i, d=p->ar.delta->i; i<l; ++i)
1395: {
1396: markdp((lispval)dataptr);
1397: dataptr += d;
1398: }
1399: }
1400: return;
1401: case SDOT:
1402: do {
1403: ftstbit;
1404: p = p->s.CDR;
1405: } while (p!=0);
1406: return;
1407:
1408: case BCD:
1409: ftstbit;
1410: markdp(p->bcd.discipline);
1411: return;
1412:
1413: case HUNK2:
1414: case HUNK4:
1415: case HUNK8:
1416: case HUNK16:
1417: case HUNK32:
1418: case HUNK64:
1419: case HUNK128:
1420: {
1421: hsize = 2 << HUNKSIZE(p);
1422: ftstbit;
1423: for (hcntr = 0; hcntr < hsize; hcntr++)
1424: MARKVAL(p->h.hunk[hcntr]);
1425: return;
1426: }
1427:
1428: case VECTORI:
1429: ftstbit;
1430: MARKVAL(p->v.vector[-1]); /* mark property */
1431: return;
1432:
1433: case VECTOR:
1434: {
1435: register int vsize;
1436: ftstbit;
1437: vsize = VecSize(p->vl.vectorl[VSizeOff]);
1438: if(debugin)
1439: fprintf(stderr,"mark vect at %x size %d\n",
1440: p,vsize);
1441: while(--vsize >= -1)
1442: {
1443: MARKVAL(p->v.vector[vsize]);
1444: };
1445: return;
1446: }
1447: }
1448: return;
1449: }
1450:
1451:
1452: /* xsbrk allocates space in large chunks (currently 16 pages)
1453: * xsbrk(1) returns a pointer to a page
1454: * xsbrk(0) returns a pointer to the next page we will allocate (like sbrk(0))
1455: */
1456:
1457: char *
1458: xsbrk(n)
1459: {
1460: static char *xx; /* pointer to next available blank page */
1461: extern int xcycle; /* number of blank pages available */
1462: lispval u; /* used to compute limits of bit table */
1463:
1464: if( (xcycle--) <= 0 )
1465: {
1466: xcycle = 15;
1467: xx = sbrk(16*LBPG); /* get pages 16 at a time */
1468: if( (int)xx== -1 )
1469: lispend("For sbrk from lisp: no space... Goodbye!");
1470: }
1471: else xx += LBPG;
1472:
1473: if(n == 0)
1474: {
1475: xcycle++; /* don't allocate the page */
1476: xx -= LBPG;
1477: return(xx); /* just return its address */
1478: }
1479:
1480: if( (u = (lispval)(xx+LBPG)) > datalim ) datalim = u;
1481: return(xx);
1482: }
1483:
1484: char *ysbrk(pages,type) int pages, type;
1485: {
1486: char *xx; /* will point to block of storage */
1487: int i;
1488:
1489: xx = sbrk(pages*LBPG);
1490: if((int)xx == -1)
1491: error("OUT OF SPACE FOR ARRAY REQUEST",FALSE);
1492:
1493: datalim = (lispval)(xx+pages*LBPG); /* compute bit table limit */
1494:
1495: /* set type for pages */
1496:
1497: for(i = 0; i < pages; ++i) {
1498: SETTYPE((xx + i*LBPG),type,10);
1499: }
1500:
1501: return(xx); /* return pointer to block of storage */
1502: }
1503:
1504: /*
1505: * getatom
1506: * returns either an existing atom with the name specified in strbuf, or
1507: * if the atom does not already exist, regurgitates a new one and
1508: * returns it.
1509: */
1510: lispval
1511: getatom(purep)
1512: { register lispval aptr;
1513: register char *name, *endname;
1514: register int hash;
1515: lispval b;
1516: char c;
1517:
1518: name = strbuf;
1519: if (*name == (char)0377) return (eofa);
1520: hash = hashfcn(name);
1521: atmlen = strlen(name) + 1;
1522: aptr = (lispval) hasht[hash];
1523: while (aptr != CNIL)
1524: /* if (strcmp(name,aptr->a.pname)==0) */
1525: if (*name==*aptr->a.pname && strcmp(name,aptr->a.pname)==0)
1526: return (aptr);
1527: else
1528: aptr = (lispval) aptr->a.hshlnk;
1529: aptr = (lispval) newatom(purep); /*share pname of atoms on oblist*/
1530: aptr->a.hshlnk = hasht[hash];
1531: hasht[hash] = (struct atom *) aptr;
1532: endname = name + atmlen - 2;
1533: if ((atmlen != 4) && (*name == 'c') && (*endname == 'r'))
1534: {
1535: b = newdot();
1536: protect(b);
1537: b->d.car = lambda;
1538: b->d.cdr = newdot();
1539: b = b->d.cdr;
1540: b->d.car = newdot();
1541: (b->d.car)->d.car = xatom;
1542: while(TRUE)
1543: {
1544: b->d.cdr = newdot();
1545: b= b->d.cdr;
1546: if(++name == endname)
1547: {
1548: b->d.car= (lispval) xatom;
1549: aptr->a.fnbnd = (--np)->val;
1550: break;
1551: }
1552: b->d.car= newdot();
1553: b= b->d.car;
1554: if((c = *name) == 'a') b->d.car = cara;
1555: else if (c == 'd') b->d.car = cdra;
1556: else{ --np;
1557: break;
1558: }
1559: }
1560: }
1561:
1562: return(aptr);
1563: }
1564:
1565: /*
1566: * inewatom is like getatom, except that you provide it a string
1567: * to be used as the print name. It doesn't do the automagic
1568: * creation of things of the form c[ad]*r.
1569: */
1570: lispval
1571: inewatom(name)
1572: register char *name;
1573: { register struct atom *aptr;
1574: register int hash;
1575: extern struct types atom_str;
1576: char c;
1577:
1578: if (*name == (char)0377) return (eofa);
1579: hash = hashfcn(name);
1580: aptr = hasht[hash];
1581: while (aptr != (struct atom *)CNIL)
1582: if (strcmp(name,aptr->pname)==0)
1583: return ((lispval) aptr);
1584: else
1585: aptr = aptr->hshlnk;
1586: aptr = (struct atom *) next_one(&atom_str) ;
1587: aptr->plist = aptr->fnbnd = nil;
1588: aptr->clb = CNIL;
1589: aptr->pname = name;
1590: aptr->hshlnk = hasht[hash];
1591: hasht[hash] = aptr;
1592: return((lispval)aptr);
1593: }
1594:
1595:
1596: /* our hash function */
1597:
1598: hashfcn(symb)
1599: register char *symb;
1600: {
1601: register int i;
1602: /* for (i=0 ; *symb ; i += i + *symb++); return(i & (HASHTOP-1)); */
1603: for (i=0 ; *symb ; i += i*2 + *symb++);
1604: return(i&077777 % HASHTOP);
1605: }
1606:
1607: lispval
1608: LImemory()
1609: {
1610: int nextadr, pagesinuse;
1611:
1612: printf("Memory report. max pages = %d (0x%x) = %d Bytes\n",
1613: TTSIZE,TTSIZE,TTSIZE*LBPG);
1614: #ifdef HOLE
1615: printf("This lisp has a hole:\n");
1616: printf(" current hole start: %d (0x%x), end %d (0x%x)\n",
1617: curhbeg, curhbeg, holend, holend);
1618: printf(" hole free: %d bytes = %d pages\n\n",
1619: holend-curhbeg, (holend-curhbeg)/LBPG);
1620: #endif
1621: nextadr = (int) xsbrk(0); /* next space to be allocated */
1622: pagesinuse = nextadr/LBPG;
1623: printf("Next allocation at addr %d (0x%x) = page %d\n",
1624: nextadr, nextadr, pagesinuse);
1625: printf("Free data pages: %d\n", TTSIZE-pagesinuse);
1626: return(nil);
1627: }
1628:
1629: extern struct atom *hasht[HASHTOP];
1630: myhook(){}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.