MagickCore 7.0.10
memory.c
Go to the documentation of this file.
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% The Wizard's Toolkit Memory Allocation Methods %
14% %
15% Software Design %
16% Cristy %
17% July 1998 %
18% %
19% %
20% Copyright @ 1999 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% https://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% We provide these memory allocators:
37%
38% AcquireCriticalMemory(): allocate a small memory request with
39% AcquireMagickMemory(), however, on fail throw a fatal exception and exit.
40% Free the memory reserve with RelinquishMagickMemory().
41% AcquireAlignedMemory(): allocate a small memory request that is aligned
42% on a cache line. On fail, return NULL for possible recovery.
43% Free the memory reserve with RelinquishMagickMemory().
44% AcquireMagickMemory()/ResizeMagickMemory(): allocate a small to medium
45% memory request, typically with malloc()/realloc(). On fail, return NULL
46% for possible recovery. Free the memory reserve with
47% RelinquishMagickMemory().
48% AcquireQuantumMemory()/ResizeQuantumMemory(): allocate a small to medium
49% memory request. This is a secure memory allocator as it accepts two
50% parameters, count and quantum, to ensure the request does not overflow.
51% It also check to ensure the request does not exceed the maximum memory
52% per the security policy. Free the memory reserve with
53% RelinquishMagickMemory().
54% AcquireVirtualMemory(): allocate a large memory request either in heap,
55% memory-mapped, or memory-mapped on disk depending on whether heap
56% allocation fails or if the request exceeds the maximum memory policy.
57% Free the memory reserve with RelinquishVirtualMemory().
58% ResetMagickMemory(): fills the bytes of the memory area with a constant
59% byte.
60%
61% In addition, we provide hooks for your own memory constructor/destructors.
62% You can also utilize our internal custom allocator as follows: Segregate
63% our memory requirements from any program that calls our API. This should
64% help reduce the risk of others changing our program state or causing memory
65% corruption.
66%
67% Our custom memory allocation manager implements a best-fit allocation policy
68% using segregated free lists. It uses a linear distribution of size classes
69% for lower sizes and a power of two distribution of size classes at higher
70% sizes. It is based on the paper, "Fast Memory Allocation using Lazy Fits."
71% written by Yoo C. Chung.
72%
73% By default, ANSI memory methods are called (e.g. malloc). Use the
74% custom memory allocator by defining WIZARDSTOOLKIT_EMBEDDABLE_SUPPORT
75% to allocate memory with private anonymous mapping rather than from the
76% heap.
77%
78*/
79
80/*
81 Include declarations.
82*/
83#include "wizard/studio.h"
84#include "wizard/blob.h"
85#include "wizard/blob-private.h"
86#include "wizard/exception.h"
88#include "wizard/memory_.h"
90#include "wizard/resource_.h"
91#include "wizard/semaphore.h"
92#include "wizard/string_.h"
94
95/*
96 Define declarations.
97*/
98#define BlockFooter(block,size) \
99 ((size_t *) ((char *) (block)+(size)-2*sizeof(size_t)))
100#define BlockHeader(block) ((size_t *) (block)-1)
101#define BlockSize 4096
102#define BlockThreshold 1024
103#define MaxBlockExponent 16
104#define MaxBlocks ((BlockThreshold/(4*sizeof(size_t)))+MaxBlockExponent+1)
105#define MaxSegments 1024
106#define MemoryGuard ((0xdeadbeef << 31)+0xdeafdeed)
107#define NextBlock(block) ((char *) (block)+SizeOfBlock(block))
108#define NextBlockInList(block) (*(void **) (block))
109#define PreviousBlock(block) ((char *) (block)-(*((size_t *) (block)-2)))
110#define PreviousBlockBit 0x01
111#define PreviousBlockInList(block) (*((void **) (block)+1))
112#define SegmentSize (2*1024*1024)
113#define SizeMask (~0x01)
114#define SizeOfBlock(block) (*BlockHeader(block) & SizeMask)
115
116/*
117 Typedef declarations.
118*/
119typedef enum
120{
126
127typedef struct _DataSegmentInfo
128{
129 void
132
135
136 size_t
138
139 struct _DataSegmentInfo
143
145{
148
151
155
157{
158 char
160
163
164 size_t
166
167 void
169
170 size_t
172};
173
174typedef struct _MemoryPool
175{
176 size_t
178
179 void
181
182 size_t
184
189
190/*
191 Global declarations.
192*/
195 {
196 (AcquireMemoryHandler) malloc,
197 (ResizeMemoryHandler) realloc,
199 };
200
201#if defined(WIZARDSTOOLKIT_EMBEDDABLE_SUPPORT)
202static MemoryPool
203 memory_pool;
204
205static SemaphoreInfo
206 *memory_semaphore = (SemaphoreInfo *) NULL;
207
208static volatile DataSegmentInfo
209 *free_segments = (DataSegmentInfo *) NULL;
210
211/*
212 Forward declarations.
213*/
215 ExpandHeap(size_t);
216#endif
217
218/*
219%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
220% %
221% %
222% %
223% A c q u i r e A l i g n e d M e m o r y %
224% %
225% %
226% %
227%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228%
229% AcquireAlignedMemory() returns a pointer to a block of memory at least size
230% bytes whose address is aligned on a cache line or page boundary.
231%
232% The format of the AcquireAlignedMemory method is:
233%
234% void *AcquireAlignedMemory(const size_t count,const size_t quantum)
235%
236% A description of each parameter follows:
237%
238% o count: the number of quantum elements to allocate.
239%
240% o quantum: the number of bytes in each quantum.
241%
242*/
243WizardExport void *AcquireAlignedMemory(const size_t count,const size_t quantum)
244{
245#define AlignedExtent(size,alignment) \
246 (((size)+((alignment)-1)) & ~((alignment)-1))
247
248 size_t
249 alignment,
250 extent,
251 size;
252
253 void
254 *memory;
255
256 size=count*quantum;
257 if ((count == 0) || (quantum != (size/count)))
258 {
259 errno=ENOMEM;
260 return((void *) NULL);
261 }
262 memory=NULL;
263 alignment=CACHE_LINE_SIZE;
264 if (size > (size_t) (GetWizardPageSize() >> 1))
265 alignment=(size_t) GetWizardPageSize();
266 extent=AlignedExtent(size,CACHE_LINE_SIZE);
267 if ((size == 0) || (extent < size))
268 return((void *) NULL);
269#if defined(WIZARDSTOOLKIT_HAVE_POSIX_MEMALIGN)
270 if (posix_memalign(&memory,alignment,extent) != 0)
271 memory=NULL;
272#elif defined(WIZARDSTOOLKIT_HAVE__ALIGNED_MALLOC)
273 memory=_aligned_malloc(extent,alignment);
274#else
275 {
276 void
277 *p;
278
279 extent=(size+alignment-1)+sizeof(void *);
280 if (extent > size)
281 {
282 p=AcquireWizardMemory(extent);
283 if (p != NULL)
284 {
285 memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
286 *((void **) memory-1)=p;
287 }
288 }
289 }
290#endif
291 return(memory);
292}
293
294#if defined(WIZARDSTOOLKIT_EMBEDDABLE_SUPPORT)
295/*
296%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
297% %
298% %
299% %
300+ A c q u i r e B l o c k %
301% %
302% %
303% %
304%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
305%
306% AcquireBlock() returns a pointer to a block of memory at least size bytes
307% suitably aligned for any use.
308%
309% The format of the AcquireBlock method is:
310%
311% void *AcquireBlock(const size_t size)
312%
313% A description of each parameter follows:
314%
315% o size: the size of the memory in bytes to allocate.
316%
317*/
318
319static inline size_t AllocationPolicy(size_t size)
320{
321 size_t
322 blocksize;
323
324 /*
325 The linear distribution.
326 */
327 assert(size != 0);
328 assert(size % (4*sizeof(size_t)) == 0);
329 if (size <= BlockThreshold)
330 return(size/(4*sizeof(size_t)));
331 /*
332 Check for the largest block size.
333 */
334 if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
335 return(MaxBlocks-1L);
336 /*
337 Otherwise use a power of two distribution.
338 */
339 blocksize=BlockThreshold/(4*sizeof(size_t));
340 for ( ; size > BlockThreshold; size/=2)
341 blocksize++;
342 assert(blocksize > (BlockThreshold/(4*sizeof(size_t))));
343 assert(blocksize < (MaxBlocks-1L));
344 return(blocksize);
345}
346
347static inline void InsertFreeBlock(void *block,const size_t i)
348{
349 void
350 *next,
351 *previous;
352
353 size_t
354 size;
355
356 size=SizeOfBlock(block);
357 previous=(void *) NULL;
358 next=memory_pool.blocks[i];
359 while ((next != (void *) NULL) && (SizeOfBlock(next) < size))
360 {
361 previous=next;
362 next=NextBlockInList(next);
363 }
364 PreviousBlockInList(block)=previous;
365 NextBlockInList(block)=next;
366 if (previous != (void *) NULL)
367 NextBlockInList(previous)=block;
368 else
369 memory_pool.blocks[i]=block;
370 if (next != (void *) NULL)
371 PreviousBlockInList(next)=block;
372}
373
374static inline void RemoveFreeBlock(void *block,const size_t i)
375{
376 void
377 *next,
378 *previous;
379
380 next=NextBlockInList(block);
381 previous=PreviousBlockInList(block);
382 if (previous == (void *) NULL)
383 memory_pool.blocks[i]=next;
384 else
385 NextBlockInList(previous)=next;
386 if (next != (void *) NULL)
387 PreviousBlockInList(next)=previous;
388}
389
390static void *AcquireBlock(size_t size)
391{
392 size_t
393 i;
394
395 void
396 *block;
397
398 /*
399 Find free block.
400 */
401 size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t));
402 i=AllocationPolicy(size);
403 block=memory_pool.blocks[i];
404 while ((block != (void *) NULL) && (SizeOfBlock(block) < size))
405 block=NextBlockInList(block);
406 if (block == (void *) NULL)
407 {
408 i++;
409 while (memory_pool.blocks[i] == (void *) NULL)
410 i++;
411 block=memory_pool.blocks[i];
412 if (i >= MaxBlocks)
413 return((void *) NULL);
414 }
415 assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
416 assert(SizeOfBlock(block) >= size);
417 RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
418 if (SizeOfBlock(block) > size)
419 {
420 size_t
421 blocksize;
422
423 void
424 *next;
425
426 /*
427 Split block.
428 */
429 next=(char *) block+size;
430 blocksize=SizeOfBlock(block)-size;
431 *BlockHeader(next)=blocksize;
432 *BlockFooter(next,blocksize)=blocksize;
433 InsertFreeBlock(next,AllocationPolicy(blocksize));
434 *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask);
435 }
436 assert(size == SizeOfBlock(block));
438 memory_pool.allocation+=size;
439 return(block);
440}
441#endif
442
443/*
444%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
445% %
446% %
447% %
448% A c q u i r e V i r t u a l M e m o r y %
449% %
450% %
451% %
452%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
453%
454% AcquireVirtualMemory() allocates a pointer to a block of memory at least size
455% bytes suitably aligned for any use.
456%
457% The format of the AcquireVirtualMemory method is:
458%
459% MemoryInfo *AcquireVirtualMemory(const size_t count,const size_t quantum,
460% ExceptionInfo *exception)
461%
462% A description of each parameter follows:
463%
464% o count: the number of quantum elements to allocate.
465%
466% o quantum: the number of bytes in each quantum.
467%
468*/
470 const size_t quantum,ExceptionInfo *exception)
471{
473 *memory_info;
474
475 size_t
476 length;
477
478 length=count*quantum;
479 if ((count == 0) || (quantum != (length/count)))
480 {
481 errno=ENOMEM;
482 return((MemoryInfo *) NULL);
483 }
485 sizeof(*memory_info)));
486 if (memory_info == (MemoryInfo *) NULL)
487 ThrowFatalException(ResourceFatalError,"memory allocation failed `%s'");
488 (void) ResetWizardMemory(memory_info,0,sizeof(*memory_info));
489 memory_info->length=length;
490 memory_info->signature=WizardSignature;
492 {
493 memory_info->blob=AcquireAlignedMemory(1,length);
494 if (memory_info->blob != NULL)
495 {
496 memory_info->type=AlignedVirtualMemory;
497 return(memory_info);
498 }
499 }
502 {
503 /*
504 Heap memory failed, try anonymous memory mapping.
505 */
506 memory_info->blob=MapBlob(-1,IOMode,0,length);
507 if (memory_info->blob != NULL)
508 {
509 memory_info->type=MapVirtualMemory;
510 return(memory_info);
511 }
513 {
514 int
515 file;
516
517 /*
518 Anonymous memory mapping failed, try file-backed memory mapping.
519 If the MapResource request failed, there is no point in trying
520 file-backed memory mapping.
521 */
522 file=AcquireUniqueFileResource("",memory_info->filename,exception);
523 if (file != -1)
524 {
526 offset;
527
528 offset=(WizardOffsetType) lseek(file,length-1,SEEK_SET);
529 if ((offset == (WizardOffsetType) (length-1)) &&
530 (write(file,"",1) == 1))
531 {
532 memory_info->blob=MapBlob(file,IOMode,0,length);
533 if (memory_info->blob != NULL)
534 {
535 (void) close(file);
536 memory_info->type=MapVirtualMemory;
537 return(memory_info);
538 }
539 }
540 /*
541 File-backed memory mapping failed, delete the temporary file.
542 */
543 (void) close(file);
544 (void) RelinquishUniqueFileResource(memory_info->filename,
545 WizardTrue);
546 *memory_info->filename = '\0';
547 }
548 }
550 }
552 if (memory_info->blob == NULL)
553 {
554 memory_info->blob=AcquireWizardMemory(length);
555 if (memory_info->blob != NULL)
556 memory_info->type=UnalignedVirtualMemory;
557 }
558 if (memory_info->blob == NULL)
559 memory_info=RelinquishVirtualMemory(memory_info);
560 return(memory_info);
561}
562
563/*
564%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
565% %
566% %
567% %
568% A c q u i r e W i z a r d M e m o r y %
569% %
570% %
571% %
572%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
573%
574% AcquireWizardMemory() returns a pointer to a block of memory at least size
575% bytes suitably aligned for any use.
576%
577% The format of the AcquireWizardMemory method is:
578%
579% void *AcquireWizardMemory(const size_t size)
580%
581% A description of each parameter follows:
582%
583% o size: the size of the memory in bytes to allocate.
584%
585*/
586WizardExport void *AcquireWizardMemory(const size_t size)
587{
588 void
589 *memory;
590
591#if !defined(WIZARDSTOOLKIT_EMBEDDABLE_SUPPORT)
592 memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
593#else
594 if (memory_semaphore == (SemaphoreInfo *) NULL)
595 ActivateSemaphoreInfo(&memory_semaphore);
596 if (free_segments == (DataSegmentInfo *) NULL)
597 {
598 LockSemaphoreInfo(memory_semaphore);
599 if (free_segments == (DataSegmentInfo *) NULL)
600 {
601 ssize_t
602 i;
603
604 assert(2*sizeof(size_t) > (size_t) (~SizeMask));
605 (void) ResetWizardMemory(&memory_pool,0,sizeof(memory_pool));
606 memory_pool.allocation=SegmentSize;
607 memory_pool.blocks[MaxBlocks]=(void *) (-1);
608 for (i=0; i < MaxSegments; i++)
609 {
610 if (i != 0)
611 memory_pool.segment_pool[i].previous=
612 (&memory_pool.segment_pool[i-1]);
613 if (i != (MaxSegments-1))
614 memory_pool.segment_pool[i].next=(&memory_pool.segment_pool[i+1]);
615 }
616 free_segments=(&memory_pool.segment_pool[0]);
617 }
618 UnlockSemaphoreInfo(memory_semaphore);
619 }
620 LockSemaphoreInfo(memory_semaphore);
621 memory=AcquireBlock(size == 0 ? 1UL : size);
622 if (memory == (void *) NULL)
623 {
624 if (ExpandHeap(size == 0 ? 1UL : size) != WizardFalse)
625 memory=AcquireBlock(size == 0 ? 1UL : size);
626 }
627 UnlockSemaphoreInfo(memory_semaphore);
628#endif
629 return(memory);
630}
631
632/*
633%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
634% %
635% %
636% %
637% A c q u i r e Q u a n t u m M e m o r y %
638% %
639% %
640% %
641%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
642%
643% AcquireQuantumMemory() returns a pointer to a block of memory at least
644% count * quantum bytes suitably aligned for any use.
645%
646% The format of the AcquireQuantumMemory method is:
647%
648% void *AcquireQuantumMemory(const size_t count,const size_t quantum)
649%
650% A description of each parameter follows:
651%
652% o count: the number of quantum elements to allocate.
653%
654% o quantum: the number of bytes in each quantum.
655%
656*/
657WizardExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
658{
659 size_t
660 size;
661
662 size=count*quantum;
663 if ((count == 0) || (quantum != (size/count)))
664 {
665 errno=ENOMEM;
666 return((void *) NULL);
667 }
668 return(AcquireWizardMemory(size));
669}
670
671/*
672%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
673% %
674% %
675% %
676% C o p y W i z a r d M e m o r y %
677% %
678% %
679% %
680%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
681%
682% CopyWizardMemory() copies size bytes from memory area source to the
683% destination. Copying between objects that overlap will take place
684% correctly. It returns destination.
685%
686% The format of the CopyWizardMemory method is:
687%
688% void *CopyWizardMemory(void *destination,const void *source,
689% const size_t size)
690%
691% A description of each parameter follows:
692%
693% o destination: the destination.
694%
695% o source: the source.
696%
697% o size: the size of the memory in bytes to allocate.
698%
699*/
700WizardExport void *CopyWizardMemory(void *destination,const void *source,
701 const size_t size)
702{
703 const unsigned char
704 *p;
705
706 unsigned char
707 *q;
708
709 assert(destination != (void *) NULL);
710 assert(source != (const void *) NULL);
711 p=(const unsigned char *) source;
712 q=(unsigned char *) destination;
713 if (((q+size) < p) || (q > (p+size)))
714 switch (size)
715 {
716 default: return(memcpy(destination,source,size));
717 case 8: *q++=(*p++);
718 case 7: *q++=(*p++);
719 case 6: *q++=(*p++);
720 case 5: *q++=(*p++);
721 case 4: *q++=(*p++);
722 case 3: *q++=(*p++);
723 case 2: *q++=(*p++);
724 case 1: *q++=(*p++);
725 case 0: return(destination);
726 }
727 return(memmove(destination,source,size));
728}
729
730/*
731%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
732% %
733% %
734% %
735+ D e s t r o y W i z a r d M e m o r y %
736% %
737% %
738% %
739%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
740%
741% DestroyWizardMemory() deallocates memory associated with the memory manager.
742%
743% The format of the DestroyWizardMemory method is:
744%
745% DestroyWizardMemory(void)
746%
747*/
749{
750#if defined(WIZARDSTOOLKIT_EMBEDDABLE_SUPPORT)
751 ssize_t
752 i;
753
754 if (memory_semaphore == (SemaphoreInfo *) NULL)
755 ActivateSemaphoreInfo(&memory_semaphore);
756 LockSemaphoreInfo(memory_semaphore);
757 for (i=0; i < (ssize_t) memory_pool.number_segments; i++)
758 if (memory_pool.segments[i]->mapped == WizardFalse)
760 memory_pool.segments[i]->allocation);
761 else
762 (void) UnmapBlob(memory_pool.segments[i]->allocation,
763 memory_pool.segments[i]->length);
764 free_segments=(DataSegmentInfo *) NULL;
765 (void) ResetWizardMemory(&memory_pool,0,sizeof(memory_pool));
766 UnlockSemaphoreInfo(memory_semaphore);
767 RelinquishSemaphoreInfo(&memory_semaphore);
768#endif
769}
770
771#if defined(WIZARDSTOOLKIT_EMBEDDABLE_SUPPORT)
772/*
773%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
774% %
775% %
776% %
777+ E x p a n d H e a p %
778% %
779% %
780% %
781%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
782%
783% ExpandHeap() get more memory from the system. It returns WizardTrue on
784% success otherwise WizardFalse.
785%
786% The format of the ExpandHeap method is:
787%
788% WizardBooleanType ExpandHeap(size_t size)
789%
790% A description of each parameter follows:
791%
792% o size: the size of the memory in bytes we require.
793%
794*/
795static WizardBooleanType ExpandHeap(size_t size)
796{
798 *segment_info;
799
801 mapped;
802
803 ssize_t
804 i;
805
806 void
807 *block;
808
809 size_t
810 blocksize;
811
812 void
813 *segment;
814
815 blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
816 assert(memory_pool.number_segments < MaxSegments);
817 segment=MapBlob(-1,IOMode,0,blocksize);
818 mapped=segment != (void *) NULL ? WizardTrue : WizardFalse;
819 if (segment == (void *) NULL)
820 segment=(void *) memory_methods.acquire_memory_handler(blocksize);
821 if (segment == (void *) NULL)
822 return(WizardFalse);
823 segment_info=(DataSegmentInfo *) free_segments;
824 free_segments=segment_info->next;
825 segment_info->mapped=mapped;
826 segment_info->length=blocksize;
827 segment_info->allocation=segment;
828 segment_info->bound=(char *) segment+blocksize;
829 i=(ssize_t) memory_pool.number_segments-1;
830 for ( ; (i >= 0) && (memory_pool.segments[i]->allocation > segment); i--)
831 memory_pool.segments[i+1]=memory_pool.segments[i];
832 memory_pool.segments[i+1]=segment_info;
833 memory_pool.number_segments++;
834 size=blocksize-12*sizeof(size_t);
835 block=(char *) segment_info->allocation+4*sizeof(size_t);
836 *BlockHeader(block)=size | PreviousBlockBit;
837 *BlockFooter(block,size)=size;
838 InsertFreeBlock(block,AllocationPolicy(size));
839 block=NextBlock(block);
840 assert(block < segment_info->bound);
841 *BlockHeader(block)=2*sizeof(size_t);
843 return(WizardTrue);
844}
845#endif
846
847/*
848%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
849% %
850% %
851% %
852% G e t W i z a r d M e m o r y M e t h o d s %
853% %
854% %
855% %
856%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
857%
858% GetWizardMemoryMethods() gets the methods to acquire, resize, and destroy
859% memory.
860%
861% The format of the GetWizardMemoryMethods() method is:
862%
863% void GetWizardMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
864% ResizeMemoryHandler *resize_memory_handler,
865% DestroyMemoryHandler *destroy_memory_handler)
866%
867% A description of each parameter follows:
868%
869% o acquire_memory_handler: method to acquire memory (e.g. malloc).
870%
871% o resize_memory_handler: method to resize memory (e.g. realloc).
872%
873% o destroy_memory_handler: method to destroy memory (e.g. free).
874%
875*/
877 AcquireMemoryHandler *acquire_memory_handler,
878 ResizeMemoryHandler *resize_memory_handler,
879 DestroyMemoryHandler *destroy_memory_handler)
880{
881 assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL);
882 assert(resize_memory_handler != (ResizeMemoryHandler *) NULL);
883 assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL);
884 *acquire_memory_handler=memory_methods.acquire_memory_handler;
885 *resize_memory_handler=memory_methods.resize_memory_handler;
886 *destroy_memory_handler=memory_methods.destroy_memory_handler;
887}
888
889/*
890%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
891% %
892% %
893% %
894% G e t V i r t u a l M e m o r y B l o b %
895% %
896% %
897% %
898%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
899%
900% GetVirtualMemoryBlob() returns the virtual memory blob associated with the
901% specified MemoryInfo structure.
902%
903% The format of the GetVirtualMemoryBlob method is:
904%
905% void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
906%
907% A description of each parameter follows:
908%
909% o memory_info: The MemoryInfo structure.
910*/
912{
913 assert(memory_info != (MemoryInfo *) NULL);
914 assert(memory_info->signature == WizardSignature);
915 return(memory_info->blob);
916}
917
918/*
919%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
920% %
921% %
922% %
923% R e l i n q u i s h A l i g n e d M e m o r y %
924% %
925% %
926% %
927%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
928%
929% RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
930% or reuse.
931%
932% The format of the RelinquishAlignedMemory method is:
933%
934% void *RelinquishAlignedMemory(void *memory)
935%
936% A description of each parameter follows:
937%
938% o memory: A pointer to a block of memory to free for reuse.
939%
940*/
942{
943 if (memory == (void *) NULL)
944 return((void *) NULL);
945#if defined(WIZARDSTOOLKIT_HAVE_POSIX_MEMALIGN)
946 free(memory);
947#elif defined(WIZARDSTOOLKIT_HAVE__ALIGNED_MALLOC)
948 _aligned_free(memory);
949#else
950 RelinquishWizardMemory(*((void **) memory-1));
951#endif
952 return(NULL);
953}
954
955/*
956%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
957% %
958% %
959% %
960% R e l i n q u i s h V i r t u a l M e m o r y %
961% %
962% %
963% %
964%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
965%
966% RelinquishVirtualMemory() destroys the MemoryInfo structure returned by a
967% previous call to AcquireVirtualMemory().
968%
969% The format of the RelinquishVirtualMemory method is:
970%
971% void *RelinquishVirtualMemory(MemoryInfo *memory_info)
972%
973% A description of each parameter follows:
974%
975% o memory_info: A pointer to a block of memory to free for reuse.
976%
977*/
979{
980 assert(memory_info != (MemoryInfo *) NULL);
981 assert(memory_info->signature == WizardSignature);
982 if (memory_info->blob != (void *) NULL)
983 switch (memory_info->type)
984 {
986 {
987 memory_info->blob=RelinquishAlignedMemory(memory_info->blob);
989 break;
990 }
991 case MapVirtualMemory:
992 {
993 (void) UnmapBlob(memory_info->blob,memory_info->length);
994 memory_info->blob=NULL;
996 if (*memory_info->filename != '\0')
997 {
998 (void) RelinquishUniqueFileResource(memory_info->filename,
999 WizardTrue);
1001 }
1002 break;
1003 }
1005 default:
1006 {
1007 memory_info->blob=RelinquishWizardMemory(memory_info->blob);
1008 break;
1009 }
1010 }
1011 memory_info->signature=(~WizardSignature);
1012 memory_info=(MemoryInfo *) RelinquishAlignedMemory(memory_info);
1013 return(memory_info);
1014}
1015
1016/*
1017%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1018% %
1019% %
1020% %
1021% R e l i n q u i s h W i z a r d M e m o r y %
1022% %
1023% %
1024% %
1025%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1026%
1027% RelinquishWizardMemory() zeros memory that has been allocated, frees it for
1028% reuse.
1029%
1030% The format of the RelinquishWizardMemory method is:
1031%
1032% void *RelinquishWizardMemory(void *memory)
1033%
1034% A description of each parameter follows:
1035%
1036% o memory: A pointer to a block of memory to free for reuse.
1037%
1038*/
1040{
1041 if (memory == (void *) NULL)
1042 return((void *) NULL);
1043#if !defined(WIZARDSTOOLKIT_EMBEDDABLE_SUPPORT)
1045#else
1046 assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
1047 assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
1048 LockSemaphoreInfo(memory_semaphore);
1049 if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
1050 {
1051 void
1052 *previous;
1053
1054 /*
1055 Coalesce with previous adjacent block.
1056 */
1057 previous=PreviousBlock(memory);
1058 RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
1059 *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
1060 (*BlockHeader(previous) & ~SizeMask);
1061 memory=previous;
1062 }
1063 if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
1064 {
1065 void
1066 *next;
1067
1068 /*
1069 Coalesce with next adjacent block.
1070 */
1071 next=NextBlock(memory);
1072 RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
1073 *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
1074 (*BlockHeader(memory) & ~SizeMask);
1075 }
1076 *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
1077 *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
1078 InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
1079 UnlockSemaphoreInfo(memory_semaphore);
1080#endif
1081 return((void *) NULL);
1082}
1083
1084/*
1085%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1086% %
1087% %
1088% %
1089% R e s e t W i z a r d M e m o r y %
1090% %
1091% %
1092% %
1093%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1094%
1095% ResetWizardMemory() fills the first size bytes of the memory area pointed to
1096% by memory with the constant byte c. We use a volatile pointer when
1097% updating the byte string. Most compilers will avoid optimizing away access
1098% to a volatile pointer, even if the pointer appears to be unused after the
1099% call.
1100%
1101% The format of the ResetWizardMemory method is:
1102%
1103% void *ResetWizardMemory(void *memory,int c,const size_t size)
1104%
1105% A description of each parameter follows:
1106%
1107% o memory: A pointer to a memory allocation.
1108%
1109% o c: Set the memory to this value.
1110%
1111% o size: Size of the memory to reset.
1112%
1113*/
1114WizardExport void *ResetWizardMemory(void *memory,int c,const size_t size)
1115{
1116 volatile unsigned char
1117 *p = (volatile unsigned char *) memory;
1118
1119 size_t
1120 n = size;
1121
1122 assert(memory != (void *) NULL);
1123 while (n-- != 0)
1124 *p++=(unsigned char) c;
1125 return(memory);
1126}
1127
1128/*
1129%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1130% %
1131% %
1132% %
1133% R e s i z e W i z a r d M e m o r y %
1134% %
1135% %
1136% %
1137%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1138%
1139% ResizeWizardMemory() changes the size of the memory and returns a pointer to
1140% the (possibly moved) block. The contents will be unchanged up to the
1141% lesser of the new and old sizes.
1142%
1143% The format of the ResizeWizardMemory method is:
1144%
1145% void *ResizeWizardMemory(void *memory,const size_t size)
1146%
1147% A description of each parameter follows:
1148%
1149% o memory: A pointer to a memory allocation.
1150%
1151% o size: the new size of the allocated memory.
1152%
1153*/
1154
1155#if defined(WIZARDSTOOLKIT_EMBEDDABLE_SUPPORT)
1156static inline void *ResizeBlock(void *block,size_t size)
1157{
1158 void
1159 *memory;
1160
1161 if (block == (void *) NULL)
1162 return(AcquireBlock(size));
1163 memory=AcquireBlock(size);
1164 if (memory == (void *) NULL)
1165 return((void *) NULL);
1166 if (size <= (SizeOfBlock(block)-sizeof(size_t)))
1167 (void) memcpy(memory,block,size);
1168 else
1169 (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
1170 memory_pool.allocation+=size;
1171 return(memory);
1172}
1173#endif
1174
1175WizardExport void *ResizeWizardMemory(void *memory,const size_t size)
1176{
1177 void
1178 *block;
1179
1180 if (memory == (void *) NULL)
1181 return(AcquireWizardMemory(size));
1182#if !defined(WIZARDSTOOLKIT_EMBEDDABLE_SUPPORT)
1183 block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
1184 if (block == (void *) NULL)
1185 memory=RelinquishWizardMemory(memory);
1186#else
1187 LockSemaphoreInfo(memory_semaphore);
1188 block=ResizeBlock(memory,size == 0 ? 1UL : size);
1189 if (block == (void *) NULL)
1190 {
1191 if (ExpandHeap(size == 0 ? 1UL : size) == WizardFalse)
1192 {
1193 UnlockSemaphoreInfo(memory_semaphore);
1194 memory=RelinquishWizardMemory(memory);
1196 "memory allocation failed `%s'");
1197 }
1198 block=ResizeBlock(memory,size == 0 ? 1UL : size);
1199 assert(block != (void *) NULL);
1200 }
1201 UnlockSemaphoreInfo(memory_semaphore);
1202 memory=RelinquishWizardMemory(memory);
1203#endif
1204 return(block);
1205}
1206
1207/*
1208%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1209% %
1210% %
1211% %
1212% R e s i z e Q u a n t u m M e m o r y %
1213% %
1214% %
1215% %
1216%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1217%
1218% ResizeQuantumMemory() changes the size of the memory and returns a pointer
1219% to the (possibly moved) block. The contents will be unchanged up to the
1220% lesser of the new and old sizes.
1221%
1222% The format of the ResizeQuantumMemory method is:
1223%
1224% void *ResizeQuantumMemory(void *memory,const size_t count,
1225% const size_t quantum)
1226%
1227% A description of each parameter follows:
1228%
1229% o memory: A pointer to a memory allocation.
1230%
1231% o count: the number of quantum elements to allocate.
1232%
1233% o quantum: the number of bytes in each quantum.
1234%
1235*/
1236WizardExport void *ResizeQuantumMemory(void *memory,const size_t count,
1237 const size_t quantum)
1238{
1239 size_t
1240 size;
1241
1242 size=count*quantum;
1243 if ((count == 0) || (quantum != (size/count)))
1244 {
1245 memory=RelinquishWizardMemory(memory);
1246 errno=ENOMEM;
1247 return((void *) NULL);
1248 }
1249 return(ResizeWizardMemory(memory,size));
1250}
1251
1252/*
1253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1254% %
1255% %
1256% %
1257% S e t W i z a r d M e m o r y M e t h o d s %
1258% %
1259% %
1260% %
1261%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1262%
1263% SetWizardMemoryMethods() sets the methods to acquire, resize, and destroy
1264% memory.
1265%
1266% The format of the SetWizardMemoryMethods() method is:
1267%
1268% SetWizardMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
1269% ResizeMemoryHandler resize_memory_handler,
1270% DestroyMemoryHandler destroy_memory_handler)
1271%
1272% A description of each parameter follows:
1273%
1274% o acquire_memory_handler: method to acquire memory (e.g. malloc).
1275%
1276% o resize_memory_handler: method to resize memory (e.g. realloc).
1277%
1278% o destroy_memory_handler: method to destroy memory (e.g. free).
1279%
1280*/
1282 AcquireMemoryHandler acquire_memory_handler,
1283 ResizeMemoryHandler resize_memory_handler,
1284 DestroyMemoryHandler destroy_memory_handler)
1285{
1286 /*
1287 Set memory methods.
1288 */
1289 if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
1290 memory_methods.acquire_memory_handler=acquire_memory_handler;
1291 if (resize_memory_handler != (ResizeMemoryHandler) NULL)
1292 memory_methods.resize_memory_handler=resize_memory_handler;
1293 if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
1294 memory_methods.destroy_memory_handler=destroy_memory_handler;
1295}
WizardExport WizardBooleanType UnmapBlob(void *map, const size_t length)
Definition blob.c:1841
WizardExport void * MapBlob(int file, const MapMode mode, const WizardOffsetType offset, const size_t length)
Definition blob.c:920
@ IOMode
Definition blob.h:35
#define ThrowFatalException(severity, tag)
@ ResourceFatalError
Definition exception.h:121
#define WizardAssumeAligned(address)
#define CACHE_LINE_SIZE
#define MaxSegments
Definition memory.c:105
VirtualMemoryType
Definition memory.c:120
@ UndefinedVirtualMemory
Definition memory.c:121
@ UnalignedVirtualMemory
Definition memory.c:124
@ MapVirtualMemory
Definition memory.c:123
@ AlignedVirtualMemory
Definition memory.c:122
WizardExport MemoryInfo * AcquireVirtualMemory(const size_t count, const size_t quantum, ExceptionInfo *exception)
Definition memory.c:469
WizardExport void * AcquireWizardMemory(const size_t size)
Definition memory.c:586
struct _DataSegmentInfo DataSegmentInfo
#define NextBlockInList(block)
Definition memory.c:108
#define PreviousBlock(block)
Definition memory.c:109
#define MaxBlocks
Definition memory.c:104
WizardExport void * AcquireAlignedMemory(const size_t count, const size_t quantum)
Definition memory.c:243
WizardExport void * GetVirtualMemoryBlob(const MemoryInfo *memory_info)
Definition memory.c:911
struct _MemoryPool MemoryPool
WizardExport void DestroyWizardMemory(void)
Definition memory.c:748
#define PreviousBlockInList(block)
Definition memory.c:111
WizardExport void * RelinquishAlignedMemory(void *memory)
Definition memory.c:941
WizardExport void * CopyWizardMemory(void *destination, const void *source, const size_t size)
Definition memory.c:700
#define BlockHeader(block)
Definition memory.c:100
WizardExport MemoryInfo * RelinquishVirtualMemory(MemoryInfo *memory_info)
Definition memory.c:978
#define BlockThreshold
Definition memory.c:102
#define SizeMask
Definition memory.c:113
WizardExport void SetWizardMemoryMethods(AcquireMemoryHandler acquire_memory_handler, ResizeMemoryHandler resize_memory_handler, DestroyMemoryHandler destroy_memory_handler)
Definition memory.c:1281
WizardExport void * ResizeWizardMemory(void *memory, const size_t size)
Definition memory.c:1175
WizardExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition memory.c:657
#define SizeOfBlock(block)
Definition memory.c:114
WizardExport void * RelinquishWizardMemory(void *memory)
Definition memory.c:1039
WizardExport void * ResizeQuantumMemory(void *memory, const size_t count, const size_t quantum)
Definition memory.c:1236
WizardExport void GetWizardMemoryMethods(AcquireMemoryHandler *acquire_memory_handler, ResizeMemoryHandler *resize_memory_handler, DestroyMemoryHandler *destroy_memory_handler)
Definition memory.c:876
#define SegmentSize
Definition memory.c:112
#define BlockFooter(block, size)
Definition memory.c:98
#define PreviousBlockBit
Definition memory.c:110
WizardExport void * ResetWizardMemory(void *memory, int c, const size_t size)
Definition memory.c:1114
static WizardMemoryMethods memory_methods
Definition memory.c:194
struct _WizardMemoryMethods WizardMemoryMethods
#define AlignedExtent(size, alignment)
#define NextBlock(block)
Definition memory.c:107
#define MaxBlockExponent
Definition memory.c:103
void *(*)(*) *(* ResizeMemoryHandler)(void *, size_t) wizard_alloc_size(2)
Definition memory_.h:31
void *(* AcquireMemoryHandler)(size_t) wizard_alloc_size(1)
Definition memory_.h:29
void *(*)(* DestroyMemoryHandler)(void *)
Definition memory_.h:30
#define WizardExport
#define WizardPathExtent
#define WizardSignature
WizardExport WizardBooleanType AcquireWizardResource(const ResourceType type, const WizardSizeType size)
Definition resource.c:388
WizardExport void RelinquishWizardResource(const ResourceType type, const WizardSizeType size)
Definition resource.c:746
WizardExport WizardBooleanType RelinquishUniqueFileResource(const char *path, const WizardBooleanType trash)
Definition resource.c:843
WizardExport int AcquireUniqueFileResource(const char *path, char *filename, ExceptionInfo *exception)
Definition resource.c:250
@ DiskResource
Definition resource_.h:36
@ MapResource
Definition resource_.h:38
@ MemoryResource
Definition resource_.h:39
WizardExport void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info)
Definition semaphore.c:338
WizardExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition semaphore.c:282
WizardExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition semaphore.c:437
WizardExport void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info)
Definition semaphore.c:247
void * allocation
Definition memory.c:130
WizardBooleanType mapped
Definition memory.c:134
struct _DataSegmentInfo * previous
Definition memory.c:139
size_t length
Definition memory.c:137
struct _DataSegmentInfo * next
Definition memory.c:141
char filename[WizardPathExtent]
Definition memory.c:159
void * blob
Definition memory.c:168
size_t signature
Definition memory.c:171
size_t length
Definition memory.c:165
VirtualMemoryType type
Definition memory.c:162
DataSegmentInfo * segments[MaxSegments]
Definition memory.c:186
void * blocks[MaxBlocks+1]
Definition memory.c:180
DataSegmentInfo segment_pool[MaxSegments]
Definition memory.c:187
size_t number_segments
Definition memory.c:183
size_t allocation
Definition memory.c:177
ResizeMemoryHandler resize_memory_handler
Definition memory.c:150
DestroyMemoryHandler destroy_memory_handler
Definition memory.c:153
AcquireMemoryHandler acquire_memory_handler
Definition memory.c:147
WizardPrivate ssize_t GetWizardPageSize(void)
Definition utility.c:817
ssize_t WizardOffsetType
Definition wizard-type.h:50
WizardBooleanType
Definition wizard-type.h:26
@ WizardTrue
Definition wizard-type.h:28
@ WizardFalse
Definition wizard-type.h:27