Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(354)

Side by Side Diff: source/common/udata.cpp

Issue 1233663005: Cherry-pick a upstream patch for a data loading bug (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/icu.git@master
Patch Set: rebased Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « patches/dataload.patch ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 ****************************************************************************** 2 ******************************************************************************
3 * 3 *
4 * Copyright (C) 1999-2014, International Business Machines 4 * Copyright (C) 1999-2015, International Business Machines
5 * Corporation and others. All Rights Reserved. 5 * Corporation and others. All Rights Reserved.
6 * 6 *
7 ****************************************************************************** 7 ******************************************************************************
8 * file name: udata.cpp 8 * file name: udata.cpp
9 * encoding: US-ASCII 9 * encoding: US-ASCII
10 * tab size: 8 (not used) 10 * tab size: 8 (not used)
11 * indentation:4 11 * indentation:4
12 * 12 *
13 * created on: 1999oct25 13 * created on: 1999oct25
14 * created by: Markus W. Scherer 14 * created by: Markus W. Scherer
15 */ 15 */
16 16
17 #include "unicode/utypes.h" /* U_PLATFORM etc. */ 17 #include "unicode/utypes.h" /* U_PLATFORM etc. */
18 18
19 #ifdef __GNUC__ 19 #ifdef __GNUC__
20 /* if gcc 20 /* if gcc
21 #define ATTRIBUTE_WEAK __attribute__ ((weak)) 21 #define ATTRIBUTE_WEAK __attribute__ ((weak))
22 might have to #include some other header 22 might have to #include some other header
23 */ 23 */
24 #endif 24 #endif
25 25
26 #include "unicode/putil.h" 26 #include "unicode/putil.h"
27 #include "unicode/udata.h" 27 #include "unicode/udata.h"
28 #include "unicode/uversion.h" 28 #include "unicode/uversion.h"
29 #include "charstr.h" 29 #include "charstr.h"
30 #include "cmemory.h" 30 #include "cmemory.h"
31 #include "cstring.h" 31 #include "cstring.h"
32 #include "mutex.h"
32 #include "putilimp.h" 33 #include "putilimp.h"
33 #include "uassert.h" 34 #include "uassert.h"
34 #include "ucln_cmn.h" 35 #include "ucln_cmn.h"
35 #include "ucmndata.h" 36 #include "ucmndata.h"
36 #include "udatamem.h" 37 #include "udatamem.h"
37 #include "uhash.h" 38 #include "uhash.h"
38 #include "umapfile.h" 39 #include "umapfile.h"
39 #include "umutex.h" 40 #include "umutex.h"
40 41
41 /*********************************************************************** 42 /***********************************************************************
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 * It is possible to combine this with dependency inversion: 94 * It is possible to combine this with dependency inversion:
94 * One or more data package libraries may export 95 * One or more data package libraries may export
95 * functions that each return a pointer to their piece of the ICU data, 96 * functions that each return a pointer to their piece of the ICU data,
96 * and this file would import them as weak functions, without a 97 * and this file would import them as weak functions, without a
97 * strong linker dependency from the common library on the data library. 98 * strong linker dependency from the common library on the data library.
98 * 99 *
99 * Then we can have applications depend on only that part of ICU's data 100 * Then we can have applications depend on only that part of ICU's data
100 * that they really need, reducing the size of binaries that take advantage 101 * that they really need, reducing the size of binaries that take advantage
101 * of this. 102 * of this.
102 */ 103 */
103 static UDataMemory *gCommonICUDataArray[10] = { NULL }; 104 static UDataMemory *gCommonICUDataArray[10] = { NULL }; // Access protected by icu global mutex.
104 105
105 static UBool gHaveTriedToLoadCommonData = FALSE; /* See extendICUData(). */ 106 static u_atomic_int32_t gHaveTriedToLoadCommonData = ATOMIC_INT32_T_INITIALIZER( 0); // See extendICUData().
106 107
107 static UHashtable *gCommonDataCache = NULL; /* Global hash table of opened ICU data files. */ 108 static UHashtable *gCommonDataCache = NULL; /* Global hash table of opened ICU data files. */
108 static icu::UInitOnce gCommonDataCacheInitOnce = U_INITONCE_INITIALIZER; 109 static icu::UInitOnce gCommonDataCacheInitOnce = U_INITONCE_INITIALIZER;
109 110
110 static UDataFileAccess gDataFileAccess = UDATA_DEFAULT_ACCESS; 111 static UDataFileAccess gDataFileAccess = UDATA_DEFAULT_ACCESS; // Access not s ynchronized.
112 // Modifying is documented as thread-unsafe.
111 113
112 static UBool U_CALLCONV 114 static UBool U_CALLCONV
113 udata_cleanup(void) 115 udata_cleanup(void)
114 { 116 {
115 int32_t i; 117 int32_t i;
116 118
117 if (gCommonDataCache) { /* Delete the cache of user data mapping s. */ 119 if (gCommonDataCache) { /* Delete the cache of user data mapping s. */
118 uhash_close(gCommonDataCache); /* Table owns the contents, and will d elete them. */ 120 uhash_close(gCommonDataCache); /* Table owns the contents, and will d elete them. */
119 gCommonDataCache = NULL; /* Cleanup is not thread safe. */ 121 gCommonDataCache = NULL; /* Cleanup is not thread safe. */
120 } 122 }
121 gCommonDataCacheInitOnce.reset(); 123 gCommonDataCacheInitOnce.reset();
122 124
123 for (i = 0; i < UPRV_LENGTHOF(gCommonICUDataArray) && gCommonICUDataArray[i] != NULL; ++i) { 125 for (i = 0; i < UPRV_LENGTHOF(gCommonICUDataArray) && gCommonICUDataArray[i] != NULL; ++i) {
124 udata_close(gCommonICUDataArray[i]); 126 udata_close(gCommonICUDataArray[i]);
125 gCommonICUDataArray[i] = NULL; 127 gCommonICUDataArray[i] = NULL;
126 } 128 }
127 gHaveTriedToLoadCommonData = FALSE; 129 gHaveTriedToLoadCommonData = 0;
128 130
129 return TRUE; /* Everything was cleaned up */ 131 return TRUE; /* Everything was cleaned up */
130 } 132 }
131 133
132 static UBool U_CALLCONV 134 static UBool U_CALLCONV
133 findCommonICUDataByName(const char *inBasename) 135 findCommonICUDataByName(const char *inBasename)
134 { 136 {
135 UBool found = FALSE; 137 UBool found = FALSE;
136 int32_t i; 138 int32_t i;
137 139
138 UDataMemory *pData = udata_findCachedData(inBasename); 140 UDataMemory *pData = udata_findCachedData(inBasename);
139 if (pData == NULL) 141 if (pData == NULL)
140 return FALSE; 142 return FALSE;
141 143
142 for (i = 0; i < UPRV_LENGTHOF(gCommonICUDataArray); ++i) { 144 {
143 if ((gCommonICUDataArray[i] != NULL) && (gCommonICUDataArray[i]->pHeader == pData->pHeader)) { 145 Mutex lock;
144 /* The data pointer is already in the array. */ 146 for (i = 0; i < UPRV_LENGTHOF(gCommonICUDataArray); ++i) {
145 found = TRUE; 147 if ((gCommonICUDataArray[i] != NULL) && (gCommonICUDataArray[i]->pHe ader == pData->pHeader)) {
146 break; 148 /* The data pointer is already in the array. */
149 found = TRUE;
150 break;
151 }
147 } 152 }
148 } 153 }
149
150 return found; 154 return found;
151 } 155 }
152 156
153 157
154 /* 158 /*
155 * setCommonICUData. Set a UDataMemory to be the global ICU Data 159 * setCommonICUData. Set a UDataMemory to be the global ICU Data
156 */ 160 */
157 static UBool 161 static UBool
158 setCommonICUData(UDataMemory *pData, /* The new common data. Belongs to ca ller, we copy it. */ 162 setCommonICUData(UDataMemory *pData, /* The new common data. Belongs to ca ller, we copy it. */
159 UBool warn, /* If true, set USING_DEFAULT warning if ICUData was */ 163 UBool warn, /* If true, set USING_DEFAULT warning if ICUData was */
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after
656 } 660 }
657 661
658 UDataMemory_init(&tData); 662 UDataMemory_init(&tData);
659 663
660 /* ??????? TODO revisit this */ 664 /* ??????? TODO revisit this */
661 if (commonDataIndex >= 0) { 665 if (commonDataIndex >= 0) {
662 /* "mini-cache" for common ICU data */ 666 /* "mini-cache" for common ICU data */
663 if(commonDataIndex >= UPRV_LENGTHOF(gCommonICUDataArray)) { 667 if(commonDataIndex >= UPRV_LENGTHOF(gCommonICUDataArray)) {
664 return NULL; 668 return NULL;
665 } 669 }
666 if(gCommonICUDataArray[commonDataIndex] == NULL) { 670 {
671 Mutex lock;
672 if(gCommonICUDataArray[commonDataIndex] != NULL) {
673 return gCommonICUDataArray[commonDataIndex];
674 }
667 int32_t i; 675 int32_t i;
668 for(i = 0; i < commonDataIndex; ++i) { 676 for(i = 0; i < commonDataIndex; ++i) {
669 if(gCommonICUDataArray[i]->pHeader == &U_ICUDATA_ENTRY_POINT.hdr ) { 677 if(gCommonICUDataArray[i]->pHeader == &U_ICUDATA_ENTRY_POINT.hdr ) {
670 /* The linked-in data is already in the list. */ 678 /* The linked-in data is already in the list. */
671 return NULL; 679 return NULL;
672 } 680 }
673 } 681 }
682 }
674 683
675 /* Add the linked-in data to the list. */ 684 /* Add the linked-in data to the list. */
676 /* 685 /*
677 * This is where we would check and call weakly linked partial-data- library 686 * This is where we would check and call weakly linked partial-data-libr ary
678 * access functions. 687 * access functions.
679 */ 688 */
680 /* 689 /*
681 if (uprv_getICUData_collation) { 690 if (uprv_getICUData_collation) {
682 setCommonICUDataPointer(uprv_getICUData_collation(), FALSE, pErr orCode); 691 setCommonICUDataPointer(uprv_getICUData_collation(), FALSE, pErrorCo de);
683 }
684 if (uprv_getICUData_conversion) {
685 setCommonICUDataPointer(uprv_getICUData_conversion(), FALSE, pEr rorCode);
686 }
687 */
688 setCommonICUDataPointer(&U_ICUDATA_ENTRY_POINT.hdr, FALSE, pErrorCod e);
689 } 692 }
690 return gCommonICUDataArray[commonDataIndex]; 693 if (uprv_getICUData_conversion) {
694 setCommonICUDataPointer(uprv_getICUData_conversion(), FALSE, pErrorC ode);
695 }
696 */
697 setCommonICUDataPointer(&U_ICUDATA_ENTRY_POINT.hdr, FALSE, pErrorCode);
698 {
699 Mutex lock;
700 return gCommonICUDataArray[commonDataIndex];
701 }
691 } 702 }
692 703
693 704
694 /* request is NOT for ICU Data. */ 705 /* request is NOT for ICU Data. */
695 706
696 /* Find the base name portion of the supplied path. */ 707 /* Find the base name portion of the supplied path. */
697 /* inBasename will be left pointing somewhere within the original path str ing. */ 708 /* inBasename will be left pointing somewhere within the original path str ing. */
698 inBasename = findBasename(path); 709 inBasename = findBasename(path);
699 #ifdef UDATA_DEBUG 710 #ifdef UDATA_DEBUG
700 fprintf(stderr, "inBasename = %s\n", inBasename); 711 fprintf(stderr, "inBasename = %s\n", inBasename);
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 * If ICU is built with data loading via fread() then the address will 799 * If ICU is built with data loading via fread() then the address will
789 * be different each time the common data is loaded and we may add 800 * be different each time the common data is loaded and we may add
790 * multiple copies of the data. 801 * multiple copies of the data.
791 * In this case, use a mutex to prevent the race. 802 * In this case, use a mutex to prevent the race.
792 * Use a specific mutex to avoid nested locks of the global mutex. 803 * Use a specific mutex to avoid nested locks of the global mutex.
793 */ 804 */
794 #if MAP_IMPLEMENTATION==MAP_STDIO 805 #if MAP_IMPLEMENTATION==MAP_STDIO
795 static UMutex extendICUDataMutex = U_MUTEX_INITIALIZER; 806 static UMutex extendICUDataMutex = U_MUTEX_INITIALIZER;
796 umtx_lock(&extendICUDataMutex); 807 umtx_lock(&extendICUDataMutex);
797 #endif 808 #endif
798 if(!gHaveTriedToLoadCommonData) { 809 if(!umtx_loadAcquire(gHaveTriedToLoadCommonData)) {
799 /* See if we can explicitly open a .dat file for the ICUData. */ 810 /* See if we can explicitly open a .dat file for the ICUData. */
800 pData = openCommonData( 811 pData = openCommonData(
801 U_ICUDATA_NAME, /* "icudt20l" , for example. */ 812 U_ICUDATA_NAME, /* "icudt20l" , for example. */
802 -1, /* Pretend we're not opening ICUD ata */ 813 -1, /* Pretend we're not opening ICUD ata */
803 pErr); 814 pErr);
804 815
805 /* How about if there is no pData, eh... */ 816 /* How about if there is no pData, eh... */
806 817
807 UDataMemory_init(&copyPData); 818 UDataMemory_init(&copyPData);
808 if(pData != NULL) { 819 if(pData != NULL) {
809 UDatamemory_assign(&copyPData, pData); 820 UDatamemory_assign(&copyPData, pData);
810 copyPData.map = 0; /* The mapping for this data is owned by the hash table */ 821 copyPData.map = 0; /* The mapping for this data is owned by the hash table */
811 copyPData.mapAddr = 0; /* which will unmap it when ICU is s hut down. */ 822 copyPData.mapAddr = 0; /* which will unmap it when ICU is s hut down. */
812 /* CommonICUData is also unmapped when ICU is shut down.*/ 823 /* CommonICUData is also unmapped when ICU is shut down.*/
813 /* To avoid unmapping the data twice, zero out the map */ 824 /* To avoid unmapping the data twice, zero out the map */
814 /* fields in the UDataMemory that we 're assigning */ 825 /* fields in the UDataMemory that we 're assigning */
815 /* to CommonICUData. */ 826 /* to CommonICUData. */
816 827
817 didUpdate = /* no longer using this result */ 828 didUpdate = /* no longer using this result */
818 setCommonICUData(&copyPData,/* The new common data. */ 829 setCommonICUData(&copyPData,/* The new common data. */
819 FALSE, /* No warnings if write didn't happen */ 830 FALSE, /* No warnings if write didn't happen */
820 pErr); /* setCommonICUData honors errors; NO P if error set */ 831 pErr); /* setCommonICUData honors errors; NO P if error set */
821 } 832 }
822 833
823 gHaveTriedToLoadCommonData = TRUE; 834 umtx_storeRelease(gHaveTriedToLoadCommonData, 1);
824 } 835 }
825 836
826 didUpdate = findCommonICUDataByName(U_ICUDATA_NAME); /* Return 'true' when a racing writes out the extended */ 837 didUpdate = findCommonICUDataByName(U_ICUDATA_NAME); /* Return 'true' when a racing writes out the extended */
827 /* data after another thread has failed to see it (in openCommonData), so */ 838 /* data after another thread has failed to see it (in openCommonData), so */
828 /* extended data can b e examined. */ 839 /* extended data can b e examined. */
829 /* Also handles a race through here before gHaveTriedToLoadCommonData is set. */ 840 /* Also handles a race through here before gHaveTriedToLoadCommonData is set. */
830 841
831 #if MAP_IMPLEMENTATION==MAP_STDIO 842 #if MAP_IMPLEMENTATION==MAP_STDIO
832 umtx_unlock(&extendICUDataMutex); 843 umtx_unlock(&extendICUDataMutex);
833 #endif 844 #endif
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after
1391 } 1402 }
1392 } else { 1403 } else {
1393 pInfo->size=0; 1404 pInfo->size=0;
1394 } 1405 }
1395 } 1406 }
1396 } 1407 }
1397 1408
1398 1409
1399 U_CAPI void U_EXPORT2 udata_setFileAccess(UDataFileAccess access, UErrorCode * / *status*/) 1410 U_CAPI void U_EXPORT2 udata_setFileAccess(UDataFileAccess access, UErrorCode * / *status*/)
1400 { 1411 {
1412 // Note: this function is documented as not thread safe.
1401 gDataFileAccess = access; 1413 gDataFileAccess = access;
1402 } 1414 }
OLDNEW
« no previous file with comments | « patches/dataload.patch ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698