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 t i v a t e S e m a p h o r e I n f o %
82 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84 % ActivateSemaphoreInfo() activates a semaphore under protection of a mutex
85 % to ensure only one thread allocates the semaphore.
87 % The format of the ActivateSemaphoreInfo method is:
89 % void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info)
91 % A description of each parameter follows:
93 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
96 MagickExport void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info)
98 assert(semaphore_info != (SemaphoreInfo **) NULL);
99 if (*semaphore_info == (SemaphoreInfo *) NULL)
101 InitializeMagickMutex();
103 if (*semaphore_info == (SemaphoreInfo *) NULL)
104 *semaphore_info=AcquireSemaphoreInfo();
110 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
114 % A c q u i r e S e m a p h o r e I n f o %
118 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120 % AcquireSemaphoreInfo() initializes the SemaphoreInfo structure.
122 % The format of the AcquireSemaphoreInfo method is:
124 % SemaphoreInfo *AcquireSemaphoreInfo(void)
128 static void *AcquireSemaphoreMemory(const size_t count,const size_t quantum)
130 #define AlignedExtent(size,alignment) \
131 (((size)+((alignment)-1)) & ~((alignment)-1))
142 if ((count == 0) || (quantum != (size/count)))
145 return((void *) NULL);
148 alignment=CACHE_LINE_SIZE;
149 extent=AlignedExtent(size,alignment);
150 if ((size == 0) || (alignment < sizeof(void *)) || (extent < size))
151 return((void *) NULL);
152 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
153 if (posix_memalign(&memory,alignment,extent) != 0)
155 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
156 memory=_aligned_malloc(extent,alignment);
162 extent=(size+alignment-1)+sizeof(void *);
168 memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
169 *((void **) memory-1)=p;
177 static void *RelinquishSemaphoreMemory(void *memory)
179 if (memory == (void *) NULL)
180 return((void *) NULL);
181 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
183 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
184 _aligned_free(memory);
186 free(*((void **) memory-1));
191 MagickExport SemaphoreInfo *AcquireSemaphoreInfo(void)
199 semaphore_info=(SemaphoreInfo *) AcquireSemaphoreMemory(1,
200 sizeof(*semaphore_info));
201 if (semaphore_info == (SemaphoreInfo *) NULL)
202 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
203 (void) ResetMagickMemory(semaphore_info,0,sizeof(SemaphoreInfo));
205 Initialize the semaphore.
207 #if defined(MAGICKCORE_OPENMP_SUPPORT)
208 omp_init_lock((omp_lock_t *) &semaphore_info->mutex);
209 #elif defined(MAGICKCORE_THREAD_SUPPORT)
217 status=pthread_mutexattr_init(&mutex_info);
221 perror("unable to initialize mutex attributes");
224 #if defined(MAGICKCORE_DEBUG)
225 #if defined(PTHREAD_MUTEX_ERRORCHECK)
226 status=pthread_mutex_settype(&mutex_info,PTHREAD_MUTEX_ERRORCHECK);
230 perror("unable to set mutex type");
235 status=pthread_mutex_init(&semaphore_info->mutex,&mutex_info);
239 perror("unable to initialize mutex");
242 status=pthread_mutexattr_destroy(&mutex_info);
246 perror("unable to destroy mutex attributes");
250 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
255 status=InitializeCriticalSectionAndSpinCount(&semaphore_info->mutex,0x0400);
259 perror("unable to initialize critical section");
264 semaphore_info->id=GetMagickThreadId();
265 semaphore_info->reference_count=0;
266 semaphore_info->signature=MagickSignature;
267 return(semaphore_info);
271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
275 % L o c k S e m a p h o r e I n f o %
279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
281 % LockSemaphoreInfo() locks a semaphore.
283 % The format of the LockSemaphoreInfo method is:
285 % void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
287 % A description of each parameter follows:
289 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
292 MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
294 assert(semaphore_info != (SemaphoreInfo *) NULL);
295 assert(semaphore_info->signature == MagickSignature);
296 #if defined(MAGICKCORE_DEBUG)
297 if ((semaphore_info->reference_count > 0) &&
298 (IsMagickThreadEqual(semaphore_info->id) != MagickFalse))
300 (void) FormatLocaleFile(stderr,"Warning: unexpected recursive lock!\n");
301 (void) fflush(stderr);
304 #if defined(MAGICKCORE_OPENMP_SUPPORT)
305 omp_set_lock((omp_lock_t *) &semaphore_info->mutex);
306 #elif defined(MAGICKCORE_THREAD_SUPPORT)
311 status=pthread_mutex_lock(&semaphore_info->mutex);
315 perror("unable to lock mutex");
319 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
320 EnterCriticalSection(&semaphore_info->mutex);
322 #if defined(MAGICKCORE_DEBUG)
323 semaphore_info->id=GetMagickThreadId();
324 semaphore_info->reference_count++;
329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
333 % R e l i n q u i s h S e m a p h o r e I n f o %
337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
339 % RelinquishSemaphoreInfo() destroys a semaphore.
341 % The format of the RelinquishSemaphoreInfo method is:
343 % void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info)
345 % A description of each parameter follows:
347 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
350 MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info)
352 assert(semaphore_info != (SemaphoreInfo **) NULL);
353 assert((*semaphore_info) != (SemaphoreInfo *) NULL);
354 assert((*semaphore_info)->signature == MagickSignature);
355 InitializeMagickMutex();
357 #if defined(MAGICKCORE_OPENMP_SUPPORT)
358 omp_destroy_lock((omp_lock_t *) &(*semaphore_info)->mutex);
359 #elif defined(MAGICKCORE_THREAD_SUPPORT)
364 status=pthread_mutex_destroy(&(*semaphore_info)->mutex);
368 perror("unable to destroy mutex");
372 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
373 DeleteCriticalSection(&(*semaphore_info)->mutex);
375 (*semaphore_info)->signature=(~MagickSignature);
376 *semaphore_info=(SemaphoreInfo *) RelinquishSemaphoreMemory(*semaphore_info);
381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
385 % 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 %
389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
391 % SemaphoreComponentGenesis() instantiates the semaphore environment.
393 % The format of the SemaphoreComponentGenesis method is:
395 % MagickBooleanType SemaphoreComponentGenesis(void)
398 MagickPrivate MagickBooleanType SemaphoreComponentGenesis(void)
400 InitializeMagickMutex();
405 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
409 % 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 %
413 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
415 % SemaphoreComponentTerminus() destroys the semaphore component.
417 % The format of the SemaphoreComponentTerminus method is:
419 % SemaphoreComponentTerminus(void)
422 MagickPrivate void SemaphoreComponentTerminus(void)
424 DestroyMagickMutex();
428 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
432 % U n l o c k S e m a p h o r e I n f o %
436 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
438 % UnlockSemaphoreInfo() unlocks a semaphore.
440 % The format of the UnlockSemaphoreInfo method is:
442 % void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
444 % A description of each parameter follows:
446 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
449 MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
451 assert(semaphore_info != (SemaphoreInfo *) NULL);
452 assert(semaphore_info->signature == MagickSignature);
453 #if defined(MAGICKCORE_DEBUG)
454 assert(IsMagickThreadEqual(semaphore_info->id) != MagickFalse);
455 if (semaphore_info->reference_count == 0)
457 (void) FormatLocaleFile(stderr,
458 "Warning: semaphore lock already unlocked!\n");
459 (void) fflush(stderr);
462 semaphore_info->reference_count--;
464 #if defined(MAGICKCORE_OPENMP_SUPPORT)
465 omp_unset_lock((omp_lock_t *) &semaphore_info->mutex);
466 #elif defined(MAGICKCORE_THREAD_SUPPORT)
471 status=pthread_mutex_unlock(&semaphore_info->mutex);
475 perror("unable to unlock mutex");
479 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
480 LeaveCriticalSection(&semaphore_info->mutex);