PageRenderTime 55ms CodeModel.GetById 31ms RepoModel.GetById 1ms app.codeStats 0ms

/plugins/ImageMagick-6.3.2/magick/memory.c

https://bitbucket.org/sisko/operation-caribou
C | 700 lines | 382 code | 38 blank | 280 comment | 89 complexity | 91136829251533e72bf5154c01e09196 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1
  1. /*
  2. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3. % %
  4. % %
  5. % %
  6. % M M EEEEE M M OOO RRRR Y Y %
  7. % MM MM E MM MM O O R R Y Y %
  8. % M M M EEE M M M O O RRRR Y %
  9. % M M E M M O O R R Y %
  10. % M M EEEEE M M OOO R R Y %
  11. % %
  12. % %
  13. % ImageMagick Memory Allocation Methods %
  14. % %
  15. % Software Design %
  16. % John Cristy %
  17. % July 1998 %
  18. % %
  19. % %
  20. % Copyright 1999-2006 ImageMagick Studio LLC, a non-profit organization %
  21. % dedicated to making software imaging solutions freely available. %
  22. % %
  23. % You may not use this file except in compliance with the License. You may %
  24. % obtain a copy of the License at %
  25. % %
  26. % http://www.imagemagick.org/script/license.php %
  27. % %
  28. % Unless required by applicable law or agreed to in writing, software %
  29. % distributed under the License is distributed on an "AS IS" BASIS, %
  30. % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
  31. % See the License for the specific language governing permissions and %
  32. % limitations under the License. %
  33. % %
  34. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  35. %
  36. % Segregate our memory requirements from any program that calls our API. This
  37. % should help reduce the risk of others changing our program state or causing
  38. % memory corruption.
  39. %
  40. % Our custom memory allocation manager implements a best-fit allocation policy
  41. % using segregated free lists. It uses a linear distribution of size classes
  42. % for lower sizes and a power of two distribution of size classes at higher
  43. % sizes. It is based on the paper, "Fast Memory Allocation using Lazy Fits."
  44. % written by Yoo C. Chung.
  45. %
  46. % By default, ANSI memory methods are called (e.g. malloc). Use the
  47. % custom memory allocator by defining UseEmbeddableMagick. The custom memory
  48. % allocator has the advantage of using memory-mapped heap allocation which
  49. % permits the virtual memory to be returned to the system in all cases, unlike
  50. % the ANSI memory methods that typically only memory-map large allocations.
  51. %
  52. */
  53. /*
  54. Include declarations.
  55. */
  56. #include "magick/studio.h"
  57. #include "magick/blob.h"
  58. #include "magick/blob-private.h"
  59. #include "magick/exception.h"
  60. #include "magick/exception-private.h"
  61. #include "magick/memory_.h"
  62. #include "magick/semaphore.h"
  63. #include "magick/string_.h"
  64. /*
  65. Define declarations.
  66. */
  67. #define BlockFooter(block,size) \
  68. ((size_t *) ((char *) (block)+(size)-2*sizeof(size_t)))
  69. #define BlockHeader(block) ((size_t *) (block)-1)
  70. #define BlockSize 4096
  71. #define BlockThreshold 1024
  72. #define MaxBlockExponent 16
  73. #define MaxBlocks ((BlockThreshold/(4*sizeof(size_t)))+MaxBlockExponent+1)
  74. #define MaxSegments 1024
  75. #define MemoryGuard ((0xdeadbeef << 31)+0xdeafdeed)
  76. #define NextBlock(block) ((char *) (block)+SizeOfBlock(block))
  77. #define NextBlockInList(block) (*(void **) (block))
  78. #define PreviousBlock(block) ((char *) (block)-(*((size_t *) (block)-2)))
  79. #define PreviousBlockBit 0x01
  80. #define PreviousBlockInList(block) (*((void **) (block)+1))
  81. #define SegmentSize (2*1024*1024)
  82. #define SizeMask (~0x01)
  83. #define SizeOfBlock(block) (*BlockHeader(block) & SizeMask)
  84. /*
  85. Typedef declarations.
  86. */
  87. typedef struct _DataSegmentInfo
  88. {
  89. void
  90. *allocation,
  91. *bound;
  92. MagickBooleanType
  93. mapped;
  94. size_t
  95. length;
  96. struct _DataSegmentInfo
  97. *previous,
  98. *next;
  99. } DataSegmentInfo;
  100. typedef struct _MemoryInfo
  101. {
  102. size_t
  103. allocation;
  104. void
  105. *blocks[MaxBlocks+1];
  106. size_t
  107. number_segments;
  108. DataSegmentInfo
  109. *segments[MaxSegments],
  110. segment_pool[MaxSegments];
  111. } MemoryInfo;
  112. /*
  113. Global declarations.
  114. */
  115. #if defined(UseEmbeddableMagick)
  116. static MemoryInfo
  117. memory_info;
  118. static SemaphoreInfo
  119. *memory_semaphore = (SemaphoreInfo *) NULL;
  120. static volatile DataSegmentInfo
  121. *free_segments = (DataSegmentInfo *) NULL;
  122. /*
  123. Forward declarations.
  124. */
  125. static MagickBooleanType
  126. ExpandHeap(size_t);
  127. #endif
  128. #if defined(UseEmbeddableMagick)
  129. /*
  130. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  131. % %
  132. % %
  133. % %
  134. + A c q u i r e B l o c k %
  135. % %
  136. % %
  137. % %
  138. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  139. %
  140. % AcquireBlock() returns a pointer to a block of memory at least size bytes
  141. % suitably aligned for any use.
  142. %
  143. % The format of the AcquireBlock method is:
  144. %
  145. % void *AcquireBlock(const size_t size)
  146. %
  147. % A description of each parameter follows:
  148. %
  149. % o size: The size of the memory in bytes to allocate.
  150. %
  151. */
  152. static inline size_t AllocationPolicy(size_t size)
  153. {
  154. register size_t
  155. blocksize;
  156. /*
  157. The linear distribution.
  158. */
  159. assert(size != 0);
  160. assert(size % (4*sizeof(size_t)) == 0);
  161. if (size <= BlockThreshold)
  162. return(size/(4*sizeof(size_t)));
  163. /*
  164. Check for the largest block size.
  165. */
  166. if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
  167. return(MaxBlocks-1L);
  168. /*
  169. Otherwise use a power of two distribution.
  170. */
  171. blocksize=BlockThreshold/(4*sizeof(size_t));
  172. for ( ; size > BlockThreshold; size/=2)
  173. blocksize++;
  174. assert(blocksize > (BlockThreshold/(4*sizeof(size_t))));
  175. assert(blocksize < (MaxBlocks-1L));
  176. return(blocksize);
  177. }
  178. static inline void InsertFreeBlock(void *block,const size_t i)
  179. {
  180. register void
  181. *next,
  182. *previous;
  183. size_t
  184. size;
  185. size=SizeOfBlock(block);
  186. previous=(void *) NULL;
  187. next=memory_info.blocks[i];
  188. while ((next != (void *) NULL) && (SizeOfBlock(next) < size))
  189. {
  190. previous=next;
  191. next=NextBlockInList(next);
  192. }
  193. PreviousBlockInList(block)=previous;
  194. NextBlockInList(block)=next;
  195. if (previous != (void *) NULL)
  196. NextBlockInList(previous)=block;
  197. else
  198. memory_info.blocks[i]=block;
  199. if (next != (void *) NULL)
  200. PreviousBlockInList(next)=block;
  201. }
  202. static inline void RemoveFreeBlock(void *block,const size_t i)
  203. {
  204. register void
  205. *next,
  206. *previous;
  207. next=NextBlockInList(block);
  208. previous=PreviousBlockInList(block);
  209. if (previous == (void *) NULL)
  210. memory_info.blocks[i]=next;
  211. else
  212. NextBlockInList(previous)=next;
  213. if (next != (void *) NULL)
  214. PreviousBlockInList(next)=previous;
  215. }
  216. static void *AcquireBlock(size_t size)
  217. {
  218. register size_t
  219. i;
  220. register void
  221. *block;
  222. /*
  223. Find free block.
  224. */
  225. size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t));
  226. i=AllocationPolicy(size);
  227. block=memory_info.blocks[i];
  228. while ((block != (void *) NULL) && (SizeOfBlock(block) < size))
  229. block=NextBlockInList(block);
  230. if (block == (void *) NULL)
  231. {
  232. i++;
  233. while (memory_info.blocks[i] == (void *) NULL)
  234. i++;
  235. block=memory_info.blocks[i];
  236. if (i >= MaxBlocks)
  237. return((void *) NULL);
  238. }
  239. assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
  240. assert(SizeOfBlock(block) >= size);
  241. RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
  242. if (SizeOfBlock(block) > size)
  243. {
  244. size_t
  245. blocksize;
  246. void
  247. *next;
  248. /*
  249. Split block.
  250. */
  251. next=(char *) block+size;
  252. blocksize=SizeOfBlock(block)-size;
  253. *BlockHeader(next)=blocksize;
  254. *BlockFooter(next,blocksize)=blocksize;
  255. InsertFreeBlock(next,AllocationPolicy(blocksize));
  256. *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask);
  257. }
  258. assert(size == SizeOfBlock(block));
  259. *BlockHeader(NextBlock(block))|=PreviousBlockBit;
  260. memory_info.allocation+=size;
  261. return(block);
  262. }
  263. #endif
  264. /*
  265. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  266. % %
  267. % %
  268. % %
  269. % A c q u i r e M a g i c k M e m o r y %
  270. % %
  271. % %
  272. % %
  273. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  274. %
  275. % AcquireMagickMemory() returns a pointer to a block of memory at least size
  276. % bytes suitably aligned for any use.
  277. %
  278. % The format of the AcquireMagickMemory method is:
  279. %
  280. % void *AcquireMagickMemory(const size_t size)
  281. %
  282. % A description of each parameter follows:
  283. %
  284. % o size: The size of the memory in bytes to allocate.
  285. %
  286. */
  287. MagickExport void *AcquireMagickMemory(const size_t size)
  288. {
  289. register void
  290. *memory;
  291. #if !defined(UseEmbeddableMagick)
  292. memory=malloc(size == 0 ? 1UL : size);
  293. #else
  294. if (free_segments == (DataSegmentInfo *) NULL)
  295. {
  296. AcquireSemaphoreInfo(&memory_semaphore);
  297. if (free_segments == (DataSegmentInfo *) NULL)
  298. {
  299. register long
  300. i;
  301. assert(2*sizeof(size_t) > (size_t) (~SizeMask));
  302. (void) ResetMagickMemory(&memory_info,0,sizeof(memory_info));
  303. memory_info.allocation=SegmentSize;
  304. memory_info.blocks[MaxBlocks]=(void *) (-1);
  305. for (i=0; i < MaxSegments; i++)
  306. {
  307. if (i != 0)
  308. memory_info.segment_pool[i].previous=
  309. (&memory_info.segment_pool[i-1]);
  310. if (i != (MaxSegments-1))
  311. memory_info.segment_pool[i].next=(&memory_info.segment_pool[i+1]);
  312. }
  313. free_segments=(&memory_info.segment_pool[0]);
  314. }
  315. RelinquishSemaphoreInfo(memory_semaphore);
  316. }
  317. AcquireSemaphoreInfo(&memory_semaphore);
  318. memory=AcquireBlock(size == 0 ? 1UL : size);
  319. if (memory == (void *) NULL)
  320. {
  321. if (ExpandHeap(size == 0 ? 1UL : size) != MagickFalse)
  322. memory=AcquireBlock(size == 0 ? 1UL : size);
  323. }
  324. RelinquishSemaphoreInfo(memory_semaphore);
  325. #endif
  326. return(memory);
  327. }
  328. /*
  329. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  330. % %
  331. % %
  332. % %
  333. % C o p y M a g i c k M e m o r y %
  334. % %
  335. % %
  336. % %
  337. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  338. %
  339. % CopyMagickMemory() copies size bytes from memory area source to the
  340. % destination. Copying between objects that overlap will take place
  341. % correctly. It returns destination.
  342. %
  343. % The format of the CopyMagickMemory method is:
  344. %
  345. % void *CopyMagickMemory(void *destination,const void *source,
  346. % const size_t size)
  347. %
  348. % A description of each parameter follows:
  349. %
  350. % o destination: The destination.
  351. %
  352. % o source: The source.
  353. %
  354. % o size: The size of the memory in bytes to allocate.
  355. %
  356. */
  357. MagickExport void *CopyMagickMemory(void *destination,const void *source,
  358. const size_t size)
  359. {
  360. register const unsigned char
  361. *p;
  362. register unsigned char
  363. *q;
  364. assert(destination != (void *) NULL);
  365. assert(source != (const void *) NULL);
  366. if ((size == 0) || (source == destination))
  367. return(destination);
  368. p=(const unsigned char *) source;
  369. q=(unsigned char *) destination;
  370. if ((q >= (p+size)) || (p >= (q+size)))
  371. return(memcpy(destination,source,size));
  372. return(memmove(destination,source,size));
  373. }
  374. /*
  375. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  376. % %
  377. % %
  378. % %
  379. + D e s t r o y M a g i c k M e m o r y %
  380. % %
  381. % %
  382. % %
  383. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  384. %
  385. % DestroyMagickMemory() deallocates memory associated with the memory manager.
  386. %
  387. % The format of the DestroyMagickMemory method is:
  388. %
  389. % DestroyMagickMemory(void)
  390. %
  391. */
  392. MagickExport void DestroyMagickMemory(void)
  393. {
  394. #if defined(UseEmbeddableMagick)
  395. register long
  396. i;
  397. AcquireSemaphoreInfo(&memory_semaphore);
  398. RelinquishSemaphoreInfo(memory_semaphore);
  399. for (i=0; i < (long) memory_info.number_segments; i++)
  400. if (memory_info.segments[i]->mapped == MagickFalse)
  401. free(memory_info.segments[i]->allocation);
  402. else
  403. (void) UnmapBlob(memory_info.segments[i]->allocation,
  404. memory_info.segments[i]->length);
  405. free_segments=(DataSegmentInfo *) NULL;
  406. (void) ResetMagickMemory(&memory_info,0,sizeof(memory_info));
  407. memory_semaphore=DestroySemaphoreInfo(memory_semaphore);
  408. #endif
  409. }
  410. #if defined(UseEmbeddableMagick)
  411. /*
  412. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  413. % %
  414. % %
  415. % %
  416. + E x p a n d H e a p %
  417. % %
  418. % %
  419. % %
  420. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  421. %
  422. % ExpandHeap() get more memory from the system. It returns MagickTrue on
  423. % success otherwise MagickFalse.
  424. %
  425. % The format of the ExpandHeap method is:
  426. %
  427. % MagickBooleanType ExpandHeap(size_t size)
  428. %
  429. % A description of each parameter follows:
  430. %
  431. % o size: The size of the memory in bytes we require.
  432. %
  433. */
  434. static MagickBooleanType ExpandHeap(size_t size)
  435. {
  436. DataSegmentInfo
  437. *segment_info;
  438. MagickBooleanType
  439. mapped;
  440. register long
  441. i;
  442. register void
  443. *block;
  444. size_t
  445. blocksize;
  446. void
  447. *segment;
  448. blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
  449. assert(memory_info.number_segments < MaxSegments);
  450. segment=MapBlob(-1,IOMode,0,blocksize);
  451. mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
  452. if (segment == (void *) NULL)
  453. segment=(void *) malloc(blocksize);
  454. if (segment == (void *) NULL)
  455. return(MagickFalse);
  456. segment_info=(DataSegmentInfo *) free_segments;
  457. free_segments=segment_info->next;
  458. segment_info->mapped=mapped;
  459. segment_info->length=blocksize;
  460. segment_info->allocation=segment;
  461. segment_info->bound=(char *) segment+blocksize;
  462. i=(long) memory_info.number_segments-1;
  463. for ( ; (i >= 0) && (memory_info.segments[i]->allocation > segment); i--)
  464. memory_info.segments[i+1]=memory_info.segments[i];
  465. memory_info.segments[i+1]=segment_info;
  466. memory_info.number_segments++;
  467. size=blocksize-12*sizeof(size_t);
  468. block=(char *) segment_info->allocation+4*sizeof(size_t);
  469. *BlockHeader(block)=size | PreviousBlockBit;
  470. *BlockFooter(block,size)=size;
  471. InsertFreeBlock(block,AllocationPolicy(size));
  472. block=NextBlock(block);
  473. assert(block < segment_info->bound);
  474. *BlockHeader(block)=2*sizeof(size_t);
  475. *BlockHeader(NextBlock(block))=PreviousBlockBit;
  476. return(MagickTrue);
  477. }
  478. #endif
  479. /*
  480. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  481. % %
  482. % %
  483. % %
  484. % R e l i n q u i s h M a g i c k M e m o r y %
  485. % %
  486. % %
  487. % %
  488. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  489. %
  490. % RelinquishMagickMemory() zeros memory that has been allocated, frees it for
  491. % reuse.
  492. %
  493. % The format of the RelinquishMagickMemory method is:
  494. %
  495. % void *RelinquishMagickMemory(void *memory)
  496. %
  497. % A description of each parameter follows:
  498. %
  499. % o memory: A pointer to a block of memory to free for reuse.
  500. %
  501. */
  502. MagickExport void *RelinquishMagickMemory(void *memory)
  503. {
  504. if (memory == (void *) NULL)
  505. return((void *) NULL);
  506. #if !defined(UseEmbeddableMagick)
  507. free(memory);
  508. #else
  509. assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
  510. assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
  511. AcquireSemaphoreInfo(&memory_semaphore);
  512. if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
  513. {
  514. void
  515. *previous;
  516. /*
  517. Coalesce with previous adjacent block.
  518. */
  519. previous=PreviousBlock(memory);
  520. RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
  521. *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
  522. (*BlockHeader(previous) & ~SizeMask);
  523. memory=previous;
  524. }
  525. if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
  526. {
  527. void
  528. *next;
  529. /*
  530. Coalesce with next adjacent block.
  531. */
  532. next=NextBlock(memory);
  533. RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
  534. *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
  535. (*BlockHeader(memory) & ~SizeMask);
  536. }
  537. *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
  538. *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
  539. InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
  540. RelinquishSemaphoreInfo(memory_semaphore);
  541. #endif
  542. return((void *) NULL);
  543. }
  544. /*
  545. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  546. % %
  547. % %
  548. % %
  549. % R e s e t M a g i c k M e m o r y %
  550. % %
  551. % %
  552. % %
  553. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  554. %
  555. % ResetMagickMemory() fills the first size bytes of the memory area pointed to
  556. % by memory with the constant byte c.
  557. %
  558. % The format of the ResetMagickMemory method is:
  559. %
  560. % void *ResetMagickMemory(void *memory,int byte,const size_t size)
  561. %
  562. % A description of each parameter follows:
  563. %
  564. % o memory: A pointer to a memory allocation.
  565. %
  566. % o byte: Set the memory to this value.
  567. %
  568. % o size: Size of the memory to reset.
  569. %
  570. */
  571. MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
  572. {
  573. assert(memory != (void *) NULL);
  574. return(memset(memory,byte,size));
  575. }
  576. /*
  577. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  578. % %
  579. % %
  580. % %
  581. % R e s i z e M a g i c k M e m o r y %
  582. % %
  583. % %
  584. % %
  585. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  586. %
  587. % ResizeMagickMemory() changes the size of the memory and returns a pointer to
  588. % the (possibly moved) block. The contents will be unchanged up to the
  589. % lesser of the new and old sizes.
  590. %
  591. % The format of the ResizeMagickMemory method is:
  592. %
  593. % void *ResizeMagickMemory(void *memory,const size_t size)
  594. %
  595. % A description of each parameter follows:
  596. %
  597. % o memory: A pointer to a memory allocation.
  598. %
  599. % o size: The new size of the allocated memory.
  600. %
  601. */
  602. #if defined(UseEmbeddableMagick)
  603. static inline void *ResizeBlock(void *block,size_t size)
  604. {
  605. register void
  606. *memory;
  607. if (block == (void *) NULL)
  608. return(AcquireBlock(size));
  609. memory=AcquireBlock(size);
  610. if (memory == (void *) NULL)
  611. return((void *) NULL);
  612. if (size <= (SizeOfBlock(block)-sizeof(size_t)))
  613. (void) memcpy(memory,block,size);
  614. else
  615. (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
  616. memory_info.allocation+=size;
  617. return(memory);
  618. }
  619. #endif
  620. MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
  621. {
  622. register void
  623. *block;
  624. if (memory == (void *) NULL)
  625. return(AcquireMagickMemory(size));
  626. #if !defined(UseEmbeddableMagick)
  627. block=realloc(memory,size == 0 ? 1UL : size);
  628. if (block == (void *) NULL)
  629. memory=RelinquishMagickMemory(memory);
  630. #else
  631. AcquireSemaphoreInfo(&memory_semaphore);
  632. block=ResizeBlock(memory,size == 0 ? 1UL : size);
  633. if (block == (void *) NULL)
  634. {
  635. if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
  636. {
  637. RelinquishSemaphoreInfo(memory_semaphore);
  638. memory=RelinquishMagickMemory(memory);
  639. ThrowMagickFatalException(ResourceLimitFatalError,
  640. "MemoryAllocationFailed",GetExceptionMessage(errno));
  641. }
  642. block=ResizeBlock(memory,size == 0 ? 1UL : size);
  643. assert(block != (void *) NULL);
  644. }
  645. RelinquishSemaphoreInfo(memory_semaphore);
  646. memory=RelinquishMagickMemory(memory);
  647. #endif
  648. return(block);
  649. }