/src/imagemagick/MagickCore/semaphore.c
Line | Count | Source |
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 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/license/ % |
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 | | */ |
60 | | struct SemaphoreInfo |
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 | | */ |
98 | | MagickExport void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info) |
99 | 613 | { |
100 | 613 | assert(semaphore_info != (SemaphoreInfo **) NULL); |
101 | 613 | if (*semaphore_info == (SemaphoreInfo *) NULL) |
102 | 613 | { |
103 | 613 | LockMagickMutex(); |
104 | 613 | if (*semaphore_info == (SemaphoreInfo *) NULL) |
105 | 613 | *semaphore_info=AcquireSemaphoreInfo(); |
106 | 613 | UnlockMagickMutex(); |
107 | 613 | } |
108 | 613 | } |
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 | | |
129 | | static void *AcquireSemaphoreMemory(const size_t count,const size_t quantum) |
130 | 210M | { |
131 | 210M | #define AlignedExtent(size,alignment) \ |
132 | 210M | (((size)+((alignment)-1)) & (size_t) ~((alignment)-1)) |
133 | | |
134 | 210M | size_t |
135 | 210M | alignment, |
136 | 210M | extent, |
137 | 210M | size; |
138 | | |
139 | 210M | void |
140 | 210M | *memory; |
141 | | |
142 | 210M | size=count*quantum; |
143 | 210M | if ((count == 0) || (quantum != (size/count))) |
144 | 0 | { |
145 | 0 | errno=ENOMEM; |
146 | 0 | return((void *) NULL); |
147 | 0 | } |
148 | 210M | memory=NULL; |
149 | 210M | alignment=CACHE_LINE_SIZE; |
150 | 210M | extent=AlignedExtent(size,CACHE_LINE_SIZE); |
151 | 210M | if ((size == 0) || (alignment < sizeof(void *)) || (extent < size)) |
152 | 0 | return((void *) NULL); |
153 | 210M | #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN) |
154 | 210M | if (posix_memalign(&memory,alignment,extent) != 0) |
155 | 0 | 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 | 210M | return(memory); |
176 | 210M | } |
177 | | |
178 | | static void *RelinquishSemaphoreMemory(void *memory) |
179 | 210M | { |
180 | 210M | if (memory == (void *) NULL) |
181 | 0 | return((void *) NULL); |
182 | 210M | #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN) |
183 | 210M | free(memory); |
184 | | #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC) |
185 | | _aligned_free(memory); |
186 | | #else |
187 | | free(*((void **) memory-1)); |
188 | | #endif |
189 | 210M | return(NULL); |
190 | 210M | } |
191 | | |
192 | | MagickExport SemaphoreInfo *AcquireSemaphoreInfo(void) |
193 | 210M | { |
194 | 210M | SemaphoreInfo |
195 | 210M | *semaphore_info; |
196 | | |
197 | | /* |
198 | | Acquire semaphore. |
199 | | */ |
200 | 210M | semaphore_info=(SemaphoreInfo *) AcquireSemaphoreMemory(1, |
201 | 210M | sizeof(*semaphore_info)); |
202 | 210M | if (semaphore_info == (SemaphoreInfo *) NULL) |
203 | 210M | ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); |
204 | 210M | (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 | 210M | int |
213 | 210M | status; |
214 | | |
215 | 210M | pthread_mutexattr_t |
216 | 210M | mutex_info; |
217 | | |
218 | 210M | status=pthread_mutexattr_init(&mutex_info); |
219 | 210M | if (status != 0) |
220 | 0 | { |
221 | 0 | errno=status; |
222 | 0 | perror("unable to initialize mutex attributes"); |
223 | 0 | _exit(1); |
224 | 0 | } |
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 | 210M | status=pthread_mutex_init(&semaphore_info->mutex,&mutex_info); |
237 | 210M | if (status != 0) |
238 | 0 | { |
239 | 0 | errno=status; |
240 | 0 | perror("unable to initialize mutex"); |
241 | 0 | _exit(1); |
242 | 0 | } |
243 | 210M | status=pthread_mutexattr_destroy(&mutex_info); |
244 | 210M | if (status != 0) |
245 | 0 | { |
246 | 0 | errno=status; |
247 | 0 | perror("unable to destroy mutex attributes"); |
248 | 0 | _exit(1); |
249 | 0 | } |
250 | 210M | } |
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 | 210M | semaphore_info->id=GetMagickThreadId(); |
266 | 210M | semaphore_info->reference_count=0; |
267 | 210M | semaphore_info->signature=MagickCoreSignature; |
268 | 210M | return(semaphore_info); |
269 | 210M | } |
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 | | */ |
293 | | MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info) |
294 | 947M | { |
295 | 947M | assert(semaphore_info != (SemaphoreInfo *) NULL); |
296 | 947M | 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 | 947M | { |
309 | 947M | int |
310 | 947M | status; |
311 | | |
312 | 947M | status=pthread_mutex_lock(&semaphore_info->mutex); |
313 | 947M | if (status != 0) |
314 | 0 | { |
315 | 0 | errno=status; |
316 | 0 | perror("unable to lock mutex"); |
317 | 0 | _exit(1); |
318 | 0 | } |
319 | 947M | } |
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 | 947M | } |
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 | | */ |
351 | | MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info) |
352 | 210M | { |
353 | 210M | assert(semaphore_info != (SemaphoreInfo **) NULL); |
354 | 210M | assert((*semaphore_info) != (SemaphoreInfo *) NULL); |
355 | 210M | assert((*semaphore_info)->signature == MagickCoreSignature); |
356 | 210M | 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 | 210M | int |
362 | 210M | status; |
363 | | |
364 | 210M | status=pthread_mutex_destroy(&(*semaphore_info)->mutex); |
365 | 210M | if (status != 0) |
366 | 0 | { |
367 | 0 | errno=status; |
368 | 0 | perror("unable to destroy mutex"); |
369 | 0 | _exit(1); |
370 | 0 | } |
371 | 210M | } |
372 | | #elif defined(MAGICKCORE_WINDOWS_SUPPORT) |
373 | | DeleteCriticalSection(&(*semaphore_info)->mutex); |
374 | | #endif |
375 | 210M | (*semaphore_info)->signature=(~MagickCoreSignature); |
376 | 210M | *semaphore_info=(SemaphoreInfo *) RelinquishSemaphoreMemory(*semaphore_info); |
377 | 210M | UnlockMagickMutex(); |
378 | 210M | } |
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 | | */ |
398 | | MagickPrivate MagickBooleanType SemaphoreComponentGenesis(void) |
399 | 295 | { |
400 | 295 | InitializeMagickMutex(); |
401 | 295 | return(MagickTrue); |
402 | 295 | } |
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 | | */ |
422 | | MagickPrivate void SemaphoreComponentTerminus(void) |
423 | 0 | { |
424 | 0 | DestroyMagickMutex(); |
425 | 0 | } |
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 | | */ |
449 | | MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info) |
450 | 947M | { |
451 | 947M | assert(semaphore_info != (SemaphoreInfo *) NULL); |
452 | 947M | 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 | 947M | { |
468 | 947M | int |
469 | 947M | status; |
470 | | |
471 | 947M | status=pthread_mutex_unlock(&semaphore_info->mutex); |
472 | 947M | if (status != 0) |
473 | 0 | { |
474 | 0 | errno=status; |
475 | 0 | perror("unable to unlock mutex"); |
476 | 0 | _exit(1); |
477 | 0 | } |
478 | 947M | } |
479 | | #elif defined(MAGICKCORE_WINDOWS_SUPPORT) |
480 | | LeaveCriticalSection(&semaphore_info->mutex); |
481 | | #endif |
482 | 947M | } |