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-2013 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,
108 MagickULLConstant(1536)*1024*1024,
109 MagickULLConstant(3072)*1024*1024,
110 MagickResourceInfinity,
111 MagickULLConstant(768),
112 MagickULLConstant(1),
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 limit=resource_info.thread_limit;
237 status=(resource_info.thread_limit == MagickResourceInfinity) ||
238 ((MagickSizeType) resource_info.thread < limit) ?
239 MagickTrue : MagickFalse;
240 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
242 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
243 MagickFalse,resource_limit);
248 resource_info.time+=size;
249 limit=resource_info.time_limit;
250 status=(resource_info.time_limit == MagickResourceInfinity) ||
251 ((MagickSizeType) resource_info.time < limit) ?
252 MagickTrue : MagickFalse;
253 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
255 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
256 MagickFalse,resource_limit);
262 UnlockSemaphoreInfo(resource_semaphore);
263 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
264 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
265 resource_request,resource_current,resource_limit);
270 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274 + 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 %
278 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
280 % AsynchronousResourceComponentTerminus() destroys the resource environment.
281 % It differs from ResourceComponentTerminus() in that it can be called from a
282 % asynchronous signal handler.
284 % The format of the ResourceComponentTerminus() method is:
286 % ResourceComponentTerminus(void)
289 MagickPrivate void AsynchronousResourceComponentTerminus(void)
294 if (temporary_resources == (SplayTreeInfo *) NULL)
297 Remove any lingering temporary files.
299 ResetSplayTreeIterator(temporary_resources);
300 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
301 while (path != (const char *) NULL)
303 (void) remove_utf8(path);
304 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
309 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
313 % 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 %
317 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
319 % AcquireUniqueFileResource() returns a unique file name, and returns a file
320 % descriptor for the file open for reading and writing.
322 % The format of the AcquireUniqueFileResource() method is:
324 % int AcquireUniqueFileResource(char *path)
326 % A description of each parameter follows:
328 % o path: Specifies a pointer to an array of characters. The unique path
329 % name is returned in this array.
333 static void *DestroyTemporaryResources(void *temporary_resource)
335 (void) remove_utf8((char *) temporary_resource);
336 temporary_resource=DestroyString((char *) temporary_resource);
337 return((void *) NULL);
340 static MagickBooleanType GetPathTemplate(char *path)
358 (void) FormatLocaleString(path,MaxTextExtent,"magick-%.20gXXXXXXXXXXXX",
360 exception=AcquireExceptionInfo();
361 directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
363 exception=DestroyExceptionInfo(exception);
364 if (directory == (char *) NULL)
365 directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
366 if (directory == (char *) NULL)
367 directory=GetEnvironmentValue("MAGICK_TMPDIR");
368 if (directory == (char *) NULL)
369 directory=GetEnvironmentValue("TMPDIR");
370 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
371 if (directory == (char *) NULL)
372 directory=GetEnvironmentValue("TMP");
373 if (directory == (char *) NULL)
374 directory=GetEnvironmentValue("TEMP");
377 if (directory == (char *) NULL)
378 directory=GetEnvironmentValue("MTMPDIR");
380 #if defined(P_tmpdir)
381 if (directory == (char *) NULL)
382 directory=ConstantString(P_tmpdir);
384 if (directory == (char *) NULL)
386 value=GetPolicyValue("temporary-path");
387 if (value != (char *) NULL)
388 (void) CloneString(&directory,value);
389 if (strlen(directory) > (MaxTextExtent-25))
391 directory=DestroyString(directory);
394 status=GetPathAttributes(directory,&attributes);
395 if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
397 directory=DestroyString(directory);
400 if (directory[strlen(directory)-1] == *DirectorySeparator)
401 (void) FormatLocaleString(path,MaxTextExtent,"%smagick-%.20gXXXXXXXXXXXX",
402 directory,(double) getpid());
404 (void) FormatLocaleString(path,MaxTextExtent,"%s%smagick-%.20gXXXXXXXXXXXX",
405 directory,DirectorySeparator,(double) getpid());
406 directory=DestroyString(directory);
407 if (*DirectorySeparator != '/')
408 for (p=path; *p != '\0'; p++)
409 if (*p == *DirectorySeparator)
414 MagickExport int AcquireUniqueFileResource(char *path)
416 #if !defined(O_NOFOLLOW)
419 #if !defined(TMP_MAX)
420 # define TMP_MAX 238328
434 portable_filename[65] =
435 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
443 assert(path != (char *) NULL);
444 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
445 if (random_info == (RandomInfo *) NULL)
446 random_info=AcquireRandomInfo();
448 for (i=0; i < (ssize_t) TMP_MAX; i++)
451 Get temporary pathname.
453 (void) GetPathTemplate(path);
454 key=GetRandomKey(random_info,6);
455 p=path+strlen(path)-12;
456 datum=GetStringInfoDatum(key);
457 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
459 c=(int) (datum[i] & 0x3f);
460 *p++=portable_filename[c];
462 key=DestroyStringInfo(key);
463 #if defined(MAGICKCORE_HAVE_MKSTEMP)
466 setmode(file,O_BINARY);
471 key=GetRandomKey(random_info,12);
472 p=path+strlen(path)-12;
473 datum=GetStringInfoDatum(key);
474 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
476 c=(int) (datum[i] & 0x3f);
477 *p++=portable_filename[c];
479 key=DestroyStringInfo(key);
480 file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,
482 if ((file >= 0) || (errno != EEXIST))
485 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
488 if (resource_semaphore == (SemaphoreInfo *) NULL)
489 AcquireSemaphoreInfo(&resource_semaphore);
490 LockSemaphoreInfo(resource_semaphore);
491 if (temporary_resources == (SplayTreeInfo *) NULL)
492 temporary_resources=NewSplayTree(CompareSplayTreeString,
493 DestroyTemporaryResources,(void *(*)(void *)) NULL);
494 UnlockSemaphoreInfo(resource_semaphore);
495 (void) AddValueToSplayTree(temporary_resources,ConstantString(path),
496 (const void *) NULL);
501 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
505 % G e t M a g i c k R e s o u r c e %
509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
511 % GetMagickResource() returns the specified resource.
513 % The format of the GetMagickResource() method is:
515 % MagickSizeType GetMagickResource(const ResourceType type)
517 % A description of each parameter follows:
519 % o type: the type of resource.
522 MagickExport MagickSizeType GetMagickResource(const ResourceType type)
528 LockSemaphoreInfo(resource_semaphore);
533 resource=(MagickSizeType) resource_info.area;
538 resource=(MagickSizeType) resource_info.memory;
543 resource=(MagickSizeType) resource_info.map;
548 resource=(MagickSizeType) resource_info.disk;
553 resource=(MagickSizeType) resource_info.file;
558 resource=(MagickSizeType) resource_info.thread;
563 resource=(MagickSizeType) resource_info.time;
569 UnlockSemaphoreInfo(resource_semaphore);
574 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
578 % G e t M a g i c k R e s o u r c e L i m i t %
582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
584 % GetMagickResourceLimit() returns the specified resource limit.
586 % The format of the GetMagickResourceLimit() method is:
588 % MagickSizeType GetMagickResourceLimit(const ResourceType type)
590 % A description of each parameter follows:
592 % o type: the type of resource.
595 MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
601 if (resource_semaphore == (SemaphoreInfo *) NULL)
602 AcquireSemaphoreInfo(&resource_semaphore);
603 LockSemaphoreInfo(resource_semaphore);
608 resource=resource_info.area_limit;
613 resource=resource_info.memory_limit;
618 resource=resource_info.map_limit;
623 resource=resource_info.disk_limit;
628 resource=resource_info.file_limit;
633 resource=resource_info.thread_limit;
638 resource=resource_info.time_limit;
644 UnlockSemaphoreInfo(resource_semaphore);
649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
653 % L i s t M a g i c k R e s o u r c e I n f o %
657 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
659 % ListMagickResourceInfo() lists the resource info to a file.
661 % The format of the ListMagickResourceInfo method is:
663 % MagickBooleanType ListMagickResourceInfo(FILE *file,
664 % ExceptionInfo *exception)
666 % A description of each parameter follows.
668 % o file: An pointer to a FILE.
670 % o exception: return any errors or warnings in this structure.
673 MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
674 ExceptionInfo *magick_unused(exception))
677 area_limit[MaxTextExtent],
678 disk_limit[MaxTextExtent],
679 map_limit[MaxTextExtent],
680 memory_limit[MaxTextExtent],
681 time_limit[MaxTextExtent];
683 if (file == (const FILE *) NULL)
685 if (resource_semaphore == (SemaphoreInfo *) NULL)
686 AcquireSemaphoreInfo(&resource_semaphore);
687 LockSemaphoreInfo(resource_semaphore);
688 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,area_limit);
689 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,memory_limit);
690 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,map_limit);
691 (void) CopyMagickString(disk_limit,"unlimited",MaxTextExtent);
692 if (resource_info.disk_limit != MagickResourceInfinity)
693 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,disk_limit);
694 (void) CopyMagickString(time_limit,"unlimited",MaxTextExtent);
695 if (resource_info.time_limit != MagickResourceInfinity)
696 (void) FormatLocaleString(time_limit,MaxTextExtent,"%.20g",(double)
697 ((MagickOffsetType) resource_info.time_limit));
698 (void) FormatLocaleFile(file," File Area Memory Map"
699 " Disk Thread Time\n");
700 (void) FormatLocaleFile(file,
701 "--------------------------------------------------------"
702 "-----------------------\n");
703 (void) FormatLocaleFile(file,"%6g %10s %10s %10s %10s %6g %11s\n",
704 (double) ((MagickOffsetType) resource_info.file_limit),area_limit,
705 memory_limit,map_limit,disk_limit,(double) ((MagickOffsetType)
706 resource_info.thread_limit),time_limit);
708 UnlockSemaphoreInfo(resource_semaphore);
713 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
717 % R e l i n q u i s h M a g i c k R e s o u r c e %
721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723 % RelinquishMagickResource() relinquishes resources of the specified type.
725 % The format of the RelinquishMagickResource() method is:
727 % void RelinquishMagickResource(const ResourceType type,
728 % const MagickSizeType size)
730 % A description of each parameter follows:
732 % o type: the type of resource.
734 % o size: the size of the resource.
737 MagickExport void RelinquishMagickResource(const ResourceType type,
738 const MagickSizeType size)
741 resource_current[MaxTextExtent],
742 resource_limit[MaxTextExtent],
743 resource_request[MaxTextExtent];
745 (void) FormatMagickSize(size,MagickFalse,resource_request);
746 if (resource_semaphore == (SemaphoreInfo *) NULL)
747 AcquireSemaphoreInfo(&resource_semaphore);
748 LockSemaphoreInfo(resource_semaphore);
753 resource_info.area=(MagickOffsetType) size;
754 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
756 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,
762 resource_info.memory-=size;
763 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
764 MagickTrue,resource_current);
765 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,
771 resource_info.map-=size;
772 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
774 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,
780 resource_info.disk-=size;
781 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
783 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,
789 resource_info.file-=size;
790 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
792 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
793 MagickFalse,resource_limit);
798 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
800 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
801 MagickFalse,resource_limit);
806 resource_info.time-=size;
807 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
809 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
810 MagickFalse,resource_limit);
816 UnlockSemaphoreInfo(resource_semaphore);
817 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
818 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
819 resource_request,resource_current,resource_limit);
823 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
827 % 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 %
831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833 % RelinquishUniqueFileResource() relinquishes a unique file resource.
835 % The format of the RelinquishUniqueFileResource() method is:
837 % MagickBooleanType RelinquishUniqueFileResource(const char *path)
839 % A description of each parameter follows:
841 % o name: the name of the temporary resource.
844 MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
847 cache_path[MaxTextExtent];
849 assert(path != (const char *) NULL);
850 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
851 if (temporary_resources != (SplayTreeInfo *) NULL)
856 ResetSplayTreeIterator(temporary_resources);
857 p=(char *) GetNextKeyInSplayTree(temporary_resources);
858 while (p != (char *) NULL)
860 if (LocaleCompare(p,path) == 0)
862 p=(char *) GetNextKeyInSplayTree(temporary_resources);
864 if (p != (char *) NULL)
865 (void) DeleteNodeFromSplayTree(temporary_resources,p);
867 (void) CopyMagickString(cache_path,path,MaxTextExtent);
868 AppendImageFormat("cache",cache_path);
869 (void) remove_utf8(cache_path);
870 return(remove_utf8(path) == 0 ? MagickTrue : MagickFalse);
874 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
878 + R e s o u r c e C o m p o n e n t G e n e s i s %
882 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
884 % ResourceComponentGenesis() instantiates the resource component.
886 % The format of the ResourceComponentGenesis method is:
888 % MagickBooleanType ResourceComponentGenesis(void)
892 static inline size_t MagickMax(const size_t x,const size_t y)
899 static inline MagickSizeType StringToSizeType(const char *string,
900 const double interval)
905 value=SiPrefixToDoubleInterval(string,interval);
906 if (value >= (double) MagickULLConstant(~0))
907 return(MagickULLConstant(~0));
908 return((MagickSizeType) value);
911 MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
925 Set Magick resource limits.
927 AcquireSemaphoreInfo(&resource_semaphore);
928 pagesize=GetMagickPageSize();
930 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
931 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
933 memory=(MagickSizeType) pages*pagesize;
934 if ((pagesize <= 0) || (pages <= 0))
935 memory=2048UL*1024UL*1024UL;
936 #if defined(PixelCacheThreshold)
937 memory=PixelCacheThreshold;
939 (void) SetMagickResourceLimit(AreaResource,2*memory);
940 (void) SetMagickResourceLimit(MemoryResource,memory);
941 (void) SetMagickResourceLimit(MapResource,2*memory);
942 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
943 if (limit == (char *) NULL)
944 limit=GetPolicyValue("area");
945 if (limit != (char *) NULL)
947 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
948 limit=DestroyString(limit);
950 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
951 if (limit == (char *) NULL)
952 limit=GetPolicyValue("memory");
953 if (limit != (char *) NULL)
955 (void) SetMagickResourceLimit(MemoryResource,
956 StringToSizeType(limit,100.0));
957 limit=DestroyString(limit);
959 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
960 if (limit == (char *) NULL)
961 limit=GetPolicyValue("map");
962 if (limit != (char *) NULL)
964 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
965 limit=DestroyString(limit);
967 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
968 if (limit == (char *) NULL)
969 limit=GetPolicyValue("disk");
970 if (limit != (char *) NULL)
972 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
973 limit=DestroyString(limit);
976 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
977 files=(ssize_t) sysconf(_SC_OPEN_MAX);
979 #if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
985 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
986 files=(ssize_t) resources.rlim_cur;
989 #if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
991 files=(ssize_t) getdtablesize();
995 (void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
997 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
998 if (limit == (char *) NULL)
999 limit=GetPolicyValue("file");
1000 if (limit != (char *) NULL)
1002 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,
1004 limit=DestroyString(limit);
1006 (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
1007 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
1008 if (limit == (char *) NULL)
1009 limit=GetPolicyValue("thread");
1010 if (limit != (char *) NULL)
1012 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
1014 limit=DestroyString(limit);
1016 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
1017 if (limit == (char *) NULL)
1018 limit=GetPolicyValue("time");
1019 if (limit != (char *) NULL)
1021 (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0));
1022 limit=DestroyString(limit);
1028 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1032 + 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 %
1036 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1038 % ResourceComponentTerminus() destroys the resource component.
1040 % The format of the ResourceComponentTerminus() method is:
1042 % ResourceComponentTerminus(void)
1045 MagickPrivate void ResourceComponentTerminus(void)
1047 if (resource_semaphore == (SemaphoreInfo *) NULL)
1048 AcquireSemaphoreInfo(&resource_semaphore);
1049 LockSemaphoreInfo(resource_semaphore);
1050 if (temporary_resources != (SplayTreeInfo *) NULL)
1051 temporary_resources=DestroySplayTree(temporary_resources);
1052 if (random_info != (RandomInfo *) NULL)
1053 random_info=DestroyRandomInfo(random_info);
1054 UnlockSemaphoreInfo(resource_semaphore);
1055 DestroySemaphoreInfo(&resource_semaphore);
1059 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1063 % S e t M a g i c k R e s o u r c e L i m i t %
1067 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1069 % SetMagickResourceLimit() sets the limit for a particular resource.
1071 % The format of the SetMagickResourceLimit() method is:
1073 % MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1074 % const MagickSizeType limit)
1076 % A description of each parameter follows:
1078 % o type: the type of resource.
1080 % o limit: the maximum limit for the resource.
1084 static inline MagickSizeType MagickMin(const MagickSizeType x,
1085 const MagickSizeType y)
1092 MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1093 const MagickSizeType limit)
1098 if (resource_semaphore == (SemaphoreInfo *) NULL)
1099 AcquireSemaphoreInfo(&resource_semaphore);
1100 LockSemaphoreInfo(resource_semaphore);
1101 value=(char *) NULL;
1106 resource_info.area_limit=limit;
1107 value=GetPolicyValue("area");
1108 if (value != (char *) NULL)
1109 resource_info.area_limit=MagickMin(limit,StringToSizeType(value,100.0));
1112 case MemoryResource:
1114 resource_info.memory_limit=limit;
1115 value=GetPolicyValue("memory");
1116 if (value != (char *) NULL)
1117 resource_info.memory_limit=MagickMin(limit,StringToSizeType(value,
1123 resource_info.map_limit=limit;
1124 value=GetPolicyValue("map");
1125 if (value != (char *) NULL)
1126 resource_info.map_limit=MagickMin(limit,StringToSizeType(value,100.0));
1131 resource_info.disk_limit=limit;
1132 value=GetPolicyValue("disk");
1133 if (value != (char *) NULL)
1134 resource_info.disk_limit=MagickMin(limit,StringToSizeType(value,100.0));
1139 resource_info.file_limit=limit;
1140 value=GetPolicyValue("file");
1141 if (value != (char *) NULL)
1142 resource_info.file_limit=MagickMin(limit,StringToSizeType(value,100.0));
1145 case ThreadResource:
1147 resource_info.thread_limit=limit;
1148 value=GetPolicyValue("thread");
1149 if (value != (char *) NULL)
1150 resource_info.thread_limit=MagickMin(limit,StringToSizeType(value,
1152 if (resource_info.thread_limit > GetOpenMPMaximumThreads())
1153 resource_info.thread_limit=GetOpenMPMaximumThreads();
1158 resource_info.time_limit=limit;
1159 value=GetPolicyValue("time");
1160 if (value != (char *) NULL)
1161 resource_info.time_limit=MagickMin(limit,StringToSizeType(value,100.0));
1167 if (value != (char *) NULL)
1168 value=DestroyString(value);
1169 UnlockSemaphoreInfo(resource_semaphore);