tizen 2.3.1 release
[external/qemu.git] / hw / 9pfs / virtio-9p-coth.c
1 /*
2  * Virtio 9p backend
3  *
4  * Copyright IBM, Corp. 2010
5  *
6  * Authors:
7  *  Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
8  *  Venkateswararao Jujjuri(JV) <jvrao@linux.vnet.ibm.com>
9  *
10  * This work is licensed under the terms of the GNU GPL, version 2.  See
11  * the COPYING file in the top-level directory.
12  *
13  */
14
15 #include "fsdev/qemu-fsdev.h"
16 #include "qemu/thread.h"
17 #include "block/coroutine.h"
18 #include "virtio-9p-coth.h"
19
20 /* v9fs glib thread pool */
21 static V9fsThPool v9fs_pool;
22
23 void co_run_in_worker_bh(void *opaque)
24 {
25     Coroutine *co = opaque;
26     g_thread_pool_push(v9fs_pool.pool, co, NULL);
27 }
28
29 static void v9fs_qemu_process_req_done(void *arg)
30 {
31     char byte;
32     ssize_t len;
33     Coroutine *co;
34
35     do {
36         len = read(v9fs_pool.rfd, &byte, sizeof(byte));
37     } while (len == -1 &&  errno == EINTR);
38
39     while ((co = g_async_queue_try_pop(v9fs_pool.completed)) != NULL) {
40         qemu_coroutine_enter(co, NULL);
41     }
42 }
43
44 static void v9fs_thread_routine(gpointer data, gpointer user_data)
45 {
46     ssize_t len;
47     char byte = 0;
48     Coroutine *co = data;
49
50     qemu_coroutine_enter(co, NULL);
51
52     g_async_queue_push(v9fs_pool.completed, co);
53     do {
54         len = write(v9fs_pool.wfd, &byte, sizeof(byte));
55     } while (len == -1 && errno == EINTR);
56 }
57
58 int v9fs_init_worker_threads(void)
59 {
60     int ret = 0;
61     int notifier_fds[2];
62     V9fsThPool *p = &v9fs_pool;
63     sigset_t set, oldset;
64
65     sigfillset(&set);
66     /* Leave signal handling to the iothread.  */
67     pthread_sigmask(SIG_SETMASK, &set, &oldset);
68
69     if (qemu_pipe(notifier_fds) == -1) {
70         ret = -1;
71         goto err_out;
72     }
73     p->pool = g_thread_pool_new(v9fs_thread_routine, p, -1, FALSE, NULL);
74     if (!p->pool) {
75         ret = -1;
76         goto err_out;
77     }
78     p->completed = g_async_queue_new();
79     if (!p->completed) {
80         /*
81          * We are going to terminate.
82          * So don't worry about cleanup
83          */
84         ret = -1;
85         goto err_out;
86     }
87     p->rfd = notifier_fds[0];
88     p->wfd = notifier_fds[1];
89
90     fcntl(p->rfd, F_SETFL, O_NONBLOCK);
91     fcntl(p->wfd, F_SETFL, O_NONBLOCK);
92
93     qemu_set_fd_handler(p->rfd, v9fs_qemu_process_req_done, NULL, NULL);
94 err_out:
95     pthread_sigmask(SIG_SETMASK, &oldset, NULL);
96     return ret;
97 }