2 ****************************************************************************** 
   4 *   Copyright (C) 1997-2003, International Business Machines 
   5 *   Corporation and others.  All Rights Reserved. 
   7 ****************************************************************************** 
  11 * Modification History: 
  13 *   Date        Name        Description 
  14 *   04/02/97    aliu        Creation. 
  15 *   04/07/99    srl         updated 
  16 *   05/13/99    stephen     Changed to umutex (from cmutex). 
  17 *   11/22/99    aliu        Make non-global mutex autoinitialize [j151] 
  18 ****************************************************************************** 
  21 /* Assume POSIX, and modify as necessary below */ 
  27 #if defined(macintosh) 
  35 /* Check our settings... */ 
  36 #include "unicode/utypes.h" 
  40 #if defined(POSIX) && (ICU_USE_THREADS==1) 
  41   /* Usage: uncomment the following, and breakpoint WeAreDeadlocked to 
  42      find reentrant issues. */ 
  43 /* # define POSIX_DEBUG_REENTRANCY 1 */ 
  44 # include <pthread.h> /* must be first, so that we get the multithread versions of things. */ 
  46 # ifdef POSIX_DEBUG_REENTRANCY 
  47  pthread_t      gLastThread
; 
  50  U_EXPORT 
void WeAreDeadlocked(); 
  52  void WeAreDeadlocked() 
  54     puts("ARGH!! We're deadlocked.. break on WeAreDeadlocked() next time."); 
  56 # endif /* POSIX_DEBUG_REENTRANCY */ 
  57 #endif /* POSIX && (ICU_USE_THREADS==1) */ 
  60 # define WIN32_LEAN_AND_MEAN 
  72 #if (ICU_USE_THREADS == 1) 
  74 /* the global mutex. Use it proudly and wash it often. */ 
  75 static UMTX    gGlobalMutex 
= NULL
; 
  77 static int32_t gRecursionCount 
= 0;       /* Detect Recursive entries.  For debugging only. */ 
  81 static CRITICAL_SECTION gPlatformMutex
; 
  84 static pthread_mutex_t gPlatformMutex
;    /* The global ICU mutex   */ 
  85 static pthread_mutex_t gIncDecMutex
;      /* For use by atomic inc/dec, on Unixes only */     
  88 #endif /* ICU_USE_THREADS==1 */ 
  92 U_CAPI UBool U_EXPORT2
 
  93 umtx_isInitialized(UMTX 
*mutex
) 
  95 #if (ICU_USE_THREADS == 1) 
  98         return (UBool
)(gGlobalMutex 
!= NULL
); 
 102         isInited 
= (*mutex 
!= NULL
); 
 107     return TRUE
;    /* Since we don't use threads, it's considered initialized. */ 
 108 #endif /* ICU_USE_THREADS==1 */ 
 111 U_CAPI 
void  U_EXPORT2
 
 112 umtx_lock(UMTX 
*mutex
) 
 114 #if (ICU_USE_THREADS == 1) 
 117         mutex 
= &gGlobalMutex
; 
 122         /* Lazy init of a non-global mutexes on first lock is NOT safe on processors 
 123          *  that reorder memory operations.  */ 
 124         /* U_ASSERT(FALSE);    TODO:  Turn this back on */ 
 125         if (mutex 
!= &gGlobalMutex
) { 
 128             umtx_init(NULL
);  /* initialize the global mutex - only get  
 129                                  here if C++ static init is NOT working, 
 130                                  and u_init() hasn't been called. 
 132                                  Not thread-safe if this call is contended! */ 
 138     EnterCriticalSection((CRITICAL_SECTION
*) *mutex
); 
 140     if (mutex 
== &gGlobalMutex
) { 
 142         U_ASSERT(gRecursionCount 
== 1); 
 148 #  ifdef POSIX_DEBUG_REENTRANCY 
 149     if (gInMutex 
== TRUE 
&& mutex 
== &gGlobalMutex
) /* in the mutex -- possible deadlock*/ 
 150         if(pthread_equal(gLastThread
, pthread_self())) 
 153     pthread_mutex_lock((pthread_mutex_t
*) *mutex
); 
 155 #  ifdef POSIX_DEBUG_REENTRANCY 
 156     if (mutex 
== &gGlobalMutex
) { 
 157         gLastThread 
= pthread_self(); 
 162 #endif /* ICU_USE_THREADS==1 */ 
 165 U_CAPI 
void  U_EXPORT2
 
 166 umtx_unlock(UMTX
* mutex
) 
 168 #if (ICU_USE_THREADS==1) 
 171         mutex 
= &gGlobalMutex
; 
 176         return; /* jitterbug 135, fix for multiprocessor machines */ 
 181     if (mutex 
== &gGlobalMutex
) { 
 183         U_ASSERT(gRecursionCount 
== 0); 
 186     LeaveCriticalSection((CRITICAL_SECTION
*)*mutex
); 
 188 #elif defined (POSIX) 
 189     pthread_mutex_unlock((pthread_mutex_t
*)*mutex
); 
 191 #ifdef POSIX_DEBUG_REENTRANCY 
 192     if (mutex 
== &gGlobalMutex
) { 
 198 #endif /* ICU_USE_THREADS == 1 */ 
 204  *   umtx_raw_init    Do the platform specific mutex allocation and initialization 
 206 #if (ICU_USE_THREADS == 1) 
 207 static UMTX 
umtx_raw_init(void  *mem
) { 
 210             mem 
= uprv_malloc(sizeof(CRITICAL_SECTION
)); 
 211             if (mem 
== NULL
) {return NULL
;} 
 213         InitializeCriticalSection((CRITICAL_SECTION
*)mem
); 
 214     #elif defined( POSIX ) 
 216             mem 
= uprv_malloc(sizeof(pthread_mutex_t
)); 
 217             if (mem 
== NULL
) {return NULL
;} 
 219         # if defined (HPUX_CMA) 
 220             pthread_mutex_init((pthread_mutex_t
*)mem
, pthread_mutexattr_default
); 
 222             pthread_mutex_init((pthread_mutex_t
*)mem
, NULL
); 
 227 #endif  /* ICU_USE_THREADS */ 
 230 U_CAPI 
void  U_EXPORT2
 
 231 umtx_init(UMTX 
*mutex
) 
 233 #if (ICU_USE_THREADS == 1) 
 235     if (mutex 
== NULL
) /* initialize the global mutex */ 
 237         /* Note:  The initialization of the global mutex is NOT thread safe.   */ 
 238         if (gGlobalMutex 
!= NULL
) { 
 241         gGlobalMutex 
= umtx_raw_init(&gPlatformMutex
); 
 243        # ifdef POSIX_DEBUG_REENTRANCY 
 251        umtx_raw_init(&gIncDecMutex
); 
 255         /* Not the global mutex. 
 256          *  Thread safe initialization, using the global mutex. 
 262         isInitialized 
= (*mutex 
!= NULL
); 
 268         tMutex 
= umtx_raw_init(NULL
); 
 271         if (*mutex 
== NULL
) { 
 277         umtx_destroy(&tMutex
);  /* NOP if (tmutex == NULL)  */ 
 279 #endif /* ICU_USE_THREADS==1 */ 
 282 U_CAPI 
void  U_EXPORT2
 
 283 umtx_destroy(UMTX 
*mutex
) { 
 284 #if (ICU_USE_THREADS == 1) 
 285     if (mutex 
== NULL
) /* destroy the global mutex */ 
 287         mutex 
= &gGlobalMutex
; 
 290     if (*mutex 
== NULL
) /* someone already did it. */ 
 294     DeleteCriticalSection((CRITICAL_SECTION
*)*mutex
); 
 296 #elif defined (POSIX) 
 297     pthread_mutex_destroy((pthread_mutex_t
*)*mutex
); 
 301     if (*mutex 
!= gGlobalMutex
) 
 307 #endif /* ICU_USE_THREADS==1 */ 
 311 #if (ICU_USE_THREADS == 1)  
 321  * Win32 - use the Windows API functions for atomic increment and decrement. 
 323 U_CAPI 
int32_t U_EXPORT2
 
 324 umtx_atomic_inc(int32_t *p
) 
 326     return InterlockedIncrement(p
); 
 329 U_CAPI 
int32_t U_EXPORT2
 
 330 umtx_atomic_dec(int32_t *p
) 
 332     return InterlockedDecrement(p
);  
 335 #elif defined (POSIX) 
 337  * POSIX platforms without specific atomic operations.  Use a posix mutex 
 338  *   to protect the increment and decrement. 
 339  *   The IncDecMutex is in static storage so we don't have to come back and delete it 
 340  *   when the process exits. 
 343 U_CAPI 
int32_t U_EXPORT2
 
 344 umtx_atomic_inc(int32_t *p
) 
 348     pthread_mutex_lock(&gIncDecMutex
); 
 350     pthread_mutex_unlock(&gIncDecMutex
); 
 355 U_CAPI 
int32_t U_EXPORT2
 
 356 umtx_atomic_dec(int32_t *p
) 
 360     pthread_mutex_lock(&gIncDecMutex
); 
 362     pthread_mutex_unlock(&gIncDecMutex
); 
 369 /* No recognized platform.  */ 
 370 #error  No atomic increment and decrement defined for this platform. \ 
 371         Either use the --disable-threads configure option, or define those functions in this file. 
 373 #endif   /* Platform selection for atomic_inc and dec. */ 
 376 #else  /* (ICU_USE_THREADS == 0) */ 
 378 /* Threads disabled here */ 
 380 U_CAPI 
int32_t U_EXPORT2
 
 381 umtx_atomic_inc(int32_t *p
) { 
 385 U_CAPI 
int32_t U_EXPORT2
 
 386 umtx_atomic_dec(int32_t *p
) { 
 390 #endif /* (ICU_USE_THREADS == 1) */