66#include "../../abspath.h"
77#include "../../trace.h"
88#include "config.h"
9+ #include "../../mem-pool.h"
910
1011static volatile long initialized ;
1112static DWORD dwTlsIndex ;
@@ -20,6 +21,7 @@ static CRITICAL_SECTION mutex;
2021struct fscache {
2122 volatile long enabled ;
2223 struct hashmap map ;
24+ struct mem_pool mem_pool ;
2325 unsigned int lstat_requests ;
2426 unsigned int opendir_requests ;
2527 unsigned int fscache_requests ;
@@ -124,11 +126,12 @@ static void fsentry_init(struct fsentry *fse, struct fsentry *list,
124126/*
125127 * Allocate an fsentry structure on the heap.
126128 */
127- static struct fsentry * fsentry_alloc (struct fsentry * list , const char * name ,
129+ static struct fsentry * fsentry_alloc (struct fscache * cache , struct fsentry * list , const char * name ,
128130 size_t len )
129131{
130132 /* overallocate fsentry and copy the name to the end */
131- struct fsentry * fse = xmalloc (sizeof (struct fsentry ) + len + 1 );
133+ struct fsentry * fse =
134+ mem_pool_alloc (& cache -> mem_pool , sizeof (* fse ) + len + 1 );
132135 /* init the rest of the structure */
133136 fsentry_init (fse , list , name , len );
134137 fse -> next = NULL ;
@@ -148,35 +151,29 @@ inline static void fsentry_addref(struct fsentry *fse)
148151}
149152
150153/*
151- * Release the reference to an fsentry, frees the memory if its the last ref .
154+ * Release the reference to an fsentry.
152155 */
153156static void fsentry_release (struct fsentry * fse )
154157{
155158 if (fse -> list )
156159 fse = fse -> list ;
157160
158- if (InterlockedDecrement (& (fse -> u .refcnt )))
159- return ;
160-
161- while (fse ) {
162- struct fsentry * next = fse -> next ;
163- free (fse );
164- fse = next ;
165- }
161+ InterlockedDecrement (& (fse -> u .refcnt ));
166162}
167163
168164/*
169165 * Allocate and initialize an fsentry from a WIN32_FIND_DATA structure.
170166 */
171- static struct fsentry * fseentry_create_entry (struct fsentry * list ,
167+ static struct fsentry * fseentry_create_entry (struct fscache * cache ,
168+ struct fsentry * list ,
172169 const WIN32_FIND_DATAW * fdata )
173170{
174171 char buf [MAX_PATH * 3 ];
175172 int len ;
176173 struct fsentry * fse ;
177174 len = xwcstoutf (buf , fdata -> cFileName , ARRAY_SIZE (buf ));
178175
179- fse = fsentry_alloc (list , buf , len );
176+ fse = fsentry_alloc (cache , list , buf , len );
180177
181178 fse -> st_mode = file_attr_to_st_mode (fdata -> dwFileAttributes );
182179 fse -> dirent .d_type = S_ISDIR (fse -> st_mode ) ? DT_DIR : DT_REG ;
@@ -194,7 +191,7 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
194191 * Dir should not contain trailing '/'. Use an empty string for the current
195192 * directory (not "."!).
196193 */
197- static struct fsentry * fsentry_create_list (const struct fsentry * dir ,
194+ static struct fsentry * fsentry_create_list (struct fscache * cache , const struct fsentry * dir ,
198195 int * dir_not_found )
199196{
200197 wchar_t pattern [MAX_PATH + 2 ]; /* + 2 for '/' '*' */
@@ -233,14 +230,14 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
233230 }
234231
235232 /* allocate object to hold directory listing */
236- list = fsentry_alloc (NULL , dir -> dirent .d_name , dir -> len );
233+ list = fsentry_alloc (cache , NULL , dir -> dirent .d_name , dir -> len );
237234 list -> st_mode = S_IFDIR ;
238235 list -> dirent .d_type = DT_DIR ;
239236
240237 /* walk directory and build linked list of fsentry structures */
241238 phead = & list -> next ;
242239 do {
243- * phead = fseentry_create_entry (list , & fdata );
240+ * phead = fseentry_create_entry (cache , list , & fdata );
244241 phead = & (* phead )-> next ;
245242 } while (FindNextFileW (h , & fdata ));
246243
@@ -252,7 +249,7 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
252249 if (err == ERROR_NO_MORE_FILES )
253250 return list ;
254251
255- /* otherwise free the list and return error */
252+ /* otherwise release the list and return error */
256253 fsentry_release (list );
257254 errno = err_win_to_posix (err );
258255 return NULL ;
@@ -275,7 +272,9 @@ static void fscache_add(struct fscache *cache, struct fsentry *fse)
275272 */
276273static void fscache_clear (struct fscache * cache )
277274{
278- hashmap_clear_and_free (& cache -> map , struct fsentry , ent );
275+ mem_pool_discard (& cache -> mem_pool , 0 );
276+ mem_pool_init (& cache -> mem_pool , 0 );
277+ hashmap_clear (& cache -> map );
279278 hashmap_init (& cache -> map , (hashmap_cmp_fn )fsentry_cmp , NULL , 0 );
280279 cache -> lstat_requests = cache -> opendir_requests = 0 ;
281280 cache -> fscache_misses = cache -> fscache_requests = 0 ;
@@ -328,7 +327,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
328327 }
329328
330329 /* create the directory listing */
331- fse = fsentry_create_list (key -> list ? key -> list : key , & dir_not_found );
330+ fse = fsentry_create_list (cache , key -> list ? key -> list : key , & dir_not_found );
332331
333332 /* leave on error (errno set by fsentry_create_list) */
334333 if (!fse ) {
@@ -338,7 +337,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
338337 * empty, which for all practical matters is the same
339338 * thing as far as fscache is concerned).
340339 */
341- fse = fsentry_alloc (key -> list -> list ,
340+ fse = fsentry_alloc (cache , key -> list -> list ,
342341 key -> list -> dirent .d_name ,
343342 key -> list -> len );
344343 fse -> st_mode = 0 ;
@@ -417,6 +416,7 @@ int fscache_enable(size_t initial_size)
417416 * '4' was determined empirically by testing several repos
418417 */
419418 hashmap_init (& cache -> map , (hashmap_cmp_fn )fsentry_cmp , NULL , initial_size * 4 );
419+ mem_pool_init (& cache -> mem_pool , 0 );
420420 if (!TlsSetValue (dwTlsIndex , cache ))
421421 BUG ("TlsSetValue error" );
422422 }
@@ -448,7 +448,8 @@ void fscache_disable(void)
448448 "total requests/misses %u/%u\n" ,
449449 cache -> lstat_requests , cache -> opendir_requests ,
450450 cache -> fscache_requests , cache -> fscache_misses );
451- fscache_clear (cache );
451+ mem_pool_discard (& cache -> mem_pool , 0 );
452+ hashmap_clear (& cache -> map );
452453 free (cache );
453454 }
454455
@@ -633,6 +634,8 @@ void fscache_merge(struct fscache *dest)
633634 while ((e = hashmap_iter_next (& iter )))
634635 hashmap_add (& dest -> map , e );
635636
637+ mem_pool_combine (& dest -> mem_pool , & cache -> mem_pool );
638+
636639 dest -> lstat_requests += cache -> lstat_requests ;
637640 dest -> opendir_requests += cache -> opendir_requests ;
638641 dest -> fscache_requests += cache -> fscache_requests ;
0 commit comments