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-2014 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)
100 InitializeMagickMutex();
102 if (*semaphore_info == (SemaphoreInfo *) NULL)
103 *semaphore_info=AllocateSemaphoreInfo();
109 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
113 % A l l o c a t e S e m a p h o r e I n f o %
117 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
119 % AllocateSemaphoreInfo() initializes the SemaphoreInfo structure.
121 % The format of the AllocateSemaphoreInfo method is:
123 % SemaphoreInfo *AllocateSemaphoreInfo(void)
127 static void *AcquireSemaphoreMemory(const size_t count,const size_t quantum)
129 #define AlignedExtent(size,alignment) \
130 (((size)+((alignment)-1)) & ~((alignment)-1))
141 if ((count == 0) || (quantum != (size/count)))
144 return((void *) NULL);
147 alignment=CACHE_LINE_SIZE;
148 extent=AlignedExtent(size,alignment);
149 if ((size == 0) || (alignment < sizeof(void *)) || (extent < size))
150 return((void *) NULL);
151 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
152 if (posix_memalign(&memory,alignment,extent) != 0)
154 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
155 memory=_aligned_malloc(extent,alignment);
161 extent=(size+alignment-1)+sizeof(void *);
167 memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
168 *((void **) memory-1)=p;
176 static void *RelinquishSemaphoreMemory(void *memory)
178 if (memory == (void *) NULL)
179 return((void *) NULL);
180 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
182 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
183 _aligned_free(memory);
185 free(*((void **) memory-1));
190 MagickExport SemaphoreInfo *AllocateSemaphoreInfo(void)
198 semaphore_info=(SemaphoreInfo *) AcquireSemaphoreMemory(1,
199 sizeof(*semaphore_info));
200 if (semaphore_info == (SemaphoreInfo *) NULL)
201 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
202 (void) ResetMagickMemory(semaphore_info,0,sizeof(SemaphoreInfo));
204 Initialize the semaphore.
206 #if defined(MAGICKCORE_OPENMP_SUPPORT)
207 omp_init_lock((omp_lock_t *) &semaphore_info->mutex);
208 #elif defined(MAGICKCORE_THREAD_SUPPORT)
216 status=pthread_mutexattr_init(&mutex_info);
220 perror("unable to initialize mutex attributes");
223 #if defined(MAGICKCORE_DEBUG)
224 #if defined(PTHREAD_MUTEX_ERRORCHECK)
225 status=pthread_mutex_settype(&mutex_info,PTHREAD_MUTEX_ERRORCHECK);
229 perror("unable to set mutex type");
234 status=pthread_mutex_init(&semaphore_info->mutex,&mutex_info);
238 perror("unable to initialize mutex");
241 status=pthread_mutexattr_destroy(&mutex_info);
245 perror("unable to destroy mutex attributes");
249 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
254 status=InitializeCriticalSectionAndSpinCount(&semaphore_info->mutex,0x0400);
258 perror("unable to initialize critical section");
263 semaphore_info->id=GetMagickThreadId();
264 semaphore_info->reference_count=0;
265 semaphore_info->signature=MagickSignature;
266 return(semaphore_info);
270 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274 % D e s t r o y S e m a p h o r e I n f o %
278 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
280 % DestroySemaphoreInfo() destroys a semaphore.
282 % The format of the DestroySemaphoreInfo method is:
284 % void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info)
286 % A description of each parameter follows:
288 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
291 MagickExport void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info)
293 assert(semaphore_info != (SemaphoreInfo **) NULL);
294 assert((*semaphore_info) != (SemaphoreInfo *) NULL);
295 assert((*semaphore_info)->signature == MagickSignature);
296 InitializeMagickMutex();
298 #if defined(MAGICKCORE_OPENMP_SUPPORT)
299 omp_destroy_lock((omp_lock_t *) &(*semaphore_info)->mutex);
300 #elif defined(MAGICKCORE_THREAD_SUPPORT)
305 status=pthread_mutex_destroy(&(*semaphore_info)->mutex);
309 perror("unable to destroy mutex");
313 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
314 DeleteCriticalSection(&(*semaphore_info)->mutex);
316 (*semaphore_info)->signature=(~MagickSignature);
317 *semaphore_info=(SemaphoreInfo *) RelinquishSemaphoreMemory(*semaphore_info);
322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
326 % L o c k S e m a p h o r e I n f o %
330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
332 % LockSemaphoreInfo() locks a semaphore.
334 % The format of the LockSemaphoreInfo method is:
336 % void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
338 % A description of each parameter follows:
340 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
343 MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
345 assert(semaphore_info != (SemaphoreInfo *) NULL);
346 assert(semaphore_info->signature == MagickSignature);
347 #if defined(MAGICKCORE_OPENMP_SUPPORT)
348 omp_set_lock((omp_lock_t *) &semaphore_info->mutex);
349 #elif defined(MAGICKCORE_THREAD_SUPPORT)
354 status=pthread_mutex_lock(&semaphore_info->mutex);
358 perror("unable to lock mutex");
362 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
363 EnterCriticalSection(&semaphore_info->mutex);
365 #if defined(MAGICKCORE_DEBUG)
366 if ((semaphore_info->reference_count > 0) &&
367 (IsMagickThreadEqual(semaphore_info->id) != MagickFalse))
369 (void) FormatLocaleFile(stderr,"Warning: unexpected recursive lock!\n");
370 (void) fflush(stderr);
373 semaphore_info->id=GetMagickThreadId();
374 semaphore_info->reference_count++;
378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
382 % R e l i n g u i s h S e m a p h o r e I n f o %
386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
388 % RelinquishSemaphoreInfo() relinquishes a semaphore.
390 % The format of the RelinquishSemaphoreInfo method is:
392 % RelinquishSemaphoreInfo(SemaphoreInfo *semaphore_info)
394 % A description of each parameter follows:
396 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
399 MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo *semaphore_info)
401 assert(semaphore_info != (SemaphoreInfo *) NULL);
402 assert(semaphore_info->signature == MagickSignature);
403 UnlockSemaphoreInfo(semaphore_info);
407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
411 % 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 %
415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
417 % SemaphoreComponentGenesis() instantiates the semaphore environment.
419 % The format of the SemaphoreComponentGenesis method is:
421 % MagickBooleanType SemaphoreComponentGenesis(void)
424 MagickPrivate MagickBooleanType SemaphoreComponentGenesis(void)
426 InitializeMagickMutex();
431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
435 % 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 %
439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
441 % SemaphoreComponentTerminus() destroys the semaphore component.
443 % The format of the SemaphoreComponentTerminus method is:
445 % SemaphoreComponentTerminus(void)
448 MagickPrivate void SemaphoreComponentTerminus(void)
450 DestroyMagickMutex();
454 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
458 % U n l o c k S e m a p h o r e I n f o %
462 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
464 % UnlockSemaphoreInfo() unlocks a semaphore.
466 % The format of the UnlockSemaphoreInfo method is:
468 % void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
470 % A description of each parameter follows:
472 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
475 MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
477 assert(semaphore_info != (SemaphoreInfo *) NULL);
478 assert(semaphore_info->signature == MagickSignature);
479 #if defined(MAGICKCORE_DEBUG)
480 assert(IsMagickThreadEqual(semaphore_info->id) != MagickFalse);
481 if (semaphore_info->reference_count == 0)
483 (void) FormatLocaleFile(stderr,
484 "Warning: semaphore lock already unlocked!\n");
485 (void) fflush(stderr);
488 semaphore_info->reference_count--;
490 #if defined(MAGICKCORE_OPENMP_SUPPORT)
491 omp_unset_lock((omp_lock_t *) &semaphore_info->mutex);
492 #elif defined(MAGICKCORE_THREAD_SUPPORT)
497 status=pthread_mutex_unlock(&semaphore_info->mutex);
501 perror("unable to unlock mutex");
505 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
506 LeaveCriticalSection(&semaphore_info->mutex);