MagickCore 7.1.1
Convert, Edit, Or Compose Bitmap Images
Loading...
Searching...
No Matches
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 @ 2000 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% https://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
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/mutex.h"
50#include "MagickCore/semaphore.h"
51#include "MagickCore/semaphore-private.h"
52#include "MagickCore/string_.h"
53#include "MagickCore/thread_.h"
54#include "MagickCore/thread-private.h"
55#include "MagickCore/utility-private.h"
56
57/*
58 Struct declarations.
59*/
61{
62 MagickMutexType
63 mutex;
64
65 MagickThreadType
66 id;
67
68 ssize_t
69 reference_count;
70
71 size_t
72 signature;
73};
74
75/*
76%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77% %
78% %
79% %
80% A c t i v a t e S e m a p h o r e I n f o %
81% %
82% %
83% %
84%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
85%
86% ActivateSemaphoreInfo() activates a semaphore under protection of a mutex
87% to ensure only one thread allocates the semaphore.
88%
89% The format of the ActivateSemaphoreInfo method is:
90%
91% void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info)
92%
93% A description of each parameter follows:
94%
95% o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
96%
97*/
98MagickExport void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info)
99{
100 assert(semaphore_info != (SemaphoreInfo **) NULL);
101 if (*semaphore_info == (SemaphoreInfo *) NULL)
102 {
103 LockMagickMutex();
104 if (*semaphore_info == (SemaphoreInfo *) NULL)
105 *semaphore_info=AcquireSemaphoreInfo();
106 UnlockMagickMutex();
107 }
108}
109
110/*
111%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
112% %
113% %
114% %
115% A c q u i r e S e m a p h o r e I n f o %
116% %
117% %
118% %
119%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120%
121% AcquireSemaphoreInfo() initializes the SemaphoreInfo structure.
122%
123% The format of the AcquireSemaphoreInfo method is:
124%
125% SemaphoreInfo *AcquireSemaphoreInfo(void)
126%
127*/
128
129static void *AcquireSemaphoreMemory(const size_t count,const size_t quantum)
130{
131#define AlignedExtent(size,alignment) \
132 (((size)+((alignment)-1)) & (size_t) ~((alignment)-1))
133
134 size_t
135 alignment,
136 extent,
137 size;
138
139 void
140 *memory;
141
142 size=count*quantum;
143 if ((count == 0) || (quantum != (size/count)))
144 {
145 errno=ENOMEM;
146 return((void *) NULL);
147 }
148 memory=NULL;
149 alignment=CACHE_LINE_SIZE;
150 extent=AlignedExtent(size,CACHE_LINE_SIZE);
151 if ((size == 0) || (alignment < sizeof(void *)) || (extent < size))
152 return((void *) NULL);
153#if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
154 if (posix_memalign(&memory,alignment,extent) != 0)
155 memory=NULL;
156#elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
157 memory=_aligned_malloc(extent,alignment);
158#else
159 {
160 void
161 *p;
162
163 extent=(size+alignment-1)+sizeof(void *);
164 if (extent > size)
165 {
166 p=malloc(extent);
167 if (p != NULL)
168 {
169 memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
170 *((void **) memory-1)=p;
171 }
172 }
173 }
174#endif
175 return(memory);
176}
177
178static void *RelinquishSemaphoreMemory(void *memory)
179{
180 if (memory == (void *) NULL)
181 return((void *) NULL);
182#if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
183 free(memory);
184#elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
185 _aligned_free(memory);
186#else
187 free(*((void **) memory-1));
188#endif
189 return(NULL);
190}
191
192MagickExport SemaphoreInfo *AcquireSemaphoreInfo(void)
193{
195 *semaphore_info;
196
197 /*
198 Acquire semaphore.
199 */
200 semaphore_info=(SemaphoreInfo *) AcquireSemaphoreMemory(1,
201 sizeof(*semaphore_info));
202 if (semaphore_info == (SemaphoreInfo *) NULL)
203 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
204 (void) memset(semaphore_info,0,sizeof(SemaphoreInfo));
205 /*
206 Initialize the semaphore.
207 */
208#if defined(MAGICKCORE_OPENMP_SUPPORT)
209 omp_init_lock((omp_lock_t *) &semaphore_info->mutex);
210#elif defined(MAGICKCORE_THREAD_SUPPORT)
211 {
212 int
213 status;
214
215 pthread_mutexattr_t
216 mutex_info;
217
218 status=pthread_mutexattr_init(&mutex_info);
219 if (status != 0)
220 {
221 errno=status;
222 perror("unable to initialize mutex attributes");
223 _exit(1);
224 }
225#if defined(MAGICKCORE_DEBUG)
226#if defined(PTHREAD_MUTEX_ERRORCHECK)
227 status=pthread_mutex_settype(&mutex_info,PTHREAD_MUTEX_ERRORCHECK);
228 if (status != 0)
229 {
230 errno=status;
231 perror("unable to set mutex type");
232 _exit(1);
233 }
234#endif
235#endif
236 status=pthread_mutex_init(&semaphore_info->mutex,&mutex_info);
237 if (status != 0)
238 {
239 errno=status;
240 perror("unable to initialize mutex");
241 _exit(1);
242 }
243 status=pthread_mutexattr_destroy(&mutex_info);
244 if (status != 0)
245 {
246 errno=status;
247 perror("unable to destroy mutex attributes");
248 _exit(1);
249 }
250 }
251#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
252 {
253 int
254 status;
255
256 status=InitializeCriticalSectionAndSpinCount(&semaphore_info->mutex,0x0400);
257 if (status == 0)
258 {
259 errno=status;
260 perror("unable to initialize critical section");
261 _exit(1);
262 }
263 }
264#endif
265 semaphore_info->id=GetMagickThreadId();
266 semaphore_info->reference_count=0;
267 semaphore_info->signature=MagickCoreSignature;
268 return(semaphore_info);
269}
270
271/*
272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
273% %
274% %
275% %
276% L o c k S e m a p h o r e I n f o %
277% %
278% %
279% %
280%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
281%
282% LockSemaphoreInfo() locks a semaphore.
283%
284% The format of the LockSemaphoreInfo method is:
285%
286% void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
287%
288% A description of each parameter follows:
289%
290% o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
291%
292*/
293MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
294{
295 assert(semaphore_info != (SemaphoreInfo *) NULL);
296 assert(semaphore_info->signature == MagickCoreSignature);
297#if defined(MAGICKCORE_DEBUG)
298 if ((semaphore_info->reference_count > 0) &&
299 (IsMagickThreadEqual(semaphore_info->id) != MagickFalse))
300 {
301 (void) FormatLocaleFile(stderr,"Warning: unexpected recursive lock!\n");
302 (void) fflush(stderr);
303 }
304#endif
305#if defined(MAGICKCORE_OPENMP_SUPPORT)
306 omp_set_lock((omp_lock_t *) &semaphore_info->mutex);
307#elif defined(MAGICKCORE_THREAD_SUPPORT)
308 {
309 int
310 status;
311
312 status=pthread_mutex_lock(&semaphore_info->mutex);
313 if (status != 0)
314 {
315 errno=status;
316 perror("unable to lock mutex");
317 _exit(1);
318 }
319 }
320#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
321 EnterCriticalSection(&semaphore_info->mutex);
322#endif
323#if defined(MAGICKCORE_DEBUG)
324 semaphore_info->id=GetMagickThreadId();
325 semaphore_info->reference_count++;
326#endif
327}
328
329/*
330%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
331% %
332% %
333% %
334% R e l i n q u i s h S e m a p h o r e I n f o %
335% %
336% %
337% %
338%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
339%
340% RelinquishSemaphoreInfo() destroys a semaphore.
341%
342% The format of the RelinquishSemaphoreInfo method is:
343%
344% void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info)
345%
346% A description of each parameter follows:
347%
348% o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
349%
350*/
351MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info)
352{
353 assert(semaphore_info != (SemaphoreInfo **) NULL);
354 assert((*semaphore_info) != (SemaphoreInfo *) NULL);
355 assert((*semaphore_info)->signature == MagickCoreSignature);
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_WINDOWS_SUPPORT)
373 DeleteCriticalSection(&(*semaphore_info)->mutex);
374#endif
375 (*semaphore_info)->signature=(~MagickCoreSignature);
376 *semaphore_info=(SemaphoreInfo *) RelinquishSemaphoreMemory(*semaphore_info);
377 UnlockMagickMutex();
378}
379
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*/
398MagickPrivate MagickBooleanType SemaphoreComponentGenesis(void)
399{
400 InitializeMagickMutex();
401 return(MagickTrue);
402}
403
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*/
422MagickPrivate void SemaphoreComponentTerminus(void)
423{
424 DestroyMagickMutex();
425}
426
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*/
449MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
450{
451 assert(semaphore_info != (SemaphoreInfo *) NULL);
452 assert(semaphore_info->signature == MagickCoreSignature);
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_WINDOWS_SUPPORT)
480 LeaveCriticalSection(&semaphore_info->mutex);
481#endif
482}