alloc.c
上传用户:nthfjj
上传日期:2007-01-07
资源大小:37k
文件大小:23k
源码类别:

系统编程

开发平台:

Unix_Linux

  1. /*
  2.  * This file contains the functions:
  3.  * void new_hblk(n)
  4.  * static void clear_marks()
  5.  * tl_mark(p)
  6.  * mark()
  7.  * mark_all(b,t)
  8.  * void gcollect()
  9.  * expand_hp: func[val Short] val Void
  10.  * struct obj * _allocobj(sz)
  11.  * struct obj * _allocaobj(sz)
  12.  *
  13.  * And the global variables:
  14.  * struct obj * objfreelist[MAXOBJSZ+1];
  15.  * struct obj * aobjfreelist[MAXOBJSZ+1];
  16.  * word * mark_stack_bottom;
  17.  * word * mark_stack_top;
  18.  */
  19. # include <stdio.h>
  20. # include <signal.h>
  21. # include <sys/types.h>
  22. # include <sys/times.h>
  23. # include "runtime.h"
  24. /* Leaving these defined enables output to stderr.  In order of */
  25. /* increasing verbosity:                                        */
  26. #define REPORT_FAILURE   /* Print values that looked "almost" like pointers */
  27. #undef REPORT_FAILURE
  28. #define DEBUG            /* Verbose debugging output */
  29. #undef DEBUG
  30. #define DEBUG2           /* EXTREMELY verbose debugging output */
  31. #undef DEBUG2
  32. #define USE_STACK       /* Put mark stack onto process stack.  This assumes */
  33. /* that it's safe to put data below the stack ptr,  */
  34. /* and that the system will expand the stack as     */
  35. /* necessary.  This is known to be true under Sun   */
  36. /* UNIX (tm) and Vax Berkeley UNIX.  It is also     */
  37. /* known to be false under some other UNIX          */
  38. /* implementations.                                 */
  39. #undef USE_HEAP
  40. #ifdef RT
  41. #   define USE_HEAP
  42. #   undef USE_STACK
  43. #endif
  44. #ifdef MIPS
  45. #   define USE_HEAP
  46. #   undef USE_STACK
  47. #endif
  48. /*
  49.  * This is an attempt at a garbage collecting storage allocator
  50.  * on a Motorola 68000 series or an a Vax.  The garbage
  51.  * collector is overly conservative in that it may fail to reclaim
  52.  * inaccessible storage.  On the other hand, it does not assume
  53.  * any runtime tag information.
  54.  * We make the following assumptions:
  55.  *  1.  We are running under something that looks like Berkeley UNIX,
  56.  *      on one of the supported architectures.
  57.  *  2.  For every accessible object, a pointer to it is stored in
  58.  *          a) the stack segment, or
  59.  *          b) the data or bss segment, or
  60.  *          c) the registers, or
  61.  *          d) an accessible block.
  62.  *
  63.  */
  64. /*
  65.  * Separate free lists are maintained for different sized objects
  66.  * up to MAXOBJSZ or MAXAOBJSZ.
  67.  * The lists objfreelist[i] contain free objects of size i which may
  68.  * contain nested pointers.  The lists aobjfreelist[i] contain free
  69.  * atomic objects, which may not contain nested pointers.
  70.  * The call allocobj(i) insures that objfreelist[i] points to a non-empty
  71.  * free list it returns a pointer to the first entry on the free list.
  72.  * Allocobj may be called from C to allocate an object of (small) size i
  73.  * as follows:
  74.  *
  75.  *            opp = &(objfreelist[i]);
  76.  *            if (*opp == (struct obj *)0) allocobj(i);
  77.  *            ptr = *opp;
  78.  *            *opp = ptr->next;
  79.  *
  80.  * Note that this is very fast if the free list is non-empty; it should
  81.  * only involve the execution of 4 or 5 simple instructions.
  82.  * All composite objects on freelists are cleared, except for
  83.  * their first longword.
  84.  */
  85. /*
  86.  *  The allocator uses allochblk to allocate large chunks of objects.
  87.  * These chunks all start on addresses which are multiples of
  88.  * HBLKSZ.  All starting addresses are maintained on a contiguous
  89.  * list so that they can be traversed in the sweep phase of garbage collection.
  90.  * This makes it possible to check quickly whether an
  91.  * arbitrary address corresponds to an object administered by the
  92.  * allocator.
  93.  *  We make the (probably false) claim that this can be interrupted
  94.  * by a signal with at most the loss of some chunk of memory.
  95.  */
  96. /* Declarations for fundamental data structures.  These are grouped */
  97. /* in a single structure, so that the collector can skip over them. */
  98. struct __gc_arrays _gc_arrays;
  99. long heapsize = 0;      /* Heap size in bytes */
  100. long non_gc_bytes = 0;  /* Number of bytes not intended to be collected */
  101. char copyright[] = "Copyright 1988,1989 Hans-J. Boehm and Alan J. Demers";
  102. /* Return a rough approximation to the stack pointer.  A hack,  */
  103. /* but it's semi-portable.                                      */
  104. word * get_current_sp()
  105. {
  106.     word x;
  107.     return(&x);
  108. }
  109. /*
  110.  * Allocate a new heapblock for objects of size n.
  111.  * Add all of the heapblock's objects to the free list for objects
  112.  * of that size.  A negative n requests atomic objects.
  113.  */
  114. void new_hblk(n)
  115. long n;
  116. {
  117.     register word *p,
  118.   *r;
  119.     word *last_object; /* points to last object in new hblk */
  120.     register struct hblk *h; /* the new heap block */
  121.     register long abs_sz; /* |n| */
  122.     register int i;
  123. #   ifdef PRINTSTATS
  124. if ((sizeof (struct hblk)) > HBLKSIZE) {
  125.     abort("HBLK SZ inconsistency");
  126.         }
  127. #   endif
  128.   /* Allocate a new heap block */
  129.     h = allochblk(n);
  130.   /* Add it to hblklist */
  131.     add_hblklist(h);
  132.   /* Add objects to free list */
  133.     abs_sz = abs(n);
  134.     p = &(h -> hb_body[abs_sz]); /* second object in *h */
  135.     r = &(h -> hb_body[0]);        /* One object behind p */
  136.     last_object = ((word *)((char *)h + HBLKSIZE)) - abs_sz;
  137.     /* Last place for last object to start */
  138.   /* make a list of all objects in *h with head as last object */
  139.     while (p <= last_object) {
  140.       /* current object's link points to last object */
  141. ((struct obj *)p) -> obj_link = (struct obj *)r;
  142. r = p;
  143. p += abs_sz;
  144.     }
  145.     p -= abs_sz; /* p now points to last object */
  146.   /*
  147.    * put p (which is now head of list of objects in *h) as first
  148.    * pointer in the appropriate free list for this size.
  149.    */
  150.     if (n < 0) {
  151. ((struct obj *)(h -> hb_body)) -> obj_link = aobjfreelist[abs_sz];
  152. aobjfreelist[abs_sz] = ((struct obj *)p);
  153.     } else {
  154. ((struct obj *)(h -> hb_body)) -> obj_link = objfreelist[abs_sz];
  155. objfreelist[abs_sz] = ((struct obj *)p);
  156.     }
  157.   /*
  158.    * Set up mask in header to facilitate alignment checks
  159.    * See "runtime.h" for a description of how this works.
  160.    */
  161. #   ifndef RT
  162. switch (abs_sz) {
  163.     case 1:
  164. h -> hb_mask = 0x3;
  165. break;
  166.     case 2:
  167. h -> hb_mask = 0x7;
  168. break;
  169.     case 4:
  170. h -> hb_mask = 0xf;
  171. break;
  172.     case 8:
  173. h -> hb_mask = 0x1f;
  174. break;
  175.     case 16:
  176. h -> hb_mask = 0x3f;
  177. break;
  178.     /* By default it remains set to a negative value */
  179. }
  180. #   else
  181.       /* the 4.2 pcc C compiler did not produce correct code for the switch */
  182. if (abs_sz == 1) { h -> hb_mask = 0x3; }
  183. else if (abs_sz == 2) { h -> hb_mask = 0x7; }
  184. else if (abs_sz == 4) { h -> hb_mask = 0xf; }
  185. else if (abs_sz == 8) { h -> hb_mask = 0x1f; }
  186. else if (abs_sz == 16) { h -> hb_mask = 0x3f; }
  187. /* else skip; */
  188. #   endif
  189. #   ifdef DEBUG
  190. printf("Allocated new heap block at address 0x%Xn",
  191. h);
  192. #   endif
  193. }
  194. /* some more variables */
  195. extern long mem_found;  /* Number of reclaimed longwords */
  196. /* after garbage collection      */
  197. extern long atomic_in_use, composite_in_use;
  198. extern errno;
  199. /*
  200.  * Clear mark bits in all allocated heap blocks
  201.  */
  202. static void clear_marks()
  203. {
  204.     register int j;
  205.     register struct hblk **p;
  206.     register struct hblk *q;
  207. # ifdef HBLK_MAP
  208.     for (q = (struct hblk *) heapstart; ((char*)q) < heaplim; q++)
  209.       if (is_hblk(q)) {
  210. # else
  211.     for (p = hblklist; p < last_hblk; p++) {
  212. q = *p;
  213. # endif
  214.         for (j = 0; j < MARK_BITS_SZ; j++) {
  215.     q -> hb_marks[j] = 0;
  216.         }
  217.     }
  218. }
  219. /* Limits of stack for mark routine.  Set by caller to mark.           */
  220. /* All items between mark_stack_top and mark_stack_bottom-1 still need */
  221. /* to be marked.  All items on the stack satisfy quicktest.  They do   */
  222. /* not necessarily reference real objects.                             */
  223. word * mark_stack_bottom;
  224. word * mark_stack_top;
  225. #ifdef USE_STACK
  226. # define STACKGAP 512 /* Gap in longwords between hardware stack and */
  227.       /* the mark stack. */
  228. #endif
  229. #ifdef USE_STACK
  230. #   define PUSH_MS(ptr) *(--mark_stack_top) = (word) ptr
  231. #   define NOT_DONE(a,b) (a < b)
  232. #else
  233. # ifdef USE_HEAP
  234.     char *cur_break = 0;
  235. #   define STACKINCR 0x4000
  236. #   define PUSH_MS(ptr) 
  237. mark_stack_top++;                                               
  238. if ((char*)mark_stack_top >= cur_break) { 
  239.     if (sbrk(STACKINCR) == -1) {
  240. fprintf(stderr, "sbrk failed, code = %dn",errno);      
  241. exit(1);
  242.     } else {
  243. cur_break += STACKINCR;                                
  244.     }
  245. }
  246. *mark_stack_top = (word) ptr
  247. #   define NOT_DONE(a,b) (a > b)
  248. # else
  249. --> where does the mark stack go? <--
  250. # endif
  251. #endif
  252. /* Top level mark routine */
  253. tl_mark(p)
  254. word * p;
  255. {
  256.     if (quicktest(p)) {
  257. /* Allocate mark stack, leaving a hole below the real stack. */
  258. #         ifdef USE_STACK
  259.     mark_stack_bottom = get_current_sp() - STACKGAP;
  260.     mark_stack_top = mark_stack_bottom;
  261. #         else
  262. #           ifdef USE_HEAP
  263.       mark_stack_bottom = (word *) sbrk(0); /* current break */
  264.       cur_break = (char *) mark_stack_bottom;
  265.       mark_stack_top = mark_stack_bottom;
  266. #           else
  267.       -> then where should the mark stack go ? <-
  268. #           endif
  269. #         endif
  270. PUSH_MS((word)p);
  271. #       ifdef DEBUG2
  272.     printf("Tl_mark found plausible pointer: %Xn", p);
  273. #       endif
  274. /* and now mark the one element on the stack */
  275.   mark();
  276.     }
  277. }
  278. mark()
  279. {
  280.   register long sz;
  281.   extern char end, etext;
  282.   register struct obj *p; /* pointer to current object to be marked */
  283.   while (NOT_DONE(mark_stack_top,mark_stack_bottom)) {
  284.       register long word_no;
  285.       register long mask;
  286.       register struct hblk * h;
  287. #    ifdef USE_STACK
  288.   p = (struct obj *)(*mark_stack_top++);
  289. #    else
  290. #     ifdef USE_HEAP
  291. p = (struct obj *)(*mark_stack_top--);
  292. #     else
  293. --> fixit <--
  294. #     endif
  295. #    endif
  296.   /* if not a pointer to obj on heap, skip it */
  297.     if (((char *) p) >= heaplim) {
  298. continue;
  299.     }
  300.     h = HBLKPTR(p);
  301. # ifndef INTERIOR_POINTERS
  302.     /* Check mark bit first, since this test is much more likely to */
  303.     /* fail than later ones.                                        */
  304.       word_no = ((word *)p) - ((word *)h);
  305.       if (mark_bit(h, word_no)) {
  306. continue;
  307.       }
  308. # endif
  309. # ifdef INTERIOR_POINTERS
  310.     if (!is_hblk(h)) {
  311. char m = get_map(h);
  312. while (m > 0 && m < 0x7f) {
  313.     h -= m;
  314.     m = get_map(h);
  315. }
  316. if (m == HBLK_INVALID) {
  317. #         ifdef REPORT_FAILURE
  318.     printf("-> Pointer to non-heap loc: %Xn", p);
  319. #         endif
  320.   continue;
  321. }
  322.     }
  323.     if (((long)p) - ((long)h) < sizeof (struct hblkhdr)) {
  324. continue;
  325.     }
  326. # else
  327.     if (!is_hblk(h)) {
  328. # ifdef REPORT_FAILURE
  329.   printf("-> Pointer to non-heap loc: %Xn", p);
  330. #       endif
  331. continue;
  332.     }
  333. # endif
  334.     sz = HB_SIZE(h);
  335.     mask = h -> hb_mask;
  336. # ifdef INTERIOR_POINTERS
  337.     word_no = get_word_no(p,h,sz,mask);
  338. # else
  339.     if (!is_proper_obj(p,h,sz,mask)) {
  340. #       ifdef REPORT_FAILURE
  341.     printf("-> Bad pointer to heap block: %X,sz = %dn",p,sz);
  342. # endif
  343. continue;
  344.     }
  345. # endif
  346.     if (word_no + sz > BYTES_TO_WORDS(HBLKSIZE)
  347. && word_no != BYTES_TO_WORDS(sizeof(struct hblkhdr))
  348.    /* Not first object */) {
  349.       /* 
  350.        * Note that we dont necessarily check for pointers to the block header.
  351.        * This doesn't cause any problems, since we have mark
  352.        * bits allocated for such bogus objects.
  353.        * We have to check for references past the last object, since
  354.        * marking from uch an "object" could cause an exception.
  355.        */
  356. #       ifdef REPORT_FAILURE
  357.     printf("-> Bad pointer to heap block: %X,sz = %dn",p,sz);
  358. # endif
  359. continue;
  360.     }
  361. #   ifdef INTERIOR_POINTERS
  362.       if (mark_bit(h, word_no)) {
  363. continue;
  364.       }
  365. #   endif
  366. #   ifdef DEBUG2
  367. printf("*** set bit for heap %x, word %xn",h,word_no);
  368. #   endif
  369.     set_mark_bit(h, word_no);
  370.     if (h -> hb_sz < 0) {
  371. /* Atomic object */
  372.   continue;
  373.     }
  374.     {
  375.       /* Mark from fields inside the object */
  376. register struct obj ** q;
  377. register struct obj * r;
  378. register long lim;   /* Should be struct obj **, but we're out of */
  379.      /* A registers on a 68000.                   */
  380. #       ifdef INTERIOR_POINTERS
  381.   /* Adjust p, so that it's properly aligned */
  382. #           ifdef DEBUG
  383.       if (p != ((struct obj *)(((word *)h) + word_no))) {
  384. printf("Adjusting from %X to ", p);
  385. p = ((struct obj *)(((word *)h) + word_no));
  386. printf("%Xn", p);
  387.       } else {
  388. p = ((struct obj *)(((word *)h) + word_no));
  389.       }
  390. #           else
  391.       p = ((struct obj *)(((word *)h) + word_no));
  392. #           endif
  393. #       endif
  394. #       ifdef UNALIGNED
  395.   lim = ((long)(&(p -> obj_component[sz]))) - 3;
  396. #       else
  397.   lim = (long)(&(p -> obj_component[sz]));
  398. #       endif
  399. for (q = (struct obj **)(&(p -> obj_component[0]));
  400. q < (struct obj **)lim;) {
  401.     r = *q;
  402.     if (quicktest(r)) {
  403. #               ifdef DEBUG2
  404.     printf("Found plausible nested pointer");
  405.     printf(": 0x%X inside 0x%X at 0x%Xn", r, p, q);
  406. #               endif
  407. PUSH_MS(((word)r));
  408.     }
  409. #           ifdef UNALIGNED
  410. q = ((struct obj **)(((long)q)+ALIGNMENT));
  411. #           else
  412. q++;
  413. #           endif 
  414. }
  415.     }
  416.   }
  417. }
  418. /*********************************************************************/
  419. /* Mark all locations reachable via pointers located between b and t */
  420. /*********************************************************************/
  421. mark_all(b, t)
  422. word * b;
  423. word * t;
  424. {
  425.     register word *p;
  426.     register word r;
  427.     register word *lim;
  428. #   ifdef DEBUG
  429. printf("Checking for pointers between 0x%X and 0x%Xn",
  430. b, t);
  431. #   endif
  432.     /* Allocate mark stack, leaving a hole below the real stack. */
  433. #     ifdef USE_STACK
  434. mark_stack_bottom = get_current_sp() - STACKGAP;
  435. mark_stack_top = mark_stack_bottom;
  436. #     else
  437. #       ifdef USE_HEAP
  438.   mark_stack_bottom = (word *) sbrk(0); /* current break */
  439.   cur_break = (char *) mark_stack_bottom;
  440.   mark_stack_top = mark_stack_bottom;
  441. #       else
  442.   -> then where should the mark stack go ? <-
  443. #       endif
  444. #     endif
  445.   /* Round b down so it is properly aligned */
  446. #   if (ALIGNMENT == 2)
  447.       b = (word *)(((long) b) & ~1);
  448. #   else
  449. #     if (ALIGNMENT == 4 || !defined(UNALIGNED))
  450. b = (word *)(((long) b) & ~3);
  451. #     endif
  452. #   endif
  453.   /* check all pointers in range and put on mark_stack if quicktest true */
  454.     lim = t - 1 /* longword */;
  455.     for (p = b; ((unsigned) p) <= ((unsigned) lim);) {
  456.     /* Coercion to unsigned in the preceding appears to be necessary */
  457.     /* due to a bug in the VAX C compiler.                           */
  458. r = *p;
  459. if (quicktest(r)) {
  460. #           ifdef DEBUG2
  461. printf("Found plausible pointer: %Xn", r);
  462. #           endif
  463.     PUSH_MS(r);         /* push r onto the mark stack */
  464. }
  465. #       ifdef UNALIGNED
  466.   p = (word *)(((char *)p) + ALIGNMENT);
  467. #       else
  468.   p++;
  469. #       endif
  470.     }
  471.     if (mark_stack_top != mark_stack_bottom) mark();
  472. #   ifdef USE_HEAP
  473.       brk(mark_stack_bottom);     /* reset break to where it was before */
  474.       cur_break = (char *) mark_stack_bottom;
  475. #   endif
  476. }
  477. /*
  478.  * Restore inaccessible objects to the free list 
  479.  * update mem_found (number of reclaimed longwords after garbage collection)
  480.  */
  481. void gcollect()
  482. {
  483.     extern void mark_regs();
  484.     register long TMP_SP; /* must be bound to r11 on VAX or RT, d7 on M68K */
  485.   /* or r3 on NS32K                                */
  486.     extern int holdsigs();  /* disables non-urgent signals - see the */
  487.     /* file "callcc.c" */
  488.     long Omask; /* mask to restore signal mask to after
  489.  * critical section.  This variable is assumed
  490.  * to be the first variable on the stack frame
  491.  * and to be longword aligned.
  492.  */
  493. #   ifdef PRINTTIMES
  494.       /* some debugging values */
  495. double start_time;
  496. double mark_time;
  497. double done_time;
  498. struct tms time_buf;
  499. #       define FTIME 
  500.  (((double)(time_buf.tms_utime + time_buf.tms_stime))/60.0)
  501.       /* Get starting time */
  502.     times(&time_buf);
  503.     start_time = FTIME;
  504. #   endif
  505. #   ifdef DEBUG2
  506. printf("Here we are in gcollectn"); 
  507. #   endif
  508.     /* Don't want to deal with signals in the middle so mask 'em out */
  509. Omask = holdsigs();
  510.     /*
  511.      * mark from registers - i.e., call tl_mark(i) for each
  512.      * register i
  513.      */
  514. mark_regs();
  515. #       ifdef DEBUG
  516.     printf("done marking from regs - calling mark_alln");
  517. # endif
  518.       /* put stack pointer into TMP_SP               */
  519.       /* and mark everything on the stack.           */
  520. /* A hack */
  521. TMP_SP = ((long)(&Omask));
  522. mark_all( TMP_SP, STACKTOP );
  523.     /* Mark everything in data and bss segments.                             */
  524.     /* Skip gc data structures. (It's OK to mark these, but it wastes time.) */
  525. {
  526.     extern char etext, end;
  527.             mark_all(DATASTART, begin_gc_arrays);
  528.             mark_all(end_gc_arrays, &end);
  529. }
  530.     /* Clear free list mark bits, in case they got accidentally marked   */
  531.     /* Note: HBLKPTR(p) == pointer to head of block containing *p        */
  532.     /* Also subtract memory remaining from mem_found count.              */
  533.     /* Note that composite objects on free list are cleared.             */
  534.     /* Thus accidentally marking a free list is not a problem;  only     */
  535.     /* objects on the list itself will be marked, and that's fixed here. */
  536.       {
  537. register int size; /* current object size */
  538. register struct obj * p; /* pointer to current object */
  539. register struct hblk * q; /* pointer to block containing *p */
  540. register int word_no;           /* "index" of *p in *q          */
  541. #       ifdef REPORT_FAILURE
  542.     int prev_failure = 0;
  543. #       endif
  544. for (size = 1; size < MAXOBJSZ; size++) {
  545.     for (p= objfreelist[size]; p != ((struct obj *)0); p=p->obj_link){
  546. q = HBLKPTR(p);
  547. word_no = (((word *)p) - ((word *)q));
  548. #               ifdef REPORT_FAILURE
  549.   if (!prev_failure && mark_bit(q, word_no)) {
  550.     printf("-> Pointer to composite free list: %X,sz = %dn",
  551.     p, size);
  552.     prev_failure = 1;
  553.   }
  554. #               endif
  555. clear_mark_bit(q, word_no);
  556. mem_found -= size;
  557.     }
  558. #           ifdef REPORT_FAILURE
  559. prev_failure = 0;
  560. #           endif
  561. }
  562. for (size = 1; size < MAXAOBJSZ; size++) {
  563.     for(p= aobjfreelist[size]; p != ((struct obj *)0); p=p->obj_link){
  564. q = HBLKPTR(p);
  565. word_no = (((long *)p) - ((long *)q));
  566. #               ifdef REPORT_FAILURE
  567.   if (!prev_failure && mark_bit(q, word_no)) {
  568.     printf("-> Pointer to atomic free list: %X,sz = %dn",
  569.     p, size);
  570.     prev_failure = 1;
  571.   }
  572. #               endif
  573. clear_mark_bit(q, word_no);
  574. mem_found -= size;
  575.     }
  576. #           ifdef REPORT_FAILURE
  577. prev_failure = 0;
  578. #           endif
  579. }
  580.       }
  581. #   ifdef PRINTTIMES
  582.       /* Get intermediate time */
  583. times(&time_buf);
  584. mark_time = FTIME;
  585. #   endif
  586. #   ifdef PRINTSTATS
  587. printf("Bytes recovered before reclaim - f.l. count = %dn",
  588.        WORDS_TO_BYTES(mem_found));
  589. #   endif
  590.   /* Reconstruct free lists to contain everything not marked */
  591.     reclaim();
  592.   /* clear mark bits in all allocated heap blocks */
  593.     clear_marks();
  594. #   ifdef PRINTSTATS
  595. printf("Reclaimed %d bytes in heap of size %d bytesn",
  596.        WORDS_TO_BYTES(mem_found), heapsize);
  597. printf("%d (atomic) + %d (composite) bytes in usen",
  598.        WORDS_TO_BYTES(atomic_in_use),
  599.        WORDS_TO_BYTES(composite_in_use));
  600. #   endif
  601.   /*
  602.    * What follows is somewhat heuristic.  Constant may benefit
  603.    * from tuning ...
  604.    */
  605.     if (WORDS_TO_BYTES(mem_found) * 4 < heapsize) {
  606.       /* Less than about 1/4 of available memory was reclaimed - get more */
  607. {
  608.     long size_to_get = HBLKSIZE + hincr * HBLKSIZE;
  609.     struct hblk * thishbp;
  610.     char * nheaplim;
  611.     thishbp = HBLKPTR(((unsigned)sbrk(0))+HBLKSIZE-1 );
  612.     nheaplim = (char *) (((unsigned)thishbp) + size_to_get);
  613.     if( ((char *) brk(nheaplim)) == ((char *)-1) ) {
  614. write(2,"Out of memory, trying to continue ...n",38);
  615.     } else {
  616. heaplim = nheaplim;
  617. thishbp->hb_sz = 
  618.     BYTES_TO_WORDS(size_to_get - sizeof(struct hblkhdr));
  619. freehblk(thishbp);
  620. heapsize += size_to_get;
  621. update_hincr;
  622.     }
  623. #           ifdef PRINTSTATS
  624. printf("Gcollect: needed to increase heap size by %dn",
  625.        size_to_get);
  626. #           endif
  627. }
  628.     }
  629.    /* Reset mem_found for next collection */
  630.      mem_found = 0;
  631.   /* Reenable signals */
  632.     sigsetmask(Omask);
  633.   /* Get final time */
  634. #   ifdef PRINTTIMES
  635. times(&time_buf);
  636. done_time = FTIME;
  637. printf("Garbage collection took %7.2f + %7.2f secsn",
  638.        mark_time - start_time, done_time - mark_time);
  639. #   endif
  640. }
  641. /*
  642.  * this is a function callable from Russell to explicity make the heap
  643.  * bigger for use by programs which know they'll need a bigger heap than
  644.  * the default.
  645.  */
  646. void expand_hp(n)
  647. int n;
  648. {
  649.     struct hblk * thishbp = HBLKPTR(((unsigned)sbrk(0))+HBLKSIZE-1 );
  650.     extern int holdsigs();
  651.     int Omask;
  652.     /* Don't want to deal with signals in the middle of this */
  653. Omask = holdsigs();
  654.     heaplim = (char *) (((unsigned)thishbp) + n * HBLKSIZE);
  655.     if (n > 2*hincr) {
  656. hincr = n/2;
  657.     }
  658.     if( ((char *) brk(heaplim)) == ((char *)-1) ) {
  659. write(2,"Out of Memory!n",15);
  660. exit(-1);
  661.     }
  662. #   ifdef PRINTSTATS
  663. printf("Voluntarily increasing heap size by %dn",
  664.        n*HBLKSIZE);
  665. #   endif
  666.     thishbp->hb_sz = BYTES_TO_WORDS(n * HBLKSIZE - sizeof(struct hblkhdr));
  667.     freehblk(thishbp);
  668.     heapsize += ((char *)heaplim) - ((char *)thishbp);
  669.     /* Reenable signals */
  670. sigsetmask(Omask);
  671. }
  672. extern int dont_gc;  /* Unsafe to start garbage collection */
  673. /*
  674.  * Make sure the composite object free list for sz is not empty.
  675.  * Return a pointer to the first object on the free list.
  676.  * The object MUST BE REMOVED FROM THE FREE LIST BY THE CALLER.
  677.  *
  678.  * note: _allocobj
  679.  */
  680. struct obj * _allocobj(sz)
  681. long sz;
  682. {
  683.     if (sz == 0) return((struct obj *)0);
  684. #   ifdef DEBUG2
  685. printf("here we are in _allocobjn");
  686. #   endif
  687.     if (objfreelist[sz] == ((struct obj *)0)) {
  688.       if (hblkfreelist == ((struct hblk *)0) && !dont_gc) {
  689. if (GC_DIV * non_gc_bytes < GC_MULT * heapsize) {
  690. #         ifdef DEBUG
  691.     printf("Calling gcollectn");
  692. #         endif
  693.   gcollect();
  694. } else {
  695.   expand_hp(NON_GC_HINCR);
  696. }
  697.       }
  698.       if (objfreelist[sz] == ((struct obj *)0)) {
  699. #       ifdef DEBUG
  700.     printf("Calling new_hblkn");
  701. # endif
  702.   new_hblk(sz);
  703.       }
  704.     }
  705. #   ifdef DEBUG2
  706. printf("Returning %x from _allocobjn",objfreelist[sz]);
  707. printf("Objfreelist[%d] = %xn",sz,objfreelist[sz]);
  708. #   endif
  709.     return(objfreelist[sz]);
  710. }
  711. /*
  712.  * Make sure the atomic object free list for sz is not empty.
  713.  * Return a pointer to the first object on the free list.
  714.  * The object MUST BE REMOVED FROM THE FREE LIST BY THE CALLER.
  715.  *
  716.  * note: this is called by allocaobj (see the file allocobj.s)
  717.  */
  718. struct obj * _allocaobj(sz)
  719. long sz;
  720. {
  721.     if (sz == 0) return((struct obj *)0);
  722.     if (aobjfreelist[sz] == ((struct obj *) 0)) {
  723.       if (hblkfreelist == ((struct hblk *)0) && !dont_gc) {
  724. if (GC_DIV * non_gc_bytes < GC_MULT * heapsize) {
  725. #         ifdef DEBUG
  726.     printf("Calling gcollectn");
  727. #         endif
  728.   gcollect();
  729. } else {
  730.   expand_hp(NON_GC_HINCR);
  731. }
  732.       }
  733.       if (aobjfreelist[sz] == ((struct obj *) 0)) {
  734.   new_hblk(-sz);
  735.       }
  736.     }
  737.     return(aobjfreelist[sz]);
  738. }
  739. # ifdef SPARC
  740.   put_mark_stack_bottom(val)
  741.   long val;
  742.   {
  743.     mark_stack_bottom = (word *)val;
  744.   }
  745. # endif