34
35
struct base_data {
36
struct base_data *base;
37
- struct base_data *child;
37
struct object_entry *obj;
38
void *data;
39
unsigned long size;
43
44
struct thread_local {
45
pthread_t thread;
47
- struct base_data *base_cache;
46
size_t base_cache_used;
47
int pack_fd;
48
};
378
}
379
}
380
383
-static void prune_base_data(struct base_data *retain)
381
+static void prune_base_data(struct base_data *youngest_child)
382
{
383
struct base_data *b;
384
struct thread_local *data = get_thread_data();
387
- for (b = data->base_cache;
388
- data->base_cache_used > delta_base_cache_limit && b;
389
- b = b->child) {
390
- if (b->data && b != retain)
391
- free_base_data(b);
385
+ struct base_data **ancestry = NULL;
386
+ size_t nr = 0, alloc = 0;
387
+ ssize_t i;
388
+
389
+ if (data->base_cache_used <= delta_base_cache_limit)
390
+ return;
391
+
392
+ /*
393
+ * Free all ancestors of youngest_child until we have enough space,
394
+ * starting with the oldest. (We cannot free youngest_child itself.)
395
+ */
396
+ for (b = youngest_child->base; b != NULL; b = b->base) {
397
+ ALLOC_GROW(ancestry, nr + 1, alloc);
398
+ ancestry[nr++] = b;
399
}
400
+ for (i = nr - 1;
401
+ i >= 0 && data->base_cache_used > delta_base_cache_limit;
402
+ i--) {
403
+ if (ancestry[i]->data)
404
+ free_base_data(ancestry[i]);
405
+ }
406
+ free(ancestry);
407
}
408
409
static void link_base_data(struct base_data *base, struct base_data *c)
410
{
397
- if (base)
398
- base->child = c;
399
- else
400
- get_thread_data()->base_cache = c;
401
-
411
c->base = base;
403
- c->child = NULL;
412
if (c->data)
413
get_thread_data()->base_cache_used += c->size;
414
prune_base_data(c);
416
417
static void unlink_base_data(struct base_data *c)
418
{
411
- struct base_data *base = c->base;
412
- if (base)
413
- base->child = NULL;
414
- else
415
- get_thread_data()->base_cache = NULL;
419
free_base_data(c);
420
}
421