2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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 %
13 % MagickCore Semaphore Methods %
21 % Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
22 % dedicated to making software imaging solutions freely available. %
24 % You may not use this file except in compliance with the License. You may %
25 % obtain a copy of the License at %
27 % http://www.imagemagick.org/script/license.php %
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. %
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
44 #include "magick/studio.h"
45 #include "magick/exception.h"
46 #include "magick/exception-private.h"
47 #include "magick/memory_.h"
48 #include "magick/semaphore.h"
49 #include "magick/string_.h"
50 #include "magick/thread_.h"
51 #include "magick/thread-private.h"
74 #if defined(MAGICKCORE_HAVE_PTHREAD)
75 static pthread_mutex_t
76 semaphore_mutex = PTHREAD_MUTEX_INITIALIZER;
77 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
86 Forward declaractions.
89 LockMagickMutex(void),
90 UnlockMagickMutex(void);
93 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
97 % A c q u i r e S e m a p h o r e I n f o %
101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
103 % AcquireSemaphoreInfo() acquires a semaphore.
105 % The format of the AcquireSemaphoreInfo method is:
107 % void AcquireSemaphoreInfo(SemaphoreInfo **semaphore_info)
109 % A description of each parameter follows:
111 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
114 MagickExport void AcquireSemaphoreInfo(SemaphoreInfo **semaphore_info)
116 assert(semaphore_info != (SemaphoreInfo **) NULL);
117 if (*semaphore_info == (SemaphoreInfo *) NULL)
120 if (*semaphore_info == (SemaphoreInfo *) NULL)
121 *semaphore_info=AllocateSemaphoreInfo();
127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
131 % A l l o c a t e S e m a p h o r e I n f o %
135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
137 % AllocateSemaphoreInfo() initializes the SemaphoreInfo structure.
139 % The format of the AllocateSemaphoreInfo method is:
141 % SemaphoreInfo *AllocateSemaphoreInfo(void)
144 MagickExport SemaphoreInfo *AllocateSemaphoreInfo(void)
152 semaphore_info=(SemaphoreInfo *) AcquireAlignedMemory(1,
153 sizeof(SemaphoreInfo));
154 if (semaphore_info == (SemaphoreInfo *) NULL)
155 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
156 (void) ResetMagickMemory(semaphore_info,0,sizeof(SemaphoreInfo));
158 Initialize the semaphore.
160 #if defined(MAGICKCORE_HAVE_PTHREAD)
168 status=pthread_mutexattr_init(&mutex_info);
172 ThrowFatalException(ResourceLimitFatalError,
173 "UnableToInitializeSemaphore");
175 status=pthread_mutex_init(&semaphore_info->mutex,&mutex_info);
179 ThrowFatalException(ResourceLimitFatalError,
180 "UnableToInitializeSemaphore");
182 status=pthread_mutexattr_destroy(&mutex_info);
186 ThrowFatalException(ResourceLimitFatalError,
187 "UnableToInitializeSemaphore");
190 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
191 InitializeCriticalSection(&semaphore_info->mutex);
193 semaphore_info->id=GetMagickThreadId();
194 semaphore_info->reference_count=0;
195 semaphore_info->signature=MagickSignature;
196 return(semaphore_info);
200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
204 % D e s t r o y S e m a p h o r e I n f o %
208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
210 % DestroySemaphoreInfo() destroys a semaphore.
212 % The format of the DestroySemaphoreInfo method is:
214 % void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info)
216 % A description of each parameter follows:
218 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
221 MagickExport void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info)
223 assert(semaphore_info != (SemaphoreInfo **) NULL);
224 assert((*semaphore_info) != (SemaphoreInfo *) NULL);
225 assert((*semaphore_info)->signature == MagickSignature);
227 #if defined(MAGICKCORE_HAVE_PTHREAD)
232 status=pthread_mutex_destroy(&(*semaphore_info)->mutex);
236 ThrowFatalException(ResourceLimitFatalError,"UnableToDestroySemaphore");
239 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
240 DeleteCriticalSection(&(*semaphore_info)->mutex);
242 (*semaphore_info)->signature=(~MagickSignature);
243 *semaphore_info=(SemaphoreInfo *) RelinquishAlignedMemory(*semaphore_info);
248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252 + L o c k M a g i c k M u t e x %
256 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
258 % LockMagickMutex() locks a global mutex. If it is already locked, the
259 % calling thread blocks until the mutex becomes available.
261 % The format of the LockMagickMutex method is:
263 % void LockMagickMutex(void)
266 static void LockMagickMutex(void)
268 #if defined(MAGICKCORE_HAVE_PTHREAD)
273 status=pthread_mutex_lock(&semaphore_mutex);
277 ThrowFatalException(ResourceLimitFatalError,"UnableToLockSemaphore");
280 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
281 while (InterlockedCompareExchange(&semaphore_mutex,1L,0L) != 0)
287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
291 % L o c k S e m a p h o r e I n f o %
295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
297 % LockSemaphoreInfo() locks a semaphore.
299 % The format of the LockSemaphoreInfo method is:
301 % void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
303 % A description of each parameter follows:
305 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
308 MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
310 assert(semaphore_info != (SemaphoreInfo *) NULL);
311 assert(semaphore_info->signature == MagickSignature);
312 #if defined(MAGICKCORE_HAVE_PTHREAD)
317 status=pthread_mutex_lock(&semaphore_info->mutex);
321 ThrowFatalException(ResourceLimitFatalError,"UnableToLockSemaphore");
324 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
325 EnterCriticalSection(&semaphore_info->mutex);
327 #if defined(MAGICKCORE_DEBUG)
328 if ((semaphore_info->reference_count > 0) &&
329 (IsMagickThreadEqual(semaphore_info->id) != MagickFalse))
331 (void) fprintf(stderr,"Warning: unexpected recursive lock!\n");
332 (void) fflush(stderr);
335 semaphore_info->id=GetMagickThreadId();
336 semaphore_info->reference_count++;
340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
344 % R e l i n g u i s h S e m a p h o r e I n f o %
348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
350 % RelinquishSemaphoreInfo() relinquishes a semaphore.
352 % The format of the RelinquishSemaphoreInfo method is:
354 % RelinquishSemaphoreInfo(SemaphoreInfo *semaphore_info)
356 % A description of each parameter follows:
358 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
361 MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo *semaphore_info)
363 assert(semaphore_info != (SemaphoreInfo *) NULL);
364 assert(semaphore_info->signature == MagickSignature);
365 UnlockSemaphoreInfo(semaphore_info);
369 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
373 % 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 %
377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
379 % SemaphoreComponentGenesis() instantiates the semaphore environment.
381 % The format of the SemaphoreComponentGenesis method is:
383 % MagickBooleanType SemaphoreComponentGenesis(void)
386 MagickExport MagickBooleanType SemaphoreComponentGenesis(void)
394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398 % 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 %
402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
404 % SemaphoreComponentTerminus() destroys the semaphore component.
406 % The format of the SemaphoreComponentTerminus method is:
408 % SemaphoreComponentTerminus(void)
411 MagickExport void SemaphoreComponentTerminus(void)
416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
420 + U n l o c k M a g i c k M u t e x %
424 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
426 % UnlockMagickMutex() releases a global mutex.
428 % The format of the LockMagickMutex method is:
430 % void UnlockMagickMutex(void)
433 static void UnlockMagickMutex(void)
435 #if defined(MAGICKCORE_HAVE_PTHREAD)
440 status=pthread_mutex_unlock(&semaphore_mutex);
444 ThrowFatalException(ResourceLimitFatalError,"UnableToUnlockSemaphore");
447 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
448 InterlockedExchange(&semaphore_mutex,0L);
453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
457 % U n l o c k S e m a p h o r e I n f o %
461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
463 % UnlockSemaphoreInfo() unlocks a semaphore.
465 % The format of the UnlockSemaphoreInfo method is:
467 % void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
469 % A description of each parameter follows:
471 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
474 MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
476 assert(semaphore_info != (SemaphoreInfo *) NULL);
477 assert(semaphore_info->signature == MagickSignature);
478 #if defined(MAGICKCORE_DEBUG)
479 assert(IsMagickThreadEqual(semaphore_info->id) != MagickFalse);
480 if (semaphore_info->reference_count == 0)
482 (void) fprintf(stderr,"Warning: semaphore lock already unlocked!\n");
483 (void) fflush(stderr);
486 semaphore_info->reference_count--;
488 #if defined(MAGICKCORE_HAVE_PTHREAD)
493 status=pthread_mutex_unlock(&semaphore_info->mutex);
497 ThrowFatalException(ResourceLimitFatalError,"UnableToUnlockSemaphore");
500 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
501 LeaveCriticalSection(&semaphore_info->mutex);