diff options
author | 2001-11-18 19:15:05 +0000 | |
---|---|---|
committer | 2001-11-18 19:15:05 +0000 | |
commit | 43696434f8fd5cd1107658f329b6922ea947ed1f (patch) | |
tree | a0aaf6056690245d3fe946bbb32fc9c80d74fd2a /lib/fuse_mt.c | |
parent | 07d2849a34149dd350e8a028e4b8012eb1d622be (diff) |
performance improvements
Diffstat (limited to 'lib/fuse_mt.c')
-rw-r--r-- | lib/fuse_mt.c | 97 |
1 files changed, 83 insertions, 14 deletions
diff --git a/lib/fuse_mt.c b/lib/fuse_mt.c index 19cc33c..6120554 100644 --- a/lib/fuse_mt.c +++ b/lib/fuse_mt.c @@ -13,23 +13,64 @@ #include <string.h> #include <pthread.h> #include <signal.h> +#include <errno.h> +#include <sys/time.h> -struct fuse_thr_data { +#define FUSE_WORKER_IDLE 10 + +static pthread_mutex_t fuse_mt_lock = PTHREAD_MUTEX_INITIALIZER; + + +struct fuse_worker { + struct fuse_worker *next; + struct fuse_worker *prev; struct fuse *f; void *data; fuse_processor_t proc; struct fuse_cmd *cmd; + int avail; + pthread_cond_t start; }; static void *do_work(void *data) { - struct fuse_thr_data *d = (struct fuse_thr_data *) data; - d->proc(d->f, d->cmd, d->data); - free(d); + struct fuse_worker *w = (struct fuse_worker *) data; + int ret; + + do { + struct timeval now; + struct timespec timeout; + + w->proc(w->f, w->cmd, w->data); + + pthread_mutex_lock(&fuse_mt_lock); + w->avail = 1; + w->cmd = NULL; + gettimeofday(&now, NULL); + timeout.tv_sec = now.tv_sec + FUSE_WORKER_IDLE; + timeout.tv_nsec = now.tv_usec * 1000; + + ret = 0; + while(w->cmd == NULL && ret != ETIMEDOUT) + ret = pthread_cond_timedwait(&w->start, &fuse_mt_lock, &timeout); + + if(ret == ETIMEDOUT) { + struct fuse_worker *next = w->next; + struct fuse_worker *prev = w->prev; + prev->next = next; + next->prev = prev; + pthread_cond_destroy(&w->start); + free(w); + } + w->avail = 0; + pthread_mutex_unlock(&fuse_mt_lock); + + } while(ret != ETIMEDOUT); + return NULL; } -static void start_thread(struct fuse_thr_data *d) +static void start_thread(struct fuse_worker *w) { pthread_t thrid; sigset_t oldset; @@ -39,7 +80,7 @@ static void start_thread(struct fuse_thr_data *d) /* Disallow signal reception in worker threads */ sigfillset(&newset); pthread_sigmask(SIG_SETMASK, &newset, &oldset); - res = pthread_create(&thrid, NULL, do_work, d); + res = pthread_create(&thrid, NULL, do_work, w); pthread_sigmask(SIG_SETMASK, &oldset, NULL); if(res != 0) { fprintf(stderr, "Error creating thread: %s\n", strerror(res)); @@ -50,19 +91,47 @@ static void start_thread(struct fuse_thr_data *d) void __fuse_loop_mt(struct fuse *f, fuse_processor_t proc, void *data) { + struct fuse_worker *head; + + head = malloc(sizeof(struct fuse_worker)); + head->next = head; + head->prev = head; + while(1) { - struct fuse_thr_data *d; + struct fuse_worker *w; struct fuse_cmd *cmd = __fuse_read_cmd(f); if(cmd == NULL) exit(1); - d = malloc(sizeof(struct fuse_thr_data)); - d->proc = proc; - d->f = f; - d->cmd = cmd; - d->data = data; - - start_thread(d); + pthread_mutex_lock(&fuse_mt_lock); + for(w = head->next; w != head; w = w->next) + if(w->avail) + break; + + if(w != head) { + pthread_cond_signal(&w->start); + w->cmd = cmd; + w = NULL; + } + else { + struct fuse_worker *prev = head->prev; + struct fuse_worker *next = head; + w = malloc(sizeof(struct fuse_worker)); + w->prev = prev; + w->next = next; + next->prev = w; + prev->next = w; + w->f = f; + w->data = data; + w->proc = proc; + w->cmd = cmd; + w->avail = 0; + pthread_cond_init(&w->start, NULL); + } + pthread_mutex_unlock(&fuse_mt_lock); + + if(w != NULL) + start_thread(w); } } |