| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % SSSSS EEEEE M M AAA PPPP H H OOO RRRR EEEEE % |
| % SS E MM MM A A P P H H O O R R E % |
| % SSS EEE M M M AAAAA PPPP HHHHH O O RRRR EEE % |
| % SS E M M A A P H H O O R R E % |
| % SSSSS EEEEE M M A A P H H OOO R R EEEEE % |
| % % |
| % % |
| % MagickCore Semaphore Methods % |
| % % |
| % Software Design % |
| % William Radcliffe % |
| % John Cristy % |
| % June 2000 % |
| % % |
| % % |
| % Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization % |
| % dedicated to making software imaging solutions freely available. % |
| % % |
| % You may not use this file except in compliance with the License. You may % |
| % obtain a copy of the License at % |
| % % |
| % http://www.imagemagick.org/script/license.php % |
| % % |
| % Unless required by applicable law or agreed to in writing, software % |
| % distributed under the License is distributed on an "AS IS" BASIS, % |
| % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % |
| % See the License for the specific language governing permissions and % |
| % limitations under the License. % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % |
| % |
| */ |
| |
| /* |
| Include declarations. |
| */ |
| #include "magick/studio.h" |
| #include "magick/exception.h" |
| #include "magick/exception-private.h" |
| #include "magick/memory_.h" |
| #include "magick/semaphore.h" |
| #include "magick/string_.h" |
| #include "magick/thread_.h" |
| #include "magick/thread-private.h" |
| |
| /* |
| Struct declaractions. |
| */ |
| struct SemaphoreInfo |
| { |
| MagickMutexType |
| mutex; |
| |
| MagickThreadType |
| id; |
| |
| long |
| reference_count; |
| |
| unsigned long |
| signature; |
| }; |
| |
| /* |
| Static declaractions. |
| */ |
| #if defined(MAGICKCORE_HAVE_PTHREAD) |
| static pthread_mutex_t |
| semaphore_mutex = PTHREAD_MUTEX_INITIALIZER; |
| #elif defined(MAGICKCORE_HAVE_WINTHREADS) |
| static LONG |
| semaphore_mutex = 0; |
| #else |
| static long |
| semaphore_mutex = 0; |
| #endif |
| |
| /* |
| Forward declaractions. |
| */ |
| static void |
| LockMagickMutex(void), |
| UnlockMagickMutex(void); |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % A c q u i r e S e m a p h o r e I n f o % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % AcquireSemaphoreInfo() acquires a semaphore. |
| % |
| % The format of the AcquireSemaphoreInfo method is: |
| % |
| % void AcquireSemaphoreInfo(SemaphoreInfo **semaphore_info) |
| % |
| % A description of each parameter follows: |
| % |
| % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure. |
| % |
| */ |
| MagickExport void AcquireSemaphoreInfo(SemaphoreInfo **semaphore_info) |
| { |
| assert(semaphore_info != (SemaphoreInfo **) NULL); |
| if (*semaphore_info == (SemaphoreInfo *) NULL) |
| { |
| LockMagickMutex(); |
| if (*semaphore_info == (SemaphoreInfo *) NULL) |
| *semaphore_info=AllocateSemaphoreInfo(); |
| UnlockMagickMutex(); |
| } |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % A l l o c a t e S e m a p h o r e I n f o % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % AllocateSemaphoreInfo() initializes the SemaphoreInfo structure. |
| % |
| % The format of the AllocateSemaphoreInfo method is: |
| % |
| % SemaphoreInfo *AllocateSemaphoreInfo(void) |
| % |
| */ |
| MagickExport SemaphoreInfo *AllocateSemaphoreInfo(void) |
| { |
| SemaphoreInfo |
| *semaphore_info; |
| |
| /* |
| Allocate semaphore. |
| */ |
| semaphore_info=(SemaphoreInfo *) AcquireAlignedMemory(1, |
| sizeof(SemaphoreInfo)); |
| if (semaphore_info == (SemaphoreInfo *) NULL) |
| ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); |
| (void) ResetMagickMemory(semaphore_info,0,sizeof(SemaphoreInfo)); |
| /* |
| Initialize the semaphore. |
| */ |
| #if defined(MAGICKCORE_HAVE_PTHREAD) |
| { |
| int |
| status; |
| |
| pthread_mutexattr_t |
| mutex_info; |
| |
| status=pthread_mutexattr_init(&mutex_info); |
| if (status != 0) |
| { |
| errno=status; |
| ThrowFatalException(ResourceLimitFatalError, |
| "UnableToInitializeSemaphore"); |
| } |
| status=pthread_mutex_init(&semaphore_info->mutex,&mutex_info); |
| if (status != 0) |
| { |
| errno=status; |
| ThrowFatalException(ResourceLimitFatalError, |
| "UnableToInitializeSemaphore"); |
| } |
| status=pthread_mutexattr_destroy(&mutex_info); |
| if (status != 0) |
| { |
| errno=status; |
| ThrowFatalException(ResourceLimitFatalError, |
| "UnableToInitializeSemaphore"); |
| } |
| } |
| #elif defined(MAGICKCORE_HAVE_WINTHREADS) |
| InitializeCriticalSection(&semaphore_info->mutex); |
| #endif |
| semaphore_info->id=GetMagickThreadId(); |
| semaphore_info->reference_count=0; |
| semaphore_info->signature=MagickSignature; |
| return(semaphore_info); |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % D e s t r o y S e m a p h o r e I n f o % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % DestroySemaphoreInfo() destroys a semaphore. |
| % |
| % The format of the DestroySemaphoreInfo method is: |
| % |
| % void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info) |
| % |
| % A description of each parameter follows: |
| % |
| % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure. |
| % |
| */ |
| MagickExport void DestroySemaphoreInfo(SemaphoreInfo **semaphore_info) |
| { |
| assert(semaphore_info != (SemaphoreInfo **) NULL); |
| assert((*semaphore_info) != (SemaphoreInfo *) NULL); |
| assert((*semaphore_info)->signature == MagickSignature); |
| LockMagickMutex(); |
| #if defined(MAGICKCORE_HAVE_PTHREAD) |
| { |
| int |
| status; |
| |
| status=pthread_mutex_destroy(&(*semaphore_info)->mutex); |
| if (status != 0) |
| { |
| errno=status; |
| ThrowFatalException(ResourceLimitFatalError,"UnableToDestroySemaphore"); |
| } |
| } |
| #elif defined(MAGICKCORE_HAVE_WINTHREADS) |
| DeleteCriticalSection(&(*semaphore_info)->mutex); |
| #endif |
| (*semaphore_info)->signature=(~MagickSignature); |
| *semaphore_info=(SemaphoreInfo *) RelinquishAlignedMemory(*semaphore_info); |
| UnlockMagickMutex(); |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| + L o c k M a g i c k M u t e x % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % LockMagickMutex() locks a global mutex. If it is already locked, the |
| % calling thread blocks until the mutex becomes available. |
| % |
| % The format of the LockMagickMutex method is: |
| % |
| % void LockMagickMutex(void) |
| % |
| */ |
| static void LockMagickMutex(void) |
| { |
| #if defined(MAGICKCORE_HAVE_PTHREAD) |
| { |
| int |
| status; |
| |
| status=pthread_mutex_lock(&semaphore_mutex); |
| if (status != 0) |
| { |
| errno=status; |
| ThrowFatalException(ResourceLimitFatalError,"UnableToLockSemaphore"); |
| } |
| } |
| #elif defined(MAGICKCORE_HAVE_WINTHREADS) |
| while (InterlockedCompareExchange(&semaphore_mutex,1L,0L) != 0) |
| Sleep(10); |
| #endif |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % L o c k S e m a p h o r e I n f o % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % LockSemaphoreInfo() locks a semaphore. |
| % |
| % The format of the LockSemaphoreInfo method is: |
| % |
| % void LockSemaphoreInfo(SemaphoreInfo *semaphore_info) |
| % |
| % A description of each parameter follows: |
| % |
| % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure. |
| % |
| */ |
| MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info) |
| { |
| assert(semaphore_info != (SemaphoreInfo *) NULL); |
| assert(semaphore_info->signature == MagickSignature); |
| #if defined(MAGICKCORE_HAVE_PTHREAD) |
| { |
| int |
| status; |
| |
| status=pthread_mutex_lock(&semaphore_info->mutex); |
| if (status != 0) |
| { |
| errno=status; |
| ThrowFatalException(ResourceLimitFatalError,"UnableToLockSemaphore"); |
| } |
| } |
| #elif defined(MAGICKCORE_HAVE_WINTHREADS) |
| EnterCriticalSection(&semaphore_info->mutex); |
| #endif |
| #if defined(MAGICKCORE_DEBUG) |
| if ((semaphore_info->reference_count > 0) && |
| (IsMagickThreadEqual(semaphore_info->id) != MagickFalse)) |
| { |
| (void) fprintf(stderr,"Warning: unexpected recursive lock!\n"); |
| (void) fflush(stderr); |
| } |
| #endif |
| semaphore_info->id=GetMagickThreadId(); |
| semaphore_info->reference_count++; |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % R e l i n g u i s h S e m a p h o r e I n f o % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % RelinquishSemaphoreInfo() relinquishes a semaphore. |
| % |
| % The format of the RelinquishSemaphoreInfo method is: |
| % |
| % RelinquishSemaphoreInfo(SemaphoreInfo *semaphore_info) |
| % |
| % A description of each parameter follows: |
| % |
| % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure. |
| % |
| */ |
| MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo *semaphore_info) |
| { |
| assert(semaphore_info != (SemaphoreInfo *) NULL); |
| assert(semaphore_info->signature == MagickSignature); |
| UnlockSemaphoreInfo(semaphore_info); |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % 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 % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % SemaphoreComponentGenesis() instantiates the semaphore environment. |
| % |
| % The format of the SemaphoreComponentGenesis method is: |
| % |
| % MagickBooleanType SemaphoreComponentGenesis(void) |
| % |
| */ |
| MagickExport MagickBooleanType SemaphoreComponentGenesis(void) |
| { |
| LockMagickMutex(); |
| UnlockMagickMutex(); |
| return(MagickTrue); |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % 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 % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % SemaphoreComponentTerminus() destroys the semaphore component. |
| % |
| % The format of the SemaphoreComponentTerminus method is: |
| % |
| % SemaphoreComponentTerminus(void) |
| % |
| */ |
| MagickExport void SemaphoreComponentTerminus(void) |
| { |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| + U n l o c k M a g i c k M u t e x % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % UnlockMagickMutex() releases a global mutex. |
| % |
| % The format of the LockMagickMutex method is: |
| % |
| % void UnlockMagickMutex(void) |
| % |
| */ |
| static void UnlockMagickMutex(void) |
| { |
| #if defined(MAGICKCORE_HAVE_PTHREAD) |
| { |
| int |
| status; |
| |
| status=pthread_mutex_unlock(&semaphore_mutex); |
| if (status != 0) |
| { |
| errno=status; |
| ThrowFatalException(ResourceLimitFatalError,"UnableToUnlockSemaphore"); |
| } |
| } |
| #elif defined(MAGICKCORE_HAVE_WINTHREADS) |
| InterlockedExchange(&semaphore_mutex,0L); |
| #endif |
| } |
| |
| /* |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % % |
| % % |
| % % |
| % U n l o c k S e m a p h o r e I n f o % |
| % % |
| % % |
| % % |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| % |
| % UnlockSemaphoreInfo() unlocks a semaphore. |
| % |
| % The format of the UnlockSemaphoreInfo method is: |
| % |
| % void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info) |
| % |
| % A description of each parameter follows: |
| % |
| % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure. |
| % |
| */ |
| MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info) |
| { |
| assert(semaphore_info != (SemaphoreInfo *) NULL); |
| assert(semaphore_info->signature == MagickSignature); |
| #if defined(MAGICKCORE_DEBUG) |
| assert(IsMagickThreadEqual(semaphore_info->id) != MagickFalse); |
| if (semaphore_info->reference_count == 0) |
| { |
| (void) fprintf(stderr,"Warning: semaphore lock already unlocked!\n"); |
| (void) fflush(stderr); |
| return; |
| } |
| semaphore_info->reference_count--; |
| #endif |
| #if defined(MAGICKCORE_HAVE_PTHREAD) |
| { |
| int |
| status; |
| |
| status=pthread_mutex_unlock(&semaphore_info->mutex); |
| if (status != 0) |
| { |
| errno=status; |
| ThrowFatalException(ResourceLimitFatalError,"UnableToUnlockSemaphore"); |
| } |
| } |
| #elif defined(MAGICKCORE_HAVE_WINTHREADS) |
| LeaveCriticalSection(&semaphore_info->mutex); |
| #endif |
| } |