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