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