U_CAPI void U_EXPORT2 umtx_lock(UMTX *mutex) { #if (ICU_USE_THREADS == 1) if (mutex == NULL) { mutex = &gGlobalMutex; } if (*mutex == NULL) { /* Lazy init of a non-global mutexes on first lock is NOT safe on processors * that reorder memory operations. */ /* U_ASSERT(FALSE); TODO: Turn this back on */ if (mutex != &gGlobalMutex) { umtx_init(mutex); } else { umtx_init(NULL); /* initialize the global mutex - only get here if C++ static init is NOT working, and u_init() hasn't been called. Not thread-safe if this call is contended! */ } } #if defined(WIN32) EnterCriticalSection((CRITICAL_SECTION*) *mutex); #ifdef _DEBUG if (mutex == &gGlobalMutex) { gRecursionCount++; U_ASSERT(gRecursionCount == 1); } #endif /*_DEBUG*/ #elif defined(POSIX) # ifdef POSIX_DEBUG_REENTRANCY if (gInMutex == TRUE && mutex == &gGlobalMutex) /* in the mutex -- possible deadlock*/ if(pthread_equal(gLastThread, pthread_self())) WeAreDeadlocked(); # endif pthread_mutex_lock((pthread_mutex_t*) *mutex); # ifdef POSIX_DEBUG_REENTRANCY if (mutex == &gGlobalMutex) { gLastThread = pthread_self(); gInMutex = TRUE; } # endif #endif #endif /* ICU_USE_THREADS==1 */ }
ICULocaleService::ICULocaleService(const UnicodeString& dname) : ICUService(dname) , fallbackLocale(Locale::getDefault()) , llock(0) { umtx_init(&llock); }
U_CAPI void U_EXPORT2 u_init(UErrorCode *status) { UTRACE_ENTRY_OC(UTRACE_U_INIT); /* Make sure the global mutexes are initialized. */ umtx_init(NULL); umtx_lock(&gICUInitMutex); if (gICUInitialized || U_FAILURE(*status)) { umtx_unlock(&gICUInitMutex); UTRACE_EXIT_STATUS(*status); return; } /* Do any required init for services that don't have open operations * and use "only" the double-check initialization method for performance * reasons (avoiding a mutex lock even for _checking_ whether the * initialization had occurred). */ /* Char Properties */ uprv_loadPropsData(status); #if !UCONFIG_NO_NORMALIZATION /* Normalization */ unorm_haveData(status); #endif gICUInitialized = TRUE; /* TODO: don't set if U_FAILURE? */ umtx_unlock(&gICUInitMutex); UTRACE_EXIT_STATUS(*status); }
/** * Inline function that returns TRUE if we have zone data, loading it * if necessary. The only time this function will return false is if * loadZoneData() fails, and UDATA_MEMORY and associated pointers are * NULL (rare). * * The difference between this function and loadZoneData() is that * this is an inline function that expands to code which avoids making * a function call in the case where the data is already loaded (the * common case). * * Must be called OUTSIDE mutex. */ static inline UBool haveZoneData() { umtx_init(&LOCK); /* This is here to prevent race conditions. */ umtx_lock(&LOCK); UBool f = (UDATA_MEMORY != 0); umtx_unlock(&LOCK); return f || loadZoneData(); }
U_CAPI void U_EXPORT2 umtx_lock(UMTX *mutex) { ICUMutex *m; if (mutex == NULL) { mutex = &globalUMTX; } m = (ICUMutex *)*mutex; if (m == NULL) { /* See note on lazy initialization, above. We can get away with it here, with mutexes, * where we couldn't with normal user level data. */ umtx_init(mutex); m = (ICUMutex *)*mutex; } U_ASSERT(m->owner == mutex); if (pMutexLockFn != NULL) { (*pMutexLockFn)(gMutexContext, &m->userMutex); } else { PLATFORM_MUTEX_LOCK(&m->platformMutex); } #if defined(U_DEBUG) m->recursionCount++; /* Recursion causes deadlock on Unixes. */ U_ASSERT(m->recursionCount == 1); /* Recursion detection works on Windows. */ /* Assertion failure on non-Windows indicates a */ /* problem with the mutex implementation itself. */ #endif }
/** * Register two targets as being inverses of one another. For * example, calling registerSpecialInverse("NFC", "NFD", TRUE) causes * Transliterator to form the following inverse relationships: * * <pre>NFC => NFD * Any-NFC => Any-NFD * NFD => NFC * Any-NFD => Any-NFC</pre> * * (Without the special inverse registration, the inverse of NFC * would be NFC-Any.) Note that NFD is shorthand for Any-NFD, but * that the presence or absence of "Any-" is preserved. * * <p>The relationship is symmetrical; registering (a, b) is * equivalent to registering (b, a). * * <p>The relevant IDs must still be registered separately as * factories or classes. * * <p>Only the targets are specified. Special inverses always * have the form Any-Target1 <=> Any-Target2. The target should * have canonical casing (the casing desired to be produced when * an inverse is formed) and should contain no whitespace or other * extraneous characters. * * @param target the target against which to register the inverse * @param inverseTarget the inverse of target, that is * Any-target.getInverse() => Any-inverseTarget * @param bidirectional if TRUE, register the reverse relation * as well, that is, Any-inverseTarget.getInverse() => Any-target */ void TransliteratorIDParser::registerSpecialInverse(const UnicodeString& target, const UnicodeString& inverseTarget, UBool bidirectional, UErrorCode &status) { init(status); if (U_FAILURE(status)) { return; } // If target == inverseTarget then force bidirectional => FALSE if (bidirectional && 0==target.caseCompare(inverseTarget, U_FOLD_CASE_DEFAULT)) { bidirectional = FALSE; } umtx_init(&LOCK); Mutex lock(&LOCK); UnicodeString *tempus = new UnicodeString(inverseTarget); // Used for null pointer check before usage. if (tempus == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return; } SPECIAL_INVERSES->put(target, tempus, status); if (bidirectional) { tempus = new UnicodeString(target); if (tempus == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return; } SPECIAL_INVERSES->put(inverseTarget, tempus, status); } }
U_NAMESPACE_BEGIN ICULocaleService::ICULocaleService() : fallbackLocale(Locale::getDefault()) , llock(0) { umtx_init(&llock); }
ICUService::ICUService(const UnicodeString& newName) : name(newName) , lock(0) , timestamp(0) , factories(NULL) , serviceCache(NULL) , idCache(NULL) , dnCache(NULL) { umtx_init(&lock); }
ICUService::ICUService() : name() , lock(0) , timestamp(0) , factories(NULL) , serviceCache(NULL) , idCache(NULL) , dnCache(NULL) { umtx_init(&lock); }
static const UChar* get(const char* id) { umtx_init(&gCRegLock); Mutex mutex(&gCRegLock); CReg* p = gCRegHead; while (p) { if (uprv_strcmp(id, p->id) == 0) { return p->iso; } p = p->next; } return NULL; }
const TimeZone* TimeZone::getGMT(void) { umtx_init(&LOCK); /* This is here to prevent race conditions. */ Mutex lock(&LOCK); // Initialize _GMT independently of other static data; it should // be valid even if we can't load the time zone UDataMemory. if (_GMT == 0) { _GMT = new SimpleTimeZone(0, UnicodeString(GMT_ID, GMT_ID_LENGTH)); } return _GMT; }
U_CAPI void U_EXPORT2 u_init(UErrorCode *status) { UTRACE_ENTRY_OC(UTRACE_U_INIT); /* Make sure the global mutexes are initialized. */ umtx_init(NULL); umtx_lock(&gICUInitMutex); if (gICUInitialized || U_FAILURE(*status)) { umtx_unlock(&gICUInitMutex); UTRACE_EXIT_STATUS(*status); return; } #if 1 /* * 2005-may-02 * * ICU4C 3.4 (jitterbug 4497) hardcodes the data for Unicode character * properties for APIs that want to be fast. * Therefore, we need not load them here nor check for errors. * Instead, we load the converter alias table to see if any ICU data * is available. * Users should really open the service objects they need and check * for errors there, to make sure that the actual items they need are * available. */ #if !UCONFIG_NO_CONVERSION ucnv_io_countKnownConverters(status); #endif #else /* Do any required init for services that don't have open operations * and use "only" the double-check initialization method for performance * reasons (avoiding a mutex lock even for _checking_ whether the * initialization had occurred). */ /* Char Properties */ uprv_haveProperties(status); /* load the case and bidi properties but don't fail if they are not available */ u_isULowercase(0x61); u_getIntPropertyValue(0x200D, UCHAR_JOINING_TYPE); /* ZERO WIDTH JOINER: Join_Causing */ #if !UCONFIG_NO_NORMALIZATION /* Normalization */ unorm_haveData(status); #endif #endif gICUInitialized = TRUE; /* TODO: don't set if U_FAILURE? */ umtx_unlock(&gICUInitMutex); UTRACE_EXIT_STATUS(*status); }
TimeZone* TimeZone::createDefault() { umtx_init(&LOCK); /* This is here to prevent race conditions. */ umtx_lock(&LOCK); UBool f = (DEFAULT_ZONE != 0); umtx_unlock(&LOCK); if (!f) { initDefault(); } Mutex lock(&LOCK); // In case adoptDefault is called return DEFAULT_ZONE->clone(); }
void TimeZone::adoptDefault(TimeZone* zone) { if (zone != NULL) { TimeZone* old = NULL; umtx_init(&LOCK); /* This is here to prevent race conditions. */ umtx_lock(&LOCK); old = DEFAULT_ZONE; DEFAULT_ZONE = zone; umtx_unlock(&LOCK); delete old; } }
/* * umtx_lock */ U_CAPI void U_EXPORT2 umtx_lock(UMTX *mutex) { if (mutex == NULL) { mutex = &gGlobalMutex; } if (*mutex == NULL) { /* Lock of an uninitialized mutex. Initialize it before proceeding. */ umtx_init(mutex); } if (pMutexLockFn != NULL) { (*pMutexLockFn)(gMutexContext, mutex); } else { #if (ICU_USE_THREADS == 1) #if defined(U_WINDOWS) EnterCriticalSection((CRITICAL_SECTION*) *mutex); #elif defined(POSIX) pthread_mutex_lock((pthread_mutex_t*) *mutex); #endif /* cascade of platforms */ #endif /* ICU_USE_THREADS==1 */ } #if defined(U_WINDOWS) && defined(U_DEBUG) && (ICU_USE_THREADS==1) if (mutex == &gGlobalMutex) { /* Detect Reentrant locking of the global mutex. */ gRecursionCount++; /* Recursion causes deadlocks on Unixes. */ U_ASSERT(gRecursionCount == 1); /* Detection works on Windows. Debug problems there. */ } /* This handles gGlobalMutex too, but only if there is no pMutexLockFn */ else if (pMutexLockFn == NULL) { /* see comments above */ size_t i = ((CRITICAL_SECTION*)*mutex) - &gMutexes[0]; U_ASSERT(i >= 0 && i < MAX_MUTEXES); ++gRecursionCountPool[i]; U_ASSERT(gRecursionCountPool[i] == 1); /* !Detect Deadlock! */ /* This works and is fast, but needs testing on Win98/NT/2K. See comments above. [alan] U_ASSERT((CRITICAL_SECTION*)*mutex >= &gMutexes[0] && (CRITICAL_SECTION*)*mutex <= &gMutexes[MAX_MUTEXES]); U_ASSERT(((CRITICAL_SECTION*)*mutex)->RecursionCount == 1); */ } #endif /*U_DEBUG*/ }
static UCurrRegistryKey reg(const UChar* _iso, const char* _id, UErrorCode* status) { if (status && U_SUCCESS(*status) && _iso && _id) { CReg* n = new CReg(_iso, _id); if (n) { umtx_init(&gCRegLock); Mutex mutex(&gCRegLock); if (!gCRegHead) { ucln_i18n_registerCleanup(); } n->next = gCRegHead; gCRegHead = n; return n; } *status = U_MEMORY_ALLOCATION_ERROR; } return 0; }
/** * Initialize static memory. */ void TransliteratorIDParser::init() { if (SPECIAL_INVERSES != NULL) { return; } Hashtable* special_inverses = new Hashtable(TRUE); special_inverses->setValueDeleter(uhash_deleteUnicodeString); umtx_init(&LOCK); umtx_lock(&LOCK); if (SPECIAL_INVERSES == NULL) { SPECIAL_INVERSES = special_inverses; special_inverses = NULL; } umtx_unlock(&LOCK); delete special_inverses; ucln_i18n_registerCleanup(); }
/** * Register two targets as being inverses of one another. For * example, calling registerSpecialInverse("NFC", "NFD", TRUE) causes * Transliterator to form the following inverse relationships: * * <pre>NFC => NFD * Any-NFC => Any-NFD * NFD => NFC * Any-NFD => Any-NFC</pre> * * (Without the special inverse registration, the inverse of NFC * would be NFC-Any.) Note that NFD is shorthand for Any-NFD, but * that the presence or absence of "Any-" is preserved. * * <p>The relationship is symmetrical; registering (a, b) is * equivalent to registering (b, a). * * <p>The relevant IDs must still be registered separately as * factories or classes. * * <p>Only the targets are specified. Special inverses always * have the form Any-Target1 <=> Any-Target2. The target should * have canonical casing (the casing desired to be produced when * an inverse is formed) and should contain no whitespace or other * extraneous characters. * * @param target the target against which to register the inverse * @param inverseTarget the inverse of target, that is * Any-target.getInverse() => Any-inverseTarget * @param bidirectional if TRUE, register the reverse relation * as well, that is, Any-inverseTarget.getInverse() => Any-target */ void TransliteratorIDParser::registerSpecialInverse(const UnicodeString& target, const UnicodeString& inverseTarget, UBool bidirectional) { init(); // If target == inverseTarget then force bidirectional => FALSE if (bidirectional && 0==target.caseCompare(inverseTarget, U_FOLD_CASE_DEFAULT)) { bidirectional = FALSE; } umtx_init(&LOCK); Mutex lock(&LOCK); UErrorCode ec = U_ZERO_ERROR; SPECIAL_INVERSES->put(target, new UnicodeString(inverseTarget), ec); if (bidirectional) { SPECIAL_INVERSES->put(inverseTarget, new UnicodeString(target), ec); } }
static UBool unreg(UCurrRegistryKey key) { umtx_init(&gCRegLock); Mutex mutex(&gCRegLock); if (gCRegHead == key) { gCRegHead = gCRegHead->next; delete (CReg*)key; return TRUE; } CReg* p = gCRegHead; while (p) { if (p->next == key) { p->next = ((CReg*)key)->next; delete (CReg*)key; return TRUE; } p = p->next; } return FALSE; }
U_CFUNC UBool umtx_cleanup(void) { ICUMutex *thisMutex = NULL; ICUMutex *nextMutex = NULL; /* Extra, do-nothing function call to suppress compiler warnings on platforms where * mutexed_compare_and_swap is not otherwise used. */ mutexed_compare_and_swap(&globalUMTX, NULL, NULL); /* Delete all of the ICU mutexes. Do the global mutex last because it is used during * the umtx_destroy operation of other mutexes. */ for (thisMutex=mutexListHead; thisMutex!=NULL; thisMutex=nextMutex) { UMTX *umtx = thisMutex->owner; nextMutex = thisMutex->next; U_ASSERT(*umtx = (void *)thisMutex); if (umtx != &globalUMTX) { umtx_destroy(umtx); } } umtx_destroy(&globalUMTX); pMutexInitFn = NULL; pMutexDestroyFn = NULL; pMutexLockFn = NULL; pMutexUnlockFn = NULL; gMutexContext = NULL; pIncFn = NULL; pDecFn = NULL; gIncDecContext = NULL; gIncDecMutex = NULL; #if defined (POSIX) /* POSIX platforms must come out of u_cleanup() with a functioning global mutex * to permit the safe resumption of use of ICU in multi-threaded environments. */ umtx_init(&globalUMTX); #endif return TRUE; }
/** * Given a Specs object, return a SingleID representing the * special inverse of that ID. If there is no special inverse * then return NULL. * @return a SingleID or NULL. Returned object always has * 'filter' field of NULL. */ TransliteratorIDParser::SingleID* TransliteratorIDParser::specsToSpecialInverse(const Specs& specs, UErrorCode &status) { if (0!=specs.source.caseCompare(ANY, U_FOLD_CASE_DEFAULT)) { return NULL; } init(status); UnicodeString* inverseTarget; umtx_init(&LOCK); umtx_lock(&LOCK); inverseTarget = (UnicodeString*) SPECIAL_INVERSES->get(specs.target); umtx_unlock(&LOCK); if (inverseTarget != NULL) { // If the original ID contained "Any-" then make the // special inverse "Any-Foo"; otherwise make it "Foo". // So "Any-NFC" => "Any-NFD" but "NFC" => "NFD". UnicodeString buf; if (specs.filter.length() != 0) { buf.append(specs.filter); } if (specs.sawSource) { buf.append(ANY).append(TARGET_SEP); } buf.append(*inverseTarget); UnicodeString basicID(ANY); basicID.append(TARGET_SEP).append(*inverseTarget); if (specs.variant.length() != 0) { buf.append(VARIANT_SEP).append(specs.variant); basicID.append(VARIANT_SEP).append(specs.variant); } return new SingleID(buf, basicID); } return NULL; }
U_CAPI void U_EXPORT2 u_setMutexFunctions(const void *context, UMtxInitFn *i, UMtxFn *d, UMtxFn *l, UMtxFn *u, UErrorCode *status) { if (U_FAILURE(*status)) { return; } /* Can not set a mutex function to a NULL value */ if (i==NULL || d==NULL || l==NULL || u==NULL) { *status = U_ILLEGAL_ARGUMENT_ERROR; return; } /* If ICU is not in an initial state, disallow this operation. */ if (cmemory_inUse()) { *status = U_INVALID_STATE_ERROR; return; } /* Kill any existing global mutex. POSIX platforms have a global mutex * even before any other part of ICU is initialized. */ umtx_destroy(&globalUMTX); /* Swap in the mutex function pointers. */ pMutexInitFn = i; pMutexDestroyFn = d; pMutexLockFn = l; pMutexUnlockFn = u; gMutexContext = context; #if defined (POSIX) /* POSIX platforms must have a pre-initialized global mutex * to allow other mutexes to initialize safely. */ umtx_init(&globalUMTX); #endif }
/** * Initialize static memory. */ void TransliteratorIDParser::init(UErrorCode &status) { if (SPECIAL_INVERSES != NULL) { return; } Hashtable* special_inverses = new Hashtable(TRUE, status); // Null pointer check if (special_inverses == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return; } special_inverses->setValueDeleter(uhash_deleteUnicodeString); umtx_init(&LOCK); umtx_lock(&LOCK); if (SPECIAL_INVERSES == NULL) { SPECIAL_INVERSES = special_inverses; special_inverses = NULL; } umtx_unlock(&LOCK); delete special_inverses; /*null instance*/ ucln_i18n_registerCleanup(UCLN_I18N_TRANSLITERATOR, utrans_transliterator_cleanup); }
ICUNotifier::ICUNotifier(void) : notifyLock(0), listeners(NULL) { umtx_init(¬ifyLock); }
U_CDECL_END static void usprep_init() { umtx_init(&usprepMutex); }
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) { struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0); umtx_init((struct umtx *) uli->lock_ptr); return uli; }
U_CFUNC void ucnv_init(UErrorCode *status) { umtx_init(&cnvCacheMutex); }