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