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-2012 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 "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"
74 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78 % A c q u i r e S e m a p h o r e I n f o %
82 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84 % AcquireSemaphoreInfo() acquires a semaphore.
86 % The format of the AcquireSemaphoreInfo method is:
88 % void AcquireSemaphoreInfo(SemaphoreInfo **semaphore_info)
90 % A description of each parameter follows:
92 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
95 MagickExport void AcquireSemaphoreInfo(SemaphoreInfo **semaphore_info)
97 assert(semaphore_info != (SemaphoreInfo **) NULL);
98 if (*semaphore_info == (SemaphoreInfo *) NULL)
101 if (*semaphore_info == (SemaphoreInfo *) NULL)
102 *semaphore_info=AllocateSemaphoreInfo();
108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
112 % A l l o c a t e S e m a p h o r e I n f o %
116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
118 % AllocateSemaphoreInfo() initializes the SemaphoreInfo structure.
120 % The format of the AllocateSemaphoreInfo method is:
122 % SemaphoreInfo *AllocateSemaphoreInfo(void)
126 static void *AcquireSemaphoreMemory(const size_t count,const size_t quantum)
128 #define AlignedExtent(size,alignment) \
129 (((size)+((alignment)-1)) & ~((alignment)-1))
140 if ((count == 0) || (quantum != (size/count)))
143 return((void *) NULL);
146 alignment=CACHE_LINE_SIZE;
147 extent=AlignedExtent(size,alignment);
148 if ((size == 0) || (alignment < sizeof(void *)) || (extent < size))
149 return((void *) NULL);
150 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
151 if (posix_memalign(&memory,alignment,extent) != 0)
153 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
154 memory=_aligned_malloc(extent,alignment);
160 extent=(size+alignment-1)+sizeof(void *);
166 memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
167 *((void **) memory-1)=p;
175 static void *RelinquishSemaphoreMemory(void *memory)
177 if (memory == (void *) NULL)
178 return((void *) NULL);
179 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
181 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
182 _aligned_free(memory);
184 free(*((void **) memory-1));
189 MagickExport SemaphoreInfo *AllocateSemaphoreInfo(void)
197 semaphore_info=(SemaphoreInfo *) AcquireSemaphoreMemory(1,
198 sizeof(*semaphore_info));
199 if (semaphore_info == (SemaphoreInfo *) NULL)
200 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
201 (void) ResetMagickMemory(semaphore_info,0,sizeof(SemaphoreInfo));
203 Initialize the semaphore.
205 #if defined(MAGICKCORE_THREAD_SUPPORT)
213 status=pthread_mutexattr_init(&mutex_info);
217 ThrowFatalException(ResourceLimitFatalError,
218 "UnableToInitializeSemaphore");
220 #if defined(MAGICKCORE_DEBUG)
221 #if defined(PTHREAD_MUTEX_ERRORCHECK)
222 status=pthread_mutex_settype(&mutex_info,PTHREAD_MUTEX_ERRORCHECK);
226 ThrowFatalException(ResourceLimitFatalError,
227 "UnableToInitializeSemaphore");
231 status=pthread_mutex_init(&semaphore_info->mutex,&mutex_info);
235 ThrowFatalException(ResourceLimitFatalError,
236 "UnableToInitializeSemaphore");
238 status=pthread_mutexattr_destroy(&mutex_info);
242 ThrowFatalException(ResourceLimitFatalError,
243 "UnableToInitializeSemaphore");
246 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
251 status=InitializeCriticalSectionAndSpinCount(&semaphore_info->mutex,0x0400);
255 ThrowFatalException(ResourceLimitFatalError,
256 "UnableToInitializeSemaphore");
260 semaphore_info->id=GetMagickThreadId();
261 semaphore_info->reference_count=0;
262 semaphore_info->signature=MagickSignature;
263 return(semaphore_info);
267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271 % D e s t r o y S e m a p h o r e I n f o %
275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
277 % DestroySemaphoreInfo() destroys a semaphore.
279 % The format of the DestroySemaphoreInfo method is:
281 % void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info)
283 % A description of each parameter follows:
285 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
288 MagickExport void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info)
290 assert(semaphore_info != (SemaphoreInfo **) NULL);
291 assert((*semaphore_info) != (SemaphoreInfo *) NULL);
292 assert((*semaphore_info)->signature == MagickSignature);
294 #if defined(MAGICKCORE_THREAD_SUPPORT)
299 status=pthread_mutex_destroy(&(*semaphore_info)->mutex);
303 ThrowFatalException(ResourceLimitFatalError,"UnableToDestroySemaphore");
306 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
307 DeleteCriticalSection(&(*semaphore_info)->mutex);
309 (*semaphore_info)->signature=(~MagickSignature);
310 *semaphore_info=(SemaphoreInfo *) RelinquishSemaphoreMemory(*semaphore_info);
315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
319 % L o c k S e m a p h o r e I n f o %
323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
325 % LockSemaphoreInfo() locks a semaphore.
327 % The format of the LockSemaphoreInfo method is:
329 % void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
331 % A description of each parameter follows:
333 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
336 MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
338 assert(semaphore_info != (SemaphoreInfo *) NULL);
339 assert(semaphore_info->signature == MagickSignature);
340 #if defined(MAGICKCORE_THREAD_SUPPORT)
345 status=pthread_mutex_lock(&semaphore_info->mutex);
349 ThrowFatalException(ResourceLimitFatalError,"UnableToLockSemaphore");
352 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
353 EnterCriticalSection(&semaphore_info->mutex);
355 #if defined(MAGICKCORE_DEBUG)
356 if ((semaphore_info->reference_count > 0) &&
357 (IsMagickThreadEqual(semaphore_info->id) != MagickFalse))
359 (void) FormatLocaleFile(stderr,"Warning: unexpected recursive lock!\n");
360 (void) fflush(stderr);
363 semaphore_info->id=GetMagickThreadId();
364 semaphore_info->reference_count++;
368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
372 % R e l i n g u i s h S e m a p h o r e I n f o %
376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
378 % RelinquishSemaphoreInfo() relinquishes a semaphore.
380 % The format of the RelinquishSemaphoreInfo method is:
382 % RelinquishSemaphoreInfo(SemaphoreInfo *semaphore_info)
384 % A description of each parameter follows:
386 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
389 MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo *semaphore_info)
391 assert(semaphore_info != (SemaphoreInfo *) NULL);
392 assert(semaphore_info->signature == MagickSignature);
393 UnlockSemaphoreInfo(semaphore_info);
397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
401 % 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 %
405 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
407 % SemaphoreComponentGenesis() instantiates the semaphore environment.
409 % The format of the SemaphoreComponentGenesis method is:
411 % MagickBooleanType SemaphoreComponentGenesis(void)
414 MagickPrivate MagickBooleanType SemaphoreComponentGenesis(void)
422 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
426 % 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 %
430 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
432 % SemaphoreComponentTerminus() destroys the semaphore component.
434 % The format of the SemaphoreComponentTerminus method is:
436 % SemaphoreComponentTerminus(void)
439 MagickPrivate void SemaphoreComponentTerminus(void)
444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
448 % U n l o c k S e m a p h o r e I n f o %
452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
454 % UnlockSemaphoreInfo() unlocks a semaphore.
456 % The format of the UnlockSemaphoreInfo method is:
458 % void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
460 % A description of each parameter follows:
462 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
465 MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
467 assert(semaphore_info != (SemaphoreInfo *) NULL);
468 assert(semaphore_info->signature == MagickSignature);
469 #if defined(MAGICKCORE_DEBUG)
470 assert(IsMagickThreadEqual(semaphore_info->id) != MagickFalse);
471 if (semaphore_info->reference_count == 0)
473 (void) FormatLocaleFile(stderr,
474 "Warning: semaphore lock already unlocked!\n");
475 (void) fflush(stderr);
478 semaphore_info->reference_count--;
480 #if defined(MAGICKCORE_THREAD_SUPPORT)
485 status=pthread_mutex_unlock(&semaphore_info->mutex);
489 ThrowFatalException(ResourceLimitFatalError,"UnableToUnlockSemaphore");
492 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
493 LeaveCriticalSection(&semaphore_info->mutex);