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 ;
@@ -129,11 +131,12 @@ static void fsentry_init(struct fsentry *fse, struct fsentry *list,
129
131
/*
130
132
* Allocate an fsentry structure on the heap.
131
133
*/
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 ,
133
135
size_t len )
134
136
{
135
137
/* 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 );
137
140
/* init the rest of the structure */
138
141
fsentry_init (fse , list , name , len );
139
142
fse -> next = NULL ;
@@ -153,35 +156,29 @@ inline static void fsentry_addref(struct fsentry *fse)
153
156
}
154
157
155
158
/*
156
- * Release the reference to an fsentry, frees the memory if its the last ref .
159
+ * Release the reference to an fsentry.
157
160
*/
158
161
static void fsentry_release (struct fsentry * fse )
159
162
{
160
163
if (fse -> list )
161
164
fse = fse -> list ;
162
165
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 ));
171
167
}
172
168
173
169
/*
174
170
* Allocate and initialize an fsentry from a WIN32_FIND_DATA structure.
175
171
*/
176
- static struct fsentry * fseentry_create_entry (struct fsentry * list ,
172
+ static struct fsentry * fseentry_create_entry (struct fscache * cache ,
173
+ struct fsentry * list ,
177
174
const WIN32_FIND_DATAW * fdata )
178
175
{
179
176
char buf [MAX_PATH * 3 ];
180
177
int len ;
181
178
struct fsentry * fse ;
182
179
len = xwcstoutf (buf , fdata -> cFileName , ARRAY_SIZE (buf ));
183
180
184
- fse = fsentry_alloc (list , buf , len );
181
+ fse = fsentry_alloc (cache , list , buf , len );
185
182
186
183
fse -> st_mode = file_attr_to_st_mode (fdata -> dwFileAttributes );
187
184
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,
199
196
* Dir should not contain trailing '/'. Use an empty string for the current
200
197
* directory (not "."!).
201
198
*/
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 ,
203
200
int * dir_not_found )
204
201
{
205
202
wchar_t pattern [MAX_PATH + 2 ]; /* + 2 for '/' '*' */
@@ -238,14 +235,14 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
238
235
}
239
236
240
237
/* 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 );
242
239
list -> st_mode = S_IFDIR ;
243
240
list -> dirent .d_type = DT_DIR ;
244
241
245
242
/* walk directory and build linked list of fsentry structures */
246
243
phead = & list -> next ;
247
244
do {
248
- * phead = fseentry_create_entry (list , & fdata );
245
+ * phead = fseentry_create_entry (cache , list , & fdata );
249
246
phead = & (* phead )-> next ;
250
247
} while (FindNextFileW (h , & fdata ));
251
248
@@ -257,7 +254,7 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
257
254
if (err == ERROR_NO_MORE_FILES )
258
255
return list ;
259
256
260
- /* otherwise free the list and return error */
257
+ /* otherwise release the list and return error */
261
258
fsentry_release (list );
262
259
errno = err_win_to_posix (err );
263
260
return NULL ;
@@ -280,7 +277,9 @@ static void fscache_add(struct fscache *cache, struct fsentry *fse)
280
277
*/
281
278
static void fscache_clear (struct fscache * cache )
282
279
{
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 );
284
283
hashmap_init (& cache -> map , (hashmap_cmp_fn )fsentry_cmp , NULL , 0 );
285
284
cache -> lstat_requests = cache -> opendir_requests = 0 ;
286
285
cache -> fscache_misses = cache -> fscache_requests = 0 ;
@@ -333,7 +332,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
333
332
}
334
333
335
334
/* 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 );
337
336
338
337
/* leave on error (errno set by fsentry_create_list) */
339
338
if (!fse ) {
@@ -343,7 +342,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
343
342
* empty, which for all practical matters is the same
344
343
* thing as far as fscache is concerned).
345
344
*/
346
- fse = fsentry_alloc (key -> list -> list ,
345
+ fse = fsentry_alloc (cache , key -> list -> list ,
347
346
key -> list -> dirent .d_name ,
348
347
key -> list -> len );
349
348
fse -> st_mode = 0 ;
@@ -422,6 +421,7 @@ int fscache_enable(size_t initial_size)
422
421
* '4' was determined empirically by testing several repos
423
422
*/
424
423
hashmap_init (& cache -> map , (hashmap_cmp_fn )fsentry_cmp , NULL , initial_size * 4 );
424
+ mem_pool_init (& cache -> mem_pool , 0 );
425
425
if (!TlsSetValue (dwTlsIndex , cache ))
426
426
BUG ("TlsSetValue error" );
427
427
}
@@ -453,7 +453,8 @@ void fscache_disable(void)
453
453
"total requests/misses %u/%u\n" ,
454
454
cache -> lstat_requests , cache -> opendir_requests ,
455
455
cache -> fscache_requests , cache -> fscache_misses );
456
- fscache_clear (cache );
456
+ mem_pool_discard (& cache -> mem_pool , 0 );
457
+ hashmap_clear (& cache -> map );
457
458
free (cache );
458
459
}
459
460
@@ -643,6 +644,8 @@ void fscache_merge(struct fscache *dest)
643
644
while ((e = hashmap_iter_next (& iter )))
644
645
hashmap_add (& dest -> map , e );
645
646
647
+ mem_pool_combine (& dest -> mem_pool , & cache -> mem_pool );
648
+
646
649
dest -> lstat_requests += cache -> lstat_requests ;
647
650
dest -> opendir_requests += cache -> opendir_requests ;
648
651
dest -> fscache_requests += cache -> fscache_requests ;
0 commit comments