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