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*/
58struct 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*/
96MagickExport 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
128static 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
177static 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
191MagickExport 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*/
292MagickExport 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*/
350MagickExport 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*/
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}
483