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 ;
@@ -106,11 +108,11 @@ static void fsentry_init(struct fsentry *fse, struct fsentry *list,
106
108
/*
107
109
* Allocate an fsentry structure on the heap.
108
110
*/
109
- static struct fsentry * fsentry_alloc (struct fsentry * list , const char * name ,
111
+ static struct fsentry * fsentry_alloc (struct fscache * cache , struct fsentry * list , const char * name ,
110
112
size_t len )
111
113
{
112
114
/* overallocate fsentry and copy the name to the end */
113
- struct fsentry * fse = xmalloc ( sizeof (struct fsentry ) + len + 1 );
115
+ struct fsentry * fse = mem_pool_alloc ( cache -> mem_pool , sizeof (struct fsentry ) + len + 1 );
114
116
char * nm = ((char * ) fse ) + sizeof (struct fsentry );
115
117
memcpy (nm , name , len );
116
118
nm [len ] = 0 ;
@@ -133,35 +135,28 @@ inline static void fsentry_addref(struct fsentry *fse)
133
135
}
134
136
135
137
/*
136
- * Release the reference to an fsentry, frees the memory if its the last ref .
138
+ * Release the reference to an fsentry.
137
139
*/
138
140
static void fsentry_release (struct fsentry * fse )
139
141
{
140
142
if (fse -> list )
141
143
fse = fse -> list ;
142
144
143
- if (InterlockedDecrement (& (fse -> u .refcnt )))
144
- return ;
145
-
146
- while (fse ) {
147
- struct fsentry * next = fse -> next ;
148
- free (fse );
149
- fse = next ;
150
- }
145
+ InterlockedDecrement (& (fse -> u .refcnt ));
151
146
}
152
147
153
148
/*
154
149
* Allocate and initialize an fsentry from a WIN32_FIND_DATA structure.
155
150
*/
156
- static struct fsentry * fseentry_create_entry (struct fsentry * list ,
151
+ static struct fsentry * fseentry_create_entry (struct fscache * cache , struct fsentry * list ,
157
152
const WIN32_FIND_DATAW * fdata )
158
153
{
159
154
char buf [MAX_PATH * 3 ];
160
155
int len ;
161
156
struct fsentry * fse ;
162
157
len = xwcstoutf (buf , fdata -> cFileName , ARRAY_SIZE (buf ));
163
158
164
- fse = fsentry_alloc (list , buf , len );
159
+ fse = fsentry_alloc (cache , list , buf , len );
165
160
166
161
fse -> st_mode = file_attr_to_st_mode (fdata -> dwFileAttributes );
167
162
fse -> u .s .st_size = (((off64_t ) (fdata -> nFileSizeHigh )) << 32 )
@@ -178,7 +173,7 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
178
173
* Dir should not contain trailing '/'. Use an empty string for the current
179
174
* directory (not "."!).
180
175
*/
181
- static struct fsentry * fsentry_create_list (const struct fsentry * dir ,
176
+ static struct fsentry * fsentry_create_list (struct fscache * cache , const struct fsentry * dir ,
182
177
int * dir_not_found )
183
178
{
184
179
wchar_t pattern [MAX_PATH + 2 ]; /* + 2 for '/' '*' */
@@ -216,13 +211,13 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
216
211
}
217
212
218
213
/* allocate object to hold directory listing */
219
- list = fsentry_alloc (NULL , dir -> name , dir -> len );
214
+ list = fsentry_alloc (cache , NULL , dir -> name , dir -> len );
220
215
list -> st_mode = S_IFDIR ;
221
216
222
217
/* walk directory and build linked list of fsentry structures */
223
218
phead = & list -> next ;
224
219
do {
225
- * phead = fseentry_create_entry (list , & fdata );
220
+ * phead = fseentry_create_entry (cache , list , & fdata );
226
221
phead = & (* phead )-> next ;
227
222
} while (FindNextFileW (h , & fdata ));
228
223
@@ -234,7 +229,7 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
234
229
if (err == ERROR_NO_MORE_FILES )
235
230
return list ;
236
231
237
- /* otherwise free the list and return error */
232
+ /* otherwise release the list and return error */
238
233
fsentry_release (list );
239
234
errno = err_win_to_posix (err );
240
235
return NULL ;
@@ -257,7 +252,10 @@ static void fscache_add(struct fscache *cache, struct fsentry *fse)
257
252
*/
258
253
static void fscache_clear (struct fscache * cache )
259
254
{
260
- hashmap_free (& cache -> map , 1 );
255
+ mem_pool_discard (cache -> mem_pool , 0 );
256
+ cache -> mem_pool = NULL ;
257
+ mem_pool_init (& cache -> mem_pool , 0 );
258
+ hashmap_free (& cache -> map , 0 );
261
259
hashmap_init (& cache -> map , (hashmap_cmp_fn )fsentry_cmp , NULL , 0 );
262
260
cache -> lstat_requests = cache -> opendir_requests = 0 ;
263
261
cache -> fscache_misses = cache -> fscache_requests = 0 ;
@@ -310,7 +308,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
310
308
}
311
309
312
310
/* create the directory listing */
313
- fse = fsentry_create_list (key -> list ? key -> list : key , & dir_not_found );
311
+ fse = fsentry_create_list (cache , key -> list ? key -> list : key , & dir_not_found );
314
312
315
313
/* leave on error (errno set by fsentry_create_list) */
316
314
if (!fse ) {
@@ -320,7 +318,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
320
318
* empty, which for all practical matters is the same
321
319
* thing as far as fscache is concerned).
322
320
*/
323
- fse = fsentry_alloc (key -> list -> list ,
321
+ fse = fsentry_alloc (cache , key -> list -> list ,
324
322
key -> list -> name , key -> list -> len );
325
323
fse -> st_mode = 0 ;
326
324
hashmap_add (& cache -> map , fse );
@@ -398,6 +396,7 @@ int fscache_enable(size_t initial_size)
398
396
* '4' was determined empirically by testing several repos
399
397
*/
400
398
hashmap_init (& cache -> map , (hashmap_cmp_fn )fsentry_cmp , NULL , initial_size * 4 );
399
+ mem_pool_init (& cache -> mem_pool , 0 );
401
400
if (!TlsSetValue (dwTlsIndex , cache ))
402
401
BUG ("TlsSetValue error" );
403
402
}
@@ -429,7 +428,8 @@ void fscache_disable(void)
429
428
"total requests/misses %u/%u\n" ,
430
429
cache -> lstat_requests , cache -> opendir_requests ,
431
430
cache -> fscache_requests , cache -> fscache_misses );
432
- fscache_clear (cache );
431
+ mem_pool_discard (cache -> mem_pool , 0 );
432
+ hashmap_free (& cache -> map , 0 );
433
433
free (cache );
434
434
}
435
435
@@ -611,6 +611,8 @@ void fscache_merge(struct fscache *dest)
611
611
while ((e = hashmap_iter_next (& iter )))
612
612
hashmap_add (& dest -> map , e );
613
613
614
+ mem_pool_combine (dest -> mem_pool , cache -> mem_pool );
615
+
614
616
dest -> lstat_requests += cache -> lstat_requests ;
615
617
dest -> opendir_requests += cache -> opendir_requests ;
616
618
dest -> fscache_requests += cache -> fscache_requests ;
0 commit comments