]> granicus.if.org Git - imagemagick/blob - MagickCore/semaphore.c
Added caNv, eXIf, and pHYs to the list of PNG chunks to be removed
[imagemagick] / MagickCore / semaphore.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %        SSSSS  EEEEE  M   M   AAA   PPPP   H   H   OOO   RRRR   EEEEE        %
7 %        SS     E      MM MM  A   A  P   P  H   H  O   O  R   R  E            %
8 %         SSS   EEE    M M M  AAAAA  PPPP   HHHHH  O   O  RRRR   EEE          %
9 %           SS  E      M   M  A   A  P      H   H  O   O  R R    E            %
10 %        SSSSS  EEEEE  M   M  A   A  P      H   H   OOO   R  R   EEEEE        %
11 %                                                                             %
12 %                                                                             %
13 %                        MagickCore Semaphore Methods                         %
14 %                                                                             %
15 %                              Software Design                                %
16 %                             William Radcliffe                               %
17 %                                   Cristy                                    %
18 %                                 June 2000                                   %
19 %                                                                             %
20 %                                                                             %
21 %  Copyright 1999-2017 ImageMagick Studio LLC, a non-profit organization      %
22 %  dedicated to making software imaging solutions freely available.           %
23 %                                                                             %
24 %  You may not use this file except in compliance with the License.  You may  %
25 %  obtain a copy of the License at                                            %
26 %                                                                             %
27 %    https://www.imagemagick.org/script/license.php                           %
28 %                                                                             %
29 %  Unless required by applicable law or agreed to in writing, software        %
30 %  distributed under the License is distributed on an "AS IS" BASIS,          %
31 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
32 %  See the License for the specific language governing permissions and        %
33 %  limitations under the License.                                             %
34 %                                                                             %
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 %
37 %
38 %
39 */
40 \f
41 /*
42   Include declarations.
43 */
44 #include "MagickCore/studio.h"
45 #include "MagickCore/exception.h"
46 #include "MagickCore/exception-private.h"
47 #include "MagickCore/memory_.h"
48 #include "MagickCore/memory-private.h"
49 #include "MagickCore/semaphore.h"
50 #include "MagickCore/semaphore-private.h"
51 #include "MagickCore/string_.h"
52 #include "MagickCore/thread_.h"
53 #include "MagickCore/thread-private.h"
54 #include "MagickCore/utility-private.h"
55 \f
56 /*
57   Struct declaractions.
58 */
59 struct SemaphoreInfo
60 {
61   MagickMutexType
62     mutex;
63
64   MagickThreadType
65     id;
66
67   ssize_t
68     reference_count;
69
70   size_t
71     signature;
72 };
73 \f
74 /*
75 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
76 %                                                                             %
77 %                                                                             %
78 %                                                                             %
79 %   A c t i v a t e S e m a p h o r e I n f o                                 %
80 %                                                                             %
81 %                                                                             %
82 %                                                                             %
83 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84 %
85 %  ActivateSemaphoreInfo() activates a semaphore under protection of a mutex
86 %  to ensure only one thread allocates the semaphore.
87 %
88 %  The format of the ActivateSemaphoreInfo method is:
89 %
90 %      void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info)
91 %
92 %  A description of each parameter follows:
93 %
94 %    o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
95 %
96 */
97 MagickExport void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info)
98 {
99   assert(semaphore_info != (SemaphoreInfo **) NULL);
100   if (*semaphore_info == (SemaphoreInfo *) NULL)
101     {
102       InitializeMagickMutex();
103       LockMagickMutex();
104       if (*semaphore_info == (SemaphoreInfo *) NULL)
105         *semaphore_info=AcquireSemaphoreInfo();
106       UnlockMagickMutex();
107     }
108 }
109 \f
110 /*
111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
112 %                                                                             %
113 %                                                                             %
114 %                                                                             %
115 %   A c q u i r e S e m a p h o r e I n f o                                   %
116 %                                                                             %
117 %                                                                             %
118 %                                                                             %
119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120 %
121 %  AcquireSemaphoreInfo() initializes the SemaphoreInfo structure.
122 %
123 %  The format of the AcquireSemaphoreInfo method is:
124 %
125 %      SemaphoreInfo *AcquireSemaphoreInfo(void)
126 %
127 */
128
129 static void *AcquireSemaphoreMemory(const size_t count,const size_t quantum)
130 {
131 #define AlignedExtent(size,alignment) \
132   (((size)+((alignment)-1)) & ~((alignment)-1))
133
134   size_t
135     alignment,
136     extent,
137     size;
138
139   void
140     *memory;
141
142   size=count*quantum;
143   if ((count == 0) || (quantum != (size/count)))
144     {
145       errno=ENOMEM;
146       return((void *) NULL);
147     }
148   memory=NULL;
149   alignment=CACHE_LINE_SIZE;
150   extent=AlignedExtent(size,CACHE_LINE_SIZE);
151   if ((size == 0) || (alignment < sizeof(void *)) || (extent < size))
152     return((void *) NULL);
153 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
154   if (posix_memalign(&memory,alignment,extent) != 0)
155     memory=NULL;
156 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
157    memory=_aligned_malloc(extent,alignment);
158 #else
159   {
160     void
161       *p;
162
163     extent=(size+alignment-1)+sizeof(void *);
164     if (extent > size)
165       {
166         p=malloc(extent);
167         if (p != NULL)
168           {
169             memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
170             *((void **) memory-1)=p;
171           }
172       }
173   }
174 #endif
175   return(memory);
176 }
177
178 static void *RelinquishSemaphoreMemory(void *memory)
179 {
180   if (memory == (void *) NULL)
181     return((void *) NULL);
182 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
183   free(memory);
184 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
185   _aligned_free(memory);
186 #else
187   free(*((void **) memory-1));
188 #endif
189   return(NULL);
190 }
191
192 MagickExport SemaphoreInfo *AcquireSemaphoreInfo(void)
193 {
194   SemaphoreInfo
195     *semaphore_info;
196
197   /*
198     Acquire semaphore.
199   */
200   semaphore_info=(SemaphoreInfo *) AcquireSemaphoreMemory(1,
201     sizeof(*semaphore_info));
202   if (semaphore_info == (SemaphoreInfo *) NULL)
203     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
204   (void) ResetMagickMemory(semaphore_info,0,sizeof(SemaphoreInfo));
205   /*
206     Initialize the semaphore.
207   */
208 #if defined(MAGICKCORE_OPENMP_SUPPORT)
209   omp_init_lock((omp_lock_t *) &semaphore_info->mutex);
210 #elif defined(MAGICKCORE_THREAD_SUPPORT)
211   {
212     int
213       status;
214
215     pthread_mutexattr_t
216       mutex_info;
217
218     status=pthread_mutexattr_init(&mutex_info);
219     if (status != 0)
220       {
221         errno=status;
222         perror("unable to initialize mutex attributes");
223         _exit(1);
224       }
225 #if defined(MAGICKCORE_DEBUG)
226 #if defined(PTHREAD_MUTEX_ERRORCHECK)
227     status=pthread_mutex_settype(&mutex_info,PTHREAD_MUTEX_ERRORCHECK);
228     if (status != 0)
229       {
230         errno=status;
231         perror("unable to set mutex type");
232         _exit(1);
233       }
234 #endif
235 #endif
236     status=pthread_mutex_init(&semaphore_info->mutex,&mutex_info);
237     if (status != 0)
238       {
239         errno=status;
240         perror("unable to initialize mutex");
241         _exit(1);
242       }
243     status=pthread_mutexattr_destroy(&mutex_info);
244     if (status != 0)
245       {
246         errno=status;
247         perror("unable to destroy mutex attributes");
248         _exit(1);
249       }
250   }
251 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
252   {
253     int
254       status;
255
256     status=InitializeCriticalSectionAndSpinCount(&semaphore_info->mutex,0x0400);
257     if (status == 0)
258       {
259         errno=status;
260         perror("unable to initialize critical section");
261         _exit(1);
262       }
263   }
264 #endif
265   semaphore_info->id=GetMagickThreadId();
266   semaphore_info->reference_count=0;
267   semaphore_info->signature=MagickCoreSignature;
268   return(semaphore_info);
269 }
270 \f
271 /*
272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
273 %                                                                             %
274 %                                                                             %
275 %                                                                             %
276 %   L o c k S e m a p h o r e I n f o                                         %
277 %                                                                             %
278 %                                                                             %
279 %                                                                             %
280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
281 %
282 %  LockSemaphoreInfo() locks a semaphore.
283 %
284 %  The format of the LockSemaphoreInfo method is:
285 %
286 %      void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
287 %
288 %  A description of each parameter follows:
289 %
290 %    o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
291 %
292 */
293 MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
294 {
295   assert(semaphore_info != (SemaphoreInfo *) NULL);
296   assert(semaphore_info->signature == MagickCoreSignature);
297 #if defined(MAGICKCORE_DEBUG)
298   if ((semaphore_info->reference_count > 0) &&
299       (IsMagickThreadEqual(semaphore_info->id) != MagickFalse))
300     {
301       (void) FormatLocaleFile(stderr,"Warning: unexpected recursive lock!\n");
302       (void) fflush(stderr);
303     }
304 #endif
305 #if defined(MAGICKCORE_OPENMP_SUPPORT)
306   omp_set_lock((omp_lock_t *) &semaphore_info->mutex);
307 #elif defined(MAGICKCORE_THREAD_SUPPORT)
308   {
309     int
310       status;
311
312     status=pthread_mutex_lock(&semaphore_info->mutex);
313     if (status != 0)
314       {
315         errno=status;
316         perror("unable to lock mutex");
317         _exit(1);
318       }
319   }
320 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
321   EnterCriticalSection(&semaphore_info->mutex);
322 #endif
323 #if defined(MAGICKCORE_DEBUG)
324   semaphore_info->id=GetMagickThreadId();
325   semaphore_info->reference_count++;
326 #endif
327 }
328 \f
329 /*
330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
331 %                                                                             %
332 %                                                                             %
333 %                                                                             %
334 %   R e l i n q u i s h S e m a p h o r e I n f o                             %
335 %                                                                             %
336 %                                                                             %
337 %                                                                             %
338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
339 %
340 %  RelinquishSemaphoreInfo() destroys a semaphore.
341 %
342 %  The format of the RelinquishSemaphoreInfo method is:
343 %
344 %      void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info)
345 %
346 %  A description of each parameter follows:
347 %
348 %    o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
349 %
350 */
351 MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info)
352 {
353   assert(semaphore_info != (SemaphoreInfo **) NULL);
354   assert((*semaphore_info) != (SemaphoreInfo *) NULL);
355   assert((*semaphore_info)->signature == MagickCoreSignature);
356   InitializeMagickMutex();
357   LockMagickMutex();
358 #if defined(MAGICKCORE_OPENMP_SUPPORT)
359   omp_destroy_lock((omp_lock_t *) &(*semaphore_info)->mutex);
360 #elif defined(MAGICKCORE_THREAD_SUPPORT)
361   {
362     int
363       status;
364
365     status=pthread_mutex_destroy(&(*semaphore_info)->mutex);
366     if (status != 0)
367       {
368         errno=status;
369         perror("unable to destroy mutex");
370         _exit(1);
371       }
372   }
373 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
374   DeleteCriticalSection(&(*semaphore_info)->mutex);
375 #endif
376   (*semaphore_info)->signature=(~MagickCoreSignature);
377   *semaphore_info=(SemaphoreInfo *) RelinquishSemaphoreMemory(*semaphore_info);
378   UnlockMagickMutex();
379 }
380 \f
381 /*
382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
383 %                                                                             %
384 %                                                                             %
385 %                                                                             %
386 %   S e m a p h o r e C o m p o n e n t G e n e s i s                         %
387 %                                                                             %
388 %                                                                             %
389 %                                                                             %
390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
391 %
392 %  SemaphoreComponentGenesis() instantiates the semaphore environment.
393 %
394 %  The format of the SemaphoreComponentGenesis method is:
395 %
396 %      MagickBooleanType SemaphoreComponentGenesis(void)
397 %
398 */
399 MagickPrivate MagickBooleanType SemaphoreComponentGenesis(void)
400 {
401   InitializeMagickMutex();
402   return(MagickTrue);
403 }
404 \f
405 /*
406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
407 %                                                                             %
408 %                                                                             %
409 %                                                                             %
410 %   S e m a p h o r e C o m p o n e n t T e r m i n u s                       %
411 %                                                                             %
412 %                                                                             %
413 %                                                                             %
414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
415 %
416 %  SemaphoreComponentTerminus() destroys the semaphore component.
417 %
418 %  The format of the SemaphoreComponentTerminus method is:
419 %
420 %      SemaphoreComponentTerminus(void)
421 %
422 */
423 MagickPrivate void SemaphoreComponentTerminus(void)
424 {
425   DestroyMagickMutex();
426 }
427 \f
428 /*
429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
430 %                                                                             %
431 %                                                                             %
432 %                                                                             %
433 %   U n l o c k S e m a p h o r e I n f o                                     %
434 %                                                                             %
435 %                                                                             %
436 %                                                                             %
437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
438 %
439 %  UnlockSemaphoreInfo() unlocks a semaphore.
440 %
441 %  The format of the UnlockSemaphoreInfo method is:
442 %
443 %      void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
444 %
445 %  A description of each parameter follows:
446 %
447 %    o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
448 %
449 */
450 MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
451 {
452   assert(semaphore_info != (SemaphoreInfo *) NULL);
453   assert(semaphore_info->signature == MagickCoreSignature);
454 #if defined(MAGICKCORE_DEBUG)
455   assert(IsMagickThreadEqual(semaphore_info->id) != MagickFalse);
456   if (semaphore_info->reference_count == 0)
457     {
458       (void) FormatLocaleFile(stderr,
459         "Warning: semaphore lock already unlocked!\n");
460       (void) fflush(stderr);
461       return;
462     }
463   semaphore_info->reference_count--;
464 #endif
465 #if defined(MAGICKCORE_OPENMP_SUPPORT)
466   omp_unset_lock((omp_lock_t *) &semaphore_info->mutex);
467 #elif defined(MAGICKCORE_THREAD_SUPPORT)
468   {
469     int
470       status;
471
472     status=pthread_mutex_unlock(&semaphore_info->mutex);
473     if (status != 0)
474       {
475         errno=status;
476         perror("unable to unlock mutex");
477         _exit(1);
478       }
479   }
480 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
481   LeaveCriticalSection(&semaphore_info->mutex);
482 #endif
483 }