From: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
To: qemu-devel@nongnu.org
Cc: peter.maydell@linaro.org, peter.crosthwaite@xilinx.com,
alex.bennee@linaro.org, mark.burton@greensocs.com,
real@ispras.ru, batuzovk@ispras.ru,
maria.klimushenkova@ispras.ru, pavel.dovgaluk@ispras.ru,
pbonzini@redhat.com, afaerber@suse.de, fred.konrad@greensocs.com
Subject: [Qemu-devel] [RFC PATCH v4 20/25] replay: bottom halves
Date: Fri, 07 Nov 2014 13:33:21 +0300 [thread overview]
Message-ID: <20141107103321.6136.72502.stgit@PASHA-ISP> (raw)
In-Reply-To: <20141107103123.6136.18545.stgit@PASHA-ISP>
This patch introduces bottom half event for replay queue. It saves the events
into the queue and process them at the checkpoints and instructions execution.
Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
---
async.c | 46 ++++++++++++++++++++++++++++++++++++++++------
dma-helpers.c | 4 +++-
hw/ide/ahci.c | 4 +++-
hw/ide/core.c | 4 +++-
hw/timer/arm_timer.c | 2 +-
hw/usb/hcd-uhci.c | 2 +-
include/block/aio.h | 18 ++++++++++++++++++
include/qemu/main-loop.h | 1 +
main-loop.c | 5 +++++
replay/replay-events.c | 16 ++++++++++++++++
replay/replay-internal.h | 3 ++-
replay/replay.h | 2 ++
stubs/replay.c | 4 ++++
13 files changed, 99 insertions(+), 12 deletions(-)
diff --git a/async.c b/async.c
index 6e1b282..97111c0 100644
--- a/async.c
+++ b/async.c
@@ -27,6 +27,7 @@
#include "block/thread-pool.h"
#include "qemu/main-loop.h"
#include "qemu/atomic.h"
+#include "replay/replay.h"
/***********************************************************/
/* bottom halves (can be seen as timers which expire ASAP) */
@@ -39,24 +40,53 @@ struct QEMUBH {
bool scheduled;
bool idle;
bool deleted;
+ bool replay;
+ uint64_t id;
};
QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
{
- QEMUBH *bh;
+ QEMUBH *bh, **last;
bh = g_malloc0(sizeof(QEMUBH));
bh->ctx = ctx;
bh->cb = cb;
bh->opaque = opaque;
qemu_mutex_lock(&ctx->bh_lock);
- bh->next = ctx->first_bh;
- /* Make sure that the members are ready before putting bh into list */
- smp_wmb();
- ctx->first_bh = bh;
+ if (replay_mode != REPLAY_MODE_NONE) {
+ /* Slower way, but this is a queue and not a stack.
+ Replay will process the BH in the same order they
+ came into the queue. */
+ last = &ctx->first_bh;
+ while (*last) {
+ last = &(*last)->next;
+ }
+ smp_wmb();
+ *last = bh;
+ } else {
+ bh->next = ctx->first_bh;
+ /* Make sure that the members are ready before putting bh into list */
+ smp_wmb();
+ ctx->first_bh = bh;
+ }
qemu_mutex_unlock(&ctx->bh_lock);
return bh;
}
+QEMUBH *aio_bh_new_replay(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
+ uint64_t id)
+{
+ QEMUBH *bh = aio_bh_new(ctx, cb, opaque);
+ bh->replay = true;
+ bh->id = id;
+ return bh;
+}
+
+void aio_bh_call(void *opaque)
+{
+ QEMUBH *bh = (QEMUBH *)opaque;
+ bh->cb(bh->opaque);
+}
+
/* Multiple occurrences of aio_bh_poll cannot be called concurrently */
int aio_bh_poll(AioContext *ctx)
{
@@ -79,7 +109,11 @@ int aio_bh_poll(AioContext *ctx)
if (!bh->idle)
ret = 1;
bh->idle = 0;
- bh->cb(bh->opaque);
+ if (!bh->replay) {
+ aio_bh_call(bh);
+ } else {
+ replay_add_bh_event(bh, bh->id);
+ }
}
}
diff --git a/dma-helpers.c b/dma-helpers.c
index 6918572..357d7e9 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -13,6 +13,7 @@
#include "qemu/range.h"
#include "qemu/thread.h"
#include "qemu/main-loop.h"
+#include "replay/replay.h"
/* #define DEBUG_IOMMU */
@@ -96,7 +97,8 @@ static void continue_after_map_failure(void *opaque)
{
DMAAIOCB *dbs = (DMAAIOCB *)opaque;
- dbs->bh = qemu_bh_new(reschedule_dma, dbs);
+ dbs->bh = qemu_bh_new_replay(reschedule_dma, dbs,
+ replay_get_current_step());
qemu_bh_schedule(dbs->bh);
}
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 70958e3..fbefc52 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -33,6 +33,7 @@
#include "internal.h"
#include <hw/ide/pci.h>
#include <hw/ide/ahci.h>
+#include "replay/replay.h"
/* #define DEBUG_AHCI */
@@ -1192,7 +1193,8 @@ static void ahci_cmd_done(IDEDMA *dma)
if (!ad->check_bh) {
/* maybe we still have something to process, check later */
- ad->check_bh = qemu_bh_new(ahci_check_cmd_bh, ad);
+ ad->check_bh = qemu_bh_new_replay(ahci_check_cmd_bh, ad,
+ replay_get_current_step());
qemu_bh_schedule(ad->check_bh);
}
}
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 44e3d50..b622aae 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -32,6 +32,7 @@
#include "sysemu/dma.h"
#include "hw/block/block.h"
#include "sysemu/block-backend.h"
+#include "replay/replay.h"
#include <hw/ide/internal.h>
@@ -448,7 +449,8 @@ BlockAIOCB *ide_issue_trim(BlockBackend *blk,
iocb = blk_aio_get(&trim_aiocb_info, blk, cb, opaque);
iocb->blk = blk;
- iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb);
+ iocb->bh = qemu_bh_new_replay(ide_trim_bh_cb, iocb,
+ replay_get_current_step());
iocb->ret = 0;
iocb->qiov = qiov;
iocb->i = -1;
diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c
index 1452910..97784a0 100644
--- a/hw/timer/arm_timer.c
+++ b/hw/timer/arm_timer.c
@@ -168,7 +168,7 @@ static arm_timer_state *arm_timer_init(uint32_t freq)
s->freq = freq;
s->control = TIMER_CTRL_IE;
- bh = qemu_bh_new(arm_timer_tick, s);
+ bh = qemu_bh_new_replay(arm_timer_tick, s, 0);
s->timer = ptimer_init(bh);
vmstate_register(NULL, -1, &vmstate_arm_timer, s);
return s;
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 5b88f30..dc17e5f 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -1224,7 +1224,7 @@ static int usb_uhci_common_initfn(PCIDevice *dev)
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
}
}
- s->bh = qemu_bh_new(uhci_bh, s);
+ s->bh = qemu_bh_new_replay(uhci_bh, s, 0);
s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, uhci_frame_timer, s);
s->num_ports_vmstate = NB_PORTS;
QTAILQ_INIT(&s->queues);
diff --git a/include/block/aio.h b/include/block/aio.h
index 6bf0e04..5a77431 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -35,6 +35,8 @@ struct BlockAIOCB {
const AIOCBInfo *aiocb_info;
BlockDriverState *bs;
BlockCompletionFunc *cb;
+ bool replay;
+ uint64_t replay_step;
void *opaque;
int refcnt;
};
@@ -144,6 +146,17 @@ void aio_context_release(AioContext *ctx);
QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque);
/**
+ * aio_bh_new_replay: Allocate a new bottom half structure for replay.
+ *
+ * This function calls aio_bh_new function and also fills replay parameters
+ * of the BH structure. BH created with this function in record/replay mode
+ * are executed through the replay queue only at checkpoints and instructions
+ * executions.
+ */
+QEMUBH *aio_bh_new_replay(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
+ uint64_t id);
+
+/**
* aio_notify: Force processing of pending events.
*
* Similar to signaling a condition variable, aio_notify forces
@@ -159,6 +172,11 @@ QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque);
void aio_notify(AioContext *ctx);
/**
+ * aio_bh_call: Executes callback function of the specified BH.
+ */
+void aio_bh_call(void *opaque);
+
+/**
* aio_bh_poll: Poll bottom halves for an AioContext.
*
* These are internal functions used by the QEMU main loop.
diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h
index 62c68c0..f5a98fe 100644
--- a/include/qemu/main-loop.h
+++ b/include/qemu/main-loop.h
@@ -306,6 +306,7 @@ void qemu_iohandler_fill(GArray *pollfds);
void qemu_iohandler_poll(GArray *pollfds, int rc);
QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque);
+QEMUBH *qemu_bh_new_replay(QEMUBHFunc *cb, void *opaque, uint64_t id);
void qemu_bh_schedule_idle(QEMUBH *bh);
#endif
diff --git a/main-loop.c b/main-loop.c
index 981bcb5..342aeef 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -508,3 +508,8 @@ QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
{
return aio_bh_new(qemu_aio_context, cb, opaque);
}
+
+QEMUBH *qemu_bh_new_replay(QEMUBHFunc *cb, void *opaque, uint64_t id)
+{
+ return aio_bh_new_replay(qemu_aio_context, cb, opaque, id);
+}
diff --git a/replay/replay-events.c b/replay/replay-events.c
index f3c9b16..1aee0a4 100755
--- a/replay/replay-events.c
+++ b/replay/replay-events.c
@@ -36,6 +36,9 @@ static bool replay_events_enabled = false;
static void replay_run_event(Event *event)
{
switch (event->event_kind) {
+ case REPLAY_ASYNC_EVENT_BH:
+ aio_bh_call(event->opaque);
+ break;
default:
fprintf(stderr, "Replay: invalid async event ID (%d) in the queue\n",
event->event_kind);
@@ -119,6 +122,11 @@ void replay_add_event(int event_kind, void *opaque)
replay_add_event_internal(event_kind, opaque, NULL, 0);
}
+void replay_add_bh_event(void *bh, uint64_t id)
+{
+ replay_add_event_internal(REPLAY_ASYNC_EVENT_BH, bh, NULL, id);
+}
+
void replay_save_events(int opt)
{
qemu_mutex_lock(&lock);
@@ -132,6 +140,9 @@ void replay_save_events(int opt)
/* save event-specific data */
switch (event->event_kind) {
+ case REPLAY_ASYNC_EVENT_BH:
+ replay_put_qword(event->id);
+ break;
}
}
@@ -158,6 +169,11 @@ void replay_read_events(int opt)
}
/* Execute some events without searching them in the queue */
switch (read_event_kind) {
+ case REPLAY_ASYNC_EVENT_BH:
+ if (read_id == -1) {
+ read_id = replay_get_qword();
+ }
+ break;
default:
fprintf(stderr, "Unknown ID %d of replay event\n", read_event_kind);
exit(1);
diff --git a/replay/replay-internal.h b/replay/replay-internal.h
index e73fa7a..ec36f44 100755
--- a/replay/replay-internal.h
+++ b/replay/replay-internal.h
@@ -37,7 +37,8 @@
/* Asynchronous events IDs */
-#define REPLAY_ASYNC_COUNT 0
+#define REPLAY_ASYNC_EVENT_BH 0
+#define REPLAY_ASYNC_COUNT 1
typedef struct ReplayState {
/*! Cached clock values. */
diff --git a/replay/replay.h b/replay/replay.h
index e76c541..ad8bdd3 100755
--- a/replay/replay.h
+++ b/replay/replay.h
@@ -91,5 +91,7 @@ int replay_checkpoint(unsigned int checkpoint);
/*! Disables storing events in the queue */
void replay_disable_events(void);
+/*! Adds BH event to the queue */
+void replay_add_bh_event(void *bh, uint64_t id);
#endif
diff --git a/stubs/replay.c b/stubs/replay.c
index ab9ede9..6d6c2eb 100755
--- a/stubs/replay.c
+++ b/stubs/replay.c
@@ -26,3 +26,7 @@ int runstate_is_running(void)
{
return 0;
}
+
+void replay_add_bh_event(void *bh, uint64_t id)
+{
+}
next prev parent reply other threads:[~2014-11-07 10:33 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-11-07 10:31 [Qemu-devel] [RFC PATCH v4 00/25] Deterministic replay and reverse execution Pavel Dovgalyuk
2014-11-07 10:31 ` [Qemu-devel] [RFC PATCH v4 01/25] acpi: accurate overflow check Pavel Dovgalyuk
2014-11-07 11:16 ` Paolo Bonzini
2014-11-07 10:31 ` [Qemu-devel] [RFC PATCH v4 02/25] mc146818rtc: add missed field to vmstate Pavel Dovgalyuk
2014-11-07 11:18 ` Paolo Bonzini
2014-11-07 10:31 ` [Qemu-devel] [RFC PATCH v4 03/25] replay: global variables and function stubs Pavel Dovgalyuk
2014-11-07 10:44 ` Eric Blake
2014-11-07 10:31 ` [Qemu-devel] [RFC PATCH v4 04/25] sysemu: system functions for replay Pavel Dovgalyuk
2014-11-07 15:51 ` Alex Bennée
2014-11-07 10:31 ` [Qemu-devel] [RFC PATCH v4 05/25] replay: internal functions for replay log Pavel Dovgalyuk
2014-11-07 16:01 ` Alex Bennée
2014-11-07 10:32 ` [Qemu-devel] [RFC PATCH v4 06/25] cpu-exec: reset exception_index correctly Pavel Dovgalyuk
2014-11-07 11:27 ` Paolo Bonzini
2014-11-12 12:02 ` Paolo Bonzini
2014-11-13 11:41 ` Pavel Dovgaluk
2014-11-07 10:32 ` [Qemu-devel] [RFC PATCH v4 07/25] icount: implement icount requesting Pavel Dovgalyuk
2014-11-07 11:19 ` Paolo Bonzini
2014-11-07 11:36 ` Pavel Dovgaluk
2014-11-07 11:45 ` Frederic Konrad
2014-11-11 9:41 ` Pavel Dovgaluk
2014-11-07 10:32 ` [Qemu-devel] [RFC PATCH v4 08/25] icount: improve enable/disable ticks Pavel Dovgalyuk
2014-11-07 11:20 ` Paolo Bonzini
2014-11-07 10:32 ` [Qemu-devel] [RFC PATCH v4 09/25] replay: introduce icount event Pavel Dovgalyuk
2014-11-07 10:32 ` [Qemu-devel] [RFC PATCH v4 10/25] i386: do not cross the pages boundaries in replay mode Pavel Dovgalyuk
2014-11-07 11:20 ` Paolo Bonzini
2014-11-07 11:39 ` Pavel Dovgaluk
2014-11-07 11:27 ` Andreas Färber
2014-11-07 10:32 ` [Qemu-devel] [RFC PATCH v4 11/25] cpu-exec: allow temporary disabling icount Pavel Dovgalyuk
2014-11-07 11:22 ` Paolo Bonzini
2014-11-11 9:49 ` Pavel Dovgaluk
2014-11-13 14:16 ` Paolo Bonzini
2014-11-17 9:35 ` Pavel Dovgaluk
2014-11-07 10:32 ` [Qemu-devel] [RFC PATCH v4 12/25] replay: interrupts and exceptions Pavel Dovgalyuk
2014-11-07 10:32 ` [Qemu-devel] [RFC PATCH v4 13/25] replay: asynchronous events infrastructure Pavel Dovgalyuk
2014-11-07 10:53 ` Eric Blake
2014-11-07 10:32 ` [Qemu-devel] [RFC PATCH v4 14/25] cpu: replay instructions sequence Pavel Dovgalyuk
2014-11-07 10:32 ` [Qemu-devel] [RFC PATCH v4 15/25] replay: recording and replaying clock ticks Pavel Dovgalyuk
2014-11-07 10:32 ` [Qemu-devel] [RFC PATCH v4 16/25] replay: recording and replaying different timers Pavel Dovgalyuk
2014-11-07 10:33 ` [Qemu-devel] [RFC PATCH v4 17/25] cpus: make icount warp deterministic in replay mode Pavel Dovgalyuk
2014-11-07 11:24 ` Paolo Bonzini
2014-11-07 11:45 ` Pavel Dovgaluk
2014-11-07 12:00 ` Paolo Bonzini
2014-11-07 10:33 ` [Qemu-devel] [RFC PATCH v4 18/25] replay: shutdown event Pavel Dovgalyuk
2014-11-07 10:33 ` [Qemu-devel] [RFC PATCH v4 19/25] replay: checkpoints Pavel Dovgalyuk
2014-11-07 10:33 ` Pavel Dovgalyuk [this message]
2014-11-07 10:33 ` [Qemu-devel] [RFC PATCH v4 21/25] replay: replay aio requests Pavel Dovgalyuk
2014-11-07 10:33 ` [Qemu-devel] [RFC PATCH v4 22/25] replay: thread pool Pavel Dovgalyuk
2014-11-07 10:33 ` [Qemu-devel] [RFC PATCH v4 23/25] replay: initialization and deinitialization Pavel Dovgalyuk
2014-11-07 10:33 ` [Qemu-devel] [RFC PATCH v4 24/25] replay: command line options Pavel Dovgalyuk
2014-11-07 10:33 ` [Qemu-devel] [RFC PATCH v4 25/25] replay: recording of the user input Pavel Dovgalyuk
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=20141107103321.6136.72502.stgit@PASHA-ISP \
--to=pavel.dovgaluk@ispras.ru \
--cc=afaerber@suse.de \
--cc=alex.bennee@linaro.org \
--cc=batuzovk@ispras.ru \
--cc=fred.konrad@greensocs.com \
--cc=maria.klimushenkova@ispras.ru \
--cc=mark.burton@greensocs.com \
--cc=pbonzini@redhat.com \
--cc=peter.crosthwaite@xilinx.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=real@ispras.ru \
/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.