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-2019 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://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 /* 43 Include declarations. 44 */ 45 #include "MagickCore/studio.h" 46 #include "MagickCore/exception.h" 47 #include "MagickCore/exception-private.h" 48 #include "MagickCore/memory_.h" 49 #include "MagickCore/memory-private.h" 50 #include "MagickCore/semaphore.h" 51 #include "MagickCore/semaphore-private.h" 52 #include "MagickCore/string_.h" 53 #include "MagickCore/thread_.h" 54 #include "MagickCore/thread-private.h" 55 #include "MagickCore/utility-private.h" 56 57 /* 59 Struct declaractions. 60 */ 61 struct SemaphoreInfo 62 { 63 MagickMutexType 64 mutex; 65 66 MagickThreadType 67 id; 68 69 ssize_t 70 reference_count; 71 72 size_t 73 signature; 74 }; 75 76 /* 78 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 79 % % 80 % % 81 % % 82 % A c t i v a t e S e m a p h o r e I n f o % 83 % % 84 % % 85 % % 86 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 87 % 88 % ActivateSemaphoreInfo() activates a semaphore under protection of a mutex 89 % to ensure only one thread allocates the semaphore. 90 % 91 % The format of the ActivateSemaphoreInfo method is: 92 % 93 % void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info) 94 % 95 % A description of each parameter follows: 96 % 97 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure. 98 % 99 */ 100 MagickExport void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info) 101 { 102 assert(semaphore_info != (SemaphoreInfo **) NULL); 103 if (*semaphore_info == (SemaphoreInfo *) NULL) 104 { 105 InitializeMagickMutex(); 106 LockMagickMutex(); 107 if (*semaphore_info == (SemaphoreInfo *) NULL) 108 *semaphore_info=AcquireSemaphoreInfo(); 109 UnlockMagickMutex(); 110 } 111 } 112 113 /* 115 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 116 % % 117 % % 118 % % 119 % A c q u i r e S e m a p h o r e I n f o % 120 % % 121 % % 122 % % 123 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 124 % 125 % AcquireSemaphoreInfo() initializes the SemaphoreInfo structure. 126 % 127 % The format of the AcquireSemaphoreInfo method is: 128 % 129 % SemaphoreInfo *AcquireSemaphoreInfo(void) 130 % 131 */ 132 133 static void *AcquireSemaphoreMemory(const size_t count,const size_t quantum) 134 { 135 #define AlignedExtent(size,alignment) \ 136 (((size)+((alignment)-1)) & ~((alignment)-1)) 137 138 size_t 139 alignment, 140 extent, 141 size; 142 143 void 144 *memory; 145 146 size=count*quantum; 147 if ((count == 0) || (quantum != (size/count))) 148 { 149 errno=ENOMEM; 150 return((void *) NULL); 151 } 152 memory=NULL; 153 alignment=CACHE_LINE_SIZE; 154 extent=AlignedExtent(size,CACHE_LINE_SIZE); 155 if ((size == 0) || (alignment < sizeof(void *)) || (extent < size)) 156 return((void *) NULL); 157 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN) 158 if (posix_memalign(&memory,alignment,extent) != 0) 159 memory=NULL; 160 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC) 161 memory=_aligned_malloc(extent,alignment); 162 #else 163 { 164 void 165 *p; 166 167 extent=(size+alignment-1)+sizeof(void *); 168 if (extent > size) 169 { 170 p=malloc(extent); 171 if (p != NULL) 172 { 173 memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment); 174 *((void **) memory-1)=p; 175 } 176 } 177 } 178 #endif 179 return(memory); 180 } 181 182 static void *RelinquishSemaphoreMemory(void *memory) 183 { 184 if (memory == (void *) NULL) 185 return((void *) NULL); 186 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN) 187 free(memory); 188 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC) 189 _aligned_free(memory); 190 #else 191 free(*((void **) memory-1)); 192 #endif 193 return(NULL); 194 } 195 196 MagickExport SemaphoreInfo *AcquireSemaphoreInfo(void) 197 { 198 SemaphoreInfo 199 *semaphore_info; 200 201 /* 202 Acquire semaphore. 203 */ 204 semaphore_info=(SemaphoreInfo *) AcquireSemaphoreMemory(1, 205 sizeof(*semaphore_info)); 206 if (semaphore_info == (SemaphoreInfo *) NULL) 207 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 208 (void) memset(semaphore_info,0,sizeof(SemaphoreInfo)); 209 /* 210 Initialize the semaphore. 211 */ 212 #if defined(MAGICKCORE_OPENMP_SUPPORT) 213 omp_init_lock((omp_lock_t *) &semaphore_info->mutex); 214 #elif defined(MAGICKCORE_THREAD_SUPPORT) 215 { 216 int 217 status; 218 219 pthread_mutexattr_t 220 mutex_info; 221 222 status=pthread_mutexattr_init(&mutex_info); 223 if (status != 0) 224 { 225 errno=status; 226 perror("unable to initialize mutex attributes"); 227 _exit(1); 228 } 229 #if defined(MAGICKCORE_DEBUG) 230 #if defined(PTHREAD_MUTEX_ERRORCHECK) 231 status=pthread_mutex_settype(&mutex_info,PTHREAD_MUTEX_ERRORCHECK); 232 if (status != 0) 233 { 234 errno=status; 235 perror("unable to set mutex type"); 236 _exit(1); 237 } 238 #endif 239 #endif 240 status=pthread_mutex_init(&semaphore_info->mutex,&mutex_info); 241 if (status != 0) 242 { 243 errno=status; 244 perror("unable to initialize mutex"); 245 _exit(1); 246 } 247 status=pthread_mutexattr_destroy(&mutex_info); 248 if (status != 0) 249 { 250 errno=status; 251 perror("unable to destroy mutex attributes"); 252 _exit(1); 253 } 254 } 255 #elif defined(MAGICKCORE_WINDOWS_SUPPORT) 256 { 257 int 258 status; 259 260 status=InitializeCriticalSectionAndSpinCount(&semaphore_info->mutex,0x0400); 261 if (status == 0) 262 { 263 errno=status; 264 perror("unable to initialize critical section"); 265 _exit(1); 266 } 267 } 268 #endif 269 semaphore_info->id=GetMagickThreadId(); 270 semaphore_info->reference_count=0; 271 semaphore_info->signature=MagickCoreSignature; 272 return(semaphore_info); 273 } 274 275 /* 277 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 278 % % 279 % % 280 % % 281 % L o c k S e m a p h o r e I n f o % 282 % % 283 % % 284 % % 285 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 286 % 287 % LockSemaphoreInfo() locks a semaphore. 288 % 289 % The format of the LockSemaphoreInfo method is: 290 % 291 % void LockSemaphoreInfo(SemaphoreInfo *semaphore_info) 292 % 293 % A description of each parameter follows: 294 % 295 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure. 296 % 297 */ 298 MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info) 299 { 300 assert(semaphore_info != (SemaphoreInfo *) NULL); 301 assert(semaphore_info->signature == MagickCoreSignature); 302 #if defined(MAGICKCORE_DEBUG) 303 if ((semaphore_info->reference_count > 0) && 304 (IsMagickThreadEqual(semaphore_info->id) != MagickFalse)) 305 { 306 (void) FormatLocaleFile(stderr,"Warning: unexpected recursive lock!\n"); 307 (void) fflush(stderr); 308 } 309 #endif 310 #if defined(MAGICKCORE_OPENMP_SUPPORT) 311 omp_set_lock((omp_lock_t *) &semaphore_info->mutex); 312 #elif defined(MAGICKCORE_THREAD_SUPPORT) 313 { 314 int 315 status; 316 317 status=pthread_mutex_lock(&semaphore_info->mutex); 318 if (status != 0) 319 { 320 errno=status; 321 perror("unable to lock mutex"); 322 _exit(1); 323 } 324 } 325 #elif defined(MAGICKCORE_WINDOWS_SUPPORT) 326 EnterCriticalSection(&semaphore_info->mutex); 327 #endif 328 #if defined(MAGICKCORE_DEBUG) 329 semaphore_info->id=GetMagickThreadId(); 330 semaphore_info->reference_count++; 331 #endif 332 } 333 334 /* 336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 337 % % 338 % % 339 % % 340 % R e l i n q u i s h S e m a p h o r e I n f o % 341 % % 342 % % 343 % % 344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 345 % 346 % RelinquishSemaphoreInfo() destroys a semaphore. 347 % 348 % The format of the RelinquishSemaphoreInfo method is: 349 % 350 % void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info) 351 % 352 % A description of each parameter follows: 353 % 354 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure. 355 % 356 */ 357 MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info) 358 { 359 assert(semaphore_info != (SemaphoreInfo **) NULL); 360 assert((*semaphore_info) != (SemaphoreInfo *) NULL); 361 assert((*semaphore_info)->signature == MagickCoreSignature); 362 InitializeMagickMutex(); 363 LockMagickMutex(); 364 #if defined(MAGICKCORE_OPENMP_SUPPORT) 365 omp_destroy_lock((omp_lock_t *) &(*semaphore_info)->mutex); 366 #elif defined(MAGICKCORE_THREAD_SUPPORT) 367 { 368 int 369 status; 370 371 status=pthread_mutex_destroy(&(*semaphore_info)->mutex); 372 if (status != 0) 373 { 374 errno=status; 375 perror("unable to destroy mutex"); 376 _exit(1); 377 } 378 } 379 #elif defined(MAGICKCORE_WINDOWS_SUPPORT) 380 DeleteCriticalSection(&(*semaphore_info)->mutex); 381 #endif 382 (*semaphore_info)->signature=(~MagickCoreSignature); 383 *semaphore_info=(SemaphoreInfo *) RelinquishSemaphoreMemory(*semaphore_info); 384 UnlockMagickMutex(); 385 } 386 387 /* 389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 390 % % 391 % % 392 % % 393 % 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 % 394 % % 395 % % 396 % % 397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 398 % 399 % SemaphoreComponentGenesis() instantiates the semaphore environment. 400 % 401 % The format of the SemaphoreComponentGenesis method is: 402 % 403 % MagickBooleanType SemaphoreComponentGenesis(void) 404 % 405 */ 406 MagickPrivate MagickBooleanType SemaphoreComponentGenesis(void) 407 { 408 InitializeMagickMutex(); 409 return(MagickTrue); 410 } 411 412 /* 414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 415 % % 416 % % 417 % % 418 % 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 % 419 % % 420 % % 421 % % 422 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 423 % 424 % SemaphoreComponentTerminus() destroys the semaphore component. 425 % 426 % The format of the SemaphoreComponentTerminus method is: 427 % 428 % SemaphoreComponentTerminus(void) 429 % 430 */ 431 MagickPrivate void SemaphoreComponentTerminus(void) 432 { 433 DestroyMagickMutex(); 434 } 435 436 /* 438 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 439 % % 440 % % 441 % % 442 % U n l o c k S e m a p h o r e I n f o % 443 % % 444 % % 445 % % 446 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 447 % 448 % UnlockSemaphoreInfo() unlocks a semaphore. 449 % 450 % The format of the UnlockSemaphoreInfo method is: 451 % 452 % void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info) 453 % 454 % A description of each parameter follows: 455 % 456 % o semaphore_info: Specifies a pointer to an SemaphoreInfo structure. 457 % 458 */ 459 MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info) 460 { 461 assert(semaphore_info != (SemaphoreInfo *) NULL); 462 assert(semaphore_info->signature == MagickCoreSignature); 463 #if defined(MAGICKCORE_DEBUG) 464 assert(IsMagickThreadEqual(semaphore_info->id) != MagickFalse); 465 if (semaphore_info->reference_count == 0) 466 { 467 (void) FormatLocaleFile(stderr, 468 "Warning: semaphore lock already unlocked!\n"); 469 (void) fflush(stderr); 470 return; 471 } 472 semaphore_info->reference_count--; 473 #endif 474 #if defined(MAGICKCORE_OPENMP_SUPPORT) 475 omp_unset_lock((omp_lock_t *) &semaphore_info->mutex); 476 #elif defined(MAGICKCORE_THREAD_SUPPORT) 477 { 478 int 479 status; 480 481 status=pthread_mutex_unlock(&semaphore_info->mutex); 482 if (status != 0) 483 { 484 errno=status; 485 perror("unable to unlock mutex"); 486 _exit(1); 487 } 488 } 489 #elif defined(MAGICKCORE_WINDOWS_SUPPORT) 490 LeaveCriticalSection(&semaphore_info->mutex); 491 #endif 492 } 493