154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius/* 254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius****************************************************************************** 354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* 41b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert* Copyright (C) 1997-2015, International Business Machines 554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* Corporation and others. All Rights Reserved. 654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* 754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius****************************************************************************** 854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* 954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* File umutex.cpp 1054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* 1154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* Modification History: 1254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* 1354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* Date Name Description 1454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* 04/02/97 aliu Creation. 1554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* 04/07/99 srl updated 1654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* 05/13/99 stephen Changed to umutex (from cmutex). 1754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* 11/22/99 aliu Make non-global mutex autoinitialize [j151] 1854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius****************************************************************************** 1954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius*/ 2054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 2159d709d503bab6e2b61931737e662dd293b40578ccornelius#include "umutex.h" 2259d709d503bab6e2b61931737e662dd293b40578ccornelius 2354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "unicode/utypes.h" 2454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "uassert.h" 2559d709d503bab6e2b61931737e662dd293b40578ccornelius#include "cmemory.h" 2654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 2759d709d503bab6e2b61931737e662dd293b40578ccornelius 2859d709d503bab6e2b61931737e662dd293b40578ccornelius// The ICU global mutex. Used when ICU implementation code passes NULL for the mutex pointer. 2959d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic UMutex globalMutex = U_MUTEX_INITIALIZER; 3059d709d503bab6e2b61931737e662dd293b40578ccornelius 3154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius/* 3254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius * ICU Mutex wrappers. Wrap operating system mutexes, giving the rest of ICU a 3354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius * platform independent set of mutex operations. For internal ICU use only. 3454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius */ 3554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 3659d709d503bab6e2b61931737e662dd293b40578ccornelius#if defined(U_USER_MUTEX_CPP) 3759d709d503bab6e2b61931737e662dd293b40578ccornelius// Build time user mutex hook: #include "U_USER_MUTEX_CPP" 3859d709d503bab6e2b61931737e662dd293b40578ccornelius#include U_MUTEX_XSTR(U_USER_MUTEX_CPP) 3954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 4059d709d503bab6e2b61931737e662dd293b40578ccornelius#elif U_PLATFORM_HAS_WIN32_API 4154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 4259d709d503bab6e2b61931737e662dd293b40578ccornelius//------------------------------------------------------------------------------------------- 4359d709d503bab6e2b61931737e662dd293b40578ccornelius// 4459d709d503bab6e2b61931737e662dd293b40578ccornelius// Windows Specific Definitions 4559d709d503bab6e2b61931737e662dd293b40578ccornelius// 4659d709d503bab6e2b61931737e662dd293b40578ccornelius// Note: Cygwin (and possibly others) have both WIN32 and POSIX. 4759d709d503bab6e2b61931737e662dd293b40578ccornelius// Prefer Win32 in these cases. (Win32 comes ahead in the #if chain) 4859d709d503bab6e2b61931737e662dd293b40578ccornelius// 4959d709d503bab6e2b61931737e662dd293b40578ccornelius//------------------------------------------------------------------------------------------- 5054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 5159d709d503bab6e2b61931737e662dd293b40578ccornelius#if defined U_NO_PLATFORM_ATOMICS 5259d709d503bab6e2b61931737e662dd293b40578ccornelius#error ICU on Win32 requires support for low level atomic operations. 5359d709d503bab6e2b61931737e662dd293b40578ccornelius// Visual Studio, gcc, clang are OK. Shouldn't get here. 5454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#endif 5554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 5654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 5759d709d503bab6e2b61931737e662dd293b40578ccornelius// This function is called when a test of a UInitOnce::fState reveals that 5859d709d503bab6e2b61931737e662dd293b40578ccornelius// initialization has not completed, that we either need to call the 5959d709d503bab6e2b61931737e662dd293b40578ccornelius// function on this thread, or wait for some other thread to complete. 6054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius// 6159d709d503bab6e2b61931737e662dd293b40578ccornelius// The actual call to the init function is made inline by template code 6259d709d503bab6e2b61931737e662dd293b40578ccornelius// that knows the C++ types involved. This function returns TRUE if 6359d709d503bab6e2b61931737e662dd293b40578ccornelius// the caller needs to call the Init function. 6454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius// 6554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 6659d709d503bab6e2b61931737e662dd293b40578ccorneliusU_NAMESPACE_BEGIN 6754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 6859d709d503bab6e2b61931737e662dd293b40578ccorneliusU_COMMON_API UBool U_EXPORT2 umtx_initImplPreInit(UInitOnce &uio) { 6959d709d503bab6e2b61931737e662dd293b40578ccornelius for (;;) { 7059d709d503bab6e2b61931737e662dd293b40578ccornelius int32_t previousState = InterlockedCompareExchange( 71f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#if (U_PLATFORM == U_PF_MINGW) || (U_PLATFORM == U_PF_CYGWIN) || defined(__clang__) 7259d709d503bab6e2b61931737e662dd293b40578ccornelius (LONG volatile *) // this is the type given in the API doc for this function. 7359d709d503bab6e2b61931737e662dd293b40578ccornelius#endif 7459d709d503bab6e2b61931737e662dd293b40578ccornelius &uio.fState, // Destination 7559d709d503bab6e2b61931737e662dd293b40578ccornelius 1, // Exchange Value 7659d709d503bab6e2b61931737e662dd293b40578ccornelius 0); // Compare value 7759d709d503bab6e2b61931737e662dd293b40578ccornelius 7859d709d503bab6e2b61931737e662dd293b40578ccornelius if (previousState == 0) { 7959d709d503bab6e2b61931737e662dd293b40578ccornelius return true; // Caller will next call the init function. 8059d709d503bab6e2b61931737e662dd293b40578ccornelius // Current state == 1. 8159d709d503bab6e2b61931737e662dd293b40578ccornelius } else if (previousState == 2) { 8259d709d503bab6e2b61931737e662dd293b40578ccornelius // Another thread already completed the initialization. 8359d709d503bab6e2b61931737e662dd293b40578ccornelius // We can simply return FALSE, indicating no 8459d709d503bab6e2b61931737e662dd293b40578ccornelius // further action is needed by the caller. 8559d709d503bab6e2b61931737e662dd293b40578ccornelius return FALSE; 8659d709d503bab6e2b61931737e662dd293b40578ccornelius } else { 8759d709d503bab6e2b61931737e662dd293b40578ccornelius // Another thread is currently running the initialization. 8859d709d503bab6e2b61931737e662dd293b40578ccornelius // Wait until it completes. 8959d709d503bab6e2b61931737e662dd293b40578ccornelius do { 9059d709d503bab6e2b61931737e662dd293b40578ccornelius Sleep(1); 9159d709d503bab6e2b61931737e662dd293b40578ccornelius previousState = umtx_loadAcquire(uio.fState); 9259d709d503bab6e2b61931737e662dd293b40578ccornelius } while (previousState == 1); 9354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 9454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 9554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius} 9654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 9759d709d503bab6e2b61931737e662dd293b40578ccornelius// This function is called by the thread that ran an initialization function, 9859d709d503bab6e2b61931737e662dd293b40578ccornelius// just after completing the function. 9954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 10059d709d503bab6e2b61931737e662dd293b40578ccorneliusU_COMMON_API void U_EXPORT2 umtx_initImplPostInit(UInitOnce &uio) { 10159d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_storeRelease(uio.fState, 2); 10254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius} 10354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 10459d709d503bab6e2b61931737e662dd293b40578ccorneliusU_NAMESPACE_END 10554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 10659d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void winMutexInit(CRITICAL_SECTION *cs) { 10759d709d503bab6e2b61931737e662dd293b40578ccornelius InitializeCriticalSection(cs); 10859d709d503bab6e2b61931737e662dd293b40578ccornelius return; 10959d709d503bab6e2b61931737e662dd293b40578ccornelius} 11054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 11154dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusU_CAPI void U_EXPORT2 11254dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusumtx_lock(UMutex *mutex) { 11354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (mutex == NULL) { 11454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius mutex = &globalMutex; 11554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 11659d709d503bab6e2b61931737e662dd293b40578ccornelius CRITICAL_SECTION *cs = &mutex->fCS; 11759d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_initOnce(mutex->fInitOnce, winMutexInit, cs); 11859d709d503bab6e2b61931737e662dd293b40578ccornelius EnterCriticalSection(cs); 11954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius} 12054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 12154dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusU_CAPI void U_EXPORT2 12254dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusumtx_unlock(UMutex* mutex) 12354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius{ 12454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (mutex == NULL) { 12554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius mutex = &globalMutex; 12654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 12759d709d503bab6e2b61931737e662dd293b40578ccornelius LeaveCriticalSection(&mutex->fCS); 12854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius} 12954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 130f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 131f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CAPI void U_EXPORT2 132f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusumtx_condBroadcast(UConditionVar *condition) { 133f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius // We require that the associated mutex be held by the caller, 134f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius // so access to fWaitCount is protected and safe. No other thread can 135f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius // call condWait() while we are here. 136f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius if (condition->fWaitCount == 0) { 137f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius return; 138f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius } 139f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius ResetEvent(condition->fExitGate); 140f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius SetEvent(condition->fEntryGate); 141f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius} 142f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 143f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CAPI void U_EXPORT2 144f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusumtx_condSignal(UConditionVar *condition) { 145f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius // Function not implemented. There is no immediate requirement from ICU to have it. 146f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius // Once ICU drops support for Windows XP and Server 2003, ICU Condition Variables will be 147f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius // changed to be thin wrappers on native Windows CONDITION_VARIABLEs, and this function 148f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius // becomes trivial to provide. 149f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius U_ASSERT(FALSE); 150f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius} 151f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 152f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CAPI void U_EXPORT2 153f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusumtx_condWait(UConditionVar *condition, UMutex *mutex) { 154f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius if (condition->fEntryGate == NULL) { 155f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius // Note: because the associated mutex must be locked when calling 156f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius // wait, we know that there can not be multiple threads 157f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius // running here with the same condition variable. 158f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius // Meaning that lazy initialization is safe. 159f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius U_ASSERT(condition->fExitGate == NULL); 160f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius condition->fEntryGate = CreateEvent(NULL, // Security Attributes 161f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius TRUE, // Manual Reset 162f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius FALSE, // Initially reset 163f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius NULL); // Name. 164f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius U_ASSERT(condition->fEntryGate != NULL); 165f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius condition->fExitGate = CreateEvent(NULL, TRUE, TRUE, NULL); 166f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius U_ASSERT(condition->fExitGate != NULL); 167f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius } 168f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 169f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius condition->fWaitCount++; 170f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius umtx_unlock(mutex); 171f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius WaitForSingleObject(condition->fEntryGate, INFINITE); 172f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius umtx_lock(mutex); 173f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius condition->fWaitCount--; 174f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius if (condition->fWaitCount == 0) { 175f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius // All threads that were waiting at the entry gate have woken up 176f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius // and moved through. Shut the entry gate and open the exit gate. 177f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius ResetEvent(condition->fEntryGate); 178f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius SetEvent(condition->fExitGate); 179f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius } else { 180f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius umtx_unlock(mutex); 181f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius WaitForSingleObject(condition->fExitGate, INFINITE); 182f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius umtx_lock(mutex); 183f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius } 184f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius} 185f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 186f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 18759d709d503bab6e2b61931737e662dd293b40578ccornelius#elif U_PLATFORM_IMPLEMENTS_POSIX 18859d709d503bab6e2b61931737e662dd293b40578ccornelius 18959d709d503bab6e2b61931737e662dd293b40578ccornelius//------------------------------------------------------------------------------------------- 19054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius// 19159d709d503bab6e2b61931737e662dd293b40578ccornelius// POSIX specific definitions 19254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius// 19359d709d503bab6e2b61931737e662dd293b40578ccornelius//------------------------------------------------------------------------------------------- 19459d709d503bab6e2b61931737e662dd293b40578ccornelius 19559d709d503bab6e2b61931737e662dd293b40578ccornelius# include <pthread.h> 19659d709d503bab6e2b61931737e662dd293b40578ccornelius 19759d709d503bab6e2b61931737e662dd293b40578ccornelius// Each UMutex consists of a pthread_mutex_t. 19859d709d503bab6e2b61931737e662dd293b40578ccornelius// All are statically initialized and ready for use. 19959d709d503bab6e2b61931737e662dd293b40578ccornelius// There is no runtime mutex initialization code needed. 20054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 20154dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusU_CAPI void U_EXPORT2 20254dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusumtx_lock(UMutex *mutex) { 20354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (mutex == NULL) { 20454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius mutex = &globalMutex; 20554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 20659d709d503bab6e2b61931737e662dd293b40578ccornelius int sysErr = pthread_mutex_lock(&mutex->fMutex); 20759d709d503bab6e2b61931737e662dd293b40578ccornelius (void)sysErr; // Suppress unused variable warnings. 20859d709d503bab6e2b61931737e662dd293b40578ccornelius U_ASSERT(sysErr == 0); 20954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius} 21054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 21159d709d503bab6e2b61931737e662dd293b40578ccornelius 21254dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusU_CAPI void U_EXPORT2 21354dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusumtx_unlock(UMutex* mutex) 21454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius{ 21554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (mutex == NULL) { 21654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius mutex = &globalMutex; 21754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 21859d709d503bab6e2b61931737e662dd293b40578ccornelius int sysErr = pthread_mutex_unlock(&mutex->fMutex); 21959d709d503bab6e2b61931737e662dd293b40578ccornelius (void)sysErr; // Suppress unused variable warnings. 22059d709d503bab6e2b61931737e662dd293b40578ccornelius U_ASSERT(sysErr == 0); 22154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius} 22254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 223f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 224f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CAPI void U_EXPORT2 225f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusumtx_condWait(UConditionVar *cond, UMutex *mutex) { 226f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius if (mutex == NULL) { 227f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius mutex = &globalMutex; 228f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius } 229f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius int sysErr = pthread_cond_wait(&cond->fCondition, &mutex->fMutex); 230f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius (void)sysErr; 231f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius U_ASSERT(sysErr == 0); 232f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius} 233f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 234f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CAPI void U_EXPORT2 235f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusumtx_condBroadcast(UConditionVar *cond) { 236f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius int sysErr = pthread_cond_broadcast(&cond->fCondition); 237f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius (void)sysErr; 238f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius U_ASSERT(sysErr == 0); 239f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius} 240f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 241f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CAPI void U_EXPORT2 242f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusumtx_condSignal(UConditionVar *cond) { 243f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius int sysErr = pthread_cond_signal(&cond->fCondition); 244f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius (void)sysErr; 245f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius U_ASSERT(sysErr == 0); 246f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius} 247f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 248f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 249f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 25059d709d503bab6e2b61931737e662dd293b40578ccorneliusU_NAMESPACE_BEGIN 25154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 25259d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic pthread_mutex_t initMutex = PTHREAD_MUTEX_INITIALIZER; 25359d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic pthread_cond_t initCondition = PTHREAD_COND_INITIALIZER; 25454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 25554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 25659d709d503bab6e2b61931737e662dd293b40578ccornelius// This function is called when a test of a UInitOnce::fState reveals that 25759d709d503bab6e2b61931737e662dd293b40578ccornelius// initialization has not completed, that we either need to call the 25859d709d503bab6e2b61931737e662dd293b40578ccornelius// function on this thread, or wait for some other thread to complete. 25959d709d503bab6e2b61931737e662dd293b40578ccornelius// 26059d709d503bab6e2b61931737e662dd293b40578ccornelius// The actual call to the init function is made inline by template code 26159d709d503bab6e2b61931737e662dd293b40578ccornelius// that knows the C++ types involved. This function returns TRUE if 26259d709d503bab6e2b61931737e662dd293b40578ccornelius// the caller needs to call the Init function. 26359d709d503bab6e2b61931737e662dd293b40578ccornelius// 26459d709d503bab6e2b61931737e662dd293b40578ccorneliusU_COMMON_API UBool U_EXPORT2 26559d709d503bab6e2b61931737e662dd293b40578ccorneliusumtx_initImplPreInit(UInitOnce &uio) { 26659d709d503bab6e2b61931737e662dd293b40578ccornelius pthread_mutex_lock(&initMutex); 26759d709d503bab6e2b61931737e662dd293b40578ccornelius int32_t state = uio.fState; 26859d709d503bab6e2b61931737e662dd293b40578ccornelius if (state == 0) { 26959d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_storeRelease(uio.fState, 1); 27059d709d503bab6e2b61931737e662dd293b40578ccornelius pthread_mutex_unlock(&initMutex); 27159d709d503bab6e2b61931737e662dd293b40578ccornelius return TRUE; // Caller will next call the init function. 27259d709d503bab6e2b61931737e662dd293b40578ccornelius } else { 27359d709d503bab6e2b61931737e662dd293b40578ccornelius while (uio.fState == 1) { 27459d709d503bab6e2b61931737e662dd293b40578ccornelius // Another thread is currently running the initialization. 27559d709d503bab6e2b61931737e662dd293b40578ccornelius // Wait until it completes. 27659d709d503bab6e2b61931737e662dd293b40578ccornelius pthread_cond_wait(&initCondition, &initMutex); 27759d709d503bab6e2b61931737e662dd293b40578ccornelius } 27859d709d503bab6e2b61931737e662dd293b40578ccornelius pthread_mutex_unlock(&initMutex); 27959d709d503bab6e2b61931737e662dd293b40578ccornelius U_ASSERT(uio.fState == 2); 28059d709d503bab6e2b61931737e662dd293b40578ccornelius return FALSE; 28154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 28259d709d503bab6e2b61931737e662dd293b40578ccornelius} 28354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 28454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 28559d709d503bab6e2b61931737e662dd293b40578ccornelius 28659d709d503bab6e2b61931737e662dd293b40578ccornelius// This function is called by the thread that ran an initialization function, 28759d709d503bab6e2b61931737e662dd293b40578ccornelius// just after completing the function. 28859d709d503bab6e2b61931737e662dd293b40578ccornelius// Some threads may be waiting on the condition, requiring the broadcast wakeup. 28959d709d503bab6e2b61931737e662dd293b40578ccornelius// Some threads may be racing to test the fState variable outside of the mutex, 29059d709d503bab6e2b61931737e662dd293b40578ccornelius// requiring the use of store/release when changing its value. 29159d709d503bab6e2b61931737e662dd293b40578ccornelius 29259d709d503bab6e2b61931737e662dd293b40578ccorneliusU_COMMON_API void U_EXPORT2 29359d709d503bab6e2b61931737e662dd293b40578ccorneliusumtx_initImplPostInit(UInitOnce &uio) { 29459d709d503bab6e2b61931737e662dd293b40578ccornelius pthread_mutex_lock(&initMutex); 29559d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_storeRelease(uio.fState, 2); 29659d709d503bab6e2b61931737e662dd293b40578ccornelius pthread_cond_broadcast(&initCondition); 29759d709d503bab6e2b61931737e662dd293b40578ccornelius pthread_mutex_unlock(&initMutex); 29854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius} 29954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 30059d709d503bab6e2b61931737e662dd293b40578ccorneliusU_NAMESPACE_END 30154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 30259d709d503bab6e2b61931737e662dd293b40578ccornelius// End of POSIX specific umutex implementation. 30354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 30459d709d503bab6e2b61931737e662dd293b40578ccornelius#else // Platform #define chain. 30554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 30659d709d503bab6e2b61931737e662dd293b40578ccornelius#error Unknown Platform 30754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 30859d709d503bab6e2b61931737e662dd293b40578ccornelius#endif // Platform #define chain. 30954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 31054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 31159d709d503bab6e2b61931737e662dd293b40578ccornelius//------------------------------------------------------------------------------- 31259d709d503bab6e2b61931737e662dd293b40578ccornelius// 31359d709d503bab6e2b61931737e662dd293b40578ccornelius// Atomic Operations, out-of-line versions. 31459d709d503bab6e2b61931737e662dd293b40578ccornelius// These are conditional, only defined if better versions 31559d709d503bab6e2b61931737e662dd293b40578ccornelius// were not available for the platform. 31659d709d503bab6e2b61931737e662dd293b40578ccornelius// 31759d709d503bab6e2b61931737e662dd293b40578ccornelius// These versions are platform neutral. 31859d709d503bab6e2b61931737e662dd293b40578ccornelius// 31959d709d503bab6e2b61931737e662dd293b40578ccornelius//-------------------------------------------------------------------------------- 32054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 32159d709d503bab6e2b61931737e662dd293b40578ccornelius#if defined U_NO_PLATFORM_ATOMICS 32254dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UMutex gIncDecMutex = U_MUTEX_INITIALIZER; 32354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 32459d709d503bab6e2b61931737e662dd293b40578ccorneliusU_NAMESPACE_BEGIN 32559d709d503bab6e2b61931737e662dd293b40578ccornelius 32659d709d503bab6e2b61931737e662dd293b40578ccorneliusU_COMMON_API int32_t U_EXPORT2 32759d709d503bab6e2b61931737e662dd293b40578ccorneliusumtx_atomic_inc(u_atomic_int32_t *p) { 32854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int32_t retVal; 32959d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_lock(&gIncDecMutex); 33059d709d503bab6e2b61931737e662dd293b40578ccornelius retVal = ++(*p); 33159d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_unlock(&gIncDecMutex); 33254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius return retVal; 33354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius} 33454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 33559d709d503bab6e2b61931737e662dd293b40578ccornelius 33659d709d503bab6e2b61931737e662dd293b40578ccorneliusU_COMMON_API int32_t U_EXPORT2 33759d709d503bab6e2b61931737e662dd293b40578ccorneliusumtx_atomic_dec(u_atomic_int32_t *p) { 33854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int32_t retVal; 33959d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_lock(&gIncDecMutex); 34059d709d503bab6e2b61931737e662dd293b40578ccornelius retVal = --(*p); 34159d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_unlock(&gIncDecMutex); 34254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius return retVal; 34354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius} 34454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 34559d709d503bab6e2b61931737e662dd293b40578ccorneliusU_COMMON_API int32_t U_EXPORT2 34659d709d503bab6e2b61931737e662dd293b40578ccorneliusumtx_loadAcquire(u_atomic_int32_t &var) { 34759d709d503bab6e2b61931737e662dd293b40578ccornelius int32_t val = var; 34859d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_lock(&gIncDecMutex); 34959d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_unlock(&gIncDecMutex); 35059d709d503bab6e2b61931737e662dd293b40578ccornelius return val; 35159d709d503bab6e2b61931737e662dd293b40578ccornelius} 35259d709d503bab6e2b61931737e662dd293b40578ccornelius 35359d709d503bab6e2b61931737e662dd293b40578ccorneliusU_COMMON_API void U_EXPORT2 35459d709d503bab6e2b61931737e662dd293b40578ccorneliusumtx_storeRelease(u_atomic_int32_t &var, int32_t val) { 35559d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_lock(&gIncDecMutex); 35659d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_unlock(&gIncDecMutex); 35759d709d503bab6e2b61931737e662dd293b40578ccornelius var = val; 35859d709d503bab6e2b61931737e662dd293b40578ccornelius} 35954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 36059d709d503bab6e2b61931737e662dd293b40578ccorneliusU_NAMESPACE_END 36159d709d503bab6e2b61931737e662dd293b40578ccornelius#endif 36254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 36359d709d503bab6e2b61931737e662dd293b40578ccornelius//-------------------------------------------------------------------------- 36459d709d503bab6e2b61931737e662dd293b40578ccornelius// 36559d709d503bab6e2b61931737e662dd293b40578ccornelius// Deprecated functions for setting user mutexes. 36659d709d503bab6e2b61931737e662dd293b40578ccornelius// 36759d709d503bab6e2b61931737e662dd293b40578ccornelius//-------------------------------------------------------------------------- 36854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 36959d709d503bab6e2b61931737e662dd293b40578ccorneliusU_DEPRECATED void U_EXPORT2 37059d709d503bab6e2b61931737e662dd293b40578ccorneliusu_setMutexFunctions(const void * /*context */, UMtxInitFn *, UMtxFn *, 37159d709d503bab6e2b61931737e662dd293b40578ccornelius UMtxFn *, UMtxFn *, UErrorCode *status) { 37259d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_SUCCESS(*status)) { 37359d709d503bab6e2b61931737e662dd293b40578ccornelius *status = U_UNSUPPORTED_ERROR; 37454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 37559d709d503bab6e2b61931737e662dd293b40578ccornelius return; 37654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius} 37754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 37854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 37959d709d503bab6e2b61931737e662dd293b40578ccornelius 38059d709d503bab6e2b61931737e662dd293b40578ccorneliusU_DEPRECATED void U_EXPORT2 38159d709d503bab6e2b61931737e662dd293b40578ccorneliusu_setAtomicIncDecFunctions(const void * /*context */, UMtxAtomicFn *, UMtxAtomicFn *, 38259d709d503bab6e2b61931737e662dd293b40578ccornelius UErrorCode *status) { 38359d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_SUCCESS(*status)) { 38459d709d503bab6e2b61931737e662dd293b40578ccornelius *status = U_UNSUPPORTED_ERROR; 38559d709d503bab6e2b61931737e662dd293b40578ccornelius } 38659d709d503bab6e2b61931737e662dd293b40578ccornelius return; 38754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius} 388