aboutsummaryrefslogtreecommitdiff
path: root/lib/fuse_mt.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/fuse_mt.c')
-rw-r--r--lib/fuse_mt.c111
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);
+ }
+}