|
WizardsToolkit
1.0.7
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % M M EEEEE M M OOO RRRR Y Y % 00007 % MM MM E MM MM O O R R Y Y % 00008 % M M M EEE M M M O O RRRR Y % 00009 % M M E M M O O R R Y % 00010 % M M EEEEE M M OOO R R Y % 00011 % % 00012 % % 00013 % The Wizard's Toolkit Memory Allocation Methods % 00014 % % 00015 % Software Design % 00016 % John Cristy % 00017 % July 1998 % 00018 % % 00019 % % 00020 % Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization % 00021 % dedicated to making software imaging solutions freely available. % 00022 % % 00023 % You may not use this file except in compliance with the License. You may % 00024 % obtain a copy of the License at % 00025 % % 00026 % http://www.wizards-toolkit.org/script/license.php % 00027 % % 00028 % Unless required by applicable law or agreed to in writing, software % 00029 % distributed under the License is distributed on an "AS IS" BASIS, % 00030 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00031 % See the License for the specific language governing permissions and % 00032 % limitations under the License. % 00033 % % 00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00035 % 00036 % Segregate our memory requirements from any program that calls our API. This 00037 % should help reduce the risk of others changing our program state or causing 00038 % memory corruption. 00039 % 00040 % Our custom memory allocation manager implements a best-fit allocation policy 00041 % using segregated free lists. It uses a linear distribution of size classes 00042 % for lower sizes and a power of two distribution of size classes at higher 00043 % sizes. It is based on the paper, "Fast Memory Allocation using Lazy Fits." 00044 % written by Yoo C. Chung. 00045 % 00046 % By default, ANSI memory methods are called (e.g. malloc). Use the 00047 % custom memory allocator by defining WIZARDSTOOLKIT_EMBEDDABLE_SUPPORT 00048 % to allocate memory with private anonymous mapping rather than from the 00049 % heap. 00050 % 00051 */ 00052 00053 /* 00054 Include declarations. 00055 */ 00056 #include "wizard/studio.h" 00057 #include "wizard/blob.h" 00058 #include "wizard/blob-private.h" 00059 #include "wizard/exception.h" 00060 #include "wizard/exception-private.h" 00061 #include "wizard/memory_.h" 00062 #include "wizard/semaphore.h" 00063 #include "wizard/string_.h" 00064 00065 /* 00066 Define declarations. 00067 */ 00068 #define BlockFooter(block,size) \ 00069 ((size_t *) ((char *) (block)+(size)-2*sizeof(size_t))) 00070 #define BlockHeader(block) ((size_t *) (block)-1) 00071 #define BlockSize 4096 00072 #define BlockThreshold 1024 00073 #define AlignedSize (16*sizeof(void *)) 00074 #define MaxBlockExponent 16 00075 #define MaxBlocks ((BlockThreshold/(4*sizeof(size_t)))+MaxBlockExponent+1) 00076 #define MaxSegments 1024 00077 #define MemoryGuard ((0xdeadbeef << 31)+0xdeafdeed) 00078 #define NextBlock(block) ((char *) (block)+SizeOfBlock(block)) 00079 #define NextBlockInList(block) (*(void **) (block)) 00080 #define PreviousBlock(block) ((char *) (block)-(*((size_t *) (block)-2))) 00081 #define PreviousBlockBit 0x01 00082 #define PreviousBlockInList(block) (*((void **) (block)+1)) 00083 #define SegmentSize (2*1024*1024) 00084 #define SizeMask (~0x01) 00085 #define SizeOfBlock(block) (*BlockHeader(block) & SizeMask) 00086 00087 /* 00088 Typedef declarations. 00089 */ 00090 typedef struct _DataSegmentInfo 00091 { 00092 void 00093 *allocation, 00094 *bound; 00095 00096 WizardBooleanType 00097 mapped; 00098 00099 size_t 00100 length; 00101 00102 struct _DataSegmentInfo 00103 *previous, 00104 *next; 00105 } DataSegmentInfo; 00106 00107 typedef struct _MemoryInfo 00108 { 00109 size_t 00110 allocation; 00111 00112 void 00113 *blocks[MaxBlocks+1]; 00114 00115 size_t 00116 number_segments; 00117 00118 DataSegmentInfo 00119 *segments[MaxSegments], 00120 segment_pool[MaxSegments]; 00121 } MemoryInfo; 00122 00123 typedef struct _WizardMemoryMethods 00124 { 00125 AcquireMemoryHandler 00126 acquire_memory_handler; 00127 00128 ResizeMemoryHandler 00129 resize_memory_handler; 00130 00131 DestroyMemoryHandler 00132 destroy_memory_handler; 00133 } WizardMemoryMethods; 00134 00135 /* 00136 Global declarations. 00137 */ 00138 static WizardMemoryMethods 00139 memory_methods = 00140 { 00141 (AcquireMemoryHandler) malloc, 00142 (ResizeMemoryHandler) realloc, 00143 (DestroyMemoryHandler) free 00144 }; 00145 00146 #if defined(WIZARDSTOOLKIT_EMBEDDABLE_SUPPORT) 00147 static MemoryInfo 00148 memory_info; 00149 00150 static SemaphoreInfo 00151 *memory_semaphore = (SemaphoreInfo *) NULL; 00152 00153 static volatile DataSegmentInfo 00154 *free_segments = (DataSegmentInfo *) NULL; 00155 00156 /* 00157 Forward declarations. 00158 */ 00159 static WizardBooleanType 00160 ExpandHeap(size_t); 00161 #endif 00162 00163 /* 00164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00165 % % 00166 % % 00167 % % 00168 % A c q u i r e A l i g n e d M e m o r y % 00169 % % 00170 % % 00171 % % 00172 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00173 % 00174 % AcquireAlignedMemory() returns a pointer to a block of memory at least size 00175 % bytes whose address is a multiple of 16*sizeof(void *). 00176 % 00177 % The format of the AcquireAlignedMemory method is: 00178 % 00179 % void *AcquireAlignedMemory(const size_t count,const size_t quantum) 00180 % 00181 % A description of each parameter follows: 00182 % 00183 % o count: the number of quantum elements to allocate. 00184 % 00185 % o quantum: the number of bytes in each quantum. 00186 % 00187 */ 00188 00189 static inline size_t WizardMax(const size_t x,const size_t y) 00190 { 00191 if (x > y) 00192 return(x); 00193 return(y); 00194 } 00195 00196 WizardExport void *AcquireAlignedMemory(const size_t count,const size_t quantum) 00197 { 00198 size_t 00199 size; 00200 00201 size=count*quantum; 00202 if ((count == 0) || (quantum != (size/count))) 00203 { 00204 errno=ENOMEM; 00205 return((void *) NULL); 00206 } 00207 #if defined(WIZARDSTOOLKIT_HAVE_POSIX_MEMALIGN) 00208 { 00209 void 00210 *memory; 00211 00212 if (posix_memalign(&memory,AlignedSize,WizardMax(size,AlignedSize)) == 0) 00213 return(memory); 00214 } 00215 #endif 00216 return(malloc(WizardMax(size,AlignedSize))); 00217 } 00218 00219 #if defined(WIZARDSTOOLKIT_EMBEDDABLE_SUPPORT) 00220 /* 00221 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00222 % % 00223 % % 00224 % % 00225 + A c q u i r e B l o c k % 00226 % % 00227 % % 00228 % % 00229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00230 % 00231 % AcquireBlock() returns a pointer to a block of memory at least size bytes 00232 % suitably aligned for any use. 00233 % 00234 % The format of the AcquireBlock method is: 00235 % 00236 % void *AcquireBlock(const size_t size) 00237 % 00238 % A description of each parameter follows: 00239 % 00240 % o size: the size of the memory in bytes to allocate. 00241 % 00242 */ 00243 00244 static inline size_t AllocationPolicy(size_t size) 00245 { 00246 register size_t 00247 blocksize; 00248 00249 /* 00250 The linear distribution. 00251 */ 00252 assert(size != 0); 00253 assert(size % (4*sizeof(size_t)) == 0); 00254 if (size <= BlockThreshold) 00255 return(size/(4*sizeof(size_t))); 00256 /* 00257 Check for the largest block size. 00258 */ 00259 if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L)))) 00260 return(MaxBlocks-1L); 00261 /* 00262 Otherwise use a power of two distribution. 00263 */ 00264 blocksize=BlockThreshold/(4*sizeof(size_t)); 00265 for ( ; size > BlockThreshold; size/=2) 00266 blocksize++; 00267 assert(blocksize > (BlockThreshold/(4*sizeof(size_t)))); 00268 assert(blocksize < (MaxBlocks-1L)); 00269 return(blocksize); 00270 } 00271 00272 static inline void InsertFreeBlock(void *block,const size_t i) 00273 { 00274 register void 00275 *next, 00276 *previous; 00277 00278 size_t 00279 size; 00280 00281 size=SizeOfBlock(block); 00282 previous=(void *) NULL; 00283 next=memory_info.blocks[i]; 00284 while ((next != (void *) NULL) && (SizeOfBlock(next) < size)) 00285 { 00286 previous=next; 00287 next=NextBlockInList(next); 00288 } 00289 PreviousBlockInList(block)=previous; 00290 NextBlockInList(block)=next; 00291 if (previous != (void *) NULL) 00292 NextBlockInList(previous)=block; 00293 else 00294 memory_info.blocks[i]=block; 00295 if (next != (void *) NULL) 00296 PreviousBlockInList(next)=block; 00297 } 00298 00299 static inline void RemoveFreeBlock(void *block,const size_t i) 00300 { 00301 register void 00302 *next, 00303 *previous; 00304 00305 next=NextBlockInList(block); 00306 previous=PreviousBlockInList(block); 00307 if (previous == (void *) NULL) 00308 memory_info.blocks[i]=next; 00309 else 00310 NextBlockInList(previous)=next; 00311 if (next != (void *) NULL) 00312 PreviousBlockInList(next)=previous; 00313 } 00314 00315 static void *AcquireBlock(size_t size) 00316 { 00317 register size_t 00318 i; 00319 00320 register void 00321 *block; 00322 00323 /* 00324 Find free block. 00325 */ 00326 size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t)); 00327 i=AllocationPolicy(size); 00328 block=memory_info.blocks[i]; 00329 while ((block != (void *) NULL) && (SizeOfBlock(block) < size)) 00330 block=NextBlockInList(block); 00331 if (block == (void *) NULL) 00332 { 00333 i++; 00334 while (memory_info.blocks[i] == (void *) NULL) 00335 i++; 00336 block=memory_info.blocks[i]; 00337 if (i >= MaxBlocks) 00338 return((void *) NULL); 00339 } 00340 assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0); 00341 assert(SizeOfBlock(block) >= size); 00342 RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block))); 00343 if (SizeOfBlock(block) > size) 00344 { 00345 size_t 00346 blocksize; 00347 00348 void 00349 *next; 00350 00351 /* 00352 Split block. 00353 */ 00354 next=(char *) block+size; 00355 blocksize=SizeOfBlock(block)-size; 00356 *BlockHeader(next)=blocksize; 00357 *BlockFooter(next,blocksize)=blocksize; 00358 InsertFreeBlock(next,AllocationPolicy(blocksize)); 00359 *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask); 00360 } 00361 assert(size == SizeOfBlock(block)); 00362 *BlockHeader(NextBlock(block))|=PreviousBlockBit; 00363 memory_info.allocation+=size; 00364 return(block); 00365 } 00366 #endif 00367 00368 /* 00369 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00370 % % 00371 % % 00372 % % 00373 % A c q u i r e W i z a r d M e m o r y % 00374 % % 00375 % % 00376 % % 00377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00378 % 00379 % AcquireWizardMemory() returns a pointer to a block of memory at least size 00380 % bytes suitably aligned for any use. 00381 % 00382 % The format of the AcquireWizardMemory method is: 00383 % 00384 % void *AcquireWizardMemory(const size_t size) 00385 % 00386 % A description of each parameter follows: 00387 % 00388 % o size: the size of the memory in bytes to allocate. 00389 % 00390 */ 00391 WizardExport void *AcquireWizardMemory(const size_t size) 00392 { 00393 register void 00394 *memory; 00395 00396 #if !defined(WIZARDSTOOLKIT_EMBEDDABLE_SUPPORT) 00397 memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size); 00398 #else 00399 if (memory_semaphore == (SemaphoreInfo *) NULL) 00400 AcquireSemaphoreInfo(&memory_semaphore); 00401 if (free_segments == (DataSegmentInfo *) NULL) 00402 { 00403 LockSemaphoreInfo(memory_semaphore); 00404 if (free_segments == (DataSegmentInfo *) NULL) 00405 { 00406 register ssize_t 00407 i; 00408 00409 assert(2*sizeof(size_t) > (size_t) (~SizeMask)); 00410 (void) ResetWizardMemory(&memory_info,0,sizeof(memory_info)); 00411 memory_info.allocation=SegmentSize; 00412 memory_info.blocks[MaxBlocks]=(void *) (-1); 00413 for (i=0; i < MaxSegments; i++) 00414 { 00415 if (i != 0) 00416 memory_info.segment_pool[i].previous= 00417 (&memory_info.segment_pool[i-1]); 00418 if (i != (MaxSegments-1)) 00419 memory_info.segment_pool[i].next=(&memory_info.segment_pool[i+1]); 00420 } 00421 free_segments=(&memory_info.segment_pool[0]); 00422 } 00423 UnlockSemaphoreInfo(memory_semaphore); 00424 } 00425 LockSemaphoreInfo(memory_semaphore); 00426 memory=AcquireBlock(size == 0 ? 1UL : size); 00427 if (memory == (void *) NULL) 00428 { 00429 if (ExpandHeap(size == 0 ? 1UL : size) != WizardFalse) 00430 memory=AcquireBlock(size == 0 ? 1UL : size); 00431 } 00432 UnlockSemaphoreInfo(memory_semaphore); 00433 #endif 00434 return(memory); 00435 } 00436 00437 /* 00438 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00439 % % 00440 % % 00441 % % 00442 % A c q u i r e Q u a n t u m M e m o r y % 00443 % % 00444 % % 00445 % % 00446 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00447 % 00448 % AcquireQuantumMemory() returns a pointer to a block of memory at least 00449 % count * quantum bytes suitably aligned for any use. 00450 % 00451 % The format of the AcquireQuantumMemory method is: 00452 % 00453 % void *AcquireQuantumMemory(const size_t count,const size_t quantum) 00454 % 00455 % A description of each parameter follows: 00456 % 00457 % o count: the number of quantum elements to allocate. 00458 % 00459 % o quantum: the number of bytes in each quantum. 00460 % 00461 */ 00462 WizardExport void *AcquireQuantumMemory(const size_t count,const size_t quantum) 00463 { 00464 size_t 00465 size; 00466 00467 size=count*quantum; 00468 if ((count == 0) || (quantum != (size/count))) 00469 { 00470 errno=ENOMEM; 00471 return((void *) NULL); 00472 } 00473 return(AcquireWizardMemory(size)); 00474 } 00475 00476 /* 00477 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00478 % % 00479 % % 00480 % % 00481 % C o p y W i z a r d M e m o r y % 00482 % % 00483 % % 00484 % % 00485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00486 % 00487 % CopyWizardMemory() copies size bytes from memory area source to the 00488 % destination. Copying between objects that overlap will take place 00489 % correctly. It returns destination. 00490 % 00491 % The format of the CopyWizardMemory method is: 00492 % 00493 % void *CopyWizardMemory(void *destination,const void *source, 00494 % const size_t size) 00495 % 00496 % A description of each parameter follows: 00497 % 00498 % o destination: the destination. 00499 % 00500 % o source: the source. 00501 % 00502 % o size: the size of the memory in bytes to allocate. 00503 % 00504 */ 00505 WizardExport void *CopyWizardMemory(void *destination,const void *source, 00506 const size_t size) 00507 { 00508 register const unsigned char 00509 *p; 00510 00511 register unsigned char 00512 *q; 00513 00514 assert(destination != (void *) NULL); 00515 assert(source != (const void *) NULL); 00516 p=(const unsigned char *) source; 00517 q=(unsigned char *) destination; 00518 if (((q+size) < p) || (q > (p+size))) 00519 switch (size) 00520 { 00521 default: return(memcpy(destination,source,size)); 00522 case 8: *q++=(*p++); 00523 case 7: *q++=(*p++); 00524 case 6: *q++=(*p++); 00525 case 5: *q++=(*p++); 00526 case 4: *q++=(*p++); 00527 case 3: *q++=(*p++); 00528 case 2: *q++=(*p++); 00529 case 1: *q++=(*p++); 00530 case 0: return(destination); 00531 } 00532 return(memmove(destination,source,size)); 00533 } 00534 00535 /* 00536 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00537 % % 00538 % % 00539 % % 00540 + D e s t r o y W i z a r d M e m o r y % 00541 % % 00542 % % 00543 % % 00544 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00545 % 00546 % DestroyWizardMemory() deallocates memory associated with the memory manager. 00547 % 00548 % The format of the DestroyWizardMemory method is: 00549 % 00550 % DestroyWizardMemory(void) 00551 % 00552 */ 00553 WizardExport void DestroyWizardMemory(void) 00554 { 00555 #if defined(WIZARDSTOOLKIT_EMBEDDABLE_SUPPORT) 00556 register ssize_t 00557 i; 00558 00559 if (memory_semaphore == (SemaphoreInfo *) NULL) 00560 AcquireSemaphoreInfo(&memory_semaphore); 00561 LockSemaphoreInfo(memory_semaphore); 00562 UnlockSemaphoreInfo(memory_semaphore); 00563 for (i=0; i < (ssize_t) memory_info.number_segments; i++) 00564 if (memory_info.segments[i]->mapped == WizardFalse) 00565 memory_methods.destroy_memory_handler( 00566 memory_info.segments[i]->allocation); 00567 else 00568 (void) UnmapBlob(memory_info.segments[i]->allocation, 00569 memory_info.segments[i]->length); 00570 free_segments=(DataSegmentInfo *) NULL; 00571 (void) ResetWizardMemory(&memory_info,0,sizeof(memory_info)); 00572 DestroySemaphoreInfo(&memory_semaphore); 00573 #endif 00574 } 00575 00576 #if defined(WIZARDSTOOLKIT_EMBEDDABLE_SUPPORT) 00577 /* 00578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00579 % % 00580 % % 00581 % % 00582 + E x p a n d H e a p % 00583 % % 00584 % % 00585 % % 00586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00587 % 00588 % ExpandHeap() get more memory from the system. It returns WizardTrue on 00589 % success otherwise WizardFalse. 00590 % 00591 % The format of the ExpandHeap method is: 00592 % 00593 % WizardBooleanType ExpandHeap(size_t size) 00594 % 00595 % A description of each parameter follows: 00596 % 00597 % o size: the size of the memory in bytes we require. 00598 % 00599 */ 00600 static WizardBooleanType ExpandHeap(size_t size) 00601 { 00602 DataSegmentInfo 00603 *segment_info; 00604 00605 WizardBooleanType 00606 mapped; 00607 00608 register ssize_t 00609 i; 00610 00611 register void 00612 *block; 00613 00614 size_t 00615 blocksize; 00616 00617 void 00618 *segment; 00619 00620 blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize; 00621 assert(memory_info.number_segments < MaxSegments); 00622 segment=MapBlob(-1,IOMode,0,blocksize); 00623 mapped=segment != (void *) NULL ? WizardTrue : WizardFalse; 00624 if (segment == (void *) NULL) 00625 segment=(void *) memory_methods.acquire_memory_handler(blocksize); 00626 if (segment == (void *) NULL) 00627 return(WizardFalse); 00628 segment_info=(DataSegmentInfo *) free_segments; 00629 free_segments=segment_info->next; 00630 segment_info->mapped=mapped; 00631 segment_info->length=blocksize; 00632 segment_info->allocation=segment; 00633 segment_info->bound=(char *) segment+blocksize; 00634 i=(ssize_t) memory_info.number_segments-1; 00635 for ( ; (i >= 0) && (memory_info.segments[i]->allocation > segment); i--) 00636 memory_info.segments[i+1]=memory_info.segments[i]; 00637 memory_info.segments[i+1]=segment_info; 00638 memory_info.number_segments++; 00639 size=blocksize-12*sizeof(size_t); 00640 block=(char *) segment_info->allocation+4*sizeof(size_t); 00641 *BlockHeader(block)=size | PreviousBlockBit; 00642 *BlockFooter(block,size)=size; 00643 InsertFreeBlock(block,AllocationPolicy(size)); 00644 block=NextBlock(block); 00645 assert(block < segment_info->bound); 00646 *BlockHeader(block)=2*sizeof(size_t); 00647 *BlockHeader(NextBlock(block))=PreviousBlockBit; 00648 return(WizardTrue); 00649 } 00650 #endif 00651 00652 /* 00653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00654 % % 00655 % % 00656 % % 00657 % G e t W i z a r d M e m o r y M e t h o d s % 00658 % % 00659 % % 00660 % % 00661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00662 % 00663 % GetWizardMemoryMethods() gets the methods to acquire, resize, and destroy 00664 % memory. 00665 % 00666 % The format of the GetWizardMemoryMethods() method is: 00667 % 00668 % void GetWizardMemoryMethods(AcquireMemoryHandler *acquire_memory_handler, 00669 % ResizeMemoryHandler *resize_memory_handler, 00670 % DestroyMemoryHandler *destroy_memory_handler) 00671 % 00672 % A description of each parameter follows: 00673 % 00674 % o acquire_memory_handler: method to acquire memory (e.g. malloc). 00675 % 00676 % o resize_memory_handler: method to resize memory (e.g. realloc). 00677 % 00678 % o destroy_memory_handler: method to destroy memory (e.g. free). 00679 % 00680 */ 00681 WizardExport void GetWizardMemoryMethods( 00682 AcquireMemoryHandler *acquire_memory_handler, 00683 ResizeMemoryHandler *resize_memory_handler, 00684 DestroyMemoryHandler *destroy_memory_handler) 00685 { 00686 assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL); 00687 assert(resize_memory_handler != (ResizeMemoryHandler *) NULL); 00688 assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL); 00689 *acquire_memory_handler=memory_methods.acquire_memory_handler; 00690 *resize_memory_handler=memory_methods.resize_memory_handler; 00691 *destroy_memory_handler=memory_methods.destroy_memory_handler; 00692 } 00693 00694 /* 00695 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00696 % % 00697 % % 00698 % % 00699 % R e l i n q u i s h A l i g n e d M e m o r y % 00700 % % 00701 % % 00702 % % 00703 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00704 % 00705 % RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory() 00706 % or reuse. 00707 % 00708 % The format of the RelinquishAlignedMemory method is: 00709 % 00710 % void *RelinquishAlignedMemory(void *memory) 00711 % 00712 % A description of each parameter follows: 00713 % 00714 % o memory: A pointer to a block of memory to free for reuse. 00715 % 00716 */ 00717 WizardExport void *RelinquishAlignedMemory(void *memory) 00718 { 00719 if (memory == (void *) NULL) 00720 return((void *) NULL); 00721 free(memory); 00722 return((void *) NULL); 00723 } 00724 00725 /* 00726 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00727 % % 00728 % % 00729 % % 00730 % R e l i n q u i s h W i z a r d M e m o r y % 00731 % % 00732 % % 00733 % % 00734 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00735 % 00736 % RelinquishWizardMemory() zeros memory that has been allocated, frees it for 00737 % reuse. 00738 % 00739 % The format of the RelinquishWizardMemory method is: 00740 % 00741 % void *RelinquishWizardMemory(void *memory) 00742 % 00743 % A description of each parameter follows: 00744 % 00745 % o memory: A pointer to a block of memory to free for reuse. 00746 % 00747 */ 00748 WizardExport void *RelinquishWizardMemory(void *memory) 00749 { 00750 if (memory == (void *) NULL) 00751 return((void *) NULL); 00752 #if !defined(WIZARDSTOOLKIT_EMBEDDABLE_SUPPORT) 00753 memory_methods.destroy_memory_handler(memory); 00754 #else 00755 assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0); 00756 assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0); 00757 LockSemaphoreInfo(memory_semaphore); 00758 if ((*BlockHeader(memory) & PreviousBlockBit) == 0) 00759 { 00760 void 00761 *previous; 00762 00763 /* 00764 Coalesce with previous adjacent block. 00765 */ 00766 previous=PreviousBlock(memory); 00767 RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous))); 00768 *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) | 00769 (*BlockHeader(previous) & ~SizeMask); 00770 memory=previous; 00771 } 00772 if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0) 00773 { 00774 void 00775 *next; 00776 00777 /* 00778 Coalesce with next adjacent block. 00779 */ 00780 next=NextBlock(memory); 00781 RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next))); 00782 *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) | 00783 (*BlockHeader(memory) & ~SizeMask); 00784 } 00785 *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory); 00786 *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit); 00787 InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory))); 00788 UnlockSemaphoreInfo(memory_semaphore); 00789 #endif 00790 return((void *) NULL); 00791 } 00792 00793 /* 00794 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00795 % % 00796 % % 00797 % % 00798 % R e s e t W i z a r d M e m o r y % 00799 % % 00800 % % 00801 % % 00802 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00803 % 00804 % ResetWizardMemory() fills the first size bytes of the memory area pointed to 00805 % by memory with the constant byte c. 00806 % 00807 % The format of the ResetWizardMemory method is: 00808 % 00809 % void *ResetWizardMemory(void *memory,int byte,const size_t size) 00810 % 00811 % A description of each parameter follows: 00812 % 00813 % o memory: A pointer to a memory allocation. 00814 % 00815 % o byte: Set the memory to this value. 00816 % 00817 % o size: Size of the memory to reset. 00818 % 00819 */ 00820 WizardExport void *ResetWizardMemory(void *memory,int byte,const size_t size) 00821 { 00822 assert(memory != (void *) NULL); 00823 return(memset(memory,byte,size)); 00824 } 00825 00826 /* 00827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00828 % % 00829 % % 00830 % % 00831 % R e s i z e W i z a r d M e m o r y % 00832 % % 00833 % % 00834 % % 00835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00836 % 00837 % ResizeWizardMemory() changes the size of the memory and returns a pointer to 00838 % the (possibly moved) block. The contents will be unchanged up to the 00839 % lesser of the new and old sizes. 00840 % 00841 % The format of the ResizeWizardMemory method is: 00842 % 00843 % void *ResizeWizardMemory(void *memory,const size_t size) 00844 % 00845 % A description of each parameter follows: 00846 % 00847 % o memory: A pointer to a memory allocation. 00848 % 00849 % o size: the new size of the allocated memory. 00850 % 00851 */ 00852 00853 #if defined(WIZARDSTOOLKIT_EMBEDDABLE_SUPPORT) 00854 static inline void *ResizeBlock(void *block,size_t size) 00855 { 00856 register void 00857 *memory; 00858 00859 if (block == (void *) NULL) 00860 return(AcquireBlock(size)); 00861 memory=AcquireBlock(size); 00862 if (memory == (void *) NULL) 00863 return((void *) NULL); 00864 if (size <= (SizeOfBlock(block)-sizeof(size_t))) 00865 (void) memcpy(memory,block,size); 00866 else 00867 (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t)); 00868 memory_info.allocation+=size; 00869 return(memory); 00870 } 00871 #endif 00872 00873 WizardExport void *ResizeWizardMemory(void *memory,const size_t size) 00874 { 00875 register void 00876 *block; 00877 00878 if (memory == (void *) NULL) 00879 return(AcquireWizardMemory(size)); 00880 #if !defined(WIZARDSTOOLKIT_EMBEDDABLE_SUPPORT) 00881 block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size); 00882 if (block == (void *) NULL) 00883 memory=RelinquishWizardMemory(memory); 00884 #else 00885 LockSemaphoreInfo(memory_semaphore); 00886 block=ResizeBlock(memory,size == 0 ? 1UL : size); 00887 if (block == (void *) NULL) 00888 { 00889 if (ExpandHeap(size == 0 ? 1UL : size) == WizardFalse) 00890 { 00891 UnlockSemaphoreInfo(memory_semaphore); 00892 memory=RelinquishWizardMemory(memory); 00893 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 00894 } 00895 block=ResizeBlock(memory,size == 0 ? 1UL : size); 00896 assert(block != (void *) NULL); 00897 } 00898 UnlockSemaphoreInfo(memory_semaphore); 00899 memory=RelinquishWizardMemory(memory); 00900 #endif 00901 return(block); 00902 } 00903 00904 /* 00905 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00906 % % 00907 % % 00908 % % 00909 % R e s i z e Q u a n t u m M e m o r y % 00910 % % 00911 % % 00912 % % 00913 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00914 % 00915 % ResizeQuantumMemory() changes the size of the memory and returns a pointer 00916 % to the (possibly moved) block. The contents will be unchanged up to the 00917 % lesser of the new and old sizes. 00918 % 00919 % The format of the ResizeQuantumMemory method is: 00920 % 00921 % void *ResizeQuantumMemory(void *memory,const size_t count, 00922 % const size_t quantum) 00923 % 00924 % A description of each parameter follows: 00925 % 00926 % o memory: A pointer to a memory allocation. 00927 % 00928 % o count: the number of quantum elements to allocate. 00929 % 00930 % o quantum: the number of bytes in each quantum. 00931 % 00932 */ 00933 WizardExport void *ResizeQuantumMemory(void *memory,const size_t count, 00934 const size_t quantum) 00935 { 00936 size_t 00937 size; 00938 00939 size=count*quantum; 00940 if ((count == 0) || (quantum != (size/count))) 00941 { 00942 memory=RelinquishWizardMemory(memory); 00943 errno=ENOMEM; 00944 return((void *) NULL); 00945 } 00946 return(ResizeWizardMemory(memory,size)); 00947 } 00948 00949 /* 00950 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00951 % % 00952 % % 00953 % % 00954 % S e t W i z a r d M e m o r y M e t h o d s % 00955 % % 00956 % % 00957 % % 00958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00959 % 00960 % SetWizardMemoryMethods() sets the methods to acquire, resize, and destroy 00961 % memory. 00962 % 00963 % The format of the SetWizardMemoryMethods() method is: 00964 % 00965 % SetWizardMemoryMethods(AcquireMemoryHandler acquire_memory_handler, 00966 % ResizeMemoryHandler resize_memory_handler, 00967 % DestroyMemoryHandler destroy_memory_handler) 00968 % 00969 % A description of each parameter follows: 00970 % 00971 % o acquire_memory_handler: method to acquire memory (e.g. malloc). 00972 % 00973 % o resize_memory_handler: method to resize memory (e.g. realloc). 00974 % 00975 % o destroy_memory_handler: method to destroy memory (e.g. free). 00976 % 00977 */ 00978 WizardExport void SetWizardMemoryMethods( 00979 AcquireMemoryHandler acquire_memory_handler, 00980 ResizeMemoryHandler resize_memory_handler, 00981 DestroyMemoryHandler destroy_memory_handler) 00982 { 00983 /* 00984 Set memory methods. 00985 */ 00986 if (acquire_memory_handler != (AcquireMemoryHandler) NULL) 00987 memory_methods.acquire_memory_handler=acquire_memory_handler; 00988 if (resize_memory_handler != (ResizeMemoryHandler) NULL) 00989 memory_methods.resize_memory_handler=resize_memory_handler; 00990 if (destroy_memory_handler != (DestroyMemoryHandler) NULL) 00991 memory_methods.destroy_memory_handler=destroy_memory_handler; 00992 }