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-2011 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/semaphore.h"
49 #include "MagickCore/semaphore-private.h"
50 #include "MagickCore/string_.h"
51 #include "MagickCore/thread_.h"
52 #include "MagickCore/thread-private.h"
73 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77 % A c q u i r e S e m a p h o r e I n f o %
81 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83 % AcquireSemaphoreInfo() acquires a semaphore.
85 % The format of the AcquireSemaphoreInfo method is:
87 % void AcquireSemaphoreInfo(SemaphoreInfo **semaphore_info)
89 % A description of each parameter follows:
91 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
94 MagickExport void AcquireSemaphoreInfo(SemaphoreInfo **semaphore_info)
96 assert(semaphore_info != (SemaphoreInfo **) NULL);
97 if (*semaphore_info == (SemaphoreInfo *) NULL)
100 if (*semaphore_info == (SemaphoreInfo *) NULL)
101 *semaphore_info=AllocateSemaphoreInfo();
107 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
111 % A l l o c a t e S e m a p h o r e I n f o %
115 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
117 % AllocateSemaphoreInfo() initializes the SemaphoreInfo structure.
119 % The format of the AllocateSemaphoreInfo method is:
121 % SemaphoreInfo *AllocateSemaphoreInfo(void)
124 MagickExport SemaphoreInfo *AllocateSemaphoreInfo(void)
132 semaphore_info=(SemaphoreInfo *) malloc(sizeof(SemaphoreInfo));
133 if (semaphore_info == (SemaphoreInfo *) NULL)
134 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
135 (void) ResetMagickMemory(semaphore_info,0,sizeof(SemaphoreInfo));
137 Initialize the semaphore.
139 #if defined(MAGICKCORE_THREAD_SUPPORT)
147 status=pthread_mutexattr_init(&mutex_info);
151 ThrowFatalException(ResourceLimitFatalError,
152 "UnableToInitializeSemaphore");
154 #if defined(MAGICKCORE_DEBUG)
155 #if defined(PTHREAD_MUTEX_ERRORCHECK)
156 status=pthread_mutex_settype(&mutex_info,PTHREAD_MUTEX_ERRORCHECK);
160 ThrowFatalException(ResourceLimitFatalError,
161 "UnableToInitializeSemaphore");
165 status=pthread_mutex_init(&semaphore_info->mutex,&mutex_info);
169 ThrowFatalException(ResourceLimitFatalError,
170 "UnableToInitializeSemaphore");
172 status=pthread_mutexattr_destroy(&mutex_info);
176 ThrowFatalException(ResourceLimitFatalError,
177 "UnableToInitializeSemaphore");
180 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
185 status=InitializeCriticalSectionAndSpinCount(&semaphore_info->mutex,0x0400);
189 ThrowFatalException(ResourceLimitFatalError,
190 "UnableToInitializeSemaphore");
194 semaphore_info->id=GetMagickThreadId();
195 semaphore_info->reference_count=0;
196 semaphore_info->signature=MagickSignature;
197 return(semaphore_info);
201 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
205 % D e s t r o y S e m a p h o r e I n f o %
209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
211 % DestroySemaphoreInfo() destroys a semaphore.
213 % The format of the DestroySemaphoreInfo method is:
215 % void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info)
217 % A description of each parameter follows:
219 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
222 MagickExport void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info)
224 assert(semaphore_info != (SemaphoreInfo **) NULL);
225 assert((*semaphore_info) != (SemaphoreInfo *) NULL);
226 assert((*semaphore_info)->signature == MagickSignature);
228 #if defined(MAGICKCORE_THREAD_SUPPORT)
233 status=pthread_mutex_destroy(&(*semaphore_info)->mutex);
237 ThrowFatalException(ResourceLimitFatalError,"UnableToDestroySemaphore");
240 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
241 DeleteCriticalSection(&(*semaphore_info)->mutex);
243 (*semaphore_info)->signature=(~MagickSignature);
244 free(*semaphore_info);
245 *semaphore_info=(SemaphoreInfo *) NULL;
250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
254 % L o c k S e m a p h o r e I n f o %
258 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260 % LockSemaphoreInfo() locks a semaphore.
262 % The format of the LockSemaphoreInfo method is:
264 % void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
266 % A description of each parameter follows:
268 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
271 MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
273 assert(semaphore_info != (SemaphoreInfo *) NULL);
274 assert(semaphore_info->signature == MagickSignature);
275 #if defined(MAGICKCORE_THREAD_SUPPORT)
280 status=pthread_mutex_lock(&semaphore_info->mutex);
284 ThrowFatalException(ResourceLimitFatalError,"UnableToLockSemaphore");
287 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
288 EnterCriticalSection(&semaphore_info->mutex);
290 #if defined(MAGICKCORE_DEBUG)
291 if ((semaphore_info->reference_count > 0) &&
292 (IsMagickThreadEqual(semaphore_info->id) != MagickFalse))
294 (void) FormatLocaleFile(stderr,"Warning: unexpected recursive lock!\n");
295 (void) fflush(stderr);
298 semaphore_info->id=GetMagickThreadId();
299 semaphore_info->reference_count++;
303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307 % R e l i n g u i s h S e m a p h o r e I n f o %
311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
313 % RelinquishSemaphoreInfo() relinquishes a semaphore.
315 % The format of the RelinquishSemaphoreInfo method is:
317 % RelinquishSemaphoreInfo(SemaphoreInfo *semaphore_info)
319 % A description of each parameter follows:
321 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
324 MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo *semaphore_info)
326 assert(semaphore_info != (SemaphoreInfo *) NULL);
327 assert(semaphore_info->signature == MagickSignature);
328 UnlockSemaphoreInfo(semaphore_info);
332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
336 % 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 %
340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
342 % SemaphoreComponentGenesis() instantiates the semaphore environment.
344 % The format of the SemaphoreComponentGenesis method is:
346 % MagickBooleanType SemaphoreComponentGenesis(void)
349 MagickPrivate MagickBooleanType SemaphoreComponentGenesis(void)
357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361 % 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 %
365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367 % SemaphoreComponentTerminus() destroys the semaphore component.
369 % The format of the SemaphoreComponentTerminus method is:
371 % SemaphoreComponentTerminus(void)
374 MagickPrivate void SemaphoreComponentTerminus(void)
379 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
383 % U n l o c k S e m a p h o r e I n f o %
387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
389 % UnlockSemaphoreInfo() unlocks a semaphore.
391 % The format of the UnlockSemaphoreInfo method is:
393 % void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
395 % A description of each parameter follows:
397 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
400 MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
402 assert(semaphore_info != (SemaphoreInfo *) NULL);
403 assert(semaphore_info->signature == MagickSignature);
404 #if defined(MAGICKCORE_DEBUG)
405 assert(IsMagickThreadEqual(semaphore_info->id) != MagickFalse);
406 if (semaphore_info->reference_count == 0)
408 (void) FormatLocaleFile(stderr,
409 "Warning: semaphore lock already unlocked!\n");
410 (void) fflush(stderr);
413 semaphore_info->reference_count--;
415 #if defined(MAGICKCORE_THREAD_SUPPORT)
420 status=pthread_mutex_unlock(&semaphore_info->mutex);
424 ThrowFatalException(ResourceLimitFatalError,"UnableToUnlockSemaphore");
427 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
428 LeaveCriticalSection(&semaphore_info->mutex);