aboutsummaryrefslogtreecommitdiff
path: root/lib/fuse_mt.c
diff options
context:
space:
mode:
authorGravatar Miklos Szeredi <miklos@szeredi.hu>2001-11-18 19:15:05 +0000
committerGravatar Miklos Szeredi <miklos@szeredi.hu>2001-11-18 19:15:05 +0000
commit43696434f8fd5cd1107658f329b6922ea947ed1f (patch)
treea0aaf6056690245d3fe946bbb32fc9c80d74fd2a /lib/fuse_mt.c
parent07d2849a34149dd350e8a028e4b8012eb1d622be (diff)
performance improvements
Diffstat (limited to 'lib/fuse_mt.c')
-rw-r--r--lib/fuse_mt.c97
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);
}
}