home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / heapinit.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  16KB  |  658 lines

  1. /***
  2. *heapinit.c -  Initialze the heap
  3. *
  4. *       Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *
  8. *******************************************************************************/
  9.  
  10.  
  11. #ifdef WINHEAP
  12.  
  13.  
  14. #include <cruntime.h>
  15. #include <malloc.h>
  16. #include <winheap.h>
  17.  
  18. HANDLE _crtheap;
  19.  
  20. /*
  21.  * Dummy definition of _amblksiz. Included primarily so the dll will build
  22.  * without having to change crtlib.c (there is an access function for _amblksiz
  23.  * defined in crtlib.c).
  24.  */
  25. unsigned int _amblksiz = BYTES_PER_PARA;
  26.  
  27.  
  28. /***
  29. *_heap_init() - Initialize the heap
  30. *
  31. *Purpose:
  32. *       Setup the initial C library heap.
  33. *
  34. *       NOTES:
  35. *       (1) This routine should only be called once!
  36. *       (2) This routine must be called before any other heap requests.
  37. *
  38. *Entry:
  39. *       <void>
  40. *Exit:
  41. *       Returns 1 if successful, 0 otherwise.
  42. *
  43. *Exceptions:
  44. *       If heap cannot be initialized, the program will be terminated
  45. *       with a fatal runtime error.
  46. *
  47. *******************************************************************************/
  48.  
  49. int __cdecl _heap_init (
  50.         int mtflag
  51.         )
  52. {
  53.         //  Initialize the "big-block" heap first.
  54.         if ( (_crtheap = HeapCreate( mtflag ? 0 : HEAP_NO_SERIALIZE,
  55.                                      BYTES_PER_PAGE, 0 )) == NULL )
  56.             return 0;
  57.  
  58.         //  Initialize the small-block heap
  59.         if (__sbh_heap_init() == 0)
  60.         {
  61.             HeapDestroy(_crtheap);
  62.             return 0;
  63.         }
  64.         return 1;
  65. }
  66.  
  67. /***
  68. *_heap_term() - return the heap to the OS
  69. *
  70. *Purpose:
  71. *
  72. *       NOTES:
  73. *       (1) This routine should only be called once!
  74. *       (2) This routine must be called AFTER any other heap requests.
  75. *
  76. *Entry:
  77. *       <void>
  78. *Exit:
  79. *       <void>
  80. *
  81. *Exceptions:
  82. *
  83. *******************************************************************************/
  84.  
  85. void __cdecl _heap_term (void)
  86. {
  87.     PHEADER         pHeader = __sbh_pHeaderList;
  88.     int             cntHeader;
  89.  
  90.     //  scan through all the headers
  91.     for (cntHeader = 0; cntHeader < __sbh_cntHeaderList; cntHeader++)
  92.     {
  93.         //  decommit and release the address space for the region
  94.         VirtualFree(pHeader->pHeapData, BYTES_PER_REGION, MEM_DECOMMIT);
  95.         VirtualFree(pHeader->pHeapData, 0, MEM_RELEASE);
  96.  
  97.         //  free the region data structure
  98.         HeapFree(_crtheap, 0, pHeader->pRegion);
  99.  
  100.         pHeader++;
  101.     }
  102.     //  free the header list
  103.     HeapFree(_crtheap, 0, __sbh_pHeaderList);
  104.  
  105.     //  destroy the large-block heap
  106.     HeapDestroy(_crtheap);
  107. }
  108.  
  109.  
  110. #else  /* WINHEAP */
  111.  
  112.  
  113. #ifdef _WIN32
  114.  
  115.  
  116. #include <cruntime.h>
  117. #include <oscalls.h>
  118. #include <dos.h>
  119. #include <heap.h>
  120. #include <stddef.h>
  121. #include <stdio.h>
  122. #include <stdlib.h>
  123.  
  124. /*
  125.  * Heap descriptor
  126.  */
  127.  
  128.  
  129. struct _heap_desc_ _heap_desc = {
  130.         &_heap_desc.sentinel,           /* pfirstdesc */
  131.         &_heap_desc.sentinel,           /* proverdesc */
  132.         NULL,                           /* emptylist */
  133.         NULL,                           /* sentinel.pnextdesc */
  134.         NULL                            /* sentinel.pblock */
  135.         };
  136.  
  137. /*
  138.  * Array of region structures
  139.  * [Note: We count on the fact that this is always initialized to zero
  140.  * by the compiler.]
  141.  */
  142.  
  143. struct _heap_region_ _heap_regions[_HEAP_REGIONMAX];
  144.  
  145. void ** _heap_descpages;        /* linked list of pages used for descriptors */
  146.  
  147. /*
  148.  * Control parameter locations
  149.  */
  150.  
  151. unsigned int _heap_resetsize = 0xffffffff;
  152.  
  153. /* NOTE: Currenlty, _heap_growsize is a #define to _amblksiz */
  154. unsigned int _heap_growsize   = _HEAP_GROWSIZE;         /* region inc size */
  155. unsigned int _heap_regionsize = _HEAP_REGIONSIZE_L;     /* region size */
  156. unsigned int _heap_maxregsize = _HEAP_MAXREGSIZE_L;     /* max region size */
  157.  
  158.  
  159. /***
  160. *_heap_init() - Initialize the heap
  161. *
  162. *Purpose:
  163. *       Setup the initial C library heap.  All necessary memory and
  164. *       data bases are init'd appropriately so future requests work
  165. *       correctly.
  166. *
  167. *       NOTES:
  168. *       (1) This routine should only be called once!
  169. *       (2) This routine must be called before any other heap requests.
  170. *
  171. *
  172. *Entry:
  173. *       <void>
  174. *Exit:
  175. *       <void>
  176. *
  177. *Exceptions:
  178. *       If heap cannot be initialized, the program will be terminated
  179. *       with a fatal runtime error.
  180. *
  181. *******************************************************************************/
  182.  
  183. void __cdecl _heap_init (
  184.         void
  185.         )
  186. {
  187.         /*
  188.          * Test for Win32S or Phar Lap TNT environment
  189.          * which cannot allocate uncommitted memory
  190.          * without actually allocating physical memory
  191.          *
  192.          * High bit of _osver is set for both of those environments
  193.          * -AND- the Windows version will be less than 4.0.
  194.          */
  195.  
  196.         if ( ( _osver & 0x8000 ) && ( _winmajor < 4 ) )
  197.         {
  198.                 _heap_regionsize = _HEAP_REGIONSIZE_S;
  199.                 _heap_maxregsize = _HEAP_MAXREGSIZE_S;
  200.         }
  201. }
  202.  
  203.  
  204.  
  205. /***
  206. *_heap_term() - Clean-up the heap
  207. *
  208. *Purpose:
  209. *       This routine will decommit and release ALL of the CRT heap.
  210. *       All memory malloc-ed by the CRT will then be invalid.
  211. *
  212. *       NOTES:
  213. *       (1) This routine should only be called once!
  214. *       (2) This routine must be called AFTER any other heap requests.
  215. *
  216. *Entry:
  217. *       <void>
  218. *Exit:
  219. *       <void>
  220. *
  221. *Exceptions:
  222. *
  223. *******************************************************************************/
  224.  
  225. void __cdecl _heap_term (
  226.         void
  227.         )
  228. {
  229.     int index;
  230.     void **pageptr;
  231.  
  232.     /*
  233.      * Loop through the region descriptor table, decommitting
  234.      * and releasing (freeing up) each region that is in use.
  235.      */
  236.  
  237.     for ( index=0 ; index < _HEAP_REGIONMAX ; index++ ) {
  238.         void * regbase ;
  239.  
  240.         if ( (regbase = _heap_regions[index]._regbase)
  241.           && VirtualFree(regbase, _heap_regions[index]._currsize, MEM_DECOMMIT)
  242.           && VirtualFree(regbase, 0, MEM_RELEASE) )
  243.                 regbase = _heap_regions[index]._regbase = NULL ;
  244.     }
  245.  
  246.     /*
  247.      * Now we need to decommit and release the pages used for descriptors
  248.      * _heap_descpages points to the head of a singly-linked list of the pages.
  249.      */
  250.  
  251.     pageptr = _heap_descpages;
  252.  
  253.     while ( pageptr ) {
  254.         void **nextpage;
  255.  
  256.         nextpage = *pageptr;
  257.  
  258.         if(!VirtualFree(pageptr, 0, MEM_RELEASE))
  259.             break;      /* if the linked list is corrupted, give up */
  260.  
  261.         pageptr = nextpage;
  262.     }
  263.  
  264. }
  265.  
  266.  
  267.  
  268. /***
  269. * _heap_grow_emptylist() - Grow the empty heap descriptor list
  270. *
  271. *Purpose:
  272. *       (1) Get memory from OS
  273. *       (2) Form it into a linked list of empty heap descriptors
  274. *       (3) Attach it to the master empty list
  275. *
  276. *       NOTE:  This routine assumes that the emptylist is NULL
  277. *       when called (i.e., there are no available empty heap descriptors).
  278. *
  279. *Entry:
  280. *       (void)
  281. *
  282. *Exit:
  283. *       1, if the empty heap descriptor list was grown
  284. *       0, if the empty heap descriptor list could not be grown.
  285. *
  286. *Exceptions:
  287. *
  288. *******************************************************************************/
  289.  
  290. static int __cdecl _heap_grow_emptylist (
  291.         void
  292.         )
  293. {
  294.         REG1 _PBLKDESC first;
  295.         REG2 _PBLKDESC next;
  296.         _PBLKDESC last;
  297.  
  298.         /*
  299.          * Get memory for the new empty heap descriptors
  300.          *
  301.          * Note that last is used to hold the returned pointer because
  302.          * first (and next) are register class.
  303.          */
  304.  
  305.         if ( !(last = VirtualAlloc(NULL,
  306.                                    _HEAP_EMPTYLIST_SIZE,
  307.                                    MEM_COMMIT,
  308.                                    PAGE_READWRITE)) )
  309.                 return 0;
  310.  
  311.         /*
  312.          * Add this descriptor block to the front of the list
  313.          *
  314.          * Advance "last" to skip over the
  315.          */
  316.  
  317.         *(void **)last = _heap_descpages;
  318.         _heap_descpages = (void **)(last++);
  319.  
  320.  
  321.         /*
  322.          * Init the empty heap descriptor list.
  323.          */
  324.  
  325.         _heap_desc.emptylist = first = last;
  326.  
  327.  
  328.         /*
  329.          * Carve the memory into an empty list
  330.          */
  331.  
  332.         last = (_PBLKDESC) ((char *) first + _HEAP_EMPTYLIST_SIZE - 2 * sizeof(_BLKDESC));
  333.         next = (_PBLKDESC) ((char *) first + sizeof(_BLKDESC));
  334.  
  335.         while ( first < last ) {
  336.  
  337.                 /* Init this descriptor */
  338.                 first->pnextdesc = next;
  339.  
  340.                 /* onto the next block */
  341.  
  342.                 first = next++;
  343.  
  344.         }
  345.  
  346.         /*
  347.          * Take care of the last descriptor (end of the empty list)
  348.          */
  349.  
  350.         last->pnextdesc = NULL;
  351.  
  352.  
  353.         return 1;
  354. }
  355.  
  356.  
  357. /***
  358. *__getempty() - get an empty heap descriptor
  359. *
  360. *Purpose:
  361. *       Get a descriptor from the list of empty heap descriptors. If the list
  362. *       is empty, call _heap_grow_emptylist.
  363. *
  364. *Entry:
  365. *       no arguments
  366. *
  367. *Exit:
  368. *       If successful, a pointer to the descriptor is returned.
  369. *       Otherwise, NULL is returned.
  370. *
  371. *Exceptions:
  372. *
  373. *******************************************************************************/
  374.  
  375. _PBLKDESC __cdecl __getempty(
  376.         void
  377.         )
  378. {
  379.         _PBLKDESC pdesc;
  380.  
  381.         if ( (_heap_desc.emptylist == NULL) && (_heap_grow_emptylist()
  382.               == 0) )
  383.                 return NULL;
  384.  
  385.         pdesc = _heap_desc.emptylist;
  386.  
  387.         _heap_desc.emptylist = pdesc->pnextdesc;
  388.  
  389.         return pdesc;
  390. }
  391.  
  392.  
  393. #else  /* _WIN32 */
  394.  
  395. #if defined (_M_MPPC) || defined (_M_M68K)
  396.  
  397.  
  398. #include <cruntime.h>
  399. #include <dos.h>
  400. #include <heap.h>
  401. #include <malloc.h>
  402. #include <stddef.h>
  403. #include <stdio.h>
  404. #include <string.h>
  405. #include <dbgint.h>
  406.  
  407. #include <macos\types.h>
  408. #include <macos\errors.h>
  409. #include <macos\memory.h>               // Mac OS interface header
  410. #include <macos\lowmem.h>
  411. #include <macos\segload.h>
  412.  
  413. #define _HEAP_EMPTYLIST_SIZE    (1 * _PAGESIZE_)
  414.  
  415. #define DSErrCode   (*(short*)(0x0af0))
  416.  
  417. /*
  418.  * Heap descriptor
  419.  */
  420.  
  421. struct _heap_desc_ _heap_desc = {
  422.         &_heap_desc.sentinel,           /* pfirstdesc */
  423.         &_heap_desc.sentinel,           /* proverdesc */
  424.         NULL,                           /* emptylist */
  425.         NULL,                           /* sentinel.pnextdesc */
  426.         NULL                            /* sentinel.pblock */
  427.         };
  428.  
  429. /*
  430.  * Array of region structures
  431.  * [Note: We count on the fact that this is always initialized to zero
  432.  * by the compiler.]
  433.  */
  434.  
  435. Handle hHeapRegions = NULL;
  436. int _heap_region_table_cur = 0;
  437.  
  438. /*
  439.  * Control parameter locations
  440.  */
  441.  
  442. unsigned int _heap_resetsize = 0xffffffff;
  443.  
  444. /* NOTE: Currenlty, _heap_growsize is a #define to _amblksiz */
  445. unsigned int _heap_growsize   = _HEAP_GROWSIZE;         /* region inc size */
  446. unsigned int _heap_regionsize = _HEAP_REGIONSIZE;       /* region size */
  447.  
  448.  
  449. /***
  450. *_heap_init() - Initialize the heap
  451. *
  452. *Purpose:
  453. *       Setup the initial C library heap.  All necessary memory and
  454. *       data bases are init'd appropriately so future requests work
  455. *       correctly.
  456. *
  457. *       NOTES:
  458. *       (1) This routine should only be called once!
  459. *       (2) This routine must be called before any other heap requests.
  460. *
  461. *
  462. *Entry:
  463. *       <void>
  464. *Exit:
  465. *       <void>
  466. *
  467. *Exceptions:
  468. *       If heap cannot be initialized, the program will be terminated
  469. *       with a fatal runtime error.
  470. *
  471. *******************************************************************************/
  472.  
  473. void __cdecl _heap_init (
  474.         void
  475.         )
  476. {
  477.  
  478. #define _INITREGIONSZ 0x1000
  479.  
  480.         /*LATER -- do we need to do anything to init heap? Yes, in case user not malloc first*/
  481.         int oldregionsz = _heap_regionsize;     /* save current region size */
  482.  
  483.         struct _heap_region_ *pHeapRegions;
  484.         void *p;
  485.         void *p2;
  486.  
  487.         if (hHeapRegions == NULL)
  488.                 {
  489.                 hHeapRegions = NewHandle(sizeof(struct _heap_region_)*_HEAP_REGIONMAX);
  490.                 if (hHeapRegions == NULL)
  491.                         {
  492.                         DSErrCode = appMemFullErr;
  493.                         ExitToShell();
  494.                         }
  495.                 HLock(hHeapRegions);
  496.                 pHeapRegions = (struct _heap_region_ *)(*hHeapRegions);
  497.                 memset(pHeapRegions, 0, sizeof(struct _heap_region_)*_HEAP_REGIONMAX);
  498.                 _heap_region_table_cur = _HEAP_REGIONMAX;
  499.                 }
  500.  
  501.  
  502.         _heap_regionsize = _INITREGIONSZ;       /* set region size to 64 Kb */
  503.  
  504.         /* make sure we have enough memory to do initialization */
  505.         if ((p = NewPtr(_HEAP_EMPTYLIST_SIZE)) == NULL)
  506.                 {
  507.                 DSErrCode = appMemFullErr;
  508.                 ExitToShell();
  509.                 }
  510.  
  511.         if ((p2 = NewPtr(_heap_regionsize)) == NULL)
  512.                 {
  513.                 DSErrCode = appMemFullErr;
  514.                 ExitToShell();
  515.                 }
  516.  
  517.         if (p)
  518.                 {
  519.                 DisposePtr(p);
  520.                 }
  521.         if (p2)
  522.                 {
  523.                 DisposePtr(p2);
  524.                 }
  525.  
  526.         p = _malloc_base(4);
  527.         if (p == NULL)
  528.                 {
  529.                 DSErrCode = appMemFullErr;
  530.                 ExitToShell();
  531.                 }
  532.         _free_base( p );                /* malloc, then free a block */
  533.         _heap_regionsize = oldregionsz;         /* restore region size */
  534.  
  535. }
  536.  
  537.  
  538.  
  539. /***
  540. * _heap_grow_emptylist() - Grow the empty heap descriptor list
  541. *
  542. *Purpose:
  543. *       (1) Get memory from OS
  544. *       (2) Form it into a linked list of empty heap descriptors
  545. *       (3) Attach it to the master empty list
  546. *
  547. *       NOTE:  This routine assumes that the emptylist is NULL
  548. *       when called (i.e., there are no available empty heap descriptors).
  549. *
  550. *Entry:
  551. *       (void)
  552. *
  553. *Exit:
  554. *       (void)
  555. *
  556. *Exceptions:
  557. *
  558. *******************************************************************************/
  559.  
  560. static int __cdecl _heap_grow_emptylist (
  561.         void
  562.         )
  563. {
  564.         REG1 _PBLKDESC first;
  565.         REG2 _PBLKDESC next;
  566.         _PBLKDESC last;
  567.  
  568.  
  569.         /*
  570.          * Get memory for the new empty heap descriptors
  571.          *
  572.          * Note that last is used to hold the returned pointer because
  573.          * first (and next) are register class.
  574.          */
  575.  
  576.         if ((last = (_PBLKDESC)NewPtr(_HEAP_EMPTYLIST_SIZE)) == NULL)
  577.                 {
  578.                 return 0;
  579.                 }
  580.  
  581.         /*
  582.          * Init the empty heap descriptor list.
  583.          */
  584.  
  585.         _heap_desc.emptylist = first = last;
  586.  
  587.  
  588.         /*
  589.          * Carve the memory into an empty list
  590.          */
  591.  
  592.         last = (_PBLKDESC) ((char *) first + _HEAP_EMPTYLIST_SIZE - sizeof(_BLKDESC));
  593.         next = (_PBLKDESC) ((char *) first + sizeof(_BLKDESC));
  594.  
  595.         while ( first < last ) {
  596.  
  597.                 /* Init this descriptor */
  598.                 first->pnextdesc = next;
  599.  
  600.                 /* onto the next block */
  601.  
  602.                 first = next++;
  603.  
  604.         }
  605.  
  606.         /*
  607.          * Take care of the last descriptor (end of the empty list)
  608.          */
  609.  
  610.         last->pnextdesc = NULL;
  611.  
  612.  
  613.         return 1;
  614.  
  615. }
  616.  
  617. /***
  618. *__getempty() - get an empty heap descriptor
  619. *
  620. *Purpose:
  621. *       Get a descriptor from the list of empty heap descriptors. If the list
  622. *       is empty, call _heap_grow_emptylist.
  623. *
  624. *Entry:
  625. *       no arguments
  626. *
  627. *Exit:
  628. *       If successful, a pointer to the descriptor is returned.
  629. *       Otherwise, NULL is returned.
  630. *
  631. *Exceptions:
  632. *
  633. *******************************************************************************/
  634.  
  635. _PBLKDESC __cdecl __getempty(
  636.         void
  637.         )
  638. {
  639.         _PBLKDESC pdesc;
  640.  
  641.         if ( (_heap_desc.emptylist == NULL) && (_heap_grow_emptylist()
  642.               == 0) )
  643.                 return NULL;
  644.  
  645.         pdesc = _heap_desc.emptylist;
  646.  
  647.         _heap_desc.emptylist = pdesc->pnextdesc;
  648.  
  649.         return pdesc;
  650. }
  651.  
  652.  
  653. #endif  /* defined (_M_MPPC) || defined (_M_M68K) */
  654.  
  655. #endif  /* _WIN32 */
  656.  
  657. #endif  /* WINHEAP */
  658.