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