2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
5 This program can be distributed under the terms of the GNU LGPL.
6 See the file COPYING.LIB.
9 #include "fuse_lowlevel.h"
10 #include "fuse_misc.h"
21 struct fuse_worker
*prev
;
22 struct fuse_worker
*next
;
33 struct fuse_session
*se
;
34 struct fuse_chan
*prevch
;
35 struct fuse_worker main
;
40 static void list_add_worker(struct fuse_worker
*w
, struct fuse_worker
*next
)
42 struct fuse_worker
*prev
= next
->prev
;
49 static void list_del_worker(struct fuse_worker
*w
)
51 struct fuse_worker
*prev
= w
->prev
;
52 struct fuse_worker
*next
= w
->next
;
57 static int fuse_start_thread(struct fuse_mt
*mt
);
59 static void *fuse_do_work(void *data
)
61 struct fuse_worker
*w
= (struct fuse_worker
*) data
;
62 struct fuse_mt
*mt
= w
->mt
;
64 while (!fuse_session_exited(mt
->se
)) {
65 struct fuse_chan
*ch
= mt
->prevch
;
66 int res
= fuse_chan_recv(&ch
, w
->buf
, w
->bufsize
);
71 fuse_session_exit(mt
->se
);
77 pthread_mutex_lock(&mt
->lock
);
79 pthread_mutex_unlock(&mt
->lock
);
83 if (mt
->numavail
== 0)
84 fuse_start_thread(mt
);
85 pthread_mutex_unlock(&mt
->lock
);
87 fuse_session_process(mt
->se
, w
->buf
, res
, ch
);
89 pthread_mutex_lock(&mt
->lock
);
91 if (mt
->numavail
> 10) {
93 pthread_mutex_unlock(&mt
->lock
);
99 pthread_mutex_unlock(&mt
->lock
);
101 pthread_detach(w
->thread_id
);
106 pthread_mutex_unlock(&mt
->lock
);
109 pthread_kill(mt
->main
.thread_id
, SIGHUP
);
115 static int fuse_start_thread(struct fuse_mt
*mt
)
120 struct fuse_worker
*w
= malloc(sizeof(struct fuse_worker
));
122 fprintf(stderr
, "fuse: failed to allocate worker structure\n");
125 memset(w
, 0, sizeof(struct fuse_worker
));
126 w
->bufsize
= fuse_chan_bufsize(mt
->prevch
);
127 w
->buf
= malloc(w
->bufsize
);
130 fprintf(stderr
, "fuse: failed to allocate read buffer\n");
135 /* Disallow signal reception in worker threads */
136 sigemptyset(&newset
);
137 sigaddset(&newset
, SIGTERM
);
138 sigaddset(&newset
, SIGINT
);
139 sigaddset(&newset
, SIGHUP
);
140 sigaddset(&newset
, SIGQUIT
);
141 pthread_sigmask(SIG_BLOCK
, &newset
, &oldset
);
142 res
= pthread_create(&w
->thread_id
, NULL
, fuse_do_work
, w
);
143 pthread_sigmask(SIG_SETMASK
, &oldset
, NULL
);
145 fprintf(stderr
, "fuse: error creating thread: %s\n", strerror(res
));
148 list_add_worker(w
, &mt
->main
);
155 static void fuse_join_worker(struct fuse_mt
*mt
, struct fuse_worker
*w
)
157 pthread_join(w
->thread_id
, NULL
);
158 pthread_mutex_lock(&mt
->lock
);
160 pthread_mutex_unlock(&mt
->lock
);
165 int fuse_session_loop_mt(struct fuse_session
*se
)
169 struct fuse_worker
*w
;
171 memset(&mt
, 0, sizeof(struct fuse_mt
));
173 mt
.prevch
= fuse_session_next_chan(se
, NULL
);
177 mt
.main
.thread_id
= pthread_self();
178 mt
.main
.prev
= mt
.main
.next
= &mt
.main
;
179 fuse_mutex_init(&mt
.lock
);
181 pthread_mutex_lock(&mt
.lock
);
182 err
= fuse_start_thread(&mt
);
183 pthread_mutex_unlock(&mt
.lock
);
185 while (!fuse_session_exited(se
))
188 for (w
= mt
.main
.next
; w
!= &mt
.main
; w
= w
->next
)
189 pthread_cancel(w
->thread_id
);
191 pthread_mutex_unlock(&mt
.lock
);
193 while (mt
.main
.next
!= &mt
.main
)
194 fuse_join_worker(&mt
, mt
.main
.next
);
199 pthread_mutex_destroy(&mt
.lock
);
200 fuse_session_reset(se
);