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