2
% Copyright (C) 2003 GraphicsMagick Group
3
% Copyright (C) 2002 ImageMagick Studio
5
% This program is covered by multiple licenses, which are described in
6
% Copyright.txt. You should have received a copy of Copyright.txt with this
7
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
9
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12
% SSSSS EEEEE M M AAA PPPP H H OOO RRRR EEEEE %
13
% SS E MM MM A A P P H H O O R R E %
14
% SSS EEE M M M AAAAA PPPP HHHHH O O RRRR EEE %
15
% SS E M M A A P H H O O R R E %
16
% SSSSS EEEEE M M A A P H H OOO R R EEEEE %
19
% GraphicsMagick Semaphore Methods %
29
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38
#include "magick/studio.h"
39
#include "magick/utility.h"
40
#if defined(HAVE_PTHREAD)
46
#define SPINLOCK_DELAY_MILLI_SECS 10
48
#include "magick/semaphore.h"
55
#if defined(HAVE_PTHREAD)
57
mutex; /* POSIX thread mutex */
60
thread_id; /* ID of thread which holds the lock */
64
mutex; /* Windows critical section */
67
thread_id; /* ID of thread which holds the lock */
71
locked; /* True if semaphore is locked */
74
signature; /* Used to validate structure */
80
#if defined(HAVE_PTHREAD)
81
static pthread_mutex_t
82
semaphore_mutex = PTHREAD_MUTEX_INITIALIZER;
86
#if !defined(USE_SPINLOCKS)
87
static CRITICAL_SECTION
91
active_semaphore = False;
95
/* Wait for spin lock */
96
static void spinlock_wait (int *sl)
98
while (InterlockedCompareExchange (sl, 1, 0) != 0)
100
/* slight delay - just in case OS does not giveup CPU */
101
Sleep (SPINLOCK_DELAY_MILLI_SECS);
104
/* Release spin lock */
105
static void spinlock_release (int *sl)
107
InterlockedExchange (sl, 0);
113
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
117
% A c q u i r e S e m a p h o r e I n f o %
121
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
123
% AcquireSemaphoreInfo() acquires a semaphore.
125
% The format of the AcquireSemaphoreInfo method is:
127
% AcquireSemaphoreInfo(SemaphoreInfo **semaphore_info)
129
% A description of each parameter follows:
131
% o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
135
MagickExport void AcquireSemaphoreInfo(SemaphoreInfo **semaphore_info)
137
assert(semaphore_info != (SemaphoreInfo **) NULL);
138
#if defined(HAVE_PTHREAD)
139
(void) pthread_mutex_lock(&semaphore_mutex);
142
#if !defined(USE_SPINLOCKS)
143
if (!active_semaphore)
144
InitializeCriticalSection(&semaphore_mutex);
145
active_semaphore=True;
146
EnterCriticalSection(&semaphore_mutex);
148
spinlock_wait(&semaphore_mutex);
151
if (*semaphore_info == (SemaphoreInfo *) NULL)
152
*semaphore_info=AllocateSemaphoreInfo();
153
#if defined(HAVE_PTHREAD)
154
(void) pthread_mutex_unlock(&semaphore_mutex);
157
#if !defined(USE_SPINLOCKS)
158
LeaveCriticalSection(&semaphore_mutex);
160
spinlock_release(&semaphore_mutex);
163
(void) LockSemaphoreInfo(*semaphore_info);
167
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
171
% A l l o c a t e S e m a p h o r e I n f o %
175
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
177
% Method AllocateSemaphoreInfo initializes the SemaphoreInfo structure.
179
% The format of the AllocateSemaphoreInfo method is:
181
% SemaphoreInfo *AllocateSemaphoreInfo(void)
183
% A description of each parameter follows:
185
% o semaphore_info: Method AllocateSemaphoreInfo returns a pointer to an
186
% initialized SemaphoreInfo structure.
190
MagickExport SemaphoreInfo *AllocateSemaphoreInfo(void)
198
semaphore_info=MagickAllocateMemory(SemaphoreInfo *,sizeof(SemaphoreInfo));
199
if (semaphore_info == (SemaphoreInfo *) NULL)
200
MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
201
UnableToAllocateSemaphoreInfo);
202
memset(semaphore_info,0,sizeof(SemaphoreInfo));
204
Initialize the semaphore.
206
#if defined(HAVE_PTHREAD)
211
status=pthread_mutex_init(&semaphore_info->mutex,
212
(const pthread_mutexattr_t *) NULL);
215
MagickFreeMemory(semaphore_info);
216
return((SemaphoreInfo *) NULL);
221
InitializeCriticalSection(&semaphore_info->mutex);
223
semaphore_info->locked=False;
224
semaphore_info->signature=MagickSignature;
225
return(semaphore_info);
229
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233
% D e s t r o y S e m a p h o r e %
237
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239
% DestroySemaphore() destroys the semaphore environment.
241
% The format of the DestroySemaphore method is:
243
% DestroySemaphore(void)
247
MagickExport void DestroySemaphore(void)
249
#if defined(HAVE_PTHREAD)
250
(void) pthread_mutex_destroy(&semaphore_mutex);
253
#if !defined(USE_SPINLOCKS)
254
if (active_semaphore)
255
DeleteCriticalSection(&semaphore_mutex);
256
active_semaphore=False;
262
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
266
% D e s t r o y S e m a p h o r e I n f o %
270
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
272
% Method DestroySemaphoreInfo destroys a semaphore.
274
% The format of the DestroySemaphoreInfo method is:
276
% DestroySemaphoreInfo(SemaphoreInfo **semaphore_info)
278
% A description of each parameter follows:
280
% o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
284
MagickExport void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info)
286
assert(semaphore_info != (SemaphoreInfo **) NULL);
287
if (*semaphore_info == (SemaphoreInfo *) NULL)
289
assert((*semaphore_info)->signature == MagickSignature);
290
#if defined(HAVE_PTHREAD)
291
(void) pthread_mutex_lock(&semaphore_mutex);
294
#if !defined(USE_SPINLOCKS)
295
if (!active_semaphore)
296
InitializeCriticalSection(&semaphore_mutex);
297
active_semaphore=True;
298
EnterCriticalSection(&semaphore_mutex);
300
spinlock_wait(&semaphore_mutex);
303
#if defined(HAVE_PTHREAD)
304
(void) pthread_mutex_destroy(&(*semaphore_info)->mutex);
307
DeleteCriticalSection(&(*semaphore_info)->mutex);
309
MagickFreeMemory((*semaphore_info));
310
#if defined(HAVE_PTHREAD)
311
(void) pthread_mutex_unlock(&semaphore_mutex);
314
#if !defined(USE_SPINLOCKS)
315
LeaveCriticalSection(&semaphore_mutex);
317
spinlock_release(&semaphore_mutex);
323
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
327
% I n i t i a l i z e S e m a p h o r e %
331
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
333
% Method InitializeSemaphore initializes the semaphore environment.
335
% The format of the InitializeSemaphore method is:
337
% InitializeSemaphore(void)
341
MagickExport void InitializeSemaphore(void)
343
#if defined(HAVE_PTHREAD)
344
(void) pthread_mutex_init(&semaphore_mutex,
345
(const pthread_mutexattr_t *) NULL);
348
#if !defined(USE_SPINLOCKS)
349
if (!active_semaphore)
350
InitializeCriticalSection(&semaphore_mutex);
351
active_semaphore=True;
357
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361
% L i b e r a t e S e m a p h o r e I n f o %
365
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367
% Method LiberateSemaphoreInfo liberates a semaphore.
369
% The format of the LiberateSemaphoreInfo method is:
371
% LiberateSemaphoreInfo(SemaphoreInfo **semaphore_info)
373
% A description of each parameter follows:
375
% o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
379
MagickExport void LiberateSemaphoreInfo(SemaphoreInfo **semaphore_info)
381
assert(semaphore_info != (SemaphoreInfo **) NULL);
382
if (*semaphore_info == (SemaphoreInfo *) NULL)
384
assert((*semaphore_info)->signature == MagickSignature);
385
(void) UnlockSemaphoreInfo(*semaphore_info);
389
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
393
% L o c k S e m a p h o r e I n f o %
397
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
399
% Method LockSemaphoreInfo locks a semaphore.
401
% The format of the LockSemaphoreInfo method is:
403
% unsigned int LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
405
% A description of each parameter follows:
407
% o status: Method LockSemaphoreInfo returns True on success otherwise
410
% o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
414
MagickExport unsigned int LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
416
assert(semaphore_info != (SemaphoreInfo *) NULL);
417
assert(semaphore_info->signature == MagickSignature);
418
#if defined(HAVE_PTHREAD)
419
if (pthread_mutex_lock(&semaphore_info->mutex))
421
/* Record the thread ID of the locking thread */
422
semaphore_info->thread_id=pthread_self();
425
EnterCriticalSection(&semaphore_info->mutex);
426
/* Record the thread ID of the locking thread */
427
semaphore_info->thread_id=GetCurrentThreadId();
429
semaphore_info->locked=True;
434
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
438
% U n l o c k S e m a p h o r e I n f o %
442
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
444
% Method UnlockSemaphoreInfo unlocks a semaphore.
446
% The format of the LockSemaphoreInfo method is:
448
% unsigned int UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
450
% A description of each parameter follows:
452
% o status: Method UnlockSemaphoreInfo returns True on success otherwise
455
% o semaphore_info: Specifies a pointer to an SemaphoreInfo structure.
459
MagickExport unsigned int UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
461
assert(semaphore_info != (SemaphoreInfo *) NULL);
462
assert(semaphore_info->signature == MagickSignature);
463
if (semaphore_info->locked != True)
465
semaphore_info->locked=False;
466
#if defined(HAVE_PTHREAD)
467
/* Enforce that unlocking thread is the same as the locking thread */
468
assert(pthread_equal(semaphore_info->thread_id,pthread_self()));
469
if (pthread_mutex_unlock(&semaphore_info->mutex))
473
/* Enforce that unlocking thread is the same as the locking thread */
474
assert(GetCurrentThreadId() == semaphore_info->thread_id);
475
LeaveCriticalSection(&semaphore_info->mutex);