]> 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 size)
127 {
128 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
129   {
130     void
131       *memory;
132
133     if (posix_memalign(&memory,CACHE_LINE_SIZE,CacheAlign(size)) == 0)
134       return(memory);
135   }
136 #endif
137   return(malloc(CacheAlign(size)));
138 }
139
140 MagickExport SemaphoreInfo *AllocateSemaphoreInfo(void)
141 {
142   SemaphoreInfo
143     *semaphore_info;
144
145   /*
146     Allocate semaphore.
147   */
148   semaphore_info=(SemaphoreInfo *) AcquireSemaphoreMemory(
149     sizeof(*semaphore_info));
150   if (semaphore_info == (SemaphoreInfo *) NULL)
151     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
152   (void) ResetMagickMemory(semaphore_info,0,sizeof(SemaphoreInfo));
153   /*
154     Initialize the semaphore.
155   */
156 #if defined(MAGICKCORE_THREAD_SUPPORT)
157   {
158     int
159       status;
160
161     pthread_mutexattr_t
162       mutex_info;
163
164     status=pthread_mutexattr_init(&mutex_info);
165     if (status != 0)
166       {
167         errno=status;
168         ThrowFatalException(ResourceLimitFatalError,
169           "UnableToInitializeSemaphore");
170       }
171 #if defined(MAGICKCORE_DEBUG)
172 #if defined(PTHREAD_MUTEX_ERRORCHECK)
173     status=pthread_mutex_settype(&mutex_info,PTHREAD_MUTEX_ERRORCHECK);
174     if (status != 0)
175       {
176         errno=status;
177         ThrowFatalException(ResourceLimitFatalError,
178           "UnableToInitializeSemaphore");
179       }
180 #endif
181 #endif
182     status=pthread_mutex_init(&semaphore_info->mutex,&mutex_info);
183     if (status != 0)
184       {
185         errno=status;
186         ThrowFatalException(ResourceLimitFatalError,
187           "UnableToInitializeSemaphore");
188       }
189     status=pthread_mutexattr_destroy(&mutex_info);
190     if (status != 0)
191       {
192         errno=status;
193         ThrowFatalException(ResourceLimitFatalError,
194           "UnableToInitializeSemaphore");
195       }
196   }
197 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
198   {
199     int
200       status;
201
202     status=InitializeCriticalSectionAndSpinCount(&semaphore_info->mutex,0x0400);
203     if (status == 0)
204       {
205         errno=status;
206         ThrowFatalException(ResourceLimitFatalError,
207           "UnableToInitializeSemaphore");
208        }
209   }
210 #endif
211   semaphore_info->id=GetMagickThreadId();
212   semaphore_info->reference_count=0;
213   semaphore_info->signature=MagickSignature;
214   return(semaphore_info);
215 }
216 \f
217 /*
218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
219 %                                                                             %
220 %                                                                             %
221 %                                                                             %
222 %   D e s t r o y S e m a p h o r e I n f o                                   %
223 %                                                                             %
224 %                                                                             %
225 %                                                                             %
226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227 %
228 %  DestroySemaphoreInfo() destroys a semaphore.
229 %
230 %  The format of the DestroySemaphoreInfo method is:
231 %
232 %      void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info)
233 %
234 %  A description of each parameter follows:
235 %
236 %    o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
237 %
238 */
239 MagickExport void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info)
240 {
241   assert(semaphore_info != (SemaphoreInfo **) NULL);
242   assert((*semaphore_info) != (SemaphoreInfo *) NULL);
243   assert((*semaphore_info)->signature == MagickSignature);
244   LockMagickMutex();
245 #if defined(MAGICKCORE_THREAD_SUPPORT)
246   {
247     int
248       status;
249
250     status=pthread_mutex_destroy(&(*semaphore_info)->mutex);
251     if (status != 0)
252       {
253         errno=status;
254         ThrowFatalException(ResourceLimitFatalError,"UnableToDestroySemaphore");
255       }
256   }
257 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
258   DeleteCriticalSection(&(*semaphore_info)->mutex);
259 #endif
260   (*semaphore_info)->signature=(~MagickSignature);
261   free(*semaphore_info);
262   *semaphore_info=(SemaphoreInfo *) NULL;
263   UnlockMagickMutex();
264 }
265 \f
266 /*
267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
268 %                                                                             %
269 %                                                                             %
270 %                                                                             %
271 %   L o c k S e m a p h o r e I n f o                                         %
272 %                                                                             %
273 %                                                                             %
274 %                                                                             %
275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276 %
277 %  LockSemaphoreInfo() locks a semaphore.
278 %
279 %  The format of the LockSemaphoreInfo method is:
280 %
281 %      void LockSemaphoreInfo(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 LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
289 {
290   assert(semaphore_info != (SemaphoreInfo *) NULL);
291   assert(semaphore_info->signature == MagickSignature);
292 #if defined(MAGICKCORE_THREAD_SUPPORT)
293   {
294     int
295       status;
296
297     status=pthread_mutex_lock(&semaphore_info->mutex);
298     if (status != 0)
299       {
300         errno=status;
301         ThrowFatalException(ResourceLimitFatalError,"UnableToLockSemaphore");
302       }
303   }
304 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
305   EnterCriticalSection(&semaphore_info->mutex);
306 #endif
307 #if defined(MAGICKCORE_DEBUG)
308   if ((semaphore_info->reference_count > 0) &&
309       (IsMagickThreadEqual(semaphore_info->id) != MagickFalse))
310     {
311       (void) FormatLocaleFile(stderr,"Warning: unexpected recursive lock!\n");
312       (void) fflush(stderr);
313     }
314 #endif
315   semaphore_info->id=GetMagickThreadId();
316   semaphore_info->reference_count++;
317 }
318 \f
319 /*
320 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
321 %                                                                             %
322 %                                                                             %
323 %                                                                             %
324 %   R e l i n g u i s h S e m a p h o r e I n f o                             %
325 %                                                                             %
326 %                                                                             %
327 %                                                                             %
328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
329 %
330 %  RelinquishSemaphoreInfo() relinquishes a semaphore.
331 %
332 %  The format of the RelinquishSemaphoreInfo method is:
333 %
334 %      RelinquishSemaphoreInfo(SemaphoreInfo *semaphore_info)
335 %
336 %  A description of each parameter follows:
337 %
338 %    o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
339 %
340 */
341 MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo *semaphore_info)
342 {
343   assert(semaphore_info != (SemaphoreInfo *) NULL);
344   assert(semaphore_info->signature == MagickSignature);
345   UnlockSemaphoreInfo(semaphore_info);
346 }
347 \f
348 /*
349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
350 %                                                                             %
351 %                                                                             %
352 %                                                                             %
353 %   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                         %
354 %                                                                             %
355 %                                                                             %
356 %                                                                             %
357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
358 %
359 %  SemaphoreComponentGenesis() instantiates the semaphore environment.
360 %
361 %  The format of the SemaphoreComponentGenesis method is:
362 %
363 %      MagickBooleanType SemaphoreComponentGenesis(void)
364 %
365 */
366 MagickPrivate MagickBooleanType SemaphoreComponentGenesis(void)
367 {
368   LockMagickMutex();
369   UnlockMagickMutex();
370   return(MagickTrue);
371 }
372 \f
373 /*
374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375 %                                                                             %
376 %                                                                             %
377 %                                                                             %
378 %   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                       %
379 %                                                                             %
380 %                                                                             %
381 %                                                                             %
382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
383 %
384 %  SemaphoreComponentTerminus() destroys the semaphore component.
385 %
386 %  The format of the SemaphoreComponentTerminus method is:
387 %
388 %      SemaphoreComponentTerminus(void)
389 %
390 */
391 MagickPrivate void SemaphoreComponentTerminus(void)
392 {
393 }
394 \f
395 /*
396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
397 %                                                                             %
398 %                                                                             %
399 %                                                                             %
400 %   U n l o c k S e m a p h o r e I n f o                                     %
401 %                                                                             %
402 %                                                                             %
403 %                                                                             %
404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
405 %
406 %  UnlockSemaphoreInfo() unlocks a semaphore.
407 %
408 %  The format of the UnlockSemaphoreInfo method is:
409 %
410 %      void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
411 %
412 %  A description of each parameter follows:
413 %
414 %    o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
415 %
416 */
417 MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
418 {
419   assert(semaphore_info != (SemaphoreInfo *) NULL);
420   assert(semaphore_info->signature == MagickSignature);
421 #if defined(MAGICKCORE_DEBUG)
422   assert(IsMagickThreadEqual(semaphore_info->id) != MagickFalse);
423   if (semaphore_info->reference_count == 0)
424     {
425       (void) FormatLocaleFile(stderr,
426         "Warning: semaphore lock already unlocked!\n");
427       (void) fflush(stderr);
428       return;
429     }
430   semaphore_info->reference_count--;
431 #endif
432 #if defined(MAGICKCORE_THREAD_SUPPORT)
433   {
434     int
435       status;
436
437     status=pthread_mutex_unlock(&semaphore_info->mutex);
438     if (status != 0)
439       {
440         errno=status;
441         ThrowFatalException(ResourceLimitFatalError,"UnableToUnlockSemaphore");
442       }
443   }
444 #elif defined(MAGICKCORE_HAVE_WINTHREADS)
445   LeaveCriticalSection(&semaphore_info->mutex);
446 #endif
447 }