diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2001-11-16 10:12:59 +0000 |
---|---|---|
committer | Miklos Szeredi <miklos@szeredi.hu> | 2001-11-16 10:12:59 +0000 |
commit | fff56ab1242e3ad7cddf15e7e981da55d06c4da5 (patch) | |
tree | baca68469ea73b679ac2e74aba52e7312e0ea7a8 /lib/fuse_mt.c | |
parent | 39f28679ed1c313bbeea85d370d95f62551bb21b (diff) | |
download | libfuse-fff56ab1242e3ad7cddf15e7e981da55d06c4da5.tar.gz |
better thread management
Diffstat (limited to 'lib/fuse_mt.c')
-rw-r--r-- | lib/fuse_mt.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/lib/fuse_mt.c b/lib/fuse_mt.c new file mode 100644 index 0000000..ac616fe --- /dev/null +++ b/lib/fuse_mt.c @@ -0,0 +1,111 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001 Miklos Szeredi (mszeredi@inf.bme.hu) + + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. +*/ + +#include "fuse.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <pthread.h> +#include <signal.h> +#include <sys/time.h> + + +struct thread_common { + struct fuse *f; + struct fuse_cmd *cmd; + pthread_mutex_t lock; + pthread_cond_t cond; + int avail; +}; + +/* Called with c->lock held */ +static void *do_work(void *data) +{ + struct thread_common *c = (struct thread_common *) data; + struct fuse *f = c->f; + + c->avail ++; + while(1) { + int res; + struct timespec timeout; + struct timeval now; + struct fuse_cmd *cmd; + + gettimeofday(&now, NULL); + timeout.tv_sec = now.tv_sec + 1; + timeout.tv_nsec = now.tv_usec * 1000; + + res = 0; + while(c->cmd == NULL && res != ETIMEDOUT) + res = pthread_cond_timedwait(&c->cond, &c->lock, &timeout); + if(res == ETIMEDOUT) + break; + + cmd = c->cmd; + c->cmd = NULL; + c->avail --; + pthread_mutex_unlock(&c->lock); + __fuse_process_cmd(f, cmd); + pthread_mutex_lock(&c->lock); + c->avail ++; + } + + c->avail --; + pthread_mutex_unlock(&c->lock); + return NULL; +} + +static void start_thread(struct thread_common *c) +{ + pthread_attr_t attr; + pthread_t thrid; + sigset_t oldset; + sigset_t newset; + int res; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + /* Disallow signal reception in worker threads */ + sigfillset(&newset); + sigprocmask(SIG_SETMASK, &newset, &oldset); + res = pthread_create(&thrid, &attr, do_work, c); + sigprocmask(SIG_SETMASK, &oldset, NULL); + pthread_mutex_lock(&c->lock); + if(res != 0) { + fprintf(stderr, "Error creating thread: %s\n", strerror(res)); + exit(1); + } +} + +void fuse_loop_mt(struct fuse *f) +{ + struct thread_common *c; + + c = (struct thread_common *) malloc(sizeof(struct thread_common)); + c->f = f; + c->cmd = NULL; + pthread_cond_init(&c->cond, NULL); + pthread_mutex_init(&c->lock, NULL); + c->avail = 0; + + while(1) { + struct fuse_cmd *cmd = __fuse_read_cmd(f); + if(cmd == NULL) + exit(1); + + pthread_mutex_lock(&c->lock); + c->cmd = cmd; + while(c->avail == 0) + start_thread(c); + pthread_cond_signal(&c->cond); + pthread_mutex_unlock(&c->lock); + } +} |