diff --git a/src/tup/file.c b/src/tup/file.c index c14f551b4..fe7047f75 100644 --- a/src/tup/file.c +++ b/src/tup/file.c @@ -46,7 +46,12 @@ static int add_parser_files_locked(struct file_info *finfo, struct tent_entries *root, tupid_t vardt, int full_deps); -static _Thread_local struct mempool pool = MEMPOOL_INITIALIZER(struct file_entry); +// Note it will not work with per-thread pools here because all the allocation +// is done by the fuse server thread while all the free is done by the +// worker threads. Thus the free'd memory cannot be reused by the fuse server +// thread so the memory usage just keeps growing. +static struct mempool pool = MEMPOOL_INITIALIZER(struct file_entry); +static pthread_mutex_t pool_lock = PTHREAD_MUTEX_INITIALIZER; int init_file_info(struct file_info *info, int do_unlink) { @@ -549,7 +554,9 @@ static struct file_entry *new_entry(const char *filename) { struct file_entry *fent; + pthread_mutex_lock(&pool_lock); fent = mempool_alloc(&pool); + pthread_mutex_unlock(&pool_lock); if(!fent) { return NULL; } @@ -557,7 +564,9 @@ static struct file_entry *new_entry(const char *filename) fent->filename = strdup(filename); if(!fent->filename) { perror("strdup"); + pthread_mutex_lock(&pool_lock); mempool_free(&pool, fent); + pthread_mutex_unlock(&pool_lock); return NULL; } return fent; @@ -567,7 +576,9 @@ void del_file_entry(struct file_entry_head *head, struct file_entry *fent) { TAILQ_REMOVE(head, fent, list); free(fent->filename); + pthread_mutex_lock(&pool_lock); mempool_free(&pool, fent); + pthread_mutex_unlock(&pool_lock); } int handle_rename(const char *from, const char *to, struct file_info *info) diff --git a/src/tup/mempool.c b/src/tup/mempool.c index 5c7f01ab9..a59556a6d 100644 --- a/src/tup/mempool.c +++ b/src/tup/mempool.c @@ -48,7 +48,7 @@ void *mempool_alloc(struct mempool *pool) * memory allocated here is not freed until the program quits. */ if(pool->item_size < sizeof(struct mementry)) { - fprintf(stderr, "tup internal error: mempool item size too small: %i\n", pool->item_size); + fprintf(stderr, "tup internal error: mempool item size too small: %zu\n", pool->item_size); return NULL; } @@ -79,7 +79,7 @@ void *mempool_alloc(struct mempool *pool) * next item from the pool's memory. */ if(((uintptr_t)pool->mem & (pool->alignment-1)) != 0) { - fprintf(stderr, "tup internal error: memory address in mempool (%p) not aligned to %u bytes.\n", pool->mem, pool->alignment); + fprintf(stderr, "tup internal error: memory address in mempool (%p) not aligned to %zu bytes.\n", pool->mem, pool->alignment); return NULL; } ret = (void*)pool->mem; diff --git a/src/tup/mempool.h b/src/tup/mempool.h index 50f88f256..0bcbcf734 100644 --- a/src/tup/mempool.h +++ b/src/tup/mempool.h @@ -23,6 +23,8 @@ #include "bsd/queue.h" +#include + struct mementry { SLIST_ENTRY(mementry) list; }; @@ -30,10 +32,10 @@ SLIST_HEAD(mementry_head, mementry); struct mempool { struct mementry_head free_list; - unsigned int item_size; - unsigned int next_alloc_size; - unsigned int alignment; - int free_count; + size_t item_size; + size_t next_alloc_size; + size_t alignment; + size_t free_count; char *mem; }; TAILQ_HEAD(mempool_head, mempool);