3
3
#include "../win32.h"
4
4
#include "fscache.h"
5
5
#include "config.h"
6
+ #include "../../mem-pool.h"
6
7
7
8
static volatile long initialized ;
8
9
static DWORD dwTlsIndex ;
@@ -17,6 +18,7 @@ static CRITICAL_SECTION mutex;
17
18
struct fscache {
18
19
volatile long enabled ;
19
20
struct hashmap map ;
21
+ struct mem_pool mem_pool ;
20
22
unsigned int lstat_requests ;
21
23
unsigned int opendir_requests ;
22
24
unsigned int fscache_requests ;
@@ -121,11 +123,12 @@ static void fsentry_init(struct fsentry *fse, struct fsentry *list,
121
123
/*
122
124
* Allocate an fsentry structure on the heap.
123
125
*/
124
- static struct fsentry * fsentry_alloc (struct fsentry * list , const char * name ,
126
+ static struct fsentry * fsentry_alloc (struct fscache * cache , struct fsentry * list , const char * name ,
125
127
size_t len )
126
128
{
127
129
/* overallocate fsentry and copy the name to the end */
128
- struct fsentry * fse = xmalloc (sizeof (struct fsentry ) + len + 1 );
130
+ struct fsentry * fse =
131
+ mem_pool_alloc (& cache -> mem_pool , sizeof (* fse ) + len + 1 );
129
132
/* init the rest of the structure */
130
133
fsentry_init (fse , list , name , len );
131
134
fse -> next = NULL ;
@@ -145,35 +148,29 @@ inline static void fsentry_addref(struct fsentry *fse)
145
148
}
146
149
147
150
/*
148
- * Release the reference to an fsentry, frees the memory if its the last ref .
151
+ * Release the reference to an fsentry.
149
152
*/
150
153
static void fsentry_release (struct fsentry * fse )
151
154
{
152
155
if (fse -> list )
153
156
fse = fse -> list ;
154
157
155
- if (InterlockedDecrement (& (fse -> u .refcnt )))
156
- return ;
157
-
158
- while (fse ) {
159
- struct fsentry * next = fse -> next ;
160
- free (fse );
161
- fse = next ;
162
- }
158
+ InterlockedDecrement (& (fse -> u .refcnt ));
163
159
}
164
160
165
161
/*
166
162
* Allocate and initialize an fsentry from a WIN32_FIND_DATA structure.
167
163
*/
168
- static struct fsentry * fseentry_create_entry (struct fsentry * list ,
164
+ static struct fsentry * fseentry_create_entry (struct fscache * cache ,
165
+ struct fsentry * list ,
169
166
const WIN32_FIND_DATAW * fdata )
170
167
{
171
168
char buf [MAX_PATH * 3 ];
172
169
int len ;
173
170
struct fsentry * fse ;
174
171
len = xwcstoutf (buf , fdata -> cFileName , ARRAY_SIZE (buf ));
175
172
176
- fse = fsentry_alloc (list , buf , len );
173
+ fse = fsentry_alloc (cache , list , buf , len );
177
174
178
175
fse -> st_mode = file_attr_to_st_mode (fdata -> dwFileAttributes );
179
176
fse -> dirent .d_type = S_ISDIR (fse -> st_mode ) ? DT_DIR : DT_REG ;
@@ -191,7 +188,7 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
191
188
* Dir should not contain trailing '/'. Use an empty string for the current
192
189
* directory (not "."!).
193
190
*/
194
- static struct fsentry * fsentry_create_list (const struct fsentry * dir ,
191
+ static struct fsentry * fsentry_create_list (struct fscache * cache , const struct fsentry * dir ,
195
192
int * dir_not_found )
196
193
{
197
194
wchar_t pattern [MAX_PATH + 2 ]; /* + 2 for '/' '*' */
@@ -230,14 +227,14 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
230
227
}
231
228
232
229
/* allocate object to hold directory listing */
233
- list = fsentry_alloc (NULL , dir -> dirent .d_name , dir -> len );
230
+ list = fsentry_alloc (cache , NULL , dir -> dirent .d_name , dir -> len );
234
231
list -> st_mode = S_IFDIR ;
235
232
list -> dirent .d_type = DT_DIR ;
236
233
237
234
/* walk directory and build linked list of fsentry structures */
238
235
phead = & list -> next ;
239
236
do {
240
- * phead = fseentry_create_entry (list , & fdata );
237
+ * phead = fseentry_create_entry (cache , list , & fdata );
241
238
phead = & (* phead )-> next ;
242
239
} while (FindNextFileW (h , & fdata ));
243
240
@@ -249,7 +246,7 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
249
246
if (err == ERROR_NO_MORE_FILES )
250
247
return list ;
251
248
252
- /* otherwise free the list and return error */
249
+ /* otherwise release the list and return error */
253
250
fsentry_release (list );
254
251
errno = err_win_to_posix (err );
255
252
return NULL ;
@@ -272,7 +269,9 @@ static void fscache_add(struct fscache *cache, struct fsentry *fse)
272
269
*/
273
270
static void fscache_clear (struct fscache * cache )
274
271
{
275
- hashmap_clear_and_free (& cache -> map , struct fsentry , ent );
272
+ mem_pool_discard (& cache -> mem_pool , 0 );
273
+ mem_pool_init (& cache -> mem_pool , 0 );
274
+ hashmap_clear (& cache -> map );
276
275
hashmap_init (& cache -> map , (hashmap_cmp_fn )fsentry_cmp , NULL , 0 );
277
276
cache -> lstat_requests = cache -> opendir_requests = 0 ;
278
277
cache -> fscache_misses = cache -> fscache_requests = 0 ;
@@ -325,7 +324,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
325
324
}
326
325
327
326
/* create the directory listing */
328
- fse = fsentry_create_list (key -> list ? key -> list : key , & dir_not_found );
327
+ fse = fsentry_create_list (cache , key -> list ? key -> list : key , & dir_not_found );
329
328
330
329
/* leave on error (errno set by fsentry_create_list) */
331
330
if (!fse ) {
@@ -335,7 +334,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
335
334
* empty, which for all practical matters is the same
336
335
* thing as far as fscache is concerned).
337
336
*/
338
- fse = fsentry_alloc (key -> list -> list ,
337
+ fse = fsentry_alloc (cache , key -> list -> list ,
339
338
key -> list -> dirent .d_name ,
340
339
key -> list -> len );
341
340
fse -> st_mode = 0 ;
@@ -414,6 +413,7 @@ int fscache_enable(size_t initial_size)
414
413
* '4' was determined empirically by testing several repos
415
414
*/
416
415
hashmap_init (& cache -> map , (hashmap_cmp_fn )fsentry_cmp , NULL , initial_size * 4 );
416
+ mem_pool_init (& cache -> mem_pool , 0 );
417
417
if (!TlsSetValue (dwTlsIndex , cache ))
418
418
BUG ("TlsSetValue error" );
419
419
}
@@ -445,7 +445,8 @@ void fscache_disable(void)
445
445
"total requests/misses %u/%u\n" ,
446
446
cache -> lstat_requests , cache -> opendir_requests ,
447
447
cache -> fscache_requests , cache -> fscache_misses );
448
- fscache_clear (cache );
448
+ mem_pool_discard (& cache -> mem_pool , 0 );
449
+ hashmap_clear (& cache -> map );
449
450
free (cache );
450
451
}
451
452
@@ -630,6 +631,8 @@ void fscache_merge(struct fscache *dest)
630
631
while ((e = hashmap_iter_next (& iter )))
631
632
hashmap_add (& dest -> map , e );
632
633
634
+ mem_pool_combine (& dest -> mem_pool , & cache -> mem_pool );
635
+
633
636
dest -> lstat_requests += cache -> lstat_requests ;
634
637
dest -> opendir_requests += cache -> opendir_requests ;
635
638
dest -> fscache_requests += cache -> fscache_requests ;
0 commit comments