]> granicus.if.org Git - imagemagick/blob - MagickCore/semaphore.c
(no commit message)
[imagemagick] / MagickCore / 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-2012 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 "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 \f
55 /*
56   Struct declaractions.
57 */
58 struct SemaphoreInfo
59 {
60   MagickMutexType
61     mutex;
62
63   MagickThreadType
64     id;
65
66   ssize_t
67     reference_count;
68
69   size_t
70     signature;
71 };
72 \f
73 /*
74 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75 %                                                                             %
76 %                                                                             %
77 %                                                                             %
78 %   A c q u i r e S e m a p h o r e I n f o                                   %
79 %                                                                             %
80 %                                                                             %
81 %                                                                             %
82 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83 %
84 %  AcquireSemaphoreInfo() acquires a semaphore.
85 %
86 %  The format of the AcquireSemaphoreInfo method is:
87 %
88 %      void AcquireSemaphoreInfo(SemaphoreInfo **semaphore_info)
89 %
90 %  A description of each parameter follows:
91 %
92 %    o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
93 %
94 */
95 MagickExport void AcquireSemaphoreInfo(SemaphoreInfo **semaphore_info)
96 {
97   assert(semaphore_info != (SemaphoreInfo **) NULL);
98   if (*semaphore_info == (SemaphoreInfo *) NULL)
99     {
100       LockMagickMutex();
101       if (*semaphore_info == (SemaphoreInfo *) NULL)
102         *semaphore_info=AllocateSemaphoreInfo();
103       UnlockMagickMutex();
104     }
105 }
106 \f
107 /*
108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
109 %                                                                             %
110 %                                                                             %
111 %                                                                             %
112 %   A l l o c a t e S e m a p h o r e I n f o                                 %
113 %                                                                             %
114 %                                                                             %
115 %                                                                             %
116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
117 %
118 %  AllocateSemaphoreInfo() initializes the SemaphoreInfo structure.
119 %
120 %  The format of the AllocateSemaphoreInfo method is:
121 %
122 %      SemaphoreInfo *AllocateSemaphoreInfo(void)
123 %
124 */
125
126 static void *AcquireSemaphoreMemory(const size_t count,const size_t quantum)
127 {
128 #define AlignedExtent(size,alignment) \
129   (((size)+((alignment)-1)) & ~((alignment)-1))
130
131   size_t
132     alignment,
133     extent,
134     size;
135
136   void
137     *memory;
138
139   size=count*quantum;
140   if ((count == 0) || (quantum != (size/count)))
141     {
142       errno=ENOMEM;
143       return((void *) NULL);
144     }
145   memory=NULL;
146   alignment=CACHE_LINE_SIZE;
147   extent=AlignedExtent(size,alignment);
148   if ((size == 0) || (alignment < sizeof(void *)) || (extent < size))
149     return((void *) NULL);
150 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
151   if (posix_memalign(&memory,alignment,extent) != 0)
152     memory=NULL;
153 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
154   memory=_aligned_malloc(extent,alignment);
155 #else
156   {
157     void
158       *p;
159
160     extent=(size+alignment-1)+sizeof(void *);
161     if (extent > size)
162       {
163         p=malloc(extent);
164         if (p != NULL)
165           {
166             memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
167             *((void **) memory-1)=p;
168           }
169       }
170   }
171 #endif
172   return(memory);
173 }
174
175 static void *RelinquishSemaphoreMemory(void *memory)
176 {
177   if (memory == (void *) NULL)
178     return((void *) NULL);
179 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
180   free(memory);
181 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
182   _aligned_free(memory);
183 #else
184   free(*((void **) memory-1));
185 #endif
186   return(NULL);
187 }
188
189 MagickExport SemaphoreInfo *AllocateSemaphoreInfo(void)
190 {
191   SemaphoreInfo
192     *semaphore_info;
193
194   /*
195     Allocate semaphore.
196   */
197   semaphore_info=(SemaphoreInfo *) AcquireSemaphoreMemory(1,
198     sizeof(*semaphore_info));
199   if (semaphore_info == (SemaphoreInfo *) NULL)
200     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
201   (void) ResetMagickMemory(semaphore_info,0,sizeof(SemaphoreInfo));
202   /*
203     Initialize the semaphore.
204   */
205 #if defined(MAGICKCORE_THREAD_SUPPORT)
206   {
207     int
208       status;
209
210     pthread_mutexattr_t
211       mutex_info;
212
213     status=pthread_mutexattr_init(&mutex_info);
214     if (status != 0)
215       {
216         errno=status;
217         ThrowFatalException(ResourceLimitFatalError,
218           "UnableToInitializeSemaphore");
219       }
220 #if defined(MAGICKCORE_DEBUG)
221 #if defined(PTHREAD_MUTEX_ERRORCHECK)
222     status=pthread_mutex_settype(&mutex_info,PTHREAD_MUTEX_ERRORCHECK);
223     if (status != 0)
224       {
225         errno=status;
226         ThrowFatalException(ResourceLimitFatalError,
227           "UnableToInitializeSemaphore");
228       }
229 #endif
230 #endif
231     status=pthread_mutex_init(&semaphore_info->mutex,&mutex_info);
232     if (status != 0)
233       {
234         errno=status;
235         ThrowFatalException(ResourceLimitFatalError,
236           "UnableToInitializeSemaphore");
237       }
238     status=pthread_mutexattr_destroy(&mutex_info);
239     if (status != 0)
240       {
241         errno=status;
242         ThrowFatalException(ResourceLimitFatalError,
243           "UnableToInitializeSemaphore");
244       }
245   }
246 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
247   {
248     int
249       status;
250
251     status=InitializeCriticalSectionAndSpinCount(&semaphore_info->mutex,0x0400);
252     if (status == 0)
253       {
254         errno=status;
255         ThrowFatalException(ResourceLimitFatalError,
256           "UnableToInitializeSemaphore");
257        }
258   }
259 #endif
260   semaphore_info->id=GetMagickThreadId();
261   semaphore_info->reference_count=0;
262   semaphore_info->signature=MagickSignature;
263   return(semaphore_info);
264 }
265 \f
266 /*
267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
268 %                                                                             %
269 %                                                                             %
270 %                                                                             %
271 %   D e s t r o y S e m a p h o r e I n f o                                   %
272 %                                                                             %
273 %                                                                             %
274 %                                                                             %
275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276 %
277 %  DestroySemaphoreInfo() destroys a semaphore.
278 %
279 %  The format of the DestroySemaphoreInfo method is:
280 %
281 %      void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info)
282 %
283 %  A description of each parameter follows:
284 %
285 %    o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
286 %
287 */
288 MagickExport void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info)
289 {
290   assert(semaphore_info != (SemaphoreInfo **) NULL);
291   assert((*semaphore_info) != (SemaphoreInfo *) NULL);
292   assert((*semaphore_info)->signature == MagickSignature);
293   LockMagickMutex();
294 #if defined(MAGICKCORE_THREAD_SUPPORT)
295   {
296     int
297       status;
298
299     status=pthread_mutex_destroy(&(*semaphore_info)->mutex);
300     if (status != 0)
301       {
302         errno=status;
303         ThrowFatalException(ResourceLimitFatalError,"UnableToDestroySemaphore");
304       }
305   }
306 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
307   DeleteCriticalSection(&(*semaphore_info)->mutex);
308 #endif
309   (*semaphore_info)->signature=(~MagickSignature);
310   *semaphore_info=(SemaphoreInfo *) RelinquishSemaphoreMemory(*semaphore_info);
311   UnlockMagickMutex();
312 }
313 \f
314 /*
315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
316 %                                                                             %
317 %                                                                             %
318 %                                                                             %
319 %   L o c k S e m a p h o r e I n f o                                         %
320 %                                                                             %
321 %                                                                             %
322 %                                                                             %
323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
324 %
325 %  LockSemaphoreInfo() locks a semaphore.
326 %
327 %  The format of the LockSemaphoreInfo method is:
328 %
329 %      void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
330 %
331 %  A description of each parameter follows:
332 %
333 %    o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
334 %
335 */
336 MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
337 {
338   assert(semaphore_info != (SemaphoreInfo *) NULL);
339   assert(semaphore_info->signature == MagickSignature);
340 #if defined(MAGICKCORE_THREAD_SUPPORT)
341   {
342     int
343       status;
344
345     status=pthread_mutex_lock(&semaphore_info->mutex);
346     if (status != 0)
347       {
348         errno=status;
349         ThrowFatalException(ResourceLimitFatalError,"UnableToLockSemaphore");
350       }
351   }
352 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
353   EnterCriticalSection(&semaphore_info->mutex);
354 #endif
355 #if defined(MAGICKCORE_DEBUG)
356   if ((semaphore_info->reference_count > 0) &&
357       (IsMagickThreadEqual(semaphore_info->id) != MagickFalse))
358     {
359       (void) FormatLocaleFile(stderr,"Warning: unexpected recursive lock!\n");
360       (void) fflush(stderr);
361     }
362 #endif
363   semaphore_info->id=GetMagickThreadId();
364   semaphore_info->reference_count++;
365 }
366 \f
367 /*
368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
369 %                                                                             %
370 %                                                                             %
371 %                                                                             %
372 %   R e l i n g u i s h S e m a p h o r e I n f o                             %
373 %                                                                             %
374 %                                                                             %
375 %                                                                             %
376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
377 %
378 %  RelinquishSemaphoreInfo() relinquishes a semaphore.
379 %
380 %  The format of the RelinquishSemaphoreInfo method is:
381 %
382 %      RelinquishSemaphoreInfo(SemaphoreInfo *semaphore_info)
383 %
384 %  A description of each parameter follows:
385 %
386 %    o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
387 %
388 */
389 MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo *semaphore_info)
390 {
391   assert(semaphore_info != (SemaphoreInfo *) NULL);
392   assert(semaphore_info->signature == MagickSignature);
393   UnlockSemaphoreInfo(semaphore_info);
394 }
395 \f
396 /*
397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398 %                                                                             %
399 %                                                                             %
400 %                                                                             %
401 %   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                         %
402 %                                                                             %
403 %                                                                             %
404 %                                                                             %
405 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
406 %
407 %  SemaphoreComponentGenesis() instantiates the semaphore environment.
408 %
409 %  The format of the SemaphoreComponentGenesis method is:
410 %
411 %      MagickBooleanType SemaphoreComponentGenesis(void)
412 %
413 */
414 MagickPrivate MagickBooleanType SemaphoreComponentGenesis(void)
415 {
416   LockMagickMutex();
417   UnlockMagickMutex();
418   return(MagickTrue);
419 }
420 \f
421 /*
422 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
423 %                                                                             %
424 %                                                                             %
425 %                                                                             %
426 %   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                       %
427 %                                                                             %
428 %                                                                             %
429 %                                                                             %
430 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
431 %
432 %  SemaphoreComponentTerminus() destroys the semaphore component.
433 %
434 %  The format of the SemaphoreComponentTerminus method is:
435 %
436 %      SemaphoreComponentTerminus(void)
437 %
438 */
439 MagickPrivate void SemaphoreComponentTerminus(void)
440 {
441 }
442 \f
443 /*
444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
445 %                                                                             %
446 %                                                                             %
447 %                                                                             %
448 %   U n l o c k S e m a p h o r e I n f o                                     %
449 %                                                                             %
450 %                                                                             %
451 %                                                                             %
452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
453 %
454 %  UnlockSemaphoreInfo() unlocks a semaphore.
455 %
456 %  The format of the UnlockSemaphoreInfo method is:
457 %
458 %      void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
459 %
460 %  A description of each parameter follows:
461 %
462 %    o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
463 %
464 */
465 MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
466 {
467   assert(semaphore_info != (SemaphoreInfo *) NULL);
468   assert(semaphore_info->signature == MagickSignature);
469 #if defined(MAGICKCORE_DEBUG)
470   assert(IsMagickThreadEqual(semaphore_info->id) != MagickFalse);
471   if (semaphore_info->reference_count == 0)
472     {
473       (void) FormatLocaleFile(stderr,
474         "Warning: semaphore lock already unlocked!\n");
475       (void) fflush(stderr);
476       return;
477     }
478   semaphore_info->reference_count--;
479 #endif
480 #if defined(MAGICKCORE_THREAD_SUPPORT)
481   {
482     int
483       status;
484
485     status=pthread_mutex_unlock(&semaphore_info->mutex);
486     if (status != 0)
487       {
488         errno=status;
489         ThrowFatalException(ResourceLimitFatalError,"UnableToUnlockSemaphore");
490       }
491   }
492 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
493   LeaveCriticalSection(&semaphore_info->mutex);
494 #endif
495 }