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-2009 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 "magick/studio.h"
45 #include "magick/exception.h"
46 #include "magick/exception-private.h"
47 #include "magick/memory_.h"
48 #include "magick/semaphore.h"
49 #include "magick/string_.h"
50 #include "magick/thread_.h"
51 #include "magick/thread-private.h"
74 #if defined(MAGICKCORE_HAVE_PTHREAD)
75 static pthread_mutex_t
76 semaphore_mutex = PTHREAD_MUTEX_INITIALIZER;
77 #elif defined(MAGICKORE_HAVE_WINTHREADS)
86 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
90 % A c q u i r e S e m a p h o r e I n f o %
94 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
96 % AcquireSemaphoreInfo() acquires a semaphore.
98 % The format of the AcquireSemaphoreInfo method is:
100 % void AcquireSemaphoreInfo(SemaphoreInfo **semaphore_info)
102 % A description of each parameter follows:
104 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
107 MagickExport void AcquireSemaphoreInfo(SemaphoreInfo **semaphore_info)
109 assert(semaphore_info != (SemaphoreInfo **) NULL);
110 #if defined(MAGICKCORE_HAVE_PTHREAD)
111 if (pthread_mutex_lock(&semaphore_mutex) != 0)
112 (void) fprintf(stderr,"pthread_mutex_lock failed %s\n",
113 GetExceptionMessage(errno));
114 #elif defined(MAGICKORE_HAVE_WINTHREADS)
115 while (InterlockedCompareExchange(&semaphore_mutex,1L,0L) != 0)
118 if (*semaphore_info == (SemaphoreInfo *) NULL)
119 *semaphore_info=AllocateSemaphoreInfo();
120 #if defined(MAGICKCORE_HAVE_PTHREAD)
121 if (pthread_mutex_unlock(&semaphore_mutex) != 0)
122 (void) fprintf(stderr,"pthread_mutex_unlock failed %s\n",
123 GetExceptionMessage(errno));
124 #elif defined(MAGICKORE_HAVE_WINTHREADS)
125 InterlockedExchange(&semaphore_mutex,0L);
127 (void) LockSemaphoreInfo(*semaphore_info);
131 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
135 % A l l o c a t e S e m a p h o r e I n f o %
139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
141 % AllocateSemaphoreInfo() initializes the SemaphoreInfo structure.
143 % The format of the AllocateSemaphoreInfo method is:
145 % SemaphoreInfo *AllocateSemaphoreInfo(void)
148 MagickExport SemaphoreInfo *AllocateSemaphoreInfo(void)
156 semaphore_info=(SemaphoreInfo *) AcquireAlignedMemory(1,
157 sizeof(SemaphoreInfo));
158 if (semaphore_info == (SemaphoreInfo *) NULL)
159 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
160 (void) ResetMagickMemory(semaphore_info,0,sizeof(SemaphoreInfo));
162 Initialize the semaphore.
164 #if defined(MAGICKCORE_HAVE_PTHREAD)
172 status=pthread_mutexattr_init(&mutex_info);
175 semaphore_info=(SemaphoreInfo *) RelinquishAlignedMemory(
177 ThrowFatalException(ResourceLimitFatalError,
178 "UnableToInitializeSemaphore");
180 status=pthread_mutex_init(&semaphore_info->mutex,&mutex_info);
181 (void) pthread_mutexattr_destroy(&mutex_info);
184 semaphore_info=(SemaphoreInfo *) RelinquishAlignedMemory(
186 ThrowFatalException(ResourceLimitFatalError,
187 "UnableToInitializeSemaphore");
190 #elif defined(MAGICKORE_HAVE_WINTHREADS)
191 InitializeCriticalSection(&semaphore_info->mutex);
193 semaphore_info->id=GetMagickThreadId();
194 semaphore_info->reference_count=0;
195 semaphore_info->signature=MagickSignature;
196 return(semaphore_info);
200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
204 % D e s t r o y S e m a p h o r e %
208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
210 % DestroySemaphore() destroys the semaphore environment.
212 % The format of the DestroySemaphore method is:
214 % DestroySemaphore(void)
217 MagickExport void DestroySemaphore(void)
219 #if defined(MAGICKCORE_HAVE_PTHREAD)
220 if (pthread_mutex_destroy(&semaphore_mutex) != 0)
221 (void) fprintf(stderr,"pthread_mutex_destroy failed %s\n",
222 GetExceptionMessage(errno));
227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
231 % D e s t r o y S e m a p h o r e I n f o %
235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
237 % DestroySemaphoreInfo() destroys a semaphore.
239 % The format of the DestroySemaphoreInfo method is:
241 % void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info)
243 % A description of each parameter follows:
245 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
248 MagickExport void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info)
250 assert(semaphore_info != (SemaphoreInfo **) NULL);
251 assert((*semaphore_info) != (SemaphoreInfo *) NULL);
252 assert((*semaphore_info)->signature == MagickSignature);
253 #if defined(MAGICKCORE_HAVE_PTHREAD)
254 (void) pthread_mutex_lock(&semaphore_mutex);
255 #elif defined(MAGICKORE_HAVE_WINTHREADS)
256 while (InterlockedCompareExchange(&semaphore_mutex,1L,0L) != 0)
259 #if defined(MAGICKCORE_HAVE_PTHREAD)
260 (void) pthread_mutex_destroy(&(*semaphore_info)->mutex);
261 #elif defined(MAGICKORE_HAVE_WINTHREADS)
262 DeleteCriticalSection(&(*semaphore_info)->mutex);
264 (*semaphore_info)->signature=(~MagickSignature);
265 *semaphore_info=(SemaphoreInfo *) RelinquishAlignedMemory(*semaphore_info);
266 #if defined(MAGICKCORE_HAVE_PTHREAD)
267 (void) pthread_mutex_unlock(&semaphore_mutex);
268 #elif defined(MAGICKORE_HAVE_WINTHREADS)
269 InterlockedExchange(&semaphore_mutex,0L);
274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
278 % I n i t i a l i z e S e m a p h o r e %
282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
284 % InitializeSemaphore() initializes the semaphore environment.
286 % The format of the InitializeSemaphore method is:
288 % InitializeSemaphore(void)
291 MagickExport void InitializeSemaphore(void)
296 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
300 % L o c k S e m a p h o r e I n f o %
304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
306 % LockSemaphoreInfo() locks a semaphore.
308 % The format of the LockSemaphoreInfo method is:
310 % MagickBooleanType LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
312 % A description of each parameter follows:
314 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
317 MagickExport MagickBooleanType LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
319 assert(semaphore_info != (SemaphoreInfo *) NULL);
320 assert(semaphore_info->signature == MagickSignature);
321 #if defined(MAGICKCORE_HAVE_PTHREAD)
326 status=pthread_mutex_lock(&semaphore_info->mutex);
329 #if defined(MAGICKCORE_DEBUG)
331 if ((semaphore_info->reference_count > 0) &&
332 (IsMagickThreadEqual(semaphore_info->id) != MagickFalse))
334 (void) fprintf(stderr,"Warning: unexpected recursive lock!\n");
335 (void) fflush(stderr);
340 #elif defined(MAGICKORE_HAVE_WINTHREADS)
342 EnterCriticalSection(&semaphore_info->mutex);
343 #if defined(MAGICKCORE_DEBUG)
345 if ((semaphore_info->reference_count > 0) &&
346 (IsMagickThreadEqual(semaphore_info->id) != MagickFalse))
348 (void) fprintf(stderr,"Warning: unexpected recursive lock!\n");
349 (void) fflush(stderr);
355 semaphore_info->id=GetMagickThreadId();
356 semaphore_info->reference_count++;
361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
365 % R e l i n g u i s h S e m a p h o r e I n f o %
369 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
371 % RelinquishSemaphoreInfo() relinquishes a semaphore.
373 % The format of the RelinquishSemaphoreInfo method is:
375 % RelinquishSemaphoreInfo(SemaphoreInfo *semaphore_info)
377 % A description of each parameter follows:
379 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
382 MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo *semaphore_info)
384 assert(semaphore_info != (SemaphoreInfo *) NULL);
385 assert(semaphore_info->signature == MagickSignature);
386 (void) UnlockSemaphoreInfo(semaphore_info);
390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
394 % U n l o c k S e m a p h o r e I n f o %
398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
400 % UnlockSemaphoreInfo() unlocks a semaphore.
402 % The format of the UnlockSemaphoreInfo method is:
404 % MagickBooleanType UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
406 % A description of each parameter follows:
408 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
411 MagickExport MagickBooleanType UnlockSemaphoreInfo(
412 SemaphoreInfo *semaphore_info)
414 assert(semaphore_info != (SemaphoreInfo *) NULL);
415 assert(semaphore_info->signature == MagickSignature);
416 #if defined(MAGICKCORE_DEBUG)
417 assert(IsMagickThreadEqual(semaphore_info->id) != MagickFalse);
418 if (semaphore_info->reference_count == 0)
420 (void) fprintf(stderr,"Warning: semaphore lock already unlocked!\n");
421 (void) fflush(stderr);
424 semaphore_info->reference_count--;
426 #if defined(MAGICKCORE_HAVE_PTHREAD)
431 status=pthread_mutex_unlock(&semaphore_info->mutex);
434 semaphore_info->reference_count++;
438 #elif defined(MAGICKORE_HAVE_WINTHREADS)
439 LeaveCriticalSection(&semaphore_info->mutex);