Changeset 3195 for trunk/src/kmk/w32/imagecache.c
- Timestamp:
- Mar 27, 2018, 8:09:23 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/w32/imagecache.c
r3140 r3195 26 26 /* No GNU coding style here! */ 27 27 28 /******************************************************************************* 29 * Header Files *30 ******************************************************************************* /28 /********************************************************************************************************************************* 29 * Header Files * 30 *********************************************************************************************************************************/ 31 31 #include "makeint.h" 32 32 … … 34 34 35 35 36 /******************************************************************************* 37 * Structures and Typedefs *38 ******************************************************************************* /36 /********************************************************************************************************************************* 37 * Structures and Typedefs * 38 *********************************************************************************************************************************/ 39 39 typedef struct EXECCACHEENTRY 40 40 { … … 42 42 unsigned uHash; 43 43 /** The name length. */ 44 unsigned c chName;44 unsigned cwcName; 45 45 /** Pointer to the next name with the same hash. */ 46 46 struct EXECCACHEENTRY *pNext; 47 47 /** When it was last referenced. */ 48 48 unsigned uLastRef; 49 /** The module handle . */49 /** The module handle, LOAD_LIBRARY_AS_DATAFILE. */ 50 50 HMODULE hmod1; 51 /** The module handle . */51 /** The module handle, DONT_RESOLVE_DLL_REFERENCES. */ 52 52 HMODULE hmod2; 53 53 /** The executable path. */ 54 charszName[1];54 wchar_t wszName[1]; 55 55 } EXECCACHEENTRY; 56 56 typedef EXECCACHEENTRY *PEXECCACHEENTRY; 57 57 58 /******************************************************************************* 59 * Global Variables * 60 *******************************************************************************/ 58 59 /********************************************************************************************************************************* 60 * Global Variables * 61 *********************************************************************************************************************************/ 62 /** Critical section serializing all access. */ 63 static CRITICAL_SECTION g_CritSect; 64 /** Set if initialized. */ 65 static int volatile g_fInitialized = 0; 61 66 /** The number of cached images. */ 62 67 static unsigned g_cCached; … … 69 74 /** The hash table. */ 70 75 static PEXECCACHEENTRY g_apHashTab[EXECCACHE_HASHTAB_SIZE]; 76 77 78 /** A sleepy approach to do-once. */ 79 static void kmk_cache_lazy_init(void) 80 { 81 if (_InterlockedCompareExchange(&g_fInitialized, -1, 0) == 0) 82 { 83 InitializeCriticalSection(&g_CritSect); 84 _InterlockedExchange(&g_fInitialized, 1); 85 } 86 else 87 while (g_fInitialized != 1) 88 Sleep(1); 89 } 71 90 72 91 … … 83 102 elsewhere. */ 84 103 85 static unsigned execcache_calc_hash(const char *psz, unsigned*pcch)86 { 87 unsigned char *puch = (unsigned char *)psz;88 unsigned hash = 0;89 int ch;90 91 while ((ch = *p uch++))104 static unsigned execcache_calc_hash(const wchar_t *pwsz, size_t *pcch) 105 { 106 wchar_t const * const pwszStart = pwsz; 107 unsigned hash = 0; 108 int ch; 109 110 while ((ch = *pwsz++) != L'\0') 92 111 hash = ch + (hash << 6) + (hash << 16) - hash; 93 112 94 *pcch = ( unsigned)(puch - psz- 1);113 *pcch = (size_t)(pwsz - pwszStart - 1); 95 114 return hash; 96 115 } 97 116 98 99 extern void kmk_cache_exec_image(const char *pszExec) 100 { 101 /* 102 * Lookup the name. 103 */ 104 unsigned cchName; 105 const unsigned uHash = execcache_calc_hash(pszExec, &cchName); 117 /** 118 * Caches two memory mappings of the specified image so that it isn't flushed 119 * from the kernel's cache mananger. 120 * 121 * Not sure exactly how much this actually helps, but whatever... 122 * 123 * @param pwszExec The executable. 124 */ 125 extern void kmk_cache_exec_image_w(const wchar_t *pwszExec) 126 { 127 /* 128 * Prepare name lookup and to lazy init. 129 */ 130 size_t cwcName; 131 const unsigned uHash = execcache_calc_hash(pwszExec, &cwcName); 106 132 PEXECCACHEENTRY *ppCur = &g_apHashTab[uHash % EXECCACHE_HASHTAB_SIZE]; 107 PEXECCACHEENTRY pCur = *ppCur; 133 PEXECCACHEENTRY pCur; 134 135 if (g_fInitialized != 1) 136 kmk_cache_lazy_init(); 137 138 /* 139 * Do the lookup. 140 */ 141 EnterCriticalSection(&g_CritSect); 142 pCur = *ppCur; 108 143 while (pCur) 109 144 { 110 145 if ( pCur->uHash == uHash 111 && pCur->c chName == cchName112 && !memcmp(pCur-> szName, pszExec, cchName))146 && pCur->cwcName == cwcName 147 && !memcmp(pCur->wszName, pwszExec, cwcName * sizeof(wchar_t))) 113 148 { 114 149 pCur->uLastRef = ++g_uNow; 150 LeaveCriticalSection(&g_CritSect); 115 151 return; 116 152 } … … 118 154 pCur = pCur->pNext; 119 155 } 156 LeaveCriticalSection(&g_CritSect); 120 157 121 158 /* 122 159 * Not found, create a new entry. 123 160 */ 124 pCur = xmalloc(sizeof(*pCur) + c chName);161 pCur = xmalloc(sizeof(*pCur) + cwcName * sizeof(wchar_t)); 125 162 pCur->uHash = uHash; 126 pCur->c chName = cchName;163 pCur->cwcName = (unsigned)cwcName; 127 164 pCur->pNext = NULL; 128 165 pCur->uLastRef = ++g_uNow; 129 memcpy(pCur-> szName, pszExec, cchName + 1);130 pCur->hmod1 = LoadLibraryEx (pszExec, NULL, LOAD_LIBRARY_AS_DATAFILE);166 memcpy(pCur->wszName, pwszExec, (cwcName + 1) * sizeof(wchar_t)); 167 pCur->hmod1 = LoadLibraryExW(pwszExec, NULL, LOAD_LIBRARY_AS_DATAFILE); 131 168 if (pCur->hmod1 != NULL) 132 pCur->hmod2 = LoadLibraryEx (pszExec, NULL, DONT_RESOLVE_DLL_REFERENCES);169 pCur->hmod2 = LoadLibraryExW(pwszExec, NULL, DONT_RESOLVE_DLL_REFERENCES); 133 170 else 134 171 pCur->hmod2 = NULL; 135 172 136 *ppCur = pCur; 137 g_cCached++; 138 } 139 173 /* 174 * Insert it. 175 * Take into account that we might've been racing other threads, 176 * fortunately we don't evict anything from the cache. 177 */ 178 EnterCriticalSection(&g_CritSect); 179 if (*ppCur != NULL) 180 { 181 /* Find new end of chain and check for duplicate. */ 182 PEXECCACHEENTRY pCur2 = *ppCur; 183 while (pCur2) 184 { 185 if ( pCur->uHash == uHash 186 && pCur->cwcName == cwcName 187 && !memcmp(pCur->wszName, pwszExec, cwcName * sizeof(wchar_t))) 188 break; 189 ppCur = &pCur->pNext; 190 pCur = pCur->pNext; 191 } 192 193 } 194 if (*ppCur == NULL) 195 { 196 *ppCur = pCur; 197 g_cCached++; 198 LeaveCriticalSection(&g_CritSect); 199 } 200 else 201 { 202 LeaveCriticalSection(&g_CritSect); 203 204 if (pCur->hmod1 != NULL) 205 FreeLibrary(pCur->hmod1); 206 if (pCur->hmod2 != NULL) 207 FreeLibrary(pCur->hmod2); 208 free(pCur); 209 } 210 } 211 212 extern void kmk_cache_exec_image_a(const char *pszExec) 213 { 214 wchar_t wszExec[260]; 215 int cwc = MultiByteToWideChar(CP_ACP, 0 /*fFlags*/, pszExec, strlen(pszExec) + 1, wszExec, 260); 216 if (cwc > 0) 217 kmk_cache_exec_image_w(wszExec); 218 } 219
Note:
See TracChangeset
for help on using the changeset viewer.