@@ -1,14 +1,37 @@
#ifndef KVM__THREADPOOL_H
#define KVM__THREADPOOL_H
+#include "kvm/mutex.h"
+
+#include <linux/list.h>
+
struct kvm;
typedef void (*kvm_thread_callback_fn_t)(struct kvm *kvm, void *data);
-int thread_pool__init(unsigned long thread_count);
+struct thread_pool__job {
+ kvm_thread_callback_fn_t callback;
+ struct kvm *kvm;
+ void *data;
+
+ int signalcount;
+ pthread_mutex_t mutex;
-void *thread_pool__add_job(struct kvm *kvm, kvm_thread_callback_fn_t callback, void *data);
+ struct list_head queue;
+};
+
+static inline void thread_pool__init_job(struct thread_pool__job *job, struct kvm *kvm, kvm_thread_callback_fn_t callback, void *data)
+{
+ *job = (struct thread_pool__job) {
+ .kvm = kvm,
+ .callback = callback,
+ .data = data,
+ .mutex = PTHREAD_MUTEX_INITIALIZER,
+ };
+}
+
+int thread_pool__init(unsigned long thread_count);
-void thread_pool__do_job(void *job);
+void thread_pool__do_job(struct thread_pool__job *job);
#endif
@@ -6,17 +6,6 @@
#include <pthread.h>
#include <stdbool.h>
-struct thread_pool__job {
- kvm_thread_callback_fn_t callback;
- struct kvm *kvm;
- void *data;
-
- int signalcount;
- pthread_mutex_t mutex;
-
- struct list_head queue;
-};
-
static pthread_mutex_t job_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t job_cond = PTHREAD_COND_INITIALIZER;
@@ -139,26 +128,11 @@ int thread_pool__init(unsigned long thread_count)
return i;
}
-void *thread_pool__add_job(struct kvm *kvm,
- kvm_thread_callback_fn_t callback, void *data)
-{
- struct thread_pool__job *job = calloc(1, sizeof(*job));
-
- *job = (struct thread_pool__job) {
- .kvm = kvm,
- .data = data,
- .callback = callback,
- .mutex = PTHREAD_MUTEX_INITIALIZER
- };
-
- return job;
-}
-
-void thread_pool__do_job(void *job)
+void thread_pool__do_job(struct thread_pool__job *job)
{
struct thread_pool__job *jobinfo = job;
- if (jobinfo == NULL)
+ if (jobinfo == NULL || jobinfo->callback == NULL)
return;
mutex_lock(&jobinfo->mutex);
@@ -46,9 +46,9 @@ struct p9_fid {
};
struct p9_dev_job {
- struct virt_queue *vq;
- struct p9_dev *p9dev;
- void *job_id;
+ struct virt_queue *vq;
+ struct p9_dev *p9dev;
+ struct thread_pool__job job_id;
};
struct p9_dev {
@@ -696,7 +696,7 @@ static void ioevent_callback(struct kvm *kvm, void *param)
{
struct p9_dev_job *job = param;
- thread_pool__do_job(job->job_id);
+ thread_pool__do_job(&job->job_id);
}
static bool virtio_p9_pci_io_out(struct ioport *ioport, struct kvm *kvm,
@@ -731,7 +731,7 @@ static bool virtio_p9_pci_io_out(struct ioport *ioport, struct kvm *kvm,
.vq = queue,
.p9dev = p9dev,
};
- job->job_id = thread_pool__add_job(kvm, virtio_p9_do_io, job);
+ thread_pool__init_job(&job->job_id, kvm, virtio_p9_do_io, job);
ioevent = (struct ioevent) {
.io_addr = p9dev->base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
@@ -754,7 +754,7 @@ static bool virtio_p9_pci_io_out(struct ioport *ioport, struct kvm *kvm,
u16 queue_index;
queue_index = ioport__read16(data);
- thread_pool__do_job(p9dev->jobs[queue_index].job_id);
+ thread_pool__do_job(&p9dev->jobs[queue_index].job_id);
break;
}
case VIRTIO_PCI_STATUS:
@@ -31,7 +31,7 @@
struct blk_dev_job {
struct virt_queue *vq;
struct blk_dev *bdev;
- void *job_id;
+ struct thread_pool__job job_id;
};
struct blk_dev {
@@ -206,7 +206,7 @@ static bool virtio_blk_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 po
.bdev = bdev,
};
- job->job_id = thread_pool__add_job(kvm, virtio_blk_do_io, job);
+ thread_pool__init_job(&job->job_id, kvm, virtio_blk_do_io, job);
break;
}
@@ -217,7 +217,7 @@ static bool virtio_blk_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 po
u16 queue_index;
queue_index = ioport__read16(data);
- thread_pool__do_job(bdev->jobs[queue_index].job_id);
+ thread_pool__do_job(&bdev->jobs[queue_index].job_id);
break;
}
@@ -248,7 +248,7 @@ static void ioevent_callback(struct kvm *kvm, void *param)
{
struct blk_dev_job *job = param;
- thread_pool__do_job(job->job_id);
+ thread_pool__do_job(&job->job_id);
}
void virtio_blk__init(struct kvm *kvm, struct disk_image *disk)
@@ -51,7 +51,7 @@ struct con_dev {
u16 queue_selector;
u16 base_addr;
- void *jobs[VIRTIO_CONSOLE_NUM_QUEUES];
+ struct thread_pool__job jobs[VIRTIO_CONSOLE_NUM_QUEUES];
};
static struct con_dev cdev = {
@@ -93,7 +93,7 @@ static void virtio_console__inject_interrupt_callback(struct kvm *kvm, void *par
void virtio_console__inject_interrupt(struct kvm *kvm)
{
- thread_pool__do_job(cdev.jobs[VIRTIO_CONSOLE_RX_QUEUE]);
+ thread_pool__do_job(&cdev.jobs[VIRTIO_CONSOLE_RX_QUEUE]);
}
static bool virtio_console_pci_io_device_specific_in(void *data, unsigned long offset, int size, u32 count)
@@ -203,9 +203,9 @@ static bool virtio_console_pci_io_out(struct ioport *ioport, struct kvm *kvm, u1
vring_init(&queue->vring, VIRTIO_CONSOLE_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
if (cdev.queue_selector == VIRTIO_CONSOLE_TX_QUEUE)
- cdev.jobs[cdev.queue_selector] = thread_pool__add_job(kvm, virtio_console_handle_callback, queue);
+ thread_pool__init_job(&cdev.jobs[cdev.queue_selector], kvm, virtio_console_handle_callback, queue);
else if (cdev.queue_selector == VIRTIO_CONSOLE_RX_QUEUE)
- cdev.jobs[cdev.queue_selector] = thread_pool__add_job(kvm, virtio_console__inject_interrupt_callback, queue);
+ thread_pool__init_job(&cdev.jobs[cdev.queue_selector], kvm, virtio_console__inject_interrupt_callback, queue);
break;
}
@@ -214,7 +214,7 @@ static bool virtio_console_pci_io_out(struct ioport *ioport, struct kvm *kvm, u1
break;
case VIRTIO_PCI_QUEUE_NOTIFY: {
u16 queue_index = ioport__read16(data);
- thread_pool__do_job(cdev.jobs[queue_index]);
+ thread_pool__do_job(&cdev.jobs[queue_index]);
break;
}
case VIRTIO_PCI_STATUS:
@@ -21,13 +21,13 @@
#include <sys/stat.h>
#include <pthread.h>
-#define NUM_VIRT_QUEUES 1
-#define VIRTIO_RNG_QUEUE_SIZE 128
+#define NUM_VIRT_QUEUES 1
+#define VIRTIO_RNG_QUEUE_SIZE 128
struct rng_dev_job {
- struct virt_queue *vq;
- struct rng_dev *rdev;
- void *job_id;
+ struct virt_queue *vq;
+ struct rng_dev *rdev;
+ struct thread_pool__job job_id;
};
struct rng_dev {
@@ -146,7 +146,7 @@ static bool virtio_rng_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 po
.rdev = rdev,
};
- job->job_id = thread_pool__add_job(kvm, virtio_rng_do_io, job);
+ thread_pool__init_job(&job->job_id, kvm, virtio_rng_do_io, job);
break;
}
@@ -156,7 +156,7 @@ static bool virtio_rng_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 po
case VIRTIO_PCI_QUEUE_NOTIFY: {
u16 queue_index;
queue_index = ioport__read16(data);
- thread_pool__do_job(rdev->jobs[queue_index].job_id);
+ thread_pool__do_job(&rdev->jobs[queue_index].job_id);
break;
}
case VIRTIO_PCI_STATUS:
@@ -182,7 +182,7 @@ static void ioevent_callback(struct kvm *kvm, void *param)
{
struct rng_dev_job *job = param;
- thread_pool__do_job(job->job_id);
+ thread_pool__do_job(&job->job_id);
}
void virtio_rng__init(struct kvm *kvm)
To allow efficient use of shorter-term threadpool jobs, don't allocate them dynamically upon creation. Instead, store them within 'job' structures. This will prevent some overhead creating/destroying jobs which live for a short time. Signed-off-by: Sasha Levin <levinsasha928@gmail.com> --- tools/kvm/include/kvm/threadpool.h | 29 ++++++++++++++++++++++++++--- tools/kvm/threadpool.c | 30 ++---------------------------- tools/kvm/virtio/9p.c | 12 ++++++------ tools/kvm/virtio/blk.c | 8 ++++---- tools/kvm/virtio/console.c | 10 +++++----- tools/kvm/virtio/rng.c | 16 ++++++++-------- 6 files changed, 51 insertions(+), 54 deletions(-)