From: "Alex Bennée" <alex.bennee@linaro.org>
To: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: qemu-devel@nongnu.org, mst@redhat.com
Subject: Re: [PATCH v3 3/4] vhost-user-rng: backend: Add RNG vhost-user daemon implementation
Date: Wed, 21 Jul 2021 21:14:31 +0100 [thread overview]
Message-ID: <87fsw7xw2s.fsf@linaro.org> (raw)
In-Reply-To: <20210710005929.1702431-4-mathieu.poirier@linaro.org>
Mathieu Poirier <mathieu.poirier@linaro.org> writes:
> This patch provides the vhost-user backend implementation to work
> in tandem with the vhost-user-rng implementation of the QEMU VMM.
>
> It uses the vhost-user API so that other VMM can re-use the interface
> without having to write the driver again.
>
> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Try the following patch which creates a nested main loop and runs it
until the g_timeout_add fires again.
--8<---------------cut here---------------start------------->8---
tools/virtio/vhost-user-rng: avoid mutex by using nested main loop
As we are blocking anyway all we really need to do is run a main loop
until the timer fires and the data is consumed.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
1 file changed, 30 insertions(+), 76 deletions(-)
tools/vhost-user-rng/main.c | 106 +++++++++++++-------------------------------
modified tools/vhost-user-rng/main.c
@@ -42,13 +42,10 @@
typedef struct {
VugDev dev;
- struct itimerspec ts;
- timer_t rate_limit_timer;
- pthread_mutex_t rng_mutex;
- pthread_cond_t rng_cond;
int64_t quota_remaining;
- bool activate_timer;
+ guint timer;
GMainLoop *loop;
+ GMainLoop *blocked;
} VuRNG;
static gboolean print_cap, verbose;
@@ -59,66 +56,26 @@ static gint source_fd, socket_fd = -1;
static uint32_t period_ms = 1 << 16;
static uint64_t max_bytes = INT64_MAX;
-static void check_rate_limit(union sigval sv)
+static gboolean check_rate_limit(gpointer user_data)
{
- VuRNG *rng = sv.sival_ptr;
- bool wakeup = false;
+ VuRNG *rng = (VuRNG *) user_data;
- pthread_mutex_lock(&rng->rng_mutex);
- /*
- * The timer has expired and the guest has used all available
- * entropy, which means function vu_rng_handle_request() is waiting
- * on us. As such wake it up once we're done here.
- */
- if (rng->quota_remaining == 0) {
- wakeup = true;
+ if (rng->blocked) {
+ g_info("%s: called while blocked", __func__);
+ g_main_loop_quit(rng->blocked);
}
-
/*
* Reset the entropy available to the guest and tell function
* vu_rng_handle_requests() to start the timer before using it.
*/
rng->quota_remaining = max_bytes;
- rng->activate_timer = true;
- pthread_mutex_unlock(&rng->rng_mutex);
-
- if (wakeup) {
- pthread_cond_signal(&rng->rng_cond);
- }
-}
-
-static void setup_timer(VuRNG *rng)
-{
- struct sigevent sev;
- int ret;
-
- memset(&rng->ts, 0, sizeof(struct itimerspec));
- rng->ts.it_value.tv_sec = period_ms / 1000;
- rng->ts.it_value.tv_nsec = (period_ms % 1000) * 1000000;
-
- /*
- * Call function check_rate_limit() as if it was the start of
- * a new thread when the timer expires.
- */
- sev.sigev_notify = SIGEV_THREAD;
- sev.sigev_notify_function = check_rate_limit;
- sev.sigev_value.sival_ptr = rng;
- /* Needs to be NULL if defaults attributes are to be used. */
- sev.sigev_notify_attributes = NULL;
- ret = timer_create(CLOCK_MONOTONIC, &sev, &rng->rate_limit_timer);
- if (ret < 0) {
- fprintf(stderr, "timer_create() failed\n");
- }
-
+ return true;
}
-
/* Virtio helpers */
static uint64_t rng_get_features(VuDev *dev)
{
- if (verbose) {
- g_info("%s: replying", __func__);
- }
+ g_info("%s: replying", __func__);
return 0;
}
@@ -137,7 +94,7 @@ static void vu_rng_handle_requests(VuDev *dev, int qidx)
VuVirtq *vq = vu_get_queue(dev, qidx);
VuVirtqElement *elem;
size_t to_read;
- int len, ret;
+ int len;
for (;;) {
/* Get element in the vhost virtqueue */
@@ -149,24 +106,21 @@ static void vu_rng_handle_requests(VuDev *dev, int qidx)
/* Get the amount of entropy to read from the vhost server */
to_read = elem->in_sg[0].iov_len;
- pthread_mutex_lock(&rng->rng_mutex);
-
/*
* We have consumed all entropy available for this time slice.
* Wait for the timer (check_rate_limit()) to tell us about the
* start of a new time slice.
*/
if (rng->quota_remaining == 0) {
- pthread_cond_wait(&rng->rng_cond, &rng->rng_mutex);
- }
-
- /* Start the timer if the last time slice has expired */
- if (rng->activate_timer == true) {
- rng->activate_timer = false;
- ret = timer_settime(rng->rate_limit_timer, 0, &rng->ts, NULL);
- if (ret < 0) {
- fprintf(stderr, "timer_settime() failed\n");
- }
+ g_assert(!rng->blocked);
+ rng->blocked = g_main_loop_new(g_main_loop_get_context(rng->loop), false);
+ g_info("attempting to consume %ld bytes but no quota left (%s)",
+ to_read,
+ g_main_loop_is_running(rng->loop) ? "running" : "not running");
+ g_main_loop_run(rng->blocked);
+ g_info("return from blocked loop: %ld", rng->quota_remaining);
+ g_main_loop_unref(rng->blocked);
+ rng->blocked = false;
}
/* Make sure we don't read more than it's available */
@@ -183,8 +137,6 @@ static void vu_rng_handle_requests(VuDev *dev, int qidx)
rng->quota_remaining -= len;
- pthread_mutex_unlock(&rng->rng_mutex);
-
vu_queue_push(dev, vq, elem, len);
free(elem);
}
@@ -373,6 +325,7 @@ int main(int argc, char *argv[])
* can add it's GSource watches.
*/
rng.loop = g_main_loop_new(NULL, FALSE);
+ rng.blocked = NULL;
if (!vug_init(&rng.dev, 1, g_socket_get_fd(socket),
panic, &vuiface)) {
@@ -380,24 +333,25 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
- rng.quota_remaining = max_bytes;
- rng.activate_timer = true;
- pthread_mutex_init(&rng.rng_mutex, NULL);
- pthread_cond_init(&rng.rng_cond, NULL);
- setup_timer(&rng);
-
if (verbose) {
- g_info("period_ms: %d tv_sec: %ld tv_nsec: %lu\n",
- period_ms, rng.ts.it_value.tv_sec, rng.ts.it_value.tv_nsec);
+ g_log_set_handler(NULL, G_LOG_LEVEL_MASK, g_log_default_handler, NULL);
+ g_setenv("G_MESSAGES_DEBUG", "all", true);
+ } else {
+ g_log_set_handler(NULL,
+ G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR,
+ g_log_default_handler, NULL);
}
+ rng.quota_remaining = max_bytes;
+ rng.timer = g_timeout_add(period_ms, check_rate_limit, &rng);
+ g_info("period_ms: %"PRId32", timer %d\n", period_ms, rng.timer);
+
g_message("entering main loop, awaiting messages");
g_main_loop_run(rng.loop);
g_message("finished main loop, cleaning up");
g_main_loop_unref(rng.loop);
vug_deinit(&rng.dev);
- timer_delete(rng.rate_limit_timer);
close(source_fd);
unlink(socket_path);
}
--8<---------------cut here---------------end--------------->8---
--
Alex Bennée
next prev parent reply other threads:[~2021-07-21 20:24 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-07-10 0:59 [PATCH v3 0/4] virtio: Add vhost-user based RNG Mathieu Poirier
2021-07-10 0:59 ` [PATCH v3 1/4] vhost-user-rng: Add vhost-user-rng implementation Mathieu Poirier
2021-07-21 8:52 ` Alex Bennée
2021-07-22 16:44 ` Mathieu Poirier
2021-07-10 0:59 ` [PATCH v3 2/4] vhost-user-rng-pci: Add vhost-user-rng-pci implementation Mathieu Poirier
2021-07-21 8:56 ` Alex Bennée
2021-07-21 20:15 ` Alex Bennée
2021-07-10 0:59 ` [PATCH v3 3/4] vhost-user-rng: backend: Add RNG vhost-user daemon implementation Mathieu Poirier
2021-07-21 11:30 ` Alex Bennée
2021-07-21 20:14 ` Alex Bennée [this message]
2021-07-22 17:54 ` Mathieu Poirier
2021-07-23 9:01 ` Alex Bennée
2021-07-10 0:59 ` [PATCH v3 4/4] docs: Add documentation for vhost based RNG implementation Mathieu Poirier
2021-07-21 16:55 ` Alex Bennée
2021-07-17 20:32 ` [PATCH v3 0/4] virtio: Add vhost-user based RNG Michael S. Tsirkin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87fsw7xw2s.fsf@linaro.org \
--to=alex.bennee@linaro.org \
--cc=mathieu.poirier@linaro.org \
--cc=mst@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.