]> granicus.if.org Git - imagemagick/blob - magick/semaphore.c
Remove previous geometry changes
[imagemagick] / magick / semaphore.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
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        %
11 %                                                                             %
12 %                                                                             %
13 %                        MagickCore Semaphore Methods                         %
14 %                                                                             %
15 %                              Software Design                                %
16 %                             William Radcliffe                               %
17 %                                John Cristy                                  %
18 %                                 June 2000                                   %
19 %                                                                             %
20 %                                                                             %
21 %  Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization      %
22 %  dedicated to making software imaging solutions freely available.           %
23 %                                                                             %
24 %  You may not use this file except in compliance with the License.  You may  %
25 %  obtain a copy of the License at                                            %
26 %                                                                             %
27 %    http://www.imagemagick.org/script/license.php                            %
28 %                                                                             %
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.                                             %
34 %                                                                             %
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 %
37 %
38 %
39 */
40 \f
41 /*
42   Include declarations.
43 */
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"
52 \f
53 /*
54   Struct declaractions.
55 */
56 struct SemaphoreInfo
57 {
58   MagickMutexType
59     mutex;
60
61   MagickThreadType
62     id;
63
64   long
65     reference_count;
66
67   unsigned long
68     signature;
69 };
70 \f
71 /*
72   Static declaractions.
73 */
74 #if defined(MAGICKCORE_HAVE_PTHREAD)
75 static pthread_mutex_t
76   semaphore_mutex = PTHREAD_MUTEX_INITIALIZER;
77 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
78 static LONG
79   semaphore_mutex = 0;
80 #else
81 static long
82   semaphore_mutex = 0;
83 #endif
84 \f
85 /*
86   Forward declaractions.
87 */
88 static void
89   LockMagickMutex(void),
90   UnlockMagickMutex(void);
91 \f
92 /*
93 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
94 %                                                                             %
95 %                                                                             %
96 %                                                                             %
97 %   A c q u i r e S e m a p h o r e I n f o                                   %
98 %                                                                             %
99 %                                                                             %
100 %                                                                             %
101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102 %
103 %  AcquireSemaphoreInfo() acquires a semaphore.
104 %
105 %  The format of the AcquireSemaphoreInfo method is:
106 %
107 %      void AcquireSemaphoreInfo(SemaphoreInfo **semaphore_info)
108 %
109 %  A description of each parameter follows:
110 %
111 %    o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
112 %
113 */
114 MagickExport void AcquireSemaphoreInfo(SemaphoreInfo **semaphore_info)
115 {
116   assert(semaphore_info != (SemaphoreInfo **) NULL);
117   if (*semaphore_info == (SemaphoreInfo *) NULL)
118     {
119       LockMagickMutex();
120       if (*semaphore_info == (SemaphoreInfo *) NULL)
121         *semaphore_info=AllocateSemaphoreInfo();
122       UnlockMagickMutex();
123     }
124 }
125 \f
126 /*
127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
128 %                                                                             %
129 %                                                                             %
130 %                                                                             %
131 %   A l l o c a t e S e m a p h o r e I n f o                                 %
132 %                                                                             %
133 %                                                                             %
134 %                                                                             %
135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136 %
137 %  AllocateSemaphoreInfo() initializes the SemaphoreInfo structure.
138 %
139 %  The format of the AllocateSemaphoreInfo method is:
140 %
141 %      SemaphoreInfo *AllocateSemaphoreInfo(void)
142 %
143 */
144 MagickExport SemaphoreInfo *AllocateSemaphoreInfo(void)
145 {
146   SemaphoreInfo
147     *semaphore_info;
148
149   /*
150     Allocate semaphore.
151   */
152   semaphore_info=(SemaphoreInfo *) AcquireAlignedMemory(1,
153     sizeof(SemaphoreInfo));
154   if (semaphore_info == (SemaphoreInfo *) NULL)
155     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
156   (void) ResetMagickMemory(semaphore_info,0,sizeof(SemaphoreInfo));
157   /*
158     Initialize the semaphore.
159   */
160 #if defined(MAGICKCORE_HAVE_PTHREAD)
161   {
162     int
163       status;
164
165     pthread_mutexattr_t
166       mutex_info;
167
168     status=pthread_mutexattr_init(&mutex_info);
169     if (status != 0)
170       {
171         errno=status;
172         ThrowFatalException(ResourceLimitFatalError,
173           "UnableToInitializeSemaphore");
174       }
175     status=pthread_mutex_init(&semaphore_info->mutex,&mutex_info);
176     if (status != 0)
177       {
178         errno=status;
179         ThrowFatalException(ResourceLimitFatalError,
180           "UnableToInitializeSemaphore");
181       }
182     status=pthread_mutexattr_destroy(&mutex_info);
183     if (status != 0)
184       {
185         errno=status;
186         ThrowFatalException(ResourceLimitFatalError,
187           "UnableToInitializeSemaphore");
188       }
189   }
190 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
191   InitializeCriticalSection(&semaphore_info->mutex);
192 #endif
193   semaphore_info->id=GetMagickThreadId();
194   semaphore_info->reference_count=0;
195   semaphore_info->signature=MagickSignature;
196   return(semaphore_info);
197 }
198 \f
199 /*
200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
201 %                                                                             %
202 %                                                                             %
203 %                                                                             %
204 %   D e s t r o y S e m a p h o r e I n f o                                   %
205 %                                                                             %
206 %                                                                             %
207 %                                                                             %
208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
209 %
210 %  DestroySemaphoreInfo() destroys a semaphore.
211 %
212 %  The format of the DestroySemaphoreInfo method is:
213 %
214 %      void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info)
215 %
216 %  A description of each parameter follows:
217 %
218 %    o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
219 %
220 */
221 MagickExport void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info)
222 {
223   assert(semaphore_info != (SemaphoreInfo **) NULL);
224   assert((*semaphore_info) != (SemaphoreInfo *) NULL);
225   assert((*semaphore_info)->signature == MagickSignature);
226   LockMagickMutex();
227 #if defined(MAGICKCORE_HAVE_PTHREAD)
228   {
229     int
230       status;
231
232     status=pthread_mutex_destroy(&(*semaphore_info)->mutex);
233     if (status != 0)
234       {
235         errno=status;
236         ThrowFatalException(ResourceLimitFatalError,"UnableToDestroySemaphore");
237       }
238   }
239 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
240   DeleteCriticalSection(&(*semaphore_info)->mutex);
241 #endif
242   (*semaphore_info)->signature=(~MagickSignature);
243   *semaphore_info=(SemaphoreInfo *) RelinquishAlignedMemory(*semaphore_info);
244   UnlockMagickMutex();
245 }
246 \f
247 /*
248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
249 %                                                                             %
250 %                                                                             %
251 %                                                                             %
252 +   L o c k M a g i c k M u t e x                                             %
253 %                                                                             %
254 %                                                                             %
255 %                                                                             %
256 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
257 %
258 %  LockMagickMutex() locks a global mutex.  If it is already locked, the
259 %  calling thread blocks until the mutex becomes available.
260 %
261 %  The format of the LockMagickMutex method is:
262 %
263 %      void LockMagickMutex(void)
264 %
265 */
266 static void LockMagickMutex(void)
267 {
268 #if defined(MAGICKCORE_HAVE_PTHREAD)
269   {
270     int
271       status;
272
273     status=pthread_mutex_lock(&semaphore_mutex);
274     if (status != 0)
275       {
276         errno=status;
277         ThrowFatalException(ResourceLimitFatalError,"UnableToLockSemaphore");
278       }
279   }
280 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
281   while (InterlockedCompareExchange(&semaphore_mutex,1L,0L) != 0)
282     Sleep(10);
283 #endif
284 }
285 \f
286 /*
287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288 %                                                                             %
289 %                                                                             %
290 %                                                                             %
291 %   L o c k S e m a p h o r e I n f o                                         %
292 %                                                                             %
293 %                                                                             %
294 %                                                                             %
295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296 %
297 %  LockSemaphoreInfo() locks a semaphore.
298 %
299 %  The format of the LockSemaphoreInfo method is:
300 %
301 %      void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
302 %
303 %  A description of each parameter follows:
304 %
305 %    o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
306 %
307 */
308 MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
309 {
310   assert(semaphore_info != (SemaphoreInfo *) NULL);
311   assert(semaphore_info->signature == MagickSignature);
312 #if defined(MAGICKCORE_HAVE_PTHREAD)
313   {
314     int
315       status;
316
317     status=pthread_mutex_lock(&semaphore_info->mutex);
318     if (status != 0)
319       {
320         errno=status;
321         ThrowFatalException(ResourceLimitFatalError,"UnableToLockSemaphore");
322       }
323   }
324 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
325   EnterCriticalSection(&semaphore_info->mutex);
326 #endif
327 #if defined(MAGICKCORE_DEBUG)
328   if ((semaphore_info->reference_count > 0) &&
329       (IsMagickThreadEqual(semaphore_info->id) != MagickFalse))
330     {
331       (void) fprintf(stderr,"Warning: unexpected recursive lock!\n");
332       (void) fflush(stderr);
333     }
334 #endif
335   semaphore_info->id=GetMagickThreadId();
336   semaphore_info->reference_count++;
337 }
338 \f
339 /*
340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
341 %                                                                             %
342 %                                                                             %
343 %                                                                             %
344 %   R e l i n g u i s h S e m a p h o r e I n f o                             %
345 %                                                                             %
346 %                                                                             %
347 %                                                                             %
348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
349 %
350 %  RelinquishSemaphoreInfo() relinquishes a semaphore.
351 %
352 %  The format of the RelinquishSemaphoreInfo method is:
353 %
354 %      RelinquishSemaphoreInfo(SemaphoreInfo *semaphore_info)
355 %
356 %  A description of each parameter follows:
357 %
358 %    o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
359 %
360 */
361 MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo *semaphore_info)
362 {
363   assert(semaphore_info != (SemaphoreInfo *) NULL);
364   assert(semaphore_info->signature == MagickSignature);
365   UnlockSemaphoreInfo(semaphore_info);
366 }
367 \f
368 /*
369 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
370 %                                                                             %
371 %                                                                             %
372 %                                                                             %
373 %   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                         %
374 %                                                                             %
375 %                                                                             %
376 %                                                                             %
377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
378 %
379 %  SemaphoreComponentGenesis() instantiates the semaphore environment.
380 %
381 %  The format of the SemaphoreComponentGenesis method is:
382 %
383 %      MagickBooleanType SemaphoreComponentGenesis(void)
384 %
385 */
386 MagickExport MagickBooleanType SemaphoreComponentGenesis(void)
387 {
388   LockMagickMutex();
389   UnlockMagickMutex();
390   return(MagickTrue);
391 }
392 \f
393 /*
394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
395 %                                                                             %
396 %                                                                             %
397 %                                                                             %
398 %   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                       %
399 %                                                                             %
400 %                                                                             %
401 %                                                                             %
402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
403 %
404 %  SemaphoreComponentTerminus() destroys the semaphore component.
405 %
406 %  The format of the SemaphoreComponentTerminus method is:
407 %
408 %      SemaphoreComponentTerminus(void)
409 %
410 */
411 MagickExport void SemaphoreComponentTerminus(void)
412 {
413 }
414 \f
415 /*
416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
417 %                                                                             %
418 %                                                                             %
419 %                                                                             %
420 +   U n l o c k M a g i c k M u t e x                                         %
421 %                                                                             %
422 %                                                                             %
423 %                                                                             %
424 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
425 %
426 %  UnlockMagickMutex() releases a global mutex.
427 %
428 %  The format of the LockMagickMutex method is:
429 %
430 %      void UnlockMagickMutex(void)
431 %
432 */
433 static void UnlockMagickMutex(void)
434 {
435 #if defined(MAGICKCORE_HAVE_PTHREAD)
436   {
437     int
438       status;
439
440     status=pthread_mutex_unlock(&semaphore_mutex);
441     if (status != 0)
442       {
443         errno=status;
444         ThrowFatalException(ResourceLimitFatalError,"UnableToUnlockSemaphore");
445       }
446   }
447 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
448   InterlockedExchange(&semaphore_mutex,0L);
449 #endif
450 }
451 \f
452 /*
453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
454 %                                                                             %
455 %                                                                             %
456 %                                                                             %
457 %   U n l o c k S e m a p h o r e I n f o                                     %
458 %                                                                             %
459 %                                                                             %
460 %                                                                             %
461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
462 %
463 %  UnlockSemaphoreInfo() unlocks a semaphore.
464 %
465 %  The format of the UnlockSemaphoreInfo method is:
466 %
467 %      void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
468 %
469 %  A description of each parameter follows:
470 %
471 %    o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
472 %
473 */
474 MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
475 {
476   assert(semaphore_info != (SemaphoreInfo *) NULL);
477   assert(semaphore_info->signature == MagickSignature);
478 #if defined(MAGICKCORE_DEBUG)
479   assert(IsMagickThreadEqual(semaphore_info->id) != MagickFalse);
480   if (semaphore_info->reference_count == 0)
481     {
482       (void) fprintf(stderr,"Warning: semaphore lock already unlocked!\n");
483       (void) fflush(stderr);
484       return;
485     }
486   semaphore_info->reference_count--;
487 #endif
488 #if defined(MAGICKCORE_HAVE_PTHREAD)
489   {
490     int
491       status;
492
493     status=pthread_mutex_unlock(&semaphore_info->mutex);
494     if (status != 0)
495       {
496         errno=status;
497         ThrowFatalException(ResourceLimitFatalError,"UnableToUnlockSemaphore");
498       }
499   }
500 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
501   LeaveCriticalSection(&semaphore_info->mutex);
502 #endif
503 }