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