/* * Virtio 9p backend * * Copyright IBM, Corp. 2010 * * Authors: * Harsh Prateek Bora * Venkateswararao Jujjuri(JV) * * This work is licensed under the terms of the GNU GPL, version 2. See * the COPYING file in the top-level directory. * */ #include "fsdev/qemu-fsdev.h" #include "qemu/thread.h" #include "block/coroutine.h" #include "virtio-9p-coth.h" /* v9fs glib thread pool */ static V9fsThPool v9fs_pool; void co_run_in_worker_bh(void *opaque) { Coroutine *co = opaque; g_thread_pool_push(v9fs_pool.pool, co, NULL); } static void v9fs_qemu_process_req_done(void *arg) { char byte; ssize_t len; Coroutine *co; do { len = read(v9fs_pool.rfd, &byte, sizeof(byte)); } while (len == -1 && errno == EINTR); while ((co = g_async_queue_try_pop(v9fs_pool.completed)) != NULL) { qemu_coroutine_enter(co, NULL); } } static void v9fs_thread_routine(gpointer data, gpointer user_data) { ssize_t len; char byte = 0; Coroutine *co = data; qemu_coroutine_enter(co, NULL); g_async_queue_push(v9fs_pool.completed, co); do { len = write(v9fs_pool.wfd, &byte, sizeof(byte)); } while (len == -1 && errno == EINTR); } int v9fs_init_worker_threads(void) { int ret = 0; int notifier_fds[2]; V9fsThPool *p = &v9fs_pool; sigset_t set, oldset; sigfillset(&set); /* Leave signal handling to the iothread. */ pthread_sigmask(SIG_SETMASK, &set, &oldset); if (qemu_pipe(notifier_fds) == -1) { ret = -1; goto err_out; } p->pool = g_thread_pool_new(v9fs_thread_routine, p, -1, FALSE, NULL); if (!p->pool) { ret = -1; goto err_out; } p->completed = g_async_queue_new(); if (!p->completed) { /* * We are going to terminate. * So don't worry about cleanup */ ret = -1; goto err_out; } p->rfd = notifier_fds[0]; p->wfd = notifier_fds[1]; fcntl(p->rfd, F_SETFL, O_NONBLOCK); fcntl(p->wfd, F_SETFL, O_NONBLOCK); qemu_set_fd_handler(p->rfd, v9fs_qemu_process_req_done, NULL, NULL); err_out: pthread_sigmask(SIG_SETMASK, &oldset, NULL); return ret; }