MagickCore  7.0.7
Convert, Edit, Or Compose Bitmap Images
semaphore.c
Go to the documentation of this file.
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-2018 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://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"
47 #include "MagickCore/memory_.h"
49 #include "MagickCore/semaphore.h"
51 #include "MagickCore/string_.h"
52 #include "MagickCore/thread_.h"
55 
56 /*
57  Struct declaractions.
58 */
60 {
63 
65  id;
66 
67  ssize_t
69 
70  size_t
72 };
73 
74 /*
75 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
76 % %
77 % %
78 % %
79 % A c t i v a t e S e m a p h o r e I n f o %
80 % %
81 % %
82 % %
83 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84 %
85 % ActivateSemaphoreInfo() activates a semaphore under protection of a mutex
86 % to ensure only one thread allocates the semaphore.
87 %
88 % The format of the ActivateSemaphoreInfo method is:
89 %
90 % void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info)
91 %
92 % A description of each parameter follows:
93 %
94 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
95 %
96 */
98 {
99  assert(semaphore_info != (SemaphoreInfo **) NULL);
100  if (*semaphore_info == (SemaphoreInfo *) NULL)
101  {
103  LockMagickMutex();
104  if (*semaphore_info == (SemaphoreInfo *) NULL)
105  *semaphore_info=AcquireSemaphoreInfo();
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 
129 static void *AcquireSemaphoreMemory(const size_t count,const size_t quantum)
130 {
131 #define AlignedExtent(size,alignment) \
132  (((size)+((alignment)-1)) & ~((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 
178 static 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 
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) ResetMagickMemory(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 */
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 */
352 {
353  assert(semaphore_info != (SemaphoreInfo **) NULL);
354  assert((*semaphore_info) != (SemaphoreInfo *) NULL);
355  assert((*semaphore_info)->signature == MagickCoreSignature);
357  LockMagickMutex();
358 #if defined(MAGICKCORE_OPENMP_SUPPORT)
359  omp_destroy_lock((omp_lock_t *) &(*semaphore_info)->mutex);
360 #elif defined(MAGICKCORE_THREAD_SUPPORT)
361  {
362  int
363  status;
364 
365  status=pthread_mutex_destroy(&(*semaphore_info)->mutex);
366  if (status != 0)
367  {
368  errno=status;
369  perror("unable to destroy mutex");
370  _exit(1);
371  }
372  }
373 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
374  DeleteCriticalSection(&(*semaphore_info)->mutex);
375 #endif
376  (*semaphore_info)->signature=(~MagickCoreSignature);
377  *semaphore_info=(SemaphoreInfo *) RelinquishSemaphoreMemory(*semaphore_info);
379 }
380 
381 /*
382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
383 % %
384 % %
385 % %
386 % 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 %
387 % %
388 % %
389 % %
390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
391 %
392 % SemaphoreComponentGenesis() instantiates the semaphore environment.
393 %
394 % The format of the SemaphoreComponentGenesis method is:
395 %
396 % MagickBooleanType SemaphoreComponentGenesis(void)
397 %
398 */
400 {
402  return(MagickTrue);
403 }
404 
405 /*
406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
407 % %
408 % %
409 % %
410 % 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 %
411 % %
412 % %
413 % %
414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
415 %
416 % SemaphoreComponentTerminus() destroys the semaphore component.
417 %
418 % The format of the SemaphoreComponentTerminus method is:
419 %
420 % SemaphoreComponentTerminus(void)
421 %
422 */
424 {
426 }
427 
428 /*
429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
430 % %
431 % %
432 % %
433 % U n l o c k S e m a p h o r e I n f o %
434 % %
435 % %
436 % %
437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
438 %
439 % UnlockSemaphoreInfo() unlocks a semaphore.
440 %
441 % The format of the UnlockSemaphoreInfo method is:
442 %
443 % void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
444 %
445 % A description of each parameter follows:
446 %
447 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
448 %
449 */
451 {
452  assert(semaphore_info != (SemaphoreInfo *) NULL);
453  assert(semaphore_info->signature == MagickCoreSignature);
454 #if defined(MAGICKCORE_DEBUG)
455  assert(IsMagickThreadEqual(semaphore_info->id) != MagickFalse);
456  if (semaphore_info->reference_count == 0)
457  {
458  (void) FormatLocaleFile(stderr,
459  "Warning: semaphore lock already unlocked!\n");
460  (void) fflush(stderr);
461  return;
462  }
463  semaphore_info->reference_count--;
464 #endif
465 #if defined(MAGICKCORE_OPENMP_SUPPORT)
466  omp_unset_lock((omp_lock_t *) &semaphore_info->mutex);
467 #elif defined(MAGICKCORE_THREAD_SUPPORT)
468  {
469  int
470  status;
471 
472  status=pthread_mutex_unlock(&semaphore_info->mutex);
473  if (status != 0)
474  {
475  errno=status;
476  perror("unable to unlock mutex");
477  _exit(1);
478  }
479  }
480 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
481  LeaveCriticalSection(&semaphore_info->mutex);
482 #endif
483 }
static MagickThreadType GetMagickThreadId(void)
#define pthread_mutex_init
Definition: vms.h:823
static void UnlockMagickMutex(void)
MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition: semaphore.c:450
#define CACHE_LINE_SIZE
#define ThrowFatalException(severity, tag)
#define pthread_mutex_destroy
Definition: vms.h:822
MagickMutexType mutex
Definition: semaphore.c:62
MagickExport SemaphoreInfo * AcquireSemaphoreInfo(void)
Definition: semaphore.c:192
ssize_t reference_count
Definition: semaphore.c:68
static void * RelinquishSemaphoreMemory(void *memory)
Definition: semaphore.c:178
static MagickBooleanType IsMagickThreadEqual(const MagickThreadType id)
#define AlignedExtent(size, alignment)
static void * AcquireSemaphoreMemory(const size_t count, const size_t quantum)
Definition: semaphore.c:129
#define pthread_mutex_lock
Definition: vms.h:824
static void InitializeMagickMutex(void)
#define MagickCoreSignature
MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition: semaphore.c:293
size_t MagickMutexType
static void LockMagickMutex(void)
MagickExport ssize_t FormatLocaleFile(FILE *file, const char *magick_restrict format,...)
Definition: locale.c:378
MagickBooleanType
Definition: magick-type.h:156
MagickExport void * ResetMagickMemory(void *memory, int byte, const size_t size)
Definition: memory.c:1164
pid_t MagickThreadType
Definition: thread_.h:34
static void DestroyMagickMutex(void)
#define pthread_mutex_unlock
Definition: vms.h:826
MagickPrivate MagickBooleanType SemaphoreComponentGenesis(void)
Definition: semaphore.c:399
#define pthread_mutexattr_destroy
Definition: vms.h:829
MagickExport void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info)
Definition: semaphore.c:97
MagickPrivate void SemaphoreComponentTerminus(void)
Definition: semaphore.c:423
size_t signature
Definition: semaphore.c:71
#define MagickPrivate
#define MagickExport
MagickThreadType id
Definition: semaphore.c:65
#define pthread_mutexattr_init
Definition: vms.h:831
MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info)
Definition: semaphore.c:351