2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % RRRR EEEEE SSSSS OOO U U RRRR CCCC EEEEE %
7 % R R E SS O O U U R R C E %
8 % RRRR EEE SSS O O U U RRRR C EEE %
9 % R R E SS O O U U R R C E %
10 % R R EEEEE SSSSS OOO UUU R R CCCC EEEEE %
13 % Get/Set MagickCore Resources %
20 % Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "MagickCore/studio.h"
43 #include "MagickCore/cache.h"
44 #include "MagickCore/configure.h"
45 #include "MagickCore/exception.h"
46 #include "MagickCore/exception-private.h"
47 #include "MagickCore/hashmap.h"
48 #include "MagickCore/log.h"
49 #include "MagickCore/image.h"
50 #include "MagickCore/memory_.h"
51 #include "MagickCore/option.h"
52 #include "MagickCore/policy.h"
53 #include "MagickCore/random_.h"
54 #include "MagickCore/registry.h"
55 #include "MagickCore/resource_.h"
56 #include "MagickCore/resource-private.h"
57 #include "MagickCore/semaphore.h"
58 #include "MagickCore/signature-private.h"
59 #include "MagickCore/string_.h"
60 #include "MagickCore/string-private.h"
61 #include "MagickCore/splay-tree.h"
62 #include "MagickCore/thread-private.h"
63 #include "MagickCore/token.h"
64 #include "MagickCore/utility.h"
65 #include "MagickCore/utility-private.h"
70 typedef struct _ResourceInfo
95 *random_info = (RandomInfo *) NULL;
100 MagickULLConstant(0),
101 MagickULLConstant(0),
102 MagickULLConstant(0),
103 MagickULLConstant(0),
104 MagickULLConstant(0),
105 MagickULLConstant(0),
106 MagickULLConstant(0),
107 MagickULLConstant(3072)*1024*1024/sizeof(PixelPacket),
108 MagickULLConstant(1536)*1024*1024,
109 MagickULLConstant(3072)*1024*1024,
110 MagickResourceInfinity,
111 MagickULLConstant(768),
112 MagickULLConstant(4),
113 MagickResourceInfinity
117 *resource_semaphore = (SemaphoreInfo *) NULL;
120 *temporary_resources = (SplayTreeInfo *) NULL;
123 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
127 % A c q u i r e M a g i c k R e s o u r c e %
131 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
133 % AcquireMagickResource() acquires resources of the specified type.
134 % MagickFalse is returned if the specified resource is exhausted otherwise
137 % The format of the AcquireMagickResource() method is:
139 % MagickBooleanType AcquireMagickResource(const ResourceType type,
140 % const MagickSizeType size)
142 % A description of each parameter follows:
144 % o type: the type of resource.
146 % o size: the number of bytes needed from for this resource.
149 MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
150 const MagickSizeType size)
153 resource_current[MaxTextExtent],
154 resource_limit[MaxTextExtent],
155 resource_request[MaxTextExtent];
164 (void) FormatMagickSize(size,MagickFalse,resource_request);
165 if (resource_semaphore == (SemaphoreInfo *) NULL)
166 AcquireSemaphoreInfo(&resource_semaphore);
167 LockSemaphoreInfo(resource_semaphore);
172 resource_info.area=(MagickOffsetType) size;
173 limit=resource_info.area_limit;
174 status=(resource_info.area_limit == MagickResourceInfinity) ||
175 (size < limit) ? MagickTrue : MagickFalse;
176 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
178 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,
184 resource_info.memory+=size;
185 limit=resource_info.memory_limit;
186 status=(resource_info.memory_limit == MagickResourceInfinity) ||
187 ((MagickSizeType) resource_info.memory < limit) ?
188 MagickTrue : MagickFalse;
189 (void) FormatMagickSize((MagickSizeType) resource_info.memory,MagickTrue,
191 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,
197 resource_info.map+=size;
198 limit=resource_info.map_limit;
199 status=(resource_info.map_limit == MagickResourceInfinity) ||
200 ((MagickSizeType) resource_info.map < limit) ?
201 MagickTrue : MagickFalse;
202 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
204 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,
210 resource_info.disk+=size;
211 limit=resource_info.disk_limit;
212 status=(resource_info.disk_limit == MagickResourceInfinity) ||
213 ((MagickSizeType) resource_info.disk < limit) ?
214 MagickTrue : MagickFalse;
215 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
217 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,
223 resource_info.file+=size;
224 limit=resource_info.file_limit;
225 status=(resource_info.file_limit == MagickResourceInfinity) ||
226 ((MagickSizeType) resource_info.file < limit) ?
227 MagickTrue : MagickFalse;
228 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
230 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
231 MagickFalse,resource_limit);
236 resource_info.thread+=size;
237 limit=resource_info.thread_limit;
238 status=(resource_info.thread_limit == MagickResourceInfinity) ||
239 ((MagickSizeType) resource_info.thread < limit) ?
240 MagickTrue : MagickFalse;
241 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
243 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
244 MagickFalse,resource_limit);
249 resource_info.time+=size;
250 limit=resource_info.time_limit;
251 status=(resource_info.time_limit == MagickResourceInfinity) ||
252 ((MagickSizeType) resource_info.time < limit) ?
253 MagickTrue : MagickFalse;
254 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
256 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
257 MagickFalse,resource_limit);
263 UnlockSemaphoreInfo(resource_semaphore);
264 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
265 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
266 resource_request,resource_current,resource_limit);
271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
275 + A s y n c h r o n o u s R e s o u r c e C o m p o n e n t T e r m i n u s %
279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
281 % AsynchronousResourceComponentTerminus() destroys the resource environment.
282 % It differs from ResourceComponentTerminus() in that it can be called from a
283 % asynchronous signal handler.
285 % The format of the ResourceComponentTerminus() method is:
287 % ResourceComponentTerminus(void)
290 MagickPrivate void AsynchronousResourceComponentTerminus(void)
295 if (temporary_resources == (SplayTreeInfo *) NULL)
298 Remove any lingering temporary files.
300 ResetSplayTreeIterator(temporary_resources);
301 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
302 while (path != (const char *) NULL)
305 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
314 % A c q u i r e U n i q u e F i l e R e s o u r c e %
318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
320 % AcquireUniqueFileResource() returns a unique file name, and returns a file
321 % descriptor for the file open for reading and writing.
323 % The format of the AcquireUniqueFileResource() method is:
325 % int AcquireUniqueFileResource(char *path)
327 % A description of each parameter follows:
329 % o path: Specifies a pointer to an array of characters. The unique path
330 % name is returned in this array.
334 static void *DestroyTemporaryResources(void *temporary_resource)
336 (void) remove((char *) temporary_resource);
337 temporary_resource=DestroyString((char *) temporary_resource);
338 return((void *) NULL);
341 static MagickBooleanType GetPathTemplate(char *path)
358 (void) CopyMagickString(path,"magick-XXXXXXXX",MaxTextExtent);
359 exception=AcquireExceptionInfo();
360 directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
362 exception=DestroyExceptionInfo(exception);
363 if (directory == (char *) NULL)
364 directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
365 if (directory == (char *) NULL)
366 directory=GetEnvironmentValue("MAGICK_TMPDIR");
367 if (directory == (char *) NULL)
368 directory=GetPolicyValue("temporary-path");
369 if (directory == (char *) NULL)
370 directory=GetEnvironmentValue("TMPDIR");
371 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
372 if (directory == (char *) NULL)
373 directory=GetEnvironmentValue("TMP");
374 if (directory == (char *) NULL)
375 directory=GetEnvironmentValue("TEMP");
378 if (directory == (char *) NULL)
379 directory=GetEnvironmentValue("MTMPDIR");
381 #if defined(P_tmpdir)
382 if (directory == (char *) NULL)
383 directory=ConstantString(P_tmpdir);
385 if (directory == (char *) NULL)
387 if (strlen(directory) > (MaxTextExtent-15))
389 directory=DestroyString(directory);
392 status=GetPathAttributes(directory,&attributes);
393 if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
395 directory=DestroyString(directory);
398 if (directory[strlen(directory)-1] == *DirectorySeparator)
399 (void) FormatLocaleString(path,MaxTextExtent,"%smagick-XXXXXXXX",directory);
401 (void) FormatLocaleString(path,MaxTextExtent,"%s%smagick-XXXXXXXX",
402 directory,DirectorySeparator);
403 directory=DestroyString(directory);
404 if (*DirectorySeparator != '/')
405 for (p=path; *p != '\0'; p++)
406 if (*p == *DirectorySeparator)
411 MagickExport int AcquireUniqueFileResource(char *path)
413 #if !defined(O_NOFOLLOW)
416 #if !defined(TMP_MAX)
417 # define TMP_MAX 238328
431 portable_filename[65] =
432 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
440 assert(path != (char *) NULL);
441 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
442 if (random_info == (RandomInfo *) NULL)
443 random_info=AcquireRandomInfo();
445 for (i=0; i < (ssize_t) TMP_MAX; i++)
448 Get temporary pathname.
450 (void) GetPathTemplate(path);
451 key=GetRandomKey(random_info,2);
452 p=path+strlen(path)-8;
453 datum=GetStringInfoDatum(key);
454 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
456 c=(int) (datum[i] & 0x3f);
457 *p++=portable_filename[c];
459 key=DestroyStringInfo(key);
460 #if defined(MAGICKCORE_HAVE_MKSTEMP)
463 setmode(file,O_BINARY);
468 key=GetRandomKey(random_info,6);
469 p=path+strlen(path)-6;
470 datum=GetStringInfoDatum(key);
471 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
473 c=(int) (datum[i] & 0x3f);
474 *p++=portable_filename[c];
476 key=DestroyStringInfo(key);
477 file=open(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,S_MODE);
478 if ((file >= 0) || (errno != EEXIST))
481 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
484 if (resource_semaphore == (SemaphoreInfo *) NULL)
485 AcquireSemaphoreInfo(&resource_semaphore);
486 LockSemaphoreInfo(resource_semaphore);
487 if (temporary_resources == (SplayTreeInfo *) NULL)
488 temporary_resources=NewSplayTree(CompareSplayTreeString,
489 DestroyTemporaryResources,(void *(*)(void *)) NULL);
490 UnlockSemaphoreInfo(resource_semaphore);
491 (void) AddValueToSplayTree(temporary_resources,ConstantString(path),
492 (const void *) NULL);
497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
501 % G e t M a g i c k R e s o u r c e %
505 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
507 % GetMagickResource() returns the specified resource.
509 % The format of the GetMagickResource() method is:
511 % MagickSizeType GetMagickResource(const ResourceType type)
513 % A description of each parameter follows:
515 % o type: the type of resource.
518 MagickExport MagickSizeType GetMagickResource(const ResourceType type)
524 LockSemaphoreInfo(resource_semaphore);
529 resource=(MagickSizeType) resource_info.area;
534 resource=(MagickSizeType) resource_info.memory;
539 resource=(MagickSizeType) resource_info.map;
544 resource=(MagickSizeType) resource_info.disk;
549 resource=(MagickSizeType) resource_info.file;
554 resource=(MagickSizeType) resource_info.thread;
559 resource=(MagickSizeType) resource_info.time;
565 UnlockSemaphoreInfo(resource_semaphore);
570 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
574 % G e t M a g i c k R e s o u r c e L i m i t %
578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
580 % GetMagickResourceLimit() returns the specified resource limit.
582 % The format of the GetMagickResourceLimit() method is:
584 % MagickSizeType GetMagickResourceLimit(const ResourceType type)
586 % A description of each parameter follows:
588 % o type: the type of resource.
591 MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
597 if (resource_semaphore == (SemaphoreInfo *) NULL)
598 AcquireSemaphoreInfo(&resource_semaphore);
599 LockSemaphoreInfo(resource_semaphore);
604 resource=resource_info.area_limit;
609 resource=resource_info.memory_limit;
614 resource=resource_info.map_limit;
619 resource=resource_info.disk_limit;
624 resource=resource_info.file_limit;
629 resource=resource_info.thread_limit;
634 resource=resource_info.time_limit;
640 UnlockSemaphoreInfo(resource_semaphore);
645 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
649 % L i s t M a g i c k R e s o u r c e I n f o %
653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
655 % ListMagickResourceInfo() lists the resource info to a file.
657 % The format of the ListMagickResourceInfo method is:
659 % MagickBooleanType ListMagickResourceInfo(FILE *file,
660 % ExceptionInfo *exception)
662 % A description of each parameter follows.
664 % o file: An pointer to a FILE.
666 % o exception: return any errors or warnings in this structure.
669 MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
670 ExceptionInfo *magick_unused(exception))
673 area_limit[MaxTextExtent],
674 disk_limit[MaxTextExtent],
675 map_limit[MaxTextExtent],
676 memory_limit[MaxTextExtent],
677 time_limit[MaxTextExtent];
679 if (file == (const FILE *) NULL)
681 if (resource_semaphore == (SemaphoreInfo *) NULL)
682 AcquireSemaphoreInfo(&resource_semaphore);
683 LockSemaphoreInfo(resource_semaphore);
684 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,area_limit);
685 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,memory_limit);
686 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,map_limit);
687 (void) CopyMagickString(disk_limit,"unlimited",MaxTextExtent);
688 if (resource_info.disk_limit != MagickResourceInfinity)
689 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,disk_limit);
690 (void) CopyMagickString(time_limit,"unlimited",MaxTextExtent);
691 if (resource_info.time_limit != MagickResourceInfinity)
692 (void) FormatLocaleString(time_limit,MaxTextExtent,"%.20g",(double)
693 ((MagickOffsetType) resource_info.time_limit));
694 (void) FormatLocaleFile(file,"File Area Memory Map"
695 " Disk Thread Time\n");
696 (void) FormatLocaleFile(file,
697 "--------------------------------------------------------"
698 "-----------------------\n");
699 (void) FormatLocaleFile(file,"%4g %10s %10s %10s %10s %6g %11s\n",
700 (double) ((MagickOffsetType) resource_info.file_limit),area_limit,
701 memory_limit,map_limit,disk_limit,(double) ((MagickOffsetType)
702 resource_info.thread_limit),time_limit);
704 UnlockSemaphoreInfo(resource_semaphore);
709 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
713 % R e l i n q u i s h M a g i c k R e s o u r c e %
717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
719 % RelinquishMagickResource() relinquishes resources of the specified type.
721 % The format of the RelinquishMagickResource() method is:
723 % void RelinquishMagickResource(const ResourceType type,
724 % const MagickSizeType size)
726 % A description of each parameter follows:
728 % o type: the type of resource.
730 % o size: the size of the resource.
733 MagickExport void RelinquishMagickResource(const ResourceType type,
734 const MagickSizeType size)
737 resource_current[MaxTextExtent],
738 resource_limit[MaxTextExtent],
739 resource_request[MaxTextExtent];
741 (void) FormatMagickSize(size,MagickFalse,resource_request);
742 if (resource_semaphore == (SemaphoreInfo *) NULL)
743 AcquireSemaphoreInfo(&resource_semaphore);
744 LockSemaphoreInfo(resource_semaphore);
749 resource_info.area=(MagickOffsetType) size;
750 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
752 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,
758 resource_info.memory-=size;
759 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
760 MagickTrue,resource_current);
761 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,
767 resource_info.map-=size;
768 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
770 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,
776 resource_info.disk-=size;
777 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
779 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,
785 resource_info.file-=size;
786 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
788 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
789 MagickFalse,resource_limit);
794 resource_info.thread-=size;
795 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
797 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
798 MagickFalse,resource_limit);
803 resource_info.time-=size;
804 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
806 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
807 MagickFalse,resource_limit);
813 UnlockSemaphoreInfo(resource_semaphore);
814 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
815 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
816 resource_request,resource_current,resource_limit);
820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
824 % R e l i n q u i s h U n i q u e F i l e R e s o u r c e %
828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830 % RelinquishUniqueFileResource() relinquishes a unique file resource.
832 % The format of the RelinquishUniqueFileResource() method is:
834 % MagickBooleanType RelinquishUniqueFileResource(const char *path)
836 % A description of each parameter follows:
838 % o name: the name of the temporary resource.
841 MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
844 cache_path[MaxTextExtent];
846 assert(path != (const char *) NULL);
847 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
848 if (temporary_resources != (SplayTreeInfo *) NULL)
853 ResetSplayTreeIterator(temporary_resources);
854 p=(char *) GetNextKeyInSplayTree(temporary_resources);
855 while (p != (char *) NULL)
857 if (LocaleCompare(p,path) == 0)
859 p=(char *) GetNextKeyInSplayTree(temporary_resources);
861 if (p != (char *) NULL)
862 (void) DeleteNodeFromSplayTree(temporary_resources,p);
864 (void) CopyMagickString(cache_path,path,MaxTextExtent);
865 AppendImageFormat("cache",cache_path);
866 (void) remove(cache_path);
867 return(remove(path) == 0 ? MagickTrue : MagickFalse);
871 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
875 + R e s o u r c e C o m p o n e n t G e n e s i s %
879 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
881 % ResourceComponentGenesis() instantiates the resource component.
883 % The format of the ResourceComponentGenesis method is:
885 % MagickBooleanType ResourceComponentGenesis(void)
889 static inline size_t MagickMax(const size_t x,const size_t y)
896 static inline MagickSizeType StringToSizeType(const char *string,
897 const double interval)
902 value=SiPrefixToDouble(string,interval);
903 if (value >= (double) MagickULLConstant(~0))
904 return(MagickULLConstant(~0));
905 return((MagickSizeType) value);
908 MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
922 Set Magick resource limits.
924 AcquireSemaphoreInfo(&resource_semaphore);
925 pagesize=GetMagickPageSize();
927 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
928 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
930 memory=(MagickSizeType) pages*pagesize;
931 if ((pagesize <= 0) || (pages <= 0))
932 memory=2048UL*1024UL*1024UL;
933 #if defined(PixelCacheThreshold)
934 memory=PixelCacheThreshold;
936 (void) SetMagickResourceLimit(AreaResource,2*memory/sizeof(PixelPacket));
937 (void) SetMagickResourceLimit(MemoryResource,memory);
938 (void) SetMagickResourceLimit(MapResource,2*memory);
939 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
940 if (limit == (char *) NULL)
941 limit=GetPolicyValue("area");
942 if (limit != (char *) NULL)
944 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
945 limit=DestroyString(limit);
947 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
948 if (limit == (char *) NULL)
949 limit=GetPolicyValue("memory");
950 if (limit != (char *) NULL)
952 (void) SetMagickResourceLimit(MemoryResource,
953 StringToSizeType(limit,100.0));
954 limit=DestroyString(limit);
956 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
957 if (limit == (char *) NULL)
958 limit=GetPolicyValue("map");
959 if (limit != (char *) NULL)
961 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
962 limit=DestroyString(limit);
964 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
965 if (limit == (char *) NULL)
966 limit=GetPolicyValue("disk");
967 if (limit != (char *) NULL)
969 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
970 limit=DestroyString(limit);
973 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
974 files=(ssize_t) sysconf(_SC_OPEN_MAX);
976 #if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
982 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
983 files=(ssize_t) resources.rlim_cur;
986 #if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
988 files=(ssize_t) getdtablesize();
992 (void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
994 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
995 if (limit == (char *) NULL)
996 limit=GetPolicyValue("file");
997 if (limit != (char *) NULL)
999 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,100.0));
1000 limit=DestroyString(limit);
1002 (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
1003 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
1004 if (limit == (char *) NULL)
1005 limit=GetPolicyValue("thread");
1006 if (limit != (char *) NULL)
1008 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
1010 limit=DestroyString(limit);
1012 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
1013 if (limit == (char *) NULL)
1014 limit=GetPolicyValue("time");
1015 if (limit != (char *) NULL)
1017 (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0));
1018 limit=DestroyString(limit);
1024 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1028 + R e s o u r c e C o m p o n e n t T e r m i n u s %
1032 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1034 % ResourceComponentTerminus() destroys the resource component.
1036 % The format of the ResourceComponentTerminus() method is:
1038 % ResourceComponentTerminus(void)
1041 MagickPrivate void ResourceComponentTerminus(void)
1043 if (resource_semaphore == (SemaphoreInfo *) NULL)
1044 AcquireSemaphoreInfo(&resource_semaphore);
1045 LockSemaphoreInfo(resource_semaphore);
1046 if (temporary_resources != (SplayTreeInfo *) NULL)
1047 temporary_resources=DestroySplayTree(temporary_resources);
1048 if (random_info != (RandomInfo *) NULL)
1049 random_info=DestroyRandomInfo(random_info);
1050 UnlockSemaphoreInfo(resource_semaphore);
1051 DestroySemaphoreInfo(&resource_semaphore);
1055 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1059 % S e t M a g i c k R e s o u r c e L i m i t %
1063 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1065 % SetMagickResourceLimit() sets the limit for a particular resource.
1067 % The format of the SetMagickResourceLimit() method is:
1069 % MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1070 % const MagickSizeType limit)
1072 % A description of each parameter follows:
1074 % o type: the type of resource.
1076 % o limit: the maximum limit for the resource.
1080 static inline MagickSizeType MagickMin(const MagickSizeType x,
1081 const MagickSizeType y)
1088 MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1089 const MagickSizeType limit)
1094 if (resource_semaphore == (SemaphoreInfo *) NULL)
1095 AcquireSemaphoreInfo(&resource_semaphore);
1096 LockSemaphoreInfo(resource_semaphore);
1097 value=(char *) NULL;
1102 resource_info.area_limit=limit;
1103 value=GetPolicyValue("area");
1104 if (value != (char *) NULL)
1105 resource_info.area_limit=MagickMin(limit,StringToSizeType(value,100.0));
1108 case MemoryResource:
1110 resource_info.memory_limit=limit;
1111 value=GetPolicyValue("memory");
1112 if (value != (char *) NULL)
1113 resource_info.memory_limit=MagickMin(limit,StringToSizeType(value,
1119 resource_info.map_limit=limit;
1120 value=GetPolicyValue("map");
1121 if (value != (char *) NULL)
1122 resource_info.map_limit=MagickMin(limit,StringToSizeType(value,100.0));
1127 resource_info.disk_limit=limit;
1128 value=GetPolicyValue("disk");
1129 if (value != (char *) NULL)
1130 resource_info.disk_limit=MagickMin(limit,StringToSizeType(value,100.0));
1135 resource_info.file_limit=limit;
1136 value=GetPolicyValue("file");
1137 if (value != (char *) NULL)
1138 resource_info.file_limit=MagickMin(limit,StringToSizeType(value,100.0));
1141 case ThreadResource:
1143 resource_info.thread_limit=limit;
1144 value=GetPolicyValue("thread");
1145 if (value != (char *) NULL)
1146 resource_info.thread_limit=MagickMin(limit,StringToSizeType(value,
1148 SetOpenMPMaximumThreads((int) resource_info.thread_limit);
1153 resource_info.time_limit=limit;
1154 value=GetPolicyValue("time");
1155 if (value != (char *) NULL)
1156 resource_info.time_limit=MagickMin(limit,StringToSizeType(value,100.0));
1162 if (value != (char *) NULL)
1163 value=DestroyString(value);
1164 UnlockSemaphoreInfo(resource_semaphore);