Index: patches/dataload.patch |
diff --git a/patches/dataload.patch b/patches/dataload.patch |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f246f157938ed37dd8381f3b7df346e52a977e55 |
--- /dev/null |
+++ b/patches/dataload.patch |
@@ -0,0 +1,152 @@ |
+diff --git a/source/common/udata.cpp b/source/common/udata.cpp |
+index e6d8a35..80bea06 100644 |
+--- a/source/common/udata.cpp |
++++ b/source/common/udata.cpp |
+@@ -1,7 +1,7 @@ |
+ /* |
+ ****************************************************************************** |
+ * |
+-* Copyright (C) 1999-2014, International Business Machines |
++* Copyright (C) 1999-2015, International Business Machines |
+ * Corporation and others. All Rights Reserved. |
+ * |
+ ****************************************************************************** |
+@@ -29,6 +29,7 @@ might have to #include some other header |
+ #include "charstr.h" |
+ #include "cmemory.h" |
+ #include "cstring.h" |
++#include "mutex.h" |
+ #include "putilimp.h" |
+ #include "uassert.h" |
+ #include "ucln_cmn.h" |
+@@ -100,14 +101,15 @@ static UDataMemory *udata_findCachedData(const char *path); |
+ * that they really need, reducing the size of binaries that take advantage |
+ * of this. |
+ */ |
+-static UDataMemory *gCommonICUDataArray[10] = { NULL }; |
++static UDataMemory *gCommonICUDataArray[10] = { NULL }; // Access protected by icu global mutex. |
+ |
+-static UBool gHaveTriedToLoadCommonData = FALSE; /* See extendICUData(). */ |
++static u_atomic_int32_t gHaveTriedToLoadCommonData = ATOMIC_INT32_T_INITIALIZER(0); // See extendICUData(). |
+ |
+ static UHashtable *gCommonDataCache = NULL; /* Global hash table of opened ICU data files. */ |
+ static icu::UInitOnce gCommonDataCacheInitOnce = U_INITONCE_INITIALIZER; |
+ |
+-static UDataFileAccess gDataFileAccess = UDATA_DEFAULT_ACCESS; |
++static UDataFileAccess gDataFileAccess = UDATA_DEFAULT_ACCESS; // Access not synchronized. |
++ // Modifying is documented as thread-unsafe. |
+ |
+ static UBool U_CALLCONV |
+ udata_cleanup(void) |
+@@ -124,7 +126,7 @@ udata_cleanup(void) |
+ udata_close(gCommonICUDataArray[i]); |
+ gCommonICUDataArray[i] = NULL; |
+ } |
+- gHaveTriedToLoadCommonData = FALSE; |
++ gHaveTriedToLoadCommonData = 0; |
+ |
+ return TRUE; /* Everything was cleaned up */ |
+ } |
+@@ -139,14 +141,16 @@ findCommonICUDataByName(const char *inBasename) |
+ if (pData == NULL) |
+ return FALSE; |
+ |
+- for (i = 0; i < UPRV_LENGTHOF(gCommonICUDataArray); ++i) { |
+- if ((gCommonICUDataArray[i] != NULL) && (gCommonICUDataArray[i]->pHeader == pData->pHeader)) { |
+- /* The data pointer is already in the array. */ |
+- found = TRUE; |
+- break; |
++ { |
++ Mutex lock; |
++ for (i = 0; i < UPRV_LENGTHOF(gCommonICUDataArray); ++i) { |
++ if ((gCommonICUDataArray[i] != NULL) && (gCommonICUDataArray[i]->pHeader == pData->pHeader)) { |
++ /* The data pointer is already in the array. */ |
++ found = TRUE; |
++ break; |
++ } |
+ } |
+ } |
+- |
+ return found; |
+ } |
+ |
+@@ -663,7 +667,11 @@ openCommonData(const char *path, /* Path from OpenChoice? */ |
+ if(commonDataIndex >= UPRV_LENGTHOF(gCommonICUDataArray)) { |
+ return NULL; |
+ } |
+- if(gCommonICUDataArray[commonDataIndex] == NULL) { |
++ { |
++ Mutex lock; |
++ if(gCommonICUDataArray[commonDataIndex] != NULL) { |
++ return gCommonICUDataArray[commonDataIndex]; |
++ } |
+ int32_t i; |
+ for(i = 0; i < commonDataIndex; ++i) { |
+ if(gCommonICUDataArray[i]->pHeader == &U_ICUDATA_ENTRY_POINT.hdr) { |
+@@ -671,23 +679,26 @@ openCommonData(const char *path, /* Path from OpenChoice? */ |
+ return NULL; |
+ } |
+ } |
++ } |
+ |
+- /* Add the linked-in data to the list. */ |
+- /* |
+- * This is where we would check and call weakly linked partial-data-library |
+- * access functions. |
+- */ |
+- /* |
+- if (uprv_getICUData_collation) { |
+- setCommonICUDataPointer(uprv_getICUData_collation(), FALSE, pErrorCode); |
+- } |
+- if (uprv_getICUData_conversion) { |
+- setCommonICUDataPointer(uprv_getICUData_conversion(), FALSE, pErrorCode); |
+- } |
+- */ |
+- setCommonICUDataPointer(&U_ICUDATA_ENTRY_POINT.hdr, FALSE, pErrorCode); |
++ /* Add the linked-in data to the list. */ |
++ /* |
++ * This is where we would check and call weakly linked partial-data-library |
++ * access functions. |
++ */ |
++ /* |
++ if (uprv_getICUData_collation) { |
++ setCommonICUDataPointer(uprv_getICUData_collation(), FALSE, pErrorCode); |
++ } |
++ if (uprv_getICUData_conversion) { |
++ setCommonICUDataPointer(uprv_getICUData_conversion(), FALSE, pErrorCode); |
++ } |
++ */ |
++ setCommonICUDataPointer(&U_ICUDATA_ENTRY_POINT.hdr, FALSE, pErrorCode); |
++ { |
++ Mutex lock; |
++ return gCommonICUDataArray[commonDataIndex]; |
+ } |
+- return gCommonICUDataArray[commonDataIndex]; |
+ } |
+ |
+ |
+@@ -795,7 +806,7 @@ static UBool extendICUData(UErrorCode *pErr) |
+ static UMutex extendICUDataMutex = U_MUTEX_INITIALIZER; |
+ umtx_lock(&extendICUDataMutex); |
+ #endif |
+- if(!gHaveTriedToLoadCommonData) { |
++ if(!umtx_loadAcquire(gHaveTriedToLoadCommonData)) { |
+ /* See if we can explicitly open a .dat file for the ICUData. */ |
+ pData = openCommonData( |
+ U_ICUDATA_NAME, /* "icudt20l" , for example. */ |
+@@ -820,7 +831,7 @@ static UBool extendICUData(UErrorCode *pErr) |
+ pErr); /* setCommonICUData honors errors; NOP if error set */ |
+ } |
+ |
+- gHaveTriedToLoadCommonData = TRUE; |
++ umtx_storeRelease(gHaveTriedToLoadCommonData, 1); |
+ } |
+ |
+ didUpdate = findCommonICUDataByName(U_ICUDATA_NAME); /* Return 'true' when a racing writes out the extended */ |
+@@ -1398,5 +1409,6 @@ udata_getInfo(UDataMemory *pData, UDataInfo *pInfo) { |
+ |
+ U_CAPI void U_EXPORT2 udata_setFileAccess(UDataFileAccess access, UErrorCode * /*status*/) |
+ { |
++ // Note: this function is documented as not thread safe. |
+ gDataFileAccess = access; |
+ } |