memLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:30k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* memLib.c - full-featured memory partition manager */
  2. /* Copyright 1984-1995 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 05x,21feb99,jdi  doc: listed errnos.
  8. 05w,01may98,cjtc moved instrumentation point in memPartRealloc to fix problem
  9.                  with reported size of bytesPlusHeaderAlign
  10. 05v,17feb98,dvs  added instrumentation points (pr)
  11. 05u,11feb97,dbt  Fixed case of memPartRealloc() call with pBlock = NULL (SPR
  12.                  #7012)
  13. 05t,18jan96,tam  checked for nbBytes=0 in memPartRealloc() (SPR 5858).
  14.  reworked the fix for memPartRealloc() (SPR 1407 & 3564).
  15. 05s,23jan95,ism  Fixed possible problem with memPartRealloc() from earlier fix
  16.           (SPR#3563).  Fixed in-line docs.
  17. 05r,23jan95,rhp  doc: explain memPartRealloc() with NULL pointer.
  18. 05q,12jan95,rhp  doc: in memLib and memPartOptionsSet man pages, mention
  19.                  VX_UNBREAKABLE override of MEM_*_ERROR_SUSPEND_FLAG (SPR#2499)
  20. 05p,29aug94,ism  memBlockSplit() bypasses the problem with the number of free
  21.           blocks statistic by incrementing before the memBlockSplit() 
  22.  call (SPR #3564).
  23. 05q,25aug94,ism  realloc() no longer checks for NULL block; instead, this is
  24.  done at the next level down, in memPartRealloc() (SPR #3563).
  25. 05p,05sep93,jcf  calls to logMsg are now indirect for scalability.
  26. 05o,23feb93,jdi  documentation: cfree() not ANSI.
  27. 05n,10feb93,jdi  fixed spelling of stdlib.
  28. 05m,23jan93,jdi  documentation cleanup for 5.1.
  29. 05l,13nov92,dnw  added include of smObjLib.h
  30. 05k,20oct92,pme  added reference to shared memory manager documentation.
  31. 05j,15oct92,pme  fixed valloc documentation.
  32. 05i,02oct92,jdi  documentation cleanup.
  33. 05h,23aug92,jcf  added _func_{memalign,valloc}
  34. 05g,19aug92,smb  fixed SPR #1400, realloc(NULL) now malloc's memory
  35. 05f,29jul92,pme  added NULL function pointer check for smObj routines.
  36. 05e,29jul92,jcf  moved SUSPEND option to memPartLib.  beefed up package init.
  37. 05d,19jul92,pme  added shared memory object support.
  38. 05c,19jul92,smb  added some ANSI documentation.
  39. 05b,13jul92,rdc  added valloc.
  40. 05a,04jul92,jcf  split into memShow/memPartLib/memLib for modularity.
  41. 04n,22jun92,rdc  added memalign and memPartAlignedAlloc.
  42. 04m,26may92,rrr  the tree shuffle
  43. 04l,07apr92,yao  removed macros MEM_ROUND_UP/DOWN, MEM_IS_ROUND.  
  44. 04n,25mar92,jmm  Changed way we handle memory pool options for error handling
  45. 04m,23mar92,jmm  changed memBlockAllocError to handle MEM_ALLOC_ERROR_RETURN
  46.                  changed memPartAllocError to handle MEM_ALLOC_ERROR_RETURN
  47.  SPR #1377
  48. 04l,16dec91,gae  added includes for ANSI.
  49. 04k,25nov91,llk  ansi stuff.  Modified malloc(), calloc(), realloc(), free().
  50. 04j,04oct91,rrr  passed through the ansification filter
  51.                   -changed functions to ansi style
  52.   -changed includes to have absolute path from h/
  53.   -fixed #else and #endif
  54.   -changed VOID to void
  55.   -changed copyright notice
  56. 04i,07aug91,ajm  made MIPS MEM_ROUNDUP use 8 byte boundaries for
  57.                    varargs problem.
  58. 04h,23may91,jwt  forced 8-byte alignment for SPARC - stack, optimization.
  59. 04g,13may91,wmd  added define for TRON rounding.
  60. 04f,05apr91,jdi  documentation -- removed header parens and x-ref numbers;
  61.  doc review by dnw.
  62. 04e,24mar91,del  added I960 rounding and padding to structures.
  63. 04d,13feb91,jaa  documentation cleanup.
  64. 04c,05oct90,dnw  made memPartInit() be NOMANUAL.
  65. 04b,18jul90,jcf  changed free/memPartFree to return OK if pBlock is NULL.
  66. 04a,18jul90,jcf  changed partitions into objects w/ object class.
  67.  change memPartBlockIsValid () to check validity w/o race.
  68.  lint & cleanup.
  69. 03i,26jun90,jcf  changed partition semaphore to mutex w/ inversion safety.
  70. 03h,21nov89,jcf  added memSysPartId which is global variable for system part.
  71. 03g,07nov89,shl  added error checking for memPartShow().
  72.  fixed documentation on memory overhead.
  73.  fixed memPart{Block,Alloc}Error() to not suspend
  74.  unbreakable tasks.
  75.  cosmetics.
  76. 03f,15mar88,llk  fixed bug in realloc.  memBlockSplit() wasn't checking to
  77.    ensure that both resulting blocks were of minimum length.
  78. 03e,07nov88,gae  fixed memPartFindMax() return value in bytes not words.
  79. 03d,18aug88,gae  documentation.
  80. 03c,07jul88,jcf  lint.
  81. 03b,22jun88,dnw  fixed bug in realloc.
  82.  added cfree(), memPartFindMax(), and memFindMax().
  83.  changed hdr to have ptr to prev block (instead of prev block
  84.    size and free flag), as per gae suggestion.
  85. 03a,20may88,dnw  rewritten - now has following features:
  86.    - faster allocation
  87.    - much faster deallocation (no searching)
  88.    - checks validity of blocks being freed
  89.    - options to specify how to deal with errors
  90.    - always allocates on even 4 byte address
  91.    - VxWorks v4 names
  92. 02q,28mar88,gae  added calloc().
  93. 02p,22jan88,jcf  made kernel independent.
  94. 02o,19feb88,rdc  malloc of 0 bytes in no longer an error.
  95. 02n,18nov87,dnw  changed to set S_memLib_INVALID_NBYTES appropriately.
  96. 02m,17nov87,ecs  lint.
  97. 02l,13nov87,gae  moved FRAGMENT definition here from memLib.h.
  98.  fixed memFindMax() from returning too large an amount.
  99. 02k,05nov87,jlf  documentation
  100. 02j,23oct87,rdc  generalized to support private memory partitions.
  101. 02i,07apr87,jlf  delinted.
  102. 02h,24mar87,jlf  documentation.
  103. 02g,30jan87,rdc  fixed bug in memAddToPool - was screwing up allocation stats.
  104. 02f,21dec86,dnw  changed to not get include files from default directories.
  105. 02e,04sep86,jlf  documentation.
  106. 02d,02jul86,rdc  fixed bug in memStat.
  107. 02c,19jun86,rdc  spruced up memStat.
  108. 02b,18jun86,rdc  de-linted.
  109. 02a,14apr86,rdc  completely rewritten to support dynamic allocation.
  110. 01i,03mar86,jlf  added malloc and free.  free is a null routine, for now.
  111. 01h,20jul85,jlf  Documentation.
  112. 01g,08sep84,jlf  Changed to lock out while allocating memory.  added copyright
  113.  and some comments.
  114. 01f,13aug84,ecs  changed S_memLib_NO_MORE_MEMORY to S_memLib_NOT_ENOUGH_MEMORY.
  115.  added testing for negative nbytes to memAllocate.
  116.  added setting of status to S_memLib_INVALID_NBYTES.
  117. 01e,07aug84,ecs  added setStatus call to memAllocate.
  118. 01d,21may84,dnw  changed memInit to specify both start and end of pools.
  119.  removed memEnd.
  120.  added LINTLIBRARY and various coercions for lint.
  121. 01c,03sep83,dnw  added memInit.
  122. 01b,13jul83,dnw  fixed memAlloc to return NULL if insufficient memory available.
  123. 01a,24may83,dnw  written
  124. */
  125. /*
  126. DESCRIPTION
  127. This library provides full-featured facilities for managing the allocation
  128. of blocks of memory from ranges of memory called memory partitions.  The
  129. library is an extension of memPartLib and provides enhanced memory management
  130. features, including error handling, aligned allocation, and ANSI allocation
  131. routines.  For more information about the core memory partition management 
  132. facility, see the manual entry for memPartLib.
  133. The system memory partition is created when the kernel is initialized
  134. by kernelInit(), which is called by the root task, usrRoot(), in usrConfig.c.
  135. The ID of the system memory partition is stored in the global variable
  136. `memSysPartId'; its declaration is included in memLib.h.
  137. The memalign() routine is provided for allocating memory aligned to a specified
  138. boundary.
  139. This library includes three ANSI-compatible routines:
  140. calloc() allocates a block of memory for an array;
  141. realloc() changes the size of a specified block of memory; and
  142. cfree() returns to the free memory pool a block of memory that
  143. was previously allocated with calloc().
  144. ERROR OPTIONS
  145. Various debug options can be selected for each partition using
  146. memPartOptionsSet() and memOptionsSet().  Two kinds of errors are 
  147. detected: attempts to allocate more memory
  148. than is available, and bad blocks found when memory is freed.  In both
  149. cases, the error status is returned.  There are four error-handling
  150. options that can be individually selected:
  151. .iP "MEM_ALLOC_ERROR_LOG_FLAG" 8
  152. Log a message when there is an error in allocating memory.
  153. .iP "MEM_ALLOC_ERROR_SUSPEND_FLAG"
  154. Suspend the task when there is an error in allocating memory (unless
  155. the task was spawned with the VX_UNBREAKABLE option, in which case it
  156. cannot be suspended).
  157. .iP "MEM_BLOCK_ERROR_LOG_FLAG"
  158. Log a message when there is an error in freeing memory.
  159. .iP "MEM_BLOCK_ERROR_SUSPEND_FLAG"
  160. Suspend the task when there is an error in freeing memory (unless
  161. the task was spawned with the VX_UNBREAKABLE option, in which case it
  162. cannot be suspended).
  163. .LP
  164. When the following option is specified to check every block freed to the
  165. partition, memPartFree() and free() in memPartLib run consistency checks
  166. of various pointers and values in the header of the block being freed.  If
  167. this flag is not specified, no check will be performed when memory is
  168. freed.
  169. .iP "MEM_BLOCK_CHECK" 8
  170. Check each block freed.
  171. .LP
  172. Setting either of the MEM_BLOCK_ERROR options automatically 
  173. sets MEM_BLOCK_CHECK.
  174. The default options when a partition is created are:
  175.     MEM_ALLOC_ERROR_LOG_FLAG
  176.     MEM_BLOCK_CHECK
  177.     MEM_BLOCK_ERROR_LOG_FLAG
  178.     MEM_BLOCK_ERROR_SUSPEND_FLAG
  179. When setting options for a partition with memPartOptionsSet() or
  180. memOptionsSet(), use the logical OR operator between each specified
  181. option to construct the <options> parameter.  For example:
  182. .CS
  183.     memPartOptionsSet (myPartId, MEM_ALLOC_ERROR_LOG_FLAG |
  184.                                  MEM_BLOCK_CHECK |
  185.                                  MEM_BLOCK_ERROR_LOG_FLAG);
  186. .CE
  187. INCLUDE FILES: memLib.h
  188. SEE ALSO: memPartLib, smMemLib
  189. INTERNAL
  190. This package is initialized by kernelInit() which calls memInit() with a
  191. pointer to a block of memory from which memory will be allocated.
  192. Blocks allocated by malloc() are actually larger than the size requested by
  193. the user.  Each block is prefaced by a header which contains the size and
  194. status of that block and a pointer to the previous block.
  195. The pointer returned to the user points just past this header.
  196. Likewise when a block is freed, the header is found just in front of
  197. the block pointer passed by the user.
  198. The header data is arranged so that the pointer to the previous block
  199. comes first and is therefore adjacent to that previous block.  Thus each
  200. block has 4 bytes of redundant information on either side of it (the 4
  201. bytes of size and status before it in its own header, and the 4-byte
  202. pointer after it in the next header).  This redundant information is
  203. optionally used in free() and realloc() to make a consistency check on
  204. blocks specified by the user.  This mechanism helps to detect two common
  205. errors: (1) bad block pointers passed to free() or realloc() are usually
  206. detected, and (2) trashing up to 4 bytes on either side of the block will
  207. only affect that block and will also be detected by free() or realloc().
  208. There is a minimum block size which malloc() allocates; this is to insure
  209. that there will be enough room for the free list links that must be used
  210. when the block is freed if it cannot be coalesced with an adjacent block.
  211. The malloc() and realloc() routines always allocate memory aligned to the 
  212. boundary defined in the global variable memDefaultAlignment, which is 
  213. initialized to the alignment required for the specific architecture.
  214. The memory partition semaphore is a structure in the partition descriptor
  215. rather than a pointer to a dynamically created semaphore structure.
  216. This is because of the chicken-and-the-egg problem of memLib using semaphores
  217. and semCreate calling malloc.  Instead the structure is simply declared
  218. directly in the partition structure and we call semInit() instead of
  219. semCreate().
  220. */
  221. #include "vxWorks.h"
  222. #include "semLib.h"
  223. #include "dllLib.h"
  224. #include "logLib.h"
  225. #include "taskLib.h"
  226. #include "stdlib.h"
  227. #include "stdio.h"
  228. #include "string.h"
  229. #include "errno.h"
  230. #include "smObjLib.h"
  231. #include "private/memPartLibP.h"
  232. #include "private/vmLibP.h"
  233. #include "private/smMemLibP.h"
  234. #include "private/funcBindP.h"
  235. #include "private/eventP.h"
  236. /* global variables */
  237. int mutexOptionsMemLib = SEM_Q_PRIORITY |  /* default mutual exclusion */
  238.  SEM_DELETE_SAFE | /* options for memory */
  239.  SEM_INVERSION_SAFE; /* partition semaphore */
  240. /* shared memory manager function pointers */
  241. FUNCPTR  smMemPartOptionsSetRtn;
  242. FUNCPTR  smMemPartFindMaxRtn;
  243. FUNCPTR  smMemPartReallocRtn;
  244. /* local variables */
  245. LOCAL BOOL  memLibInstalled; /* TRUE if library has been installed */
  246. LOCAL char *memMsgBlockTooBig =
  247. "memPartAlloc: block too big - %d in partition %#x.n";
  248. LOCAL char *memMsgBlockError =
  249. "%s: invalid block %#x in partition %#x.n";
  250. /* forward static functions */
  251. static void memSemInit (PART_ID pPart);
  252. static void memPartAllocError (PART_ID pPart, unsigned nBytes);
  253. static void memPartBlockError (PART_ID pPart, char *pBlock, char *label);
  254. static BLOCK_HDR *memBlockSplit (BLOCK_HDR *pHdr, unsigned nWords,
  255.  unsigned minWords);
  256. /*******************************************************************************
  257. *
  258. * memLibInit - initialize the higher level memory management functions
  259. *
  260. * This routine initializes the higher level memory management functions
  261. * suchas mutex semaphore selection, and error notification.
  262. *
  263. * RETURNS: OK or ERROR.
  264. *
  265. * NOMANUAL
  266. */
  267. STATUS memLibInit (void)
  268.     {
  269.     if (!memLibInstalled)
  270. {
  271. _func_valloc       = (FUNCPTR) valloc;
  272. _func_memalign       = (FUNCPTR) memalign;
  273. memPartBlockErrorRtn   = (FUNCPTR) memPartBlockError;
  274. memPartAllocErrorRtn   = (FUNCPTR) memPartAllocError;
  275. memPartSemInitRtn      = (FUNCPTR) memSemInit;
  276.      memPartOptionsDefault = MEM_ALLOC_ERROR_LOG_FLAG |
  277.           MEM_BLOCK_ERROR_LOG_FLAG |
  278.           MEM_BLOCK_ERROR_SUSPEND_FLAG |
  279.           MEM_BLOCK_CHECK;
  280. memLibInstalled = TRUE;
  281. }
  282.     return ((memLibInstalled) ? OK : ERROR);
  283.     }
  284. /*******************************************************************************
  285. *
  286. * memInit - initialize the system memory partition
  287. *
  288. * This routine initializes the system partition free list with the
  289. * specified memory block.  It must be called exactly once before invoking any
  290. * other routine in memLib.  It is called by kernelInit() in usrRoot()
  291. * in usrConfig.c.
  292. *
  293. * RETURNS: OK or ERROR.
  294. *
  295. * NOMANUAL
  296. */
  297. STATUS memInit 
  298.     (
  299.     char *pPool,        /* pointer to memory block */
  300.     unsigned poolSize   /* block size in bytes */
  301.     )
  302.     {
  303.     memLibInit (); /* attach memLib functions to memPartLib */
  304.     return (memPartLibInit (pPool, poolSize));
  305.     }
  306. /*******************************************************************************
  307. *
  308. * memPartOptionsSet - set the debug options for a memory partition
  309. *
  310. * This routine sets the debug options for a specified memory partition.
  311. * Two kinds of errors are detected: attempts to allocate more memory
  312. * than is available, and bad blocks found when memory is freed.  In both
  313. * cases, the error status is returned.  There are four error-handling
  314. * options that can be individually selected:
  315. * .iP "MEM_ALLOC_ERROR_LOG_FLAG" 8
  316. * Log a message when there is an error in allocating memory.
  317. * .iP "MEM_ALLOC_ERROR_SUSPEND_FLAG"
  318. * Suspend the task when there is an error in allocating memory (unless
  319. * the task was spawned with the VX_UNBREAKABLE option, in which case it
  320. * cannot be suspended).
  321. * .iP "MEM_BLOCK_ERROR_LOG_FLAG"
  322. * Log a message when there is an error in freeing memory.
  323. * .iP "MEM_BLOCK_ERROR_SUSPEND_FLAG"
  324. * Suspend the task when there is an error in freeing memory (unless
  325. * the task was spawned with the VX_UNBREAKABLE option, in which case it
  326. * cannot be suspended).
  327. * .LP
  328. * These options are discussed in detail in the library manual entry for
  329. * memLib.
  330. * RETURNS: OK or ERROR.
  331. *
  332. * ERRNO: S_smObjLib_NOT_INITIALIZED
  333. *
  334. * SEE ALSO: smMemLib
  335. */
  336. STATUS memPartOptionsSet 
  337.     (
  338.     PART_ID   partId,    /* partition to set option for */
  339.     unsigned   options    /* memory management options */
  340.     )
  341.     {
  342.     if ((!memLibInstalled) && (memLibInit () != OK)) /* initialize package */
  343. return (ERROR);
  344.     if (ID_IS_SHARED (partId))  /* partition is shared? */
  345. {
  346. if (smMemPartOptionsSetRtn == NULL)
  347.     {
  348.     errno = S_smObjLib_NOT_INITIALIZED;
  349.     return (ERROR);
  350.     }
  351.         return ((*smMemPartOptionsSetRtn)(SM_OBJ_ID_TO_ADRS (partId), options));
  352. }
  353.     /* partition is local */
  354.     if (OBJ_VERIFY (partId, memPartClassId) != OK)
  355. return (ERROR);
  356.     semTake (&partId->sem, WAIT_FOREVER);
  357.     /*
  358.      * Need to convert old-style options to new-style options
  359.      */
  360.     if (options & (MEM_ALLOC_ERROR_MASK | MEM_BLOCK_ERROR_MASK))
  361. {
  362. if (options & MEM_ALLOC_ERROR_LOG_MSG)
  363.    options |= MEM_ALLOC_ERROR_LOG_FLAG;
  364. if (options & MEM_ALLOC_ERROR_LOG_AND_SUSPEND)
  365.     options |= (MEM_ALLOC_ERROR_LOG_FLAG |
  366. MEM_ALLOC_ERROR_SUSPEND_FLAG);
  367. if (options & MEM_BLOCK_ERROR_LOG_MSG)
  368.    options |= MEM_BLOCK_ERROR_LOG_FLAG;
  369. if (options & MEM_BLOCK_ERROR_LOG_AND_SUSPEND)
  370.     options |= (MEM_BLOCK_ERROR_LOG_FLAG |
  371. MEM_BLOCK_ERROR_SUSPEND_FLAG);
  372. }
  373.     /*
  374.      * If either of the MEM_BLOCK options have been set, also set
  375.      * MEM_BLOCK_CHECK.
  376.      */
  377.     if (options & (MEM_BLOCK_ERROR_LOG_FLAG | MEM_BLOCK_ERROR_SUSPEND_FLAG))
  378.         options |= MEM_BLOCK_CHECK;
  379.     
  380.     partId->options = options;
  381.     semGive (&partId->sem);
  382.     return (OK);
  383.     }
  384. /*******************************************************************************
  385. *
  386. * memalign - allocate aligned memory 
  387. *
  388. * This routine allocates a buffer of size <size> from the system memory 
  389. * partition.  Additionally, it insures that the allocated buffer begins 
  390. * on a memory address evenly divisible by the specified alignment parameter.
  391. * The alignment parameter must be a power of 2.
  392. *
  393. * RETURNS:
  394. * A pointer to the newly allocated block, or NULL if the buffer could not be
  395. * allocated.
  396. */
  397. void *memalign 
  398.     (
  399.     unsigned alignment, /* boundary to align to (power of 2) */
  400.     unsigned size               /* number of bytes to allocate */
  401.     )
  402.     {
  403.     return (memPartAlignedAlloc (memSysPartId, size, alignment));
  404.     }
  405. /*******************************************************************************
  406. *
  407. * valloc - allocate memory on a page boundary 
  408. *
  409. * This routine allocates a buffer of <size> bytes from the system memory
  410. * partition.  Additionally, it insures that the allocated buffer
  411. * begins on a page boundary.  Page sizes are architecture-dependent.
  412. *
  413. * RETURNS:
  414. * A pointer to the newly allocated block, or NULL if the buffer could not be
  415. * allocated or the memory management unit (MMU) support library has not been
  416. * initialized.
  417. *
  418. * ERRNO: S_memLib_PAGE_SIZE_UNAVAILABLE
  419. */
  420. void * valloc 
  421.     (
  422.     unsigned size /* number of bytes to allocate */
  423.     )
  424.     {
  425.     int pageSize = VM_PAGE_SIZE_GET();
  426.     if (pageSize == ERROR)
  427. {
  428. errno = S_memLib_PAGE_SIZE_UNAVAILABLE;
  429. return (NULL);
  430. }
  431.     return (memalign (pageSize, size));
  432.     }
  433. /*******************************************************************************
  434. *
  435. * memPartRealloc - reallocate a block of memory in a specified partition
  436. *
  437. * This routine changes the size of a specified block of memory and returns a
  438. * pointer to the new block.  The contents that fit inside the new size (or
  439. * old size if smaller) remain unchanged.  The memory alignment of the new
  440. * block is not guaranteed to be the same as the original block.
  441. *
  442. * If <pBlock> is NULL, this call is equivalent to memPartAlloc().
  443. *
  444. * RETURNS:
  445. * A pointer to the new block of memory, or NULL if the call fails.
  446. *
  447. * ERRNO: S_smObjLib_NOT_INITIALIZED
  448. *
  449. * SEE ALSO: smMemLib
  450. */
  451. void *memPartRealloc 
  452.     (
  453.     PART_ID partId,             /* partition ID */
  454.     char *pBlock,               /* block to be reallocated */
  455.     unsigned nBytes             /* new block size in bytes */
  456.     )
  457.     {
  458.     FAST BLOCK_HDR *pHdr = BLOCK_TO_HDR (pBlock);
  459.     FAST BLOCK_HDR *pNextHdr;
  460.     FAST unsigned nWords;
  461.     void *pNewBlock;
  462.     if (ID_IS_SHARED (partId))  /* partition is shared? */
  463. {
  464. if (smMemPartReallocRtn == NULL)
  465.     {
  466.     errno = S_smObjLib_NOT_INITIALIZED;
  467.     return (NULL);
  468.     }
  469.         return ((void *) (*smMemPartReallocRtn) (SM_OBJ_ID_TO_ADRS (partId), 
  470.  pBlock, nBytes));
  471. }
  472.     /* partition is local */
  473.     if (OBJ_VERIFY (partId, memPartClassId) != OK)
  474. return (NULL);
  475.     /* Call memPartAlloc() if user passed us a NULL pointer */
  476.     if (pBlock == NULL)
  477.         return (memPartAlloc (partId, (unsigned) nBytes));
  478.    
  479.     /* Call memPartFree() if nBytes=0 (SPR 5858) */
  480.     if (nBytes == 0)
  481. {
  482. (void) memPartFree (memSysPartId, pBlock);
  483. return (NULL);
  484. }
  485.     /* get exclusive access to the partition */
  486.     semTake (&partId->sem, WAIT_FOREVER);
  487.     /* get actual new size; round-up, add overhead, check for minimum */
  488.     nWords = (MEM_ROUND_UP (nBytes) + sizeof (BLOCK_HDR)) >> 1;
  489.     if (nWords < partId->minBlockWords)
  490. nWords = partId->minBlockWords;
  491.     /* optional check for validity of block */
  492.     if ((partId->options & MEM_BLOCK_CHECK) &&
  493.         !memPartBlockIsValid (partId, pHdr, FALSE))
  494. {
  495. semGive (&partId->sem); /* release mutual exclusion */
  496. memPartBlockError (partId, pBlock, "memPartRealloc");
  497. return (NULL);
  498. }
  499.     /* test if we are trying to increase size of block */
  500.     if (nWords > pHdr->nWords)
  501. {
  502. /* increase size of block -
  503.  * check if next block is free and is big enough to satisfy request*/
  504. pNextHdr = NEXT_HDR (pHdr);
  505. if (!pNextHdr->free || ((pHdr->nWords + pNextHdr->nWords) < nWords))
  506.     {
  507.     /* can't use adjacent free block -
  508.      * allocate an entirely new block and copy data */
  509.     semGive (&partId->sem);
  510.     if ((pNewBlock = memPartAlloc (partId, nBytes)) == NULL)
  511. return (NULL);
  512.     bcopy (pBlock, (char *) pNewBlock,
  513.    (int) (2 * pHdr->nWords - sizeof (BLOCK_HDR)));
  514.     (void) memPartFree (partId, pBlock);
  515.     return (pNewBlock); /* RETURN, don't fall through */
  516.     }
  517. else
  518.     {
  519.     /* append next block to this one -
  520.      *  - delete next block from freelist,
  521.      *  - add its size to this block,
  522.      *  - update allocation statistics,
  523.      *  - fix prev info in new "next" block header */
  524.     dllRemove (&partId->freeList, HDR_TO_NODE (pNextHdr));
  525.     pHdr->nWords += pNextHdr->nWords; /* fix size */
  526. #ifdef WV_INSTRUMENTATION
  527.     /*
  528.      * The following call to instrumentation will log an a greater
  529.      * than needed nBytesPlusHeaderAlign. This is because, at this
  530.      * point, nBytesPlusHeaderAlign includes the total size of the
  531.      * newly freed memory block. The unused portion will be returned
  532.      * to the free list (see memBlockSplit() just below, at which
  533.      * time the excess will be logged as an EVENT_MEMFREE
  534.      */
  535.     EVT_OBJ_4 (OBJ, partId, memPartClassId, EVENT_MEMREALLOC,
  536.          partId, pBlock, 2* (pHdr->nWords), nBytes);
  537. #endif
  538.     partId->curWordsAllocated += pNextHdr->nWords; /* fix stats */
  539.     partId->cumWordsAllocated += pNextHdr->nWords;
  540.     NEXT_HDR (pHdr)->pPrevHdr = pHdr; /* fix next */
  541.     /* if this combined block is too big, it will get fixed below */
  542.     }
  543. }
  544.     /* split off any extra and give it back;
  545.      * note that this covers both the case of a realloc for smaller space
  546.      * and the case of a realloc for bigger space that caused a coalesce
  547.      * with the next block that resulted in larger than required block */
  548.     pNextHdr = memBlockSplit (pHdr, pHdr->nWords - nWords,
  549.       partId->minBlockWords);
  550.     semGive (&partId->sem);
  551.     if (pNextHdr != NULL)
  552. {
  553. (void) memPartFree (partId, HDR_TO_BLOCK (pNextHdr));
  554. partId->curBlocksAllocated++;
  555. /* memPartFree() is going to subtract one from the curBlocksAllocated
  556.  * statistic. Since memPartRealloc() should not change the value of
  557.  * curBlocksAllocated, it has to be corrected  (SPR 1407 & 3564)
  558.  */
  559. }
  560.     return ((void *) pBlock);
  561.     }
  562. /*******************************************************************************
  563. *
  564. * memPartFindMax - find the size of the largest available free block
  565. *
  566. * This routine searches for the largest block in the memory partition free
  567. * list and returns its size.
  568. *
  569. * RETURNS: The size, in bytes, of the largest available block.
  570. *
  571. * ERRNO: S_smObjLib_NOT_INITIALIZED
  572. *
  573. * SEE ALSO: smMemLib
  574. */
  575. int memPartFindMax 
  576.     (
  577.     FAST PART_ID partId         /* partition ID */
  578.     )
  579.     {
  580.     FAST BLOCK_HDR * pHdr;
  581.     FAST DL_NODE * pNode;
  582.     FAST unsigned biggestWords = 0;
  583.     if (ID_IS_SHARED (partId))  /* partition is shared? */
  584. {
  585. if (smMemPartFindMaxRtn == NULL)
  586.     {
  587.     errno = S_smObjLib_NOT_INITIALIZED;
  588.     return (ERROR);
  589.     }
  590.         return ((*smMemPartFindMaxRtn) (SM_OBJ_ID_TO_ADRS (partId)));
  591. }
  592.     /* partition is local */
  593.     if (OBJ_VERIFY (partId, memPartClassId) != OK)
  594. return (ERROR);
  595.     semTake (&partId->sem, WAIT_FOREVER);
  596.     /* go through free list and find largest free */
  597.     for (pNode = DLL_FIRST (&partId->freeList);
  598.  pNode != NULL;
  599.  pNode = DLL_NEXT (pNode))
  600. {
  601. pHdr = NODE_TO_HDR (pNode);
  602. if (pHdr->nWords > biggestWords)
  603.     biggestWords = pHdr->nWords;
  604. }
  605.     semGive (&partId->sem);
  606.     return (2 * biggestWords - sizeof (BLOCK_HDR));
  607.     }
  608. /*******************************************************************************
  609. *
  610. * memPartAllocError - handle allocation error
  611. */
  612. LOCAL void memPartAllocError 
  613.     (
  614.     PART_ID pPart,
  615.     unsigned nBytes 
  616.     )
  617.     {
  618.     if ((_func_logMsg != NULL) &&
  619. (pPart->options & MEM_ALLOC_ERROR_LOG_FLAG))
  620. (* _func_logMsg) (memMsgBlockTooBig, nBytes, (int) pPart, 0, 0, 0, 0);
  621.     }
  622. /*******************************************************************************
  623. *
  624. * memPartBlockError - handle invalid block error
  625. */
  626. LOCAL void memPartBlockError 
  627.     (
  628.     PART_ID pPart,
  629.     char *pBlock,
  630.     char *label 
  631.     )
  632.     {
  633.     if ((_func_logMsg != NULL) &&
  634.         (pPart->options & MEM_BLOCK_ERROR_LOG_FLAG))
  635.         (* _func_logMsg) (memMsgBlockError, (int)label, (int) pBlock, 
  636.   (int) pPart, 0, 0, 0);
  637.     }
  638. /*****************************************************************************
  639. *
  640. * memBlockSplit - split a block into two blocks
  641. *
  642. * This routine splits the block pointed to into two blocks.  The second
  643. * block will have nWords words in it.  A pointer is returned to this block.
  644. * If either resultant block would end up having less than minWords in it,
  645. * NULL is returned.
  646. *
  647. * RETURNS: A pointer to the second block, or NULL.
  648. */
  649. LOCAL BLOCK_HDR *memBlockSplit 
  650.     (
  651.     FAST BLOCK_HDR *pHdr,
  652.     unsigned nWords,            /* number of words in second block */
  653.     unsigned minWords           /* min num of words allowed in a block */
  654.     )
  655.     {
  656.     FAST unsigned wordsLeft;
  657.     FAST BLOCK_HDR *pNewHdr;
  658.     /* check if block can be split */
  659.     if ((nWords < minWords) ||
  660.         ((wordsLeft = (pHdr->nWords - nWords)) < minWords))
  661.         return (NULL);                  /* not enough space left */
  662.     /* adjust original block size and create new block */
  663.     pHdr->nWords = wordsLeft;
  664.     pNewHdr = NEXT_HDR (pHdr);
  665.     pNewHdr->pPrevHdr = pHdr;
  666.     pNewHdr->nWords   = nWords;
  667.     pNewHdr->free     = pHdr->free;
  668.     /* fix next block */
  669.     NEXT_HDR (pNewHdr)->pPrevHdr = pNewHdr;
  670.     return (pNewHdr);
  671.     }
  672. /*******************************************************************************
  673. *
  674. * memOptionsSet - set the debug options for the system memory partition
  675. *
  676. * This routine sets the debug options for the system memory partition.
  677. * Two kinds of errors are detected:  attempts to allocate more memory than
  678. * is available, and bad blocks found when memory is freed.  In both cases,
  679. * the following options can be selected for actions to be taken when the error
  680. * is detected:  (1) return the error status, (2) log an error message and
  681. * return the error status, or (3) log an error message and suspend the
  682. * calling task.
  683. *
  684. * These options are discussed in detail in the library manual
  685. * entry for memLib.
  686. *
  687. * RETURNS: N/A
  688. *
  689. * SEE ALSO: memPartOptionsSet()
  690. */
  691. void memOptionsSet 
  692.     (
  693.     unsigned options    /* options for system partition */
  694.     )
  695.     {
  696.     memPartOptionsSet (memSysPartId, options);
  697.     }
  698. /*******************************************************************************
  699. *
  700. * calloc - allocate space for an array (ANSI)
  701. *
  702. * This routine allocates a block of memory for an array that contains
  703. * <elemNum> elements of size <elemSize>.  This space is initialized to
  704. * zeros.
  705. *
  706. * RETURNS:
  707. * A pointer to the block, or NULL if the call fails.
  708. *
  709. * SEE ALSO:
  710. * .I "American National Standard for Information Systems -"
  711. * .I "Programming Language - C, ANSI X3.159-1989: General Utilities (stdlib.h)"
  712. */
  713. void *calloc 
  714.     (
  715.     size_t elemNum, /* number of elements */
  716.     size_t elemSize /* size of elements */
  717.     )
  718.     {
  719.     FAST void *pMem;
  720.     FAST size_t nBytes = elemNum * elemSize;
  721.     
  722.     if ((pMem = memPartAlloc (memSysPartId, (unsigned) nBytes)) != NULL)
  723. bzero ((char *) pMem, (int) nBytes);
  724.     return (pMem);
  725.     }
  726. /*******************************************************************************
  727. *
  728. * realloc - reallocate a block of memory (ANSI)
  729. *
  730. * This routine changes the size of a specified block of memory and returns a
  731. * pointer to the new block of memory.  The contents that fit inside the new
  732. * size (or old size if smaller) remain unchanged.  The memory alignment of
  733. * the new block is not guaranteed to be the same as the original block.
  734. *
  735. * RETURNS:
  736. * A pointer to the new block of memory, or NULL if the call fails.
  737. *
  738. * SEE ALSO:
  739. * .I "American National Standard for Information Systems -"
  740. * .I "Programming Language - C, ANSI X3.159-1989: General Utilities (stdlib.h)"
  741. */
  742. void *realloc 
  743.     (
  744.     void *pBlock, /* block to reallocate */
  745.     size_t newSize /* new block size */
  746.     )
  747.     {
  748.         return (memPartRealloc (memSysPartId, (char *) pBlock, 
  749. (unsigned) newSize));
  750.     }
  751. /*******************************************************************************
  752. *
  753. * cfree - free a block of memory
  754. *
  755. * This routine returns to the free memory pool a block of memory 
  756. * previously allocated with calloc().
  757. *
  758. * It is an error to free a memory block that was not previously allocated.
  759. *
  760. * RETURNS: OK, or ERROR if the the block is invalid.
  761. */
  762. STATUS cfree 
  763.     (
  764.     char *pBlock        /* pointer to block of memory to free */
  765.     )
  766.     {
  767.     return (memPartFree (memSysPartId, pBlock));
  768.     }
  769. /*******************************************************************************
  770. *
  771. * memFindMax - find the largest free block in the system memory partition
  772. *
  773. * This routine searches for the largest block in the system memory partition
  774. * free list and returns its size.
  775. *
  776. * RETURNS: The size, in bytes, of the largest available block.
  777. *
  778. * SEE ALSO: memPartFindMax()
  779. */
  780. int memFindMax (void)
  781.     {
  782.     return (memPartFindMax (memSysPartId));
  783.     }
  784. /*******************************************************************************
  785. *
  786. * memSemInit - initialize the partition semaphore as type mutex
  787. *
  788. * This routine initializes the partition semaphore as a mutex semaphore with
  789. * the mutex options stored in mutexOptionsMemLib.  This function is called
  790. * indirectly from memPartInit ().  This coupling allows alternative semaphore
  791. * types to serve as the basis for memory partition interlocking.
  792. */
  793. LOCAL void memSemInit
  794.     (
  795.     PART_ID partId /* partition to initialize semaphore for */
  796.     )
  797.     {
  798.     semMInit (&partId->sem, mutexOptionsMemLib);
  799.     }