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

系统编程

开发平台:

Unix_Linux

  1. #define DEBUG
  2. #undef DEBUG
  3. #include <stdio.h>
  4. #include "runtime.h"
  5. /**/
  6. /* allocate/free routines for heap blocks
  7. /* Note that everything called from outside the garbage collector
  8. /* should be prepared to abort at any point as the result of a signal.
  9. /**/
  10. /*
  11.  * Free heap blocks are kept on a list sorted by address.
  12.  * The hb_hdr.hbh_sz field of a free heap block contains the length
  13.  * (in bytes) of the entire block.
  14.  * Neighbors are coalesced.
  15.  */
  16. struct hblk *savhbp = (struct hblk *)0;  /* heap block preceding next */
  17.  /* block to be examined by   */
  18.  /* allochblk.                */
  19. /*
  20.  * Return 1 if there is a heap block sufficient for object size sz,
  21.  * 0 otherwise.  Advance savhbp to point to the block prior to the
  22.  * first such block.
  23.  */
  24. int sufficient_hb(sz)
  25. int sz;
  26. {
  27. register struct hblk *hbp;
  28. struct hblk *prevhbp;
  29. int size_needed, size_avail;
  30. int first_time = 1;
  31.     size_needed = WORDS_TO_BYTES(sz>0? sz : -sz);
  32.     size_needed = (size_needed+sizeof(struct hblkhdr)+HBLKSIZE-1) & ~HBLKMASK;
  33. #   ifdef DEBUG
  34. printf("sufficient_hb: sz = %d, size_needed = 0x%Xn", sz, size_needed);
  35. #   endif
  36.     /* search for a big enough block in free list */
  37. hbp = savhbp;
  38. for(;;) {
  39.     prevhbp = hbp;
  40.     hbp = ((prevhbp == (struct hblk *)0)
  41.     ? hblkfreelist
  42.     : prevhbp->hb_next);
  43.     if( prevhbp == savhbp && !first_time) {
  44. /* no sufficiently big blocks on free list */
  45. return(0);
  46.     }
  47.     first_time = 0;
  48.     if( hbp == (struct hblk *)0 ) continue;
  49.     size_avail = hbp->hb_sz;
  50.     if( size_avail >= size_needed ) {
  51. savhbp = prevhbp;
  52. return(1);
  53.     }
  54. }
  55. }
  56. /*
  57.  * Allocate (and return pointer to) a heap block
  58.  *   for objects of size |sz|.
  59.  *
  60.  * NOTE: Caller is responsible for adding it to global hblklist
  61.  *       and for building an object freelist in it.
  62.  *
  63.  * The new block is guaranteed to be cleared if sz > 0.
  64.  */
  65. struct hblk *
  66. allochblk(sz)
  67. long sz;
  68. {
  69.     register struct hblk *thishbp;
  70.     register struct hblk *hbp;
  71.     struct hblk *prevhbp;
  72.     long size_needed,            /* number of bytes in requested objects */
  73.          uninit,                 /* => Found uninitialized block         */
  74.          size_avail;
  75.     int first_time = 1;
  76.     char *sbrk(); /* data segment size increasing */
  77.     char *brk(); /* functions */
  78.     size_needed = WORDS_TO_BYTES(sz>0? sz : -sz);
  79.     size_needed = (size_needed+sizeof(struct hblkhdr)+HBLKSIZE-1) & ~HBLKMASK;
  80. #   ifdef DEBUG
  81. printf("(allochblk) sz = %x, size_needed = 0x%Xn", sz, size_needed);
  82. #   endif
  83.     /* search for a big enough block in free list */
  84. hbp = savhbp;
  85. for(;;) {
  86.     prevhbp = hbp;
  87.     hbp = ((prevhbp == (struct hblk *)0)
  88.                     ? hblkfreelist
  89.     : prevhbp->hb_next);
  90.     if( prevhbp == savhbp && !first_time) {
  91. /* no sufficiently big blocks on free list, */
  92. /* let thishbp --> a newly-allocated block, */
  93. /* free it (to merge into existing block    */
  94. /* list) and start the search again, this   */
  95. /* time with guaranteed success.            */
  96.                   int size_to_get = size_needed + hincr * HBLKSIZE;
  97.   extern int holdsigs();
  98.   int Omask;
  99.   /* Don't want to deal with signals in the middle of this */
  100.       Omask = holdsigs();
  101.                     update_hincr;
  102.     thishbp = HBLKPTR(((unsigned)sbrk(0))+HBLKSIZE-1 );
  103.     heaplim = (char *) (((unsigned)thishbp) + size_to_get);
  104.     if( (brk(heaplim)) == ((char *)-1) ) {
  105.                         write(2,"Out of Memory!  Giving up ...n", 30);
  106. exit(-1);
  107.     }
  108. #                   ifdef PRINTSTATS
  109. printf("Need to increase heap size by %dn",
  110.        size_to_get);
  111. fflush(stdout);
  112. #                   endif
  113.     heapsize += size_to_get;
  114.     thishbp->hb_sz = 
  115. BYTES_TO_WORDS(size_to_get - sizeof(struct hblkhdr));
  116.     freehblk(thishbp);
  117.     /* Reenable signals */
  118.       sigsetmask(Omask);
  119.     hbp = savhbp;
  120.     first_time = 1;
  121. continue;
  122.     }
  123.     first_time = 0;
  124.     if( hbp == (struct hblk *)0 ) continue;
  125.     size_avail = hbp->hb_sz;
  126.     if( size_avail >= size_needed ) {
  127. /* found a big enough block       */
  128. /* let thishbp --> the block      */
  129. /* set prevhbp, hbp to bracket it */
  130.     thishbp = hbp;
  131.     if( size_avail == size_needed ) {
  132. hbp = hbp->hb_next;
  133. uninit = thishbp -> hb_uninit;
  134.     } else {
  135. uninit = thishbp -> hb_uninit;
  136. thishbp -> hb_uninit = 1; 
  137. /* Just in case we get interrupted by a */
  138. /* signal                               */
  139. hbp = (struct hblk *)
  140.     (((unsigned)thishbp) + size_needed);
  141. hbp->hb_uninit = uninit;
  142. hbp->hb_next = thishbp->hb_next;
  143. hbp->hb_sz = size_avail - size_needed;
  144.     }
  145. /* remove *thishbp from hblk freelist */
  146.     if( prevhbp == (struct hblk *)0 ) {
  147. hblkfreelist = hbp;
  148.     } else {
  149. prevhbp->hb_next = hbp;
  150.     }
  151. /* save current list search position */
  152.     savhbp = prevhbp;
  153. break;
  154.     }
  155. }
  156.     /* set size and mask field of *thishbp correctly */
  157. thishbp->hb_sz = sz;
  158. thishbp->hb_mask = -1;  /* may be changed by new_hblk */
  159.     /* Clear block if necessary */
  160. if (uninit && sz > 0) {
  161.     register word * p = &(thishbp -> hb_body[0]);
  162.     register word * plim;
  163.     plim = (word *)(((char *)thishbp) + size_needed);
  164.     while (p < plim) {
  165. *p++ = 0;
  166.     }
  167. }
  168.     /* Clear mark bits */
  169. {
  170.     register word *p = (word *)(&(thishbp -> hb_marks[0]));
  171.     register word * plim = (word *)(&(thishbp -> hb_marks[MARK_BITS_SZ]));
  172.     while (p < plim) {
  173. *p++ = 0;
  174.     }
  175. }
  176. #   ifdef DEBUG
  177. printf("Returning 0x%Xn", thishbp);
  178. fflush(stdout);
  179. #   endif
  180.     return( thishbp );
  181. }
  182.  
  183. /* Clear the header information in a previously allocated heap block p */
  184. /* so that it can be coalesced with an initialized heap block.         */
  185. static clear_header(p)
  186. register struct hblk *p;
  187. {
  188.     p -> hb_sz = 0;
  189. #   ifndef HBLK_MAP
  190.       p -> hb_index = (struct hblk **)0;
  191. #   endif
  192.     p -> hb_next = 0;
  193.     p -> hb_mask = 0;
  194. #   if MARK_BITS_SZ <= 60
  195. /* Since this block was deallocated, only spurious mark      */
  196. /* bits corresponding to the header could conceivably be set */
  197. p -> hb_marks[0] = 0;
  198. p -> hb_marks[1] = 0;
  199. #   else
  200. --> fix it
  201. #   endif
  202. }
  203. /*
  204.  * Free a heap block.
  205.  *
  206.  * Assume the block is not currently on hblklist.
  207.  *
  208.  * Coalesce the block with its neighbors if possible.
  209.  * All mark words (except possibly the first) are assumed to be cleared.
  210.  * The body is assumed to be cleared unless hb_uninit is nonzero.
  211.  */
  212. void
  213. freehblk(p)
  214. register struct hblk *p;
  215. {
  216. register struct hblk *hbp, *prevhbp;
  217. register int size;
  218.     /* savhbp may become invalid due to coalescing.  Clear it. */
  219. savhbp = (struct hblk *)0;
  220.     size = p->hb_sz;
  221.     if( size < 0 ) size = -size;
  222.     size = 
  223. ((WORDS_TO_BYTES(size)+sizeof(struct hblkhdr)+HBLKSIZE-1)
  224.  & (~HBLKMASK));
  225.     p->hb_sz = size;
  226.     prevhbp = (struct hblk *) 0;
  227.     hbp = hblkfreelist;
  228.     while( (hbp != (struct hblk *)0) && (hbp < p) ) {
  229. prevhbp = hbp;
  230. hbp = hbp->hb_next;
  231.     }
  232.     /* Coalesce with successor, if possible */
  233.       if( (((unsigned)p)+size) == ((unsigned)hbp) ) {
  234. (p -> hb_uninit) |= (hbp -> hb_uninit);
  235. p->hb_next = hbp->hb_next;
  236. p->hb_sz += hbp->hb_sz;
  237. if (!p -> hb_uninit) clear_header(hbp);
  238.       } else {
  239. p->hb_next = hbp;
  240.       }
  241.     if( prevhbp == (struct hblk *)0 ) {
  242. hblkfreelist = p;
  243.     } else if( (((unsigned)prevhbp) + prevhbp->hb_hdr.hbh_sz) ==
  244.     ((unsigned)p) ) {
  245.       /* Coalesce with predecessor */
  246. (prevhbp->hb_uninit) |= (p -> hb_uninit);
  247. prevhbp->hb_next = p->hb_next;
  248. prevhbp->hb_sz += p->hb_sz;
  249. if (!prevhbp -> hb_uninit) clear_header(p);
  250.     } else {
  251. prevhbp->hb_next = p;
  252.     }
  253. }
  254. /* Add a heap block to hblklist or hblkmap.  */
  255. void add_hblklist(hbp)
  256. struct hblk * hbp;
  257. {
  258. # ifdef HBLK_MAP
  259.     long size = hbp->hb_sz;
  260.     long index = divHBLKSZ(((long)hbp) - ((long)heapstart));
  261.     long i;
  262.     if( size < 0 ) size = -size;
  263.     size = (divHBLKSZ(WORDS_TO_BYTES(size)+sizeof(struct hblkhdr)+HBLKSIZE-1));
  264.    /* in units of HBLKSIZE */
  265.     hblkmap[index] = HBLK_VALID;
  266.     for (i = 1; i < size; i++) {
  267. if (i < 0x7f) {
  268.     hblkmap[index+i] = i;
  269. } else {
  270.     /* May overflow a char.  Store largest possible value */
  271.     hblkmap[index+i] = 0x7e;
  272. }
  273.     }
  274. # else
  275.     if (last_hblk >= &hblklist[MAXHBLKS]) {
  276. fprintf(stderr, "Not configured for enough memoryn");
  277. exit(1);
  278.     }
  279.     *last_hblk = hbp;
  280.     hbp -> hb_index = last_hblk;
  281.     last_hblk++;
  282. # endif
  283. }
  284. /* Delete a heap block from hblklist or hblkmap.  */
  285. void del_hblklist(hbp)
  286. struct hblk * hbp;
  287. {
  288. # ifdef HBLK_MAP
  289.     long size = hbp->hb_sz;
  290.     long index = divHBLKSZ(((long)hbp) - ((long)heapstart));
  291.     long i;
  292.     if( size < 0 ) size = -size;
  293.     size = (divHBLKSZ(WORDS_TO_BYTES(size)+sizeof(struct hblkhdr)+HBLKSIZE-1));
  294.    /* in units of HBLKSIZE */
  295.     for (i = 0; i < size; i++) {
  296. hblkmap[index+i] = HBLK_INVALID;
  297.     }
  298. # else
  299.     register struct hblk ** list_entry;
  300.     last_hblk--;
  301.     /* Let **last_hblk use the slot previously occupied by *hbp */
  302. list_entry = hbp -> hb_index;
  303. (*last_hblk) -> hb_index = list_entry;
  304. *list_entry = *last_hblk;
  305. # endif
  306. }
  307. /* Initialize hblklist */
  308. void init_hblklist()
  309. {
  310. #   ifdef DEBUG
  311. printf("Here we are in init_hblklist - ");
  312. printf("last_hblk = %xn",&(hblklist[0]));
  313. #   endif
  314. #   ifndef HBLK_MAP
  315.       last_hblk = &(hblklist[0]);
  316. #   endif
  317. }