6
6
#include "../../abspath.h"
7
7
#include "../../trace.h"
8
8
#include "config.h"
9
+ #include "../../mem-pool.h"
9
10
10
11
static volatile long initialized ;
11
12
static DWORD dwTlsIndex ;
@@ -20,6 +21,7 @@ static CRITICAL_SECTION mutex;
20
21
struct fscache {
21
22
volatile long enabled ;
22
23
struct hashmap map ;
24
+ struct mem_pool mem_pool ;
23
25
unsigned int lstat_requests ;
24
26
unsigned int opendir_requests ;
25
27
unsigned int fscache_requests ;
@@ -124,11 +126,12 @@ static void fsentry_init(struct fsentry *fse, struct fsentry *list,
124
126
/*
125
127
* Allocate an fsentry structure on the heap.
126
128
*/
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 ,
128
130
size_t len )
129
131
{
130
132
/* 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 );
132
135
/* init the rest of the structure */
133
136
fsentry_init (fse , list , name , len );
134
137
fse -> next = NULL ;
@@ -148,35 +151,29 @@ inline static void fsentry_addref(struct fsentry *fse)
148
151
}
149
152
150
153
/*
151
- * Release the reference to an fsentry, frees the memory if its the last ref .
154
+ * Release the reference to an fsentry.
152
155
*/
153
156
static void fsentry_release (struct fsentry * fse )
154
157
{
155
158
if (fse -> list )
156
159
fse = fse -> list ;
157
160
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 ));
166
162
}
167
163
168
164
/*
169
165
* Allocate and initialize an fsentry from a WIN32_FIND_DATA structure.
170
166
*/
171
- static struct fsentry * fseentry_create_entry (struct fsentry * list ,
167
+ static struct fsentry * fseentry_create_entry (struct fscache * cache ,
168
+ struct fsentry * list ,
172
169
const WIN32_FIND_DATAW * fdata )
173
170
{
174
171
char buf [MAX_PATH * 3 ];
175
172
int len ;
176
173
struct fsentry * fse ;
177
174
len = xwcstoutf (buf , fdata -> cFileName , ARRAY_SIZE (buf ));
178
175
179
- fse = fsentry_alloc (list , buf , len );
176
+ fse = fsentry_alloc (cache , list , buf , len );
180
177
181
178
fse -> st_mode = file_attr_to_st_mode (fdata -> dwFileAttributes );
182
179
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,
194
191
* Dir should not contain trailing '/'. Use an empty string for the current
195
192
* directory (not "."!).
196
193
*/
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 ,
198
195
int * dir_not_found )
199
196
{
200
197
wchar_t pattern [MAX_PATH + 2 ]; /* + 2 for '/' '*' */
@@ -233,14 +230,14 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
233
230
}
234
231
235
232
/* 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 );
237
234
list -> st_mode = S_IFDIR ;
238
235
list -> dirent .d_type = DT_DIR ;
239
236
240
237
/* walk directory and build linked list of fsentry structures */
241
238
phead = & list -> next ;
242
239
do {
243
- * phead = fseentry_create_entry (list , & fdata );
240
+ * phead = fseentry_create_entry (cache , list , & fdata );
244
241
phead = & (* phead )-> next ;
245
242
} while (FindNextFileW (h , & fdata ));
246
243
@@ -252,7 +249,7 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
252
249
if (err == ERROR_NO_MORE_FILES )
253
250
return list ;
254
251
255
- /* otherwise free the list and return error */
252
+ /* otherwise release the list and return error */
256
253
fsentry_release (list );
257
254
errno = err_win_to_posix (err );
258
255
return NULL ;
@@ -275,7 +272,9 @@ static void fscache_add(struct fscache *cache, struct fsentry *fse)
275
272
*/
276
273
static void fscache_clear (struct fscache * cache )
277
274
{
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 );
279
278
hashmap_init (& cache -> map , (hashmap_cmp_fn )fsentry_cmp , NULL , 0 );
280
279
cache -> lstat_requests = cache -> opendir_requests = 0 ;
281
280
cache -> fscache_misses = cache -> fscache_requests = 0 ;
@@ -328,7 +327,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
328
327
}
329
328
330
329
/* 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 );
332
331
333
332
/* leave on error (errno set by fsentry_create_list) */
334
333
if (!fse ) {
@@ -338,7 +337,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
338
337
* empty, which for all practical matters is the same
339
338
* thing as far as fscache is concerned).
340
339
*/
341
- fse = fsentry_alloc (key -> list -> list ,
340
+ fse = fsentry_alloc (cache , key -> list -> list ,
342
341
key -> list -> dirent .d_name ,
343
342
key -> list -> len );
344
343
fse -> st_mode = 0 ;
@@ -417,6 +416,7 @@ int fscache_enable(size_t initial_size)
417
416
* '4' was determined empirically by testing several repos
418
417
*/
419
418
hashmap_init (& cache -> map , (hashmap_cmp_fn )fsentry_cmp , NULL , initial_size * 4 );
419
+ mem_pool_init (& cache -> mem_pool , 0 );
420
420
if (!TlsSetValue (dwTlsIndex , cache ))
421
421
BUG ("TlsSetValue error" );
422
422
}
@@ -448,7 +448,8 @@ void fscache_disable(void)
448
448
"total requests/misses %u/%u\n" ,
449
449
cache -> lstat_requests , cache -> opendir_requests ,
450
450
cache -> fscache_requests , cache -> fscache_misses );
451
- fscache_clear (cache );
451
+ mem_pool_discard (& cache -> mem_pool , 0 );
452
+ hashmap_clear (& cache -> map );
452
453
free (cache );
453
454
}
454
455
@@ -633,6 +634,8 @@ void fscache_merge(struct fscache *dest)
633
634
while ((e = hashmap_iter_next (& iter )))
634
635
hashmap_add (& dest -> map , e );
635
636
637
+ mem_pool_combine (& dest -> mem_pool , & cache -> mem_pool );
638
+
636
639
dest -> lstat_requests += cache -> lstat_requests ;
637
640
dest -> opendir_requests += cache -> opendir_requests ;
638
641
dest -> fscache_requests += cache -> fscache_requests ;
0 commit comments