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-2017 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 % https://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"
54 #include "MagickCore/utility-private.h"
75 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79 % A c t i v a t e S e m a p h o r e I n f o %
83 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
85 % ActivateSemaphoreInfo() activates a semaphore under protection of a mutex
86 % to ensure only one thread allocates the semaphore.
88 % The format of the ActivateSemaphoreInfo method is:
90 % void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info)
92 % A description of each parameter follows:
94 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
97 MagickExport void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info)
99 assert(semaphore_info != (SemaphoreInfo **) NULL);
100 if (*semaphore_info == (SemaphoreInfo *) NULL)
102 InitializeMagickMutex();
104 if (*semaphore_info == (SemaphoreInfo *) NULL)
105 *semaphore_info=AcquireSemaphoreInfo();
111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
115 % A c q u i r e S e m a p h o r e I n f o %
119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
121 % AcquireSemaphoreInfo() initializes the SemaphoreInfo structure.
123 % The format of the AcquireSemaphoreInfo method is:
125 % SemaphoreInfo *AcquireSemaphoreInfo(void)
129 static void *AcquireSemaphoreMemory(const size_t count,const size_t quantum)
131 #define AlignedExtent(size,alignment) \
132 (((size)+((alignment)-1)) & ~((alignment)-1))
143 if ((count == 0) || (quantum != (size/count)))
146 return((void *) 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)
156 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
157 memory=_aligned_malloc(extent,alignment);
163 extent=(size+alignment-1)+sizeof(void *);
169 memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
170 *((void **) memory-1)=p;
178 static void *RelinquishSemaphoreMemory(void *memory)
180 if (memory == (void *) NULL)
181 return((void *) NULL);
182 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
184 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
185 _aligned_free(memory);
187 free(*((void **) memory-1));
192 MagickExport SemaphoreInfo *AcquireSemaphoreInfo(void)
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));
206 Initialize the semaphore.
208 #if defined(MAGICKCORE_OPENMP_SUPPORT)
209 omp_init_lock((omp_lock_t *) &semaphore_info->mutex);
210 #elif defined(MAGICKCORE_THREAD_SUPPORT)
218 status=pthread_mutexattr_init(&mutex_info);
222 perror("unable to initialize mutex attributes");
225 #if defined(MAGICKCORE_DEBUG)
226 #if defined(PTHREAD_MUTEX_ERRORCHECK)
227 status=pthread_mutex_settype(&mutex_info,PTHREAD_MUTEX_ERRORCHECK);
231 perror("unable to set mutex type");
236 status=pthread_mutex_init(&semaphore_info->mutex,&mutex_info);
240 perror("unable to initialize mutex");
243 status=pthread_mutexattr_destroy(&mutex_info);
247 perror("unable to destroy mutex attributes");
251 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
256 status=InitializeCriticalSectionAndSpinCount(&semaphore_info->mutex,0x0400);
260 perror("unable to initialize critical section");
265 semaphore_info->id=GetMagickThreadId();
266 semaphore_info->reference_count=0;
267 semaphore_info->signature=MagickCoreSignature;
268 return(semaphore_info);
272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276 % L o c k S e m a p h o r e I n f o %
280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
282 % LockSemaphoreInfo() locks a semaphore.
284 % The format of the LockSemaphoreInfo method is:
286 % void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
288 % A description of each parameter follows:
290 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
293 MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
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))
301 (void) FormatLocaleFile(stderr,"Warning: unexpected recursive lock!\n");
302 (void) fflush(stderr);
305 #if defined(MAGICKCORE_OPENMP_SUPPORT)
306 omp_set_lock((omp_lock_t *) &semaphore_info->mutex);
307 #elif defined(MAGICKCORE_THREAD_SUPPORT)
312 status=pthread_mutex_lock(&semaphore_info->mutex);
316 perror("unable to lock mutex");
320 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
321 EnterCriticalSection(&semaphore_info->mutex);
323 #if defined(MAGICKCORE_DEBUG)
324 semaphore_info->id=GetMagickThreadId();
325 semaphore_info->reference_count++;
330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
334 % R e l i n q u i s h S e m a p h o r e I n f o %
338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340 % RelinquishSemaphoreInfo() destroys a semaphore.
342 % The format of the RelinquishSemaphoreInfo method is:
344 % void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info)
346 % A description of each parameter follows:
348 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
351 MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info)
353 assert(semaphore_info != (SemaphoreInfo **) NULL);
354 assert((*semaphore_info) != (SemaphoreInfo *) NULL);
355 assert((*semaphore_info)->signature == MagickCoreSignature);
356 InitializeMagickMutex();
358 #if defined(MAGICKCORE_OPENMP_SUPPORT)
359 omp_destroy_lock((omp_lock_t *) &(*semaphore_info)->mutex);
360 #elif defined(MAGICKCORE_THREAD_SUPPORT)
365 status=pthread_mutex_destroy(&(*semaphore_info)->mutex);
369 perror("unable to destroy mutex");
373 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
374 DeleteCriticalSection(&(*semaphore_info)->mutex);
376 (*semaphore_info)->signature=(~MagickCoreSignature);
377 *semaphore_info=(SemaphoreInfo *) RelinquishSemaphoreMemory(*semaphore_info);
382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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 %
390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
392 % SemaphoreComponentGenesis() instantiates the semaphore environment.
394 % The format of the SemaphoreComponentGenesis method is:
396 % MagickBooleanType SemaphoreComponentGenesis(void)
399 MagickPrivate MagickBooleanType SemaphoreComponentGenesis(void)
401 InitializeMagickMutex();
406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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 %
414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
416 % SemaphoreComponentTerminus() destroys the semaphore component.
418 % The format of the SemaphoreComponentTerminus method is:
420 % SemaphoreComponentTerminus(void)
423 MagickPrivate void SemaphoreComponentTerminus(void)
425 DestroyMagickMutex();
429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
433 % U n l o c k S e m a p h o r e I n f o %
437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
439 % UnlockSemaphoreInfo() unlocks a semaphore.
441 % The format of the UnlockSemaphoreInfo method is:
443 % void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
445 % A description of each parameter follows:
447 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
450 MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
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)
458 (void) FormatLocaleFile(stderr,
459 "Warning: semaphore lock already unlocked!\n");
460 (void) fflush(stderr);
463 semaphore_info->reference_count--;
465 #if defined(MAGICKCORE_OPENMP_SUPPORT)
466 omp_unset_lock((omp_lock_t *) &semaphore_info->mutex);
467 #elif defined(MAGICKCORE_THREAD_SUPPORT)
472 status=pthread_mutex_unlock(&semaphore_info->mutex);
476 perror("unable to unlock mutex");
480 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
481 LeaveCriticalSection(&semaphore_info->mutex);