Re: [Qemu-devel] [PATCH 3/3] Add helper functions for virtio-9p to use threadlets
On Tue, Oct 19, 2010 at 6:43 PM, Arun R Bharadwaj a...@linux.vnet.ibm.com wrote: From: Gautham R Shenoy e...@in.ibm.com Add helper functions to enable virtio-9p make use of the threadlets infrastructure for offloading blocking tasks such as making posix calls on to the helper threads and handle the post_posix_operations() from the context of the iothread. This frees the vcpu thread to process any other guest operations while the processing of v9fs_io is in progress. Signed-off-by: Gautham R Shenoy e...@in.ibm.com Signed-off-by: Sripathi Kodi sripat...@in.ibm.com Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com --- hw/virtio-9p.c | 165 posix-aio-compat.c | 33 +++--- qemu-threadlets.c | 21 +++ qemu-threadlets.h | 1 vl.c | 3 + 5 files changed, 200 insertions(+), 23 deletions(-) I wish --enable-io-thread was the default and only model. The signals and pipes are ugly and should be hidden behind a QEMU eventfd abstraction, which would also reduce the code duplication between posix-aio-compat.c and virtio-9p. I'm not asking you to do this but I hope we'll get there eventually. Does anyone know why non-io-thread still exists and is used by default? diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c index a871685..174300d 100644 --- a/hw/virtio-9p.c +++ b/hw/virtio-9p.c @@ -18,6 +18,7 @@ #include fsdev/qemu-fsdev.h #include virtio-9p-debug.h #include virtio-9p-xattr.h +#include qemu-threadlets.h int debug_9p_pdu; @@ -33,6 +34,146 @@ enum { Oappend = 0x80, }; +struct v9fs_post_op { + QTAILQ_ENTRY(v9fs_post_op) node; + void (*func)(void *arg); + void *arg; +}; + +static struct { + int rfd; + int wfd; + QemuMutex lock; + QTAILQ_HEAD(, v9fs_post_op) post_op_list; +} v9fs_async_struct; + +static void die2(int err, const char *what) +{ + fprintf(stderr, %s failed: %s\n, what, strerror(err)); + abort(); +} + +static void die(const char *what) +{ + die2(errno, what); +} + +#define ASYNC_MAX_PROCESS 5 What does this constant define? I think it is an arbitrary limit on the amount of work you want to do per v9fs_process_post_ops() call? + +/** + * v9fs_process_post_ops: Process any pending v9fs_post_posix_operation + * @arg: Not used. + * + * This function serves as a callback to the iothread to be called into whenever + * the v9fs_async_struct.wfd is written into. This thread goes through the list + * of v9fs_post_posix_operations() and executes them. In the process, it might + * queue more job on the asynchronous thread pool. + */ +static void v9fs_process_post_ops(void *arg) +{ + int count = 0; + struct v9fs_post_op *post_op; + int ret; + char byte; + + qemu_mutex_lock(v9fs_async_struct.lock); + do { + ret = read(v9fs_async_struct.rfd, byte, sizeof(byte)); + } while (ret = 0 errno != EAGAIN); ret = 0 errno != EAGAIN looks odd to me. Should be ||? + + for (count = 0; count ASYNC_MAX_PROCESS; count++) { + if (QTAILQ_EMPTY((v9fs_async_struct.post_op_list))) { + break; + } + post_op = QTAILQ_FIRST((v9fs_async_struct.post_op_list)); + QTAILQ_REMOVE((v9fs_async_struct.post_op_list), post_op, node); + + qemu_mutex_unlock(v9fs_async_struct.lock); + post_op-func(post_op-arg); + qemu_free(post_op); + qemu_mutex_lock(v9fs_async_struct.lock); + } + qemu_mutex_unlock(v9fs_async_struct.lock); +} + +/** + * v9fs_async_signal: Inform the io-thread of completion of async job. + * + * This function is used to inform the iothread that a particular + * async-operation pertaining to v9fs has been completed and that the io thread + * can handle the v9fs_post_posix_operation. + * + * This is based on the aio_signal_handler + */ +static inline void v9fs_async_signal(void) +{ + char byte = 0; + ssize_t ret; + int tries = 0; + + qemu_mutex_lock(v9fs_async_struct.lock); + do { + assert(tries != 100); + ret = write(v9fs_async_struct.wfd, byte, sizeof(byte)); + tries++; + } while (ret 0 errno == EAGAIN); + qemu_mutex_unlock(v9fs_async_struct.lock); + + if (ret 0 errno != EAGAIN) + die(write() in v9fs); + + if (kill(getpid(), SIGUSR2)) die(kill failed); +} + +/** + * v9fs_async_helper_done: Marks the completion of the v9fs_async job + * @func: v9fs_post_posix_func() for post-processing invoked in the context of + * the io-thread + * @arg: Argument to func. + * + * This function is called from the context of one of the asynchronous threads + * in the thread pool. This is called when the asynchronous thread has finished + * executing a v9fs_posix_operation. It's purpose is to initiate the process of + * informing the io-thread that the v9fs_posix_operation has completed. + */ +static
Re: [Qemu-devel] [PATCH 3/3] Add helper functions for virtio-9p to use threadlets
On 10/20/2010 06:19 AM, Stefan Hajnoczi wrote: On Tue, Oct 19, 2010 at 6:43 PM, Arun R Bharadwaj a...@linux.vnet.ibm.com wrote: From: Gautham R Shenoye...@in.ibm.com Add helper functions to enable virtio-9p make use of the threadlets infrastructure for offloading blocking tasks such as making posix calls on to the helper threads and handle the post_posix_operations() from the context of the iothread. This frees the vcpu thread to process any other guest operations while the processing of v9fs_io is in progress. Signed-off-by: Gautham R Shenoye...@in.ibm.com Signed-off-by: Sripathi Kodisripat...@in.ibm.com Signed-off-by: Arun R Bharadwaja...@linux.vnet.ibm.com --- hw/virtio-9p.c | 165 posix-aio-compat.c | 33 +++--- qemu-threadlets.c | 21 +++ qemu-threadlets.h |1 vl.c |3 + 5 files changed, 200 insertions(+), 23 deletions(-) I wish --enable-io-thread was the default and only model. The signals and pipes are ugly and should be hidden behind a QEMU eventfd abstraction, which would also reduce the code duplication between posix-aio-compat.c and virtio-9p. I'm not asking you to do this but I hope we'll get there eventually. Does anyone know why non-io-thread still exists and is used by default? There are still issues with --enable-io-thread and TCG. Regards, Anthony Liguori
[Qemu-devel] [PATCH 3/3] Add helper functions for virtio-9p to use threadlets
From: Gautham R Shenoy e...@in.ibm.com Add helper functions to enable virtio-9p make use of the threadlets infrastructure for offloading blocking tasks such as making posix calls on to the helper threads and handle the post_posix_operations() from the context of the iothread. This frees the vcpu thread to process any other guest operations while the processing of v9fs_io is in progress. Signed-off-by: Gautham R Shenoy e...@in.ibm.com Signed-off-by: Sripathi Kodi sripat...@in.ibm.com Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com --- hw/virtio-9p.c | 165 posix-aio-compat.c | 33 +++--- qemu-threadlets.c | 21 +++ qemu-threadlets.h |1 vl.c |3 + 5 files changed, 200 insertions(+), 23 deletions(-) diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c index a871685..174300d 100644 --- a/hw/virtio-9p.c +++ b/hw/virtio-9p.c @@ -18,6 +18,7 @@ #include fsdev/qemu-fsdev.h #include virtio-9p-debug.h #include virtio-9p-xattr.h +#include qemu-threadlets.h int debug_9p_pdu; @@ -33,6 +34,146 @@ enum { Oappend = 0x80, }; +struct v9fs_post_op { +QTAILQ_ENTRY(v9fs_post_op) node; +void (*func)(void *arg); +void *arg; +}; + +static struct { +int rfd; +int wfd; +QemuMutex lock; +QTAILQ_HEAD(, v9fs_post_op) post_op_list; +} v9fs_async_struct; + +static void die2(int err, const char *what) +{ +fprintf(stderr, %s failed: %s\n, what, strerror(err)); +abort(); +} + +static void die(const char *what) +{ +die2(errno, what); +} + +#define ASYNC_MAX_PROCESS 5 + +/** + * v9fs_process_post_ops: Process any pending v9fs_post_posix_operation + * @arg: Not used. + * + * This function serves as a callback to the iothread to be called into whenever + * the v9fs_async_struct.wfd is written into. This thread goes through the list + * of v9fs_post_posix_operations() and executes them. In the process, it might + * queue more job on the asynchronous thread pool. + */ +static void v9fs_process_post_ops(void *arg) +{ +int count = 0; +struct v9fs_post_op *post_op; +int ret; +char byte; + +qemu_mutex_lock(v9fs_async_struct.lock); +do { +ret = read(v9fs_async_struct.rfd, byte, sizeof(byte)); +} while (ret = 0 errno != EAGAIN); + +for (count = 0; count ASYNC_MAX_PROCESS; count++) { +if (QTAILQ_EMPTY((v9fs_async_struct.post_op_list))) { + break; +} +post_op = QTAILQ_FIRST((v9fs_async_struct.post_op_list)); +QTAILQ_REMOVE((v9fs_async_struct.post_op_list), post_op, node); + +qemu_mutex_unlock(v9fs_async_struct.lock); +post_op-func(post_op-arg); +qemu_free(post_op); +qemu_mutex_lock(v9fs_async_struct.lock); +} +qemu_mutex_unlock(v9fs_async_struct.lock); +} + +/** + * v9fs_async_signal: Inform the io-thread of completion of async job. + * + * This function is used to inform the iothread that a particular + * async-operation pertaining to v9fs has been completed and that the io thread + * can handle the v9fs_post_posix_operation. + * + * This is based on the aio_signal_handler + */ +static inline void v9fs_async_signal(void) +{ +char byte = 0; +ssize_t ret; +int tries = 0; + +qemu_mutex_lock(v9fs_async_struct.lock); +do { +assert(tries != 100); + ret = write(v9fs_async_struct.wfd, byte, sizeof(byte)); +tries++; +} while (ret 0 errno == EAGAIN); +qemu_mutex_unlock(v9fs_async_struct.lock); + +if (ret 0 errno != EAGAIN) +die(write() in v9fs); + +if (kill(getpid(), SIGUSR2)) die(kill failed); +} + +/** + * v9fs_async_helper_done: Marks the completion of the v9fs_async job + * @func: v9fs_post_posix_func() for post-processing invoked in the context of + *the io-thread + * @arg: Argument to func. + * + * This function is called from the context of one of the asynchronous threads + * in the thread pool. This is called when the asynchronous thread has finished + * executing a v9fs_posix_operation. It's purpose is to initiate the process of + * informing the io-thread that the v9fs_posix_operation has completed. + */ +static void v9fs_async_helper_done(void (*func)(void *arg), void *arg) +{ +struct v9fs_post_op *post_op; + +post_op = qemu_mallocz(sizeof(*post_op)); +post_op-func = func; +post_op-arg = arg; + +qemu_mutex_lock(v9fs_async_struct.lock); +QTAILQ_INSERT_TAIL((v9fs_async_struct.post_op_list), post_op, node); +qemu_mutex_unlock(v9fs_async_struct.lock); + +v9fs_async_signal(); +} + +/** + * v9fs_do_async_posix: Offload v9fs_posix_operation onto async thread. + * @vs: V9fsOPState variable for the OP operation. + * @posix_fn: The posix function which has to be offloaded onto async thread. + * @post_fn_ptr: Address of the location to hold the post_fn corresponding to + * the posix_fn + * @post_fn: The post processing function corresponding to the posix_fn. + * + * This
[Qemu-devel] [PATCH 3/3] Add helper functions for virtio-9p to use threadlets
From: Gautham R Shenoy e...@in.ibm.com Add helper functions to enable virtio-9p make use of the threadlets infrastructure for offloading blocking tasks such as making posix calls on to the helper threads and handle the post_posix_operations() from the context of the iothread. This frees the vcpu thread to process any other guest operations while the processing of v9fs_io is in progress. Signed-off-by: Gautham R Shenoy e...@in.ibm.com Signed-off-by: Sripathi Kodi sripat...@in.ibm.com Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com --- hw/virtio-9p.c | 165 posix-aio-compat.c | 33 +++--- qemu-threadlets.c | 21 +++ qemu-threadlets.h |1 vl.c |3 + 5 files changed, 200 insertions(+), 23 deletions(-) diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c index a871685..174300d 100644 --- a/hw/virtio-9p.c +++ b/hw/virtio-9p.c @@ -18,6 +18,7 @@ #include fsdev/qemu-fsdev.h #include virtio-9p-debug.h #include virtio-9p-xattr.h +#include qemu-threadlets.h int debug_9p_pdu; @@ -33,6 +34,146 @@ enum { Oappend = 0x80, }; +struct v9fs_post_op { +QTAILQ_ENTRY(v9fs_post_op) node; +void (*func)(void *arg); +void *arg; +}; + +static struct { +int rfd; +int wfd; +QemuMutex lock; +QTAILQ_HEAD(, v9fs_post_op) post_op_list; +} v9fs_async_struct; + +static void die2(int err, const char *what) +{ +fprintf(stderr, %s failed: %s\n, what, strerror(err)); +abort(); +} + +static void die(const char *what) +{ +die2(errno, what); +} + +#define ASYNC_MAX_PROCESS 5 + +/** + * v9fs_process_post_ops: Process any pending v9fs_post_posix_operation + * @arg: Not used. + * + * This function serves as a callback to the iothread to be called into whenever + * the v9fs_async_struct.wfd is written into. This thread goes through the list + * of v9fs_post_posix_operations() and executes them. In the process, it might + * queue more job on the asynchronous thread pool. + */ +static void v9fs_process_post_ops(void *arg) +{ +int count = 0; +struct v9fs_post_op *post_op; +int ret; +char byte; + +qemu_mutex_lock(v9fs_async_struct.lock); +do { +ret = read(v9fs_async_struct.rfd, byte, sizeof(byte)); +} while (ret = 0 errno != EAGAIN); + +for (count = 0; count ASYNC_MAX_PROCESS; count++) { +if (QTAILQ_EMPTY((v9fs_async_struct.post_op_list))) { + break; +} +post_op = QTAILQ_FIRST((v9fs_async_struct.post_op_list)); +QTAILQ_REMOVE((v9fs_async_struct.post_op_list), post_op, node); + +qemu_mutex_unlock(v9fs_async_struct.lock); +post_op-func(post_op-arg); +qemu_free(post_op); +qemu_mutex_lock(v9fs_async_struct.lock); +} +qemu_mutex_unlock(v9fs_async_struct.lock); +} + +/** + * v9fs_async_signal: Inform the io-thread of completion of async job. + * + * This function is used to inform the iothread that a particular + * async-operation pertaining to v9fs has been completed and that the io thread + * can handle the v9fs_post_posix_operation. + * + * This is based on the aio_signal_handler + */ +static inline void v9fs_async_signal(void) +{ +char byte = 0; +ssize_t ret; +int tries = 0; + +qemu_mutex_lock(v9fs_async_struct.lock); +do { +assert(tries != 100); + ret = write(v9fs_async_struct.wfd, byte, sizeof(byte)); +tries++; +} while (ret 0 errno == EAGAIN); +qemu_mutex_unlock(v9fs_async_struct.lock); + +if (ret 0 errno != EAGAIN) +die(write() in v9fs); + +if (kill(getpid(), SIGUSR2)) die(kill failed); +} + +/** + * v9fs_async_helper_done: Marks the completion of the v9fs_async job + * @func: v9fs_post_posix_func() for post-processing invoked in the context of + *the io-thread + * @arg: Argument to func. + * + * This function is called from the context of one of the asynchronous threads + * in the thread pool. This is called when the asynchronous thread has finished + * executing a v9fs_posix_operation. It's purpose is to initiate the process of + * informing the io-thread that the v9fs_posix_operation has completed. + */ +static void v9fs_async_helper_done(void (*func)(void *arg), void *arg) +{ +struct v9fs_post_op *post_op; + +post_op = qemu_mallocz(sizeof(*post_op)); +post_op-func = func; +post_op-arg = arg; + +qemu_mutex_lock(v9fs_async_struct.lock); +QTAILQ_INSERT_TAIL((v9fs_async_struct.post_op_list), post_op, node); +qemu_mutex_unlock(v9fs_async_struct.lock); + +v9fs_async_signal(); +} + +/** + * v9fs_do_async_posix: Offload v9fs_posix_operation onto async thread. + * @vs: V9fsOPState variable for the OP operation. + * @posix_fn: The posix function which has to be offloaded onto async thread. + * @post_fn_ptr: Address of the location to hold the post_fn corresponding to + * the posix_fn + * @post_fn: The post processing function corresponding to the posix_fn. + * + * This
[Qemu-devel] [PATCH 3/3]: Add helper functions for virtio-9p to use threadlets
* Arun R Bharadwaj a...@linux.vnet.ibm.com [2010-10-13 22:14:39]: commit 1da2167c0c68bf24a841affa1bf6d2510cb675f2 Author: Gautham R Shenoy e...@in.ibm.com Date: Wed Oct 13 15:09:20 2010 +0530 Add helper functions for virtio-9p to use threadlets Add helper functions to enable virtio-9p make use of the threadlets infrastructure for offloading blocking tasks such as making posix calls on to the helper threads and handle the post_posix_operations() from the context of the iothread. This frees the vcpu thread to process any other guest operations while the processing of v9fs_io is in progress. Signed-off-by: Gautham R Shenoy e...@in.ibm.com Signed-off-by: Sripathi Kodi sripat...@in.ibm.com Signed-off-by: Arun R Bharadwaj a...@linux.vnet.ibm.com diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c index 3b2d49c..08af480 100644 --- a/hw/virtio-9p.c +++ b/hw/virtio-9p.c @@ -17,6 +17,7 @@ #include virtio-9p.h #include fsdev/qemu-fsdev.h #include virtio-9p-debug.h +#include qemu-threadlets.h int debug_9p_pdu; @@ -32,6 +33,146 @@ enum { Oappend = 0x80, }; +struct v9fs_post_op { +QTAILQ_ENTRY(v9fs_post_op) node; +void (*func)(void *arg); +void *arg; +}; + +static struct { +int rfd; +int wfd; +QemuMutex lock; +QTAILQ_HEAD(, v9fs_post_op) post_op_list; +} v9fs_async_struct; + +static void die2(int err, const char *what) +{ +fprintf(stderr, %s failed: %s\n, what, strerror(err)); +abort(); +} + +static void die(const char *what) +{ +die2(errno, what); +} + +#define ASYNC_MAX_PROCESS 5 + +/** + * v9fs_process_post_ops: Process any pending v9fs_post_posix_operation + * @arg: Not used. + * + * This function serves as a callback to the iothread to be called into whenever + * the v9fs_async_struct.wfd is written into. This thread goes through the list + * of v9fs_post_posix_operations() and executes them. In the process, it might + * queue more job on the asynchronous thread pool. + */ +static void v9fs_process_post_ops(void *arg) +{ +int count = 0; +struct v9fs_post_op *post_op; +int ret; +char byte; + +qemu_mutex_lock(v9fs_async_struct.lock); +do { +ret = read(v9fs_async_struct.rfd, byte, sizeof(byte)); +} while (ret = 0 errno != EAGAIN); + +for (count = 0; count ASYNC_MAX_PROCESS; count++) { +if (QTAILQ_EMPTY((v9fs_async_struct.post_op_list))) { + break; +} +post_op = QTAILQ_FIRST((v9fs_async_struct.post_op_list)); +QTAILQ_REMOVE((v9fs_async_struct.post_op_list), post_op, node); + +qemu_mutex_unlock(v9fs_async_struct.lock); +post_op-func(post_op-arg); +qemu_free(post_op); +qemu_mutex_lock(v9fs_async_struct.lock); +} +qemu_mutex_unlock(v9fs_async_struct.lock); +} + +/** + * v9fs_async_signal: Inform the io-thread of completion of async job. + * + * This function is used to inform the iothread that a particular + * async-operation pertaining to v9fs has been completed and that the io thread + * can handle the v9fs_post_posix_operation. + * + * This is based on the aio_signal_handler + */ +static inline void v9fs_async_signal(void) +{ +char byte = 0; +ssize_t ret; +int tries = 0; + +qemu_mutex_lock(v9fs_async_struct.lock); +do { +assert(tries != 100); + ret = write(v9fs_async_struct.wfd, byte, sizeof(byte)); +tries++; +} while (ret 0 errno == EAGAIN); +qemu_mutex_unlock(v9fs_async_struct.lock); + +if (ret 0 errno != EAGAIN) +die(write() in v9fs); + +if (kill(getpid(), SIGUSR2)) die(kill failed); +} + +/** + * v9fs_async_helper_done: Marks the completion of the v9fs_async job + * @func: v9fs_post_posix_func() for post-processing invoked in the context of + *the io-thread + * @arg: Argument to func. + * + * This function is called from the context of one of the asynchronous threads + * in the thread pool. This is called when the asynchronous thread has finished + * executing a v9fs_posix_operation. It's purpose is to initiate the process of + * informing the io-thread that the v9fs_posix_operation has completed. + */ +static void v9fs_async_helper_done(void (*func)(void *arg), void *arg) +{ +struct v9fs_post_op *post_op; + +post_op = qemu_mallocz(sizeof(*post_op)); +post_op-func = func; +post_op-arg = arg; + +qemu_mutex_lock(v9fs_async_struct.lock); +QTAILQ_INSERT_TAIL((v9fs_async_struct.post_op_list), post_op, node); +qemu_mutex_unlock(v9fs_async_struct.lock); + +v9fs_async_signal(); +} + +/** + * v9fs_do_async_posix: Offload v9fs_posix_operation onto async thread. + * @vs: V9fsOPState variable for the OP operation. + * @posix_fn: The posix function which has to be offloaded onto async thread. + * @post_fn_ptr: Address of the location to hold the post_fn corresponding to + * the posix_fn + * @post_fn: The post processing function corresponding to the posix_fn. + * + * This function is a helper to