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 ;
@@ -129,11 +131,12 @@ static void fsentry_init(struct fsentry *fse, struct fsentry *list,
129131/*
130132 * Allocate an fsentry structure on the heap.
131133 */
132- static struct fsentry * fsentry_alloc (struct fsentry * list , const char * name ,
134+ static struct fsentry * fsentry_alloc (struct fscache * cache , struct fsentry * list , const char * name ,
133135 size_t len )
134136{
135137 /* overallocate fsentry and copy the name to the end */
136- struct fsentry * fse = xmalloc (sizeof (struct fsentry ) + len + 1 );
138+ struct fsentry * fse =
139+ mem_pool_alloc (& cache -> mem_pool , sizeof (* fse ) + len + 1 );
137140 /* init the rest of the structure */
138141 fsentry_init (fse , list , name , len );
139142 fse -> next = NULL ;
@@ -153,35 +156,29 @@ inline static void fsentry_addref(struct fsentry *fse)
153156}
154157
155158/*
156- * Release the reference to an fsentry, frees the memory if its the last ref .
159+ * Release the reference to an fsentry.
157160 */
158161static void fsentry_release (struct fsentry * fse )
159162{
160163 if (fse -> list )
161164 fse = fse -> list ;
162165
163- if (InterlockedDecrement (& (fse -> u .refcnt )))
164- return ;
165-
166- while (fse ) {
167- struct fsentry * next = fse -> next ;
168- free (fse );
169- fse = next ;
170- }
166+ InterlockedDecrement (& (fse -> u .refcnt ));
171167}
172168
173169/*
174170 * Allocate and initialize an fsentry from a WIN32_FIND_DATA structure.
175171 */
176- static struct fsentry * fseentry_create_entry (struct fsentry * list ,
172+ static struct fsentry * fseentry_create_entry (struct fscache * cache ,
173+ struct fsentry * list ,
177174 const WIN32_FIND_DATAW * fdata )
178175{
179176 char buf [MAX_PATH * 3 ];
180177 int len ;
181178 struct fsentry * fse ;
182179 len = xwcstoutf (buf , fdata -> cFileName , ARRAY_SIZE (buf ));
183180
184- fse = fsentry_alloc (list , buf , len );
181+ fse = fsentry_alloc (cache , list , buf , len );
185182
186183 fse -> st_mode = file_attr_to_st_mode (fdata -> dwFileAttributes );
187184 fse -> dirent .d_type = S_ISDIR (fse -> st_mode ) ? DT_DIR : DT_REG ;
@@ -199,7 +196,7 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
199196 * Dir should not contain trailing '/'. Use an empty string for the current
200197 * directory (not "."!).
201198 */
202- static struct fsentry * fsentry_create_list (const struct fsentry * dir ,
199+ static struct fsentry * fsentry_create_list (struct fscache * cache , const struct fsentry * dir ,
203200 int * dir_not_found )
204201{
205202 wchar_t pattern [MAX_PATH + 2 ]; /* + 2 for '/' '*' */
@@ -238,14 +235,14 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
238235 }
239236
240237 /* allocate object to hold directory listing */
241- list = fsentry_alloc (NULL , dir -> dirent .d_name , dir -> len );
238+ list = fsentry_alloc (cache , NULL , dir -> dirent .d_name , dir -> len );
242239 list -> st_mode = S_IFDIR ;
243240 list -> dirent .d_type = DT_DIR ;
244241
245242 /* walk directory and build linked list of fsentry structures */
246243 phead = & list -> next ;
247244 do {
248- * phead = fseentry_create_entry (list , & fdata );
245+ * phead = fseentry_create_entry (cache , list , & fdata );
249246 phead = & (* phead )-> next ;
250247 } while (FindNextFileW (h , & fdata ));
251248
@@ -257,7 +254,7 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
257254 if (err == ERROR_NO_MORE_FILES )
258255 return list ;
259256
260- /* otherwise free the list and return error */
257+ /* otherwise release the list and return error */
261258 fsentry_release (list );
262259 errno = err_win_to_posix (err );
263260 return NULL ;
@@ -280,7 +277,9 @@ static void fscache_add(struct fscache *cache, struct fsentry *fse)
280277 */
281278static void fscache_clear (struct fscache * cache )
282279{
283- hashmap_clear_and_free (& cache -> map , struct fsentry , ent );
280+ mem_pool_discard (& cache -> mem_pool , 0 );
281+ mem_pool_init (& cache -> mem_pool , 0 );
282+ hashmap_clear (& cache -> map );
284283 hashmap_init (& cache -> map , (hashmap_cmp_fn )fsentry_cmp , NULL , 0 );
285284 cache -> lstat_requests = cache -> opendir_requests = 0 ;
286285 cache -> fscache_misses = cache -> fscache_requests = 0 ;
@@ -333,7 +332,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
333332 }
334333
335334 /* create the directory listing */
336- fse = fsentry_create_list (key -> list ? key -> list : key , & dir_not_found );
335+ fse = fsentry_create_list (cache , key -> list ? key -> list : key , & dir_not_found );
337336
338337 /* leave on error (errno set by fsentry_create_list) */
339338 if (!fse ) {
@@ -343,7 +342,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
343342 * empty, which for all practical matters is the same
344343 * thing as far as fscache is concerned).
345344 */
346- fse = fsentry_alloc (key -> list -> list ,
345+ fse = fsentry_alloc (cache , key -> list -> list ,
347346 key -> list -> dirent .d_name ,
348347 key -> list -> len );
349348 fse -> st_mode = 0 ;
@@ -422,6 +421,7 @@ int fscache_enable(size_t initial_size)
422421 * '4' was determined empirically by testing several repos
423422 */
424423 hashmap_init (& cache -> map , (hashmap_cmp_fn )fsentry_cmp , NULL , initial_size * 4 );
424+ mem_pool_init (& cache -> mem_pool , 0 );
425425 if (!TlsSetValue (dwTlsIndex , cache ))
426426 BUG ("TlsSetValue error" );
427427 }
@@ -453,7 +453,8 @@ void fscache_disable(void)
453453 "total requests/misses %u/%u\n" ,
454454 cache -> lstat_requests , cache -> opendir_requests ,
455455 cache -> fscache_requests , cache -> fscache_misses );
456- fscache_clear (cache );
456+ mem_pool_discard (& cache -> mem_pool , 0 );
457+ hashmap_clear (& cache -> map );
457458 free (cache );
458459 }
459460
@@ -643,6 +644,8 @@ void fscache_merge(struct fscache *dest)
643644 while ((e = hashmap_iter_next (& iter )))
644645 hashmap_add (& dest -> map , e );
645646
647+ mem_pool_combine (& dest -> mem_pool , & cache -> mem_pool );
648+
646649 dest -> lstat_requests += cache -> lstat_requests ;
647650 dest -> opendir_requests += cache -> opendir_requests ;
648651 dest -> fscache_requests += cache -> fscache_requests ;
0 commit comments