1
The following changes since commit d0ed6a69d399ae193959225cdeaa9382746c91cc:
1
The following changes since commit 6c769690ac845fa62642a5f93b4e4bd906adab95:
2
2
3
Update version for v5.1.0 release (2020-08-11 17:07:03 +0100)
3
Merge remote-tracking branch 'remotes/vsementsov/tags/pull-simplebench-2021-05-04' into staging (2021-05-21 12:02:34 +0100)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://github.com/stefanha/qemu.git tags/block-pull-request
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to 44277bf914471962c9e88e09c859aae65ae109c4:
9
for you to fetch changes up to 0a6f0c76a030710780ce10d6347a70f098024d21:
10
10
11
aio-posix: keep aio_notify_me disabled during polling (2020-08-13 13:34:14 =
11
coroutine-sleep: introduce qemu_co_sleep (2021-05-21 18:22:33 +0100)
12
+0100)
13
12
14
----------------------------------------------------------------
13
----------------------------------------------------------------
15
Pull request
14
Pull request
16
15
16
(Resent due to an email preparation mistake.)
17
17
----------------------------------------------------------------
18
----------------------------------------------------------------
18
19
19
Stefan Hajnoczi (3):
20
Paolo Bonzini (6):
20
async: rename event_notifier_dummy_cb/poll()
21
coroutine-sleep: use a stack-allocated timer
21
async: always set ctx->notified in aio_notify()
22
coroutine-sleep: disallow NULL QemuCoSleepState** argument
22
aio-posix: keep aio_notify_me disabled during polling
23
coroutine-sleep: allow qemu_co_sleep_wake that wakes nothing
24
coroutine-sleep: move timer out of QemuCoSleepState
25
coroutine-sleep: replace QemuCoSleepState pointer with struct in the
26
API
27
coroutine-sleep: introduce qemu_co_sleep
23
28
24
util/aio-posix.c | 47 +++++++++++++++++++++++++----------------------
29
Philippe Mathieu-Daudé (1):
25
util/async.c | 36 +++++++++++++++++++++++-------------
30
bitops.h: Improve find_xxx_bit() documentation
26
2 files changed, 48 insertions(+), 35 deletions(-)
27
31
28
--=20
32
Zenghui Yu (1):
29
2.26.2
33
multi-process: Initialize variables declared with g_auto*
30
34
35
include/qemu/bitops.h | 15 ++++++--
36
include/qemu/coroutine.h | 27 ++++++++-----
37
block/block-copy.c | 10 ++---
38
block/nbd.c | 14 +++----
39
hw/remote/memory.c | 5 +--
40
hw/remote/proxy.c | 3 +-
41
util/qemu-coroutine-sleep.c | 75 +++++++++++++++++++------------------
42
7 files changed, 79 insertions(+), 70 deletions(-)
43
44
--
45
2.31.1
46
diff view generated by jsdifflib
New patch
1
From: Zenghui Yu <yuzenghui@huawei.com>
1
2
3
Quote docs/devel/style.rst (section "Automatic memory deallocation"):
4
5
* Variables declared with g_auto* MUST always be initialized,
6
otherwise the cleanup function will use uninitialized stack memory
7
8
Initialize @name properly to get rid of the compilation error (using
9
gcc-7.3.0 on CentOS):
10
11
../hw/remote/proxy.c: In function 'pci_proxy_dev_realize':
12
/usr/include/glib-2.0/glib/glib-autocleanups.h:28:3: error: 'name' may be used uninitialized in this function [-Werror=maybe-uninitialized]
13
g_free (*pp);
14
^~~~~~~~~~~~
15
../hw/remote/proxy.c:350:30: note: 'name' was declared here
16
g_autofree char *name;
17
^~~~
18
19
Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
20
Reviewed-by: Jagannathan Raman <jag.raman@oracle.com>
21
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
22
Reviewed-by: Miroslav Rezanina <mrezanin@redhat.com>
23
Message-id: 20210312112143.1369-1-yuzenghui@huawei.com
24
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
25
---
26
hw/remote/memory.c | 5 ++---
27
hw/remote/proxy.c | 3 +--
28
2 files changed, 3 insertions(+), 5 deletions(-)
29
30
diff --git a/hw/remote/memory.c b/hw/remote/memory.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/remote/memory.c
33
+++ b/hw/remote/memory.c
34
@@ -XXX,XX +XXX,XX @@ void remote_sysmem_reconfig(MPQemuMsg *msg, Error **errp)
35
36
remote_sysmem_reset();
37
38
- for (region = 0; region < msg->num_fds; region++) {
39
- g_autofree char *name;
40
+ for (region = 0; region < msg->num_fds; region++, suffix++) {
41
+ g_autofree char *name = g_strdup_printf("remote-mem-%u", suffix);
42
subregion = g_new(MemoryRegion, 1);
43
- name = g_strdup_printf("remote-mem-%u", suffix++);
44
memory_region_init_ram_from_fd(subregion, NULL,
45
name, sysmem_info->sizes[region],
46
true, msg->fds[region],
47
diff --git a/hw/remote/proxy.c b/hw/remote/proxy.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/remote/proxy.c
50
+++ b/hw/remote/proxy.c
51
@@ -XXX,XX +XXX,XX @@ static void probe_pci_info(PCIDevice *dev, Error **errp)
52
PCI_BASE_ADDRESS_SPACE_IO : PCI_BASE_ADDRESS_SPACE_MEMORY;
53
54
if (size) {
55
- g_autofree char *name;
56
+ g_autofree char *name = g_strdup_printf("bar-region-%d", i);
57
pdev->region[i].dev = pdev;
58
pdev->region[i].present = true;
59
if (type == PCI_BASE_ADDRESS_SPACE_MEMORY) {
60
pdev->region[i].memory = true;
61
}
62
- name = g_strdup_printf("bar-region-%d", i);
63
memory_region_init_io(&pdev->region[i].mr, OBJECT(pdev),
64
&proxy_mr_ops, &pdev->region[i],
65
name, size);
66
--
67
2.31.1
68
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
2
3
Document the following functions return the bitmap size
4
if no matching bit is found:
5
6
- find_first_bit
7
- find_next_bit
8
- find_last_bit
9
- find_first_zero_bit
10
- find_next_zero_bit
11
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Message-id: 20210510200758.2623154-2-philmd@redhat.com
16
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
17
---
18
include/qemu/bitops.h | 15 ++++++++++++---
19
1 file changed, 12 insertions(+), 3 deletions(-)
20
21
diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/qemu/bitops.h
24
+++ b/include/qemu/bitops.h
25
@@ -XXX,XX +XXX,XX @@ static inline int test_bit(long nr, const unsigned long *addr)
26
* @addr: The address to start the search at
27
* @size: The maximum size to search
28
*
29
- * Returns the bit number of the first set bit, or size.
30
+ * Returns the bit number of the last set bit,
31
+ * or @size if there is no set bit in the bitmap.
32
*/
33
unsigned long find_last_bit(const unsigned long *addr,
34
unsigned long size);
35
@@ -XXX,XX +XXX,XX @@ unsigned long find_last_bit(const unsigned long *addr,
36
* @addr: The address to base the search on
37
* @offset: The bitnumber to start searching at
38
* @size: The bitmap size in bits
39
+ *
40
+ * Returns the bit number of the next set bit,
41
+ * or @size if there are no further set bits in the bitmap.
42
*/
43
unsigned long find_next_bit(const unsigned long *addr,
44
unsigned long size,
45
@@ -XXX,XX +XXX,XX @@ unsigned long find_next_bit(const unsigned long *addr,
46
* @addr: The address to base the search on
47
* @offset: The bitnumber to start searching at
48
* @size: The bitmap size in bits
49
+ *
50
+ * Returns the bit number of the next cleared bit,
51
+ * or @size if there are no further clear bits in the bitmap.
52
*/
53
54
unsigned long find_next_zero_bit(const unsigned long *addr,
55
@@ -XXX,XX +XXX,XX @@ unsigned long find_next_zero_bit(const unsigned long *addr,
56
* @addr: The address to start the search at
57
* @size: The maximum size to search
58
*
59
- * Returns the bit number of the first set bit.
60
+ * Returns the bit number of the first set bit,
61
+ * or @size if there is no set bit in the bitmap.
62
*/
63
static inline unsigned long find_first_bit(const unsigned long *addr,
64
unsigned long size)
65
@@ -XXX,XX +XXX,XX @@ static inline unsigned long find_first_bit(const unsigned long *addr,
66
* @addr: The address to start the search at
67
* @size: The maximum size to search
68
*
69
- * Returns the bit number of the first cleared bit.
70
+ * Returns the bit number of the first cleared bit,
71
+ * or @size if there is no clear bit in the bitmap.
72
*/
73
static inline unsigned long find_first_zero_bit(const unsigned long *addr,
74
unsigned long size)
75
--
76
2.31.1
77
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
The lifetime of the timer is well-known (it cannot outlive
4
qemu_co_sleep_ns_wakeable, because it's deleted by the time the
5
coroutine resumes), so it is not necessary to place it on the heap.
6
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Message-id: 20210517100548.28806-2-pbonzini@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
util/qemu-coroutine-sleep.c | 9 ++++-----
13
1 file changed, 4 insertions(+), 5 deletions(-)
14
15
diff --git a/util/qemu-coroutine-sleep.c b/util/qemu-coroutine-sleep.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/util/qemu-coroutine-sleep.c
18
+++ b/util/qemu-coroutine-sleep.c
19
@@ -XXX,XX +XXX,XX @@ static const char *qemu_co_sleep_ns__scheduled = "qemu_co_sleep_ns";
20
21
struct QemuCoSleepState {
22
Coroutine *co;
23
- QEMUTimer *ts;
24
+ QEMUTimer ts;
25
QemuCoSleepState **user_state_pointer;
26
};
27
28
@@ -XXX,XX +XXX,XX @@ void qemu_co_sleep_wake(QemuCoSleepState *sleep_state)
29
if (sleep_state->user_state_pointer) {
30
*sleep_state->user_state_pointer = NULL;
31
}
32
- timer_del(sleep_state->ts);
33
+ timer_del(&sleep_state->ts);
34
aio_co_wake(sleep_state->co);
35
}
36
37
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
38
AioContext *ctx = qemu_get_current_aio_context();
39
QemuCoSleepState state = {
40
.co = qemu_coroutine_self(),
41
- .ts = aio_timer_new(ctx, type, SCALE_NS, co_sleep_cb, &state),
42
.user_state_pointer = sleep_state,
43
};
44
45
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
46
abort();
47
}
48
49
+ aio_timer_init(ctx, &state.ts, type, SCALE_NS, co_sleep_cb, &state);
50
if (sleep_state) {
51
*sleep_state = &state;
52
}
53
- timer_mod(state.ts, qemu_clock_get_ns(type) + ns);
54
+ timer_mod(&state.ts, qemu_clock_get_ns(type) + ns);
55
qemu_coroutine_yield();
56
if (sleep_state) {
57
/*
58
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
59
*/
60
assert(*sleep_state == NULL);
61
}
62
- timer_free(state.ts);
63
}
64
--
65
2.31.1
66
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
Simplify the code by removing conditionals. qemu_co_sleep_ns
4
can simply point the argument to an on-stack temporary.
5
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
Message-id: 20210517100548.28806-3-pbonzini@redhat.com
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
11
include/qemu/coroutine.h | 5 +++--
12
util/qemu-coroutine-sleep.c | 18 +++++-------------
13
2 files changed, 8 insertions(+), 15 deletions(-)
14
15
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/qemu/coroutine.h
18
+++ b/include/qemu/coroutine.h
19
@@ -XXX,XX +XXX,XX @@ typedef struct QemuCoSleepState QemuCoSleepState;
20
21
/**
22
* Yield the coroutine for a given duration. During this yield, @sleep_state
23
- * (if not NULL) is set to an opaque pointer, which may be used for
24
+ * is set to an opaque pointer, which may be used for
25
* qemu_co_sleep_wake(). Be careful, the pointer is set back to zero when the
26
* timer fires. Don't save the obtained value to other variables and don't call
27
* qemu_co_sleep_wake from another aio context.
28
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
29
QemuCoSleepState **sleep_state);
30
static inline void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, int64_t ns)
31
{
32
- qemu_co_sleep_ns_wakeable(type, ns, NULL);
33
+ QemuCoSleepState *unused = NULL;
34
+ qemu_co_sleep_ns_wakeable(type, ns, &unused);
35
}
36
37
/**
38
diff --git a/util/qemu-coroutine-sleep.c b/util/qemu-coroutine-sleep.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/util/qemu-coroutine-sleep.c
41
+++ b/util/qemu-coroutine-sleep.c
42
@@ -XXX,XX +XXX,XX @@ void qemu_co_sleep_wake(QemuCoSleepState *sleep_state)
43
qemu_co_sleep_ns__scheduled, NULL);
44
45
assert(scheduled == qemu_co_sleep_ns__scheduled);
46
- if (sleep_state->user_state_pointer) {
47
- *sleep_state->user_state_pointer = NULL;
48
- }
49
+ *sleep_state->user_state_pointer = NULL;
50
timer_del(&sleep_state->ts);
51
aio_co_wake(sleep_state->co);
52
}
53
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
54
}
55
56
aio_timer_init(ctx, &state.ts, type, SCALE_NS, co_sleep_cb, &state);
57
- if (sleep_state) {
58
- *sleep_state = &state;
59
- }
60
+ *sleep_state = &state;
61
timer_mod(&state.ts, qemu_clock_get_ns(type) + ns);
62
qemu_coroutine_yield();
63
- if (sleep_state) {
64
- /*
65
- * Note that *sleep_state is cleared during qemu_co_sleep_wake
66
- * before resuming this coroutine.
67
- */
68
- assert(*sleep_state == NULL);
69
- }
70
+
71
+ /* qemu_co_sleep_wake clears *sleep_state before resuming this coroutine. */
72
+ assert(*sleep_state == NULL);
73
}
74
--
75
2.31.1
76
diff view generated by jsdifflib
1
The event_notifier_*() prefix can be confused with the EventNotifier
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
APIs that are also called event_notifier_*().
3
2
4
Rename the functions to aio_context_notifier_*() to make it clear that
3
All callers of qemu_co_sleep_wake are checking whether they are passing
5
they relate to the AioContext::notifier field.
4
a NULL argument inside the pointer-to-pointer: do the check in
5
qemu_co_sleep_wake itself.
6
6
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
As a side effect, qemu_co_sleep_wake can be called more than once and
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
it will only wake the coroutine once; after the first time, the argument
9
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
9
will be set to NULL via *sleep_state->user_state_pointer. However, this
10
Message-id: 20200806131802.569478-2-stefanha@redhat.com
10
would not be safe unless co_sleep_cb keeps using the QemuCoSleepState*
11
directly, so make it go through the pointer-to-pointer instead.
12
13
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
15
Message-id: 20210517100548.28806-4-pbonzini@redhat.com
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
---
17
---
13
util/async.c | 8 ++++----
18
block/block-copy.c | 4 +---
14
1 file changed, 4 insertions(+), 4 deletions(-)
19
block/nbd.c | 8 ++------
20
util/qemu-coroutine-sleep.c | 21 ++++++++++++---------
21
3 files changed, 15 insertions(+), 18 deletions(-)
15
22
16
diff --git a/util/async.c b/util/async.c
23
diff --git a/block/block-copy.c b/block/block-copy.c
17
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
18
--- a/util/async.c
25
--- a/block/block-copy.c
19
+++ b/util/async.c
26
+++ b/block/block-copy.c
20
@@ -XXX,XX +XXX,XX @@ static void aio_timerlist_notify(void *opaque, QEMUClockType type)
27
@@ -XXX,XX +XXX,XX @@ out:
21
aio_notify(opaque);
28
29
void block_copy_kick(BlockCopyCallState *call_state)
30
{
31
- if (call_state->sleep_state) {
32
- qemu_co_sleep_wake(call_state->sleep_state);
33
- }
34
+ qemu_co_sleep_wake(call_state->sleep_state);
22
}
35
}
23
36
24
-static void event_notifier_dummy_cb(EventNotifier *e)
37
/*
25
+static void aio_context_notifier_dummy_cb(EventNotifier *e)
38
diff --git a/block/nbd.c b/block/nbd.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/block/nbd.c
41
+++ b/block/nbd.c
42
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn nbd_client_co_drain_begin(BlockDriverState *bs)
43
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
44
45
s->drained = true;
46
- if (s->connection_co_sleep_ns_state) {
47
- qemu_co_sleep_wake(s->connection_co_sleep_ns_state);
48
- }
49
+ qemu_co_sleep_wake(s->connection_co_sleep_ns_state);
50
51
nbd_co_establish_connection_cancel(bs, false);
52
53
@@ -XXX,XX +XXX,XX @@ static void nbd_teardown_connection(BlockDriverState *bs)
54
55
s->state = NBD_CLIENT_QUIT;
56
if (s->connection_co) {
57
- if (s->connection_co_sleep_ns_state) {
58
- qemu_co_sleep_wake(s->connection_co_sleep_ns_state);
59
- }
60
+ qemu_co_sleep_wake(s->connection_co_sleep_ns_state);
61
nbd_co_establish_connection_cancel(bs, true);
62
}
63
if (qemu_in_coroutine()) {
64
diff --git a/util/qemu-coroutine-sleep.c b/util/qemu-coroutine-sleep.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/util/qemu-coroutine-sleep.c
67
+++ b/util/qemu-coroutine-sleep.c
68
@@ -XXX,XX +XXX,XX @@ struct QemuCoSleepState {
69
70
void qemu_co_sleep_wake(QemuCoSleepState *sleep_state)
26
{
71
{
72
- /* Write of schedule protected by barrier write in aio_co_schedule */
73
- const char *scheduled = qatomic_cmpxchg(&sleep_state->co->scheduled,
74
- qemu_co_sleep_ns__scheduled, NULL);
75
+ if (sleep_state) {
76
+ /* Write of schedule protected by barrier write in aio_co_schedule */
77
+ const char *scheduled = qatomic_cmpxchg(&sleep_state->co->scheduled,
78
+ qemu_co_sleep_ns__scheduled, NULL);
79
80
- assert(scheduled == qemu_co_sleep_ns__scheduled);
81
- *sleep_state->user_state_pointer = NULL;
82
- timer_del(&sleep_state->ts);
83
- aio_co_wake(sleep_state->co);
84
+ assert(scheduled == qemu_co_sleep_ns__scheduled);
85
+ *sleep_state->user_state_pointer = NULL;
86
+ timer_del(&sleep_state->ts);
87
+ aio_co_wake(sleep_state->co);
88
+ }
27
}
89
}
28
90
29
/* Returns true if aio_notify() was called (e.g. a BH was scheduled) */
91
static void co_sleep_cb(void *opaque)
30
-static bool event_notifier_poll(void *opaque)
31
+static bool aio_context_notifier_poll(void *opaque)
32
{
92
{
33
EventNotifier *e = opaque;
93
- qemu_co_sleep_wake(opaque);
34
AioContext *ctx = container_of(e, AioContext, notifier);
94
+ QemuCoSleepState **sleep_state = opaque;
35
@@ -XXX,XX +XXX,XX @@ AioContext *aio_context_new(Error **errp)
95
+ qemu_co_sleep_wake(*sleep_state);
36
96
}
37
aio_set_event_notifier(ctx, &ctx->notifier,
97
38
false,
98
void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
39
- event_notifier_dummy_cb,
99
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
40
- event_notifier_poll);
100
abort();
41
+ aio_context_notifier_dummy_cb,
101
}
42
+ aio_context_notifier_poll);
102
43
#ifdef CONFIG_LINUX_AIO
103
- aio_timer_init(ctx, &state.ts, type, SCALE_NS, co_sleep_cb, &state);
44
ctx->linux_aio = NULL;
104
+ aio_timer_init(ctx, &state.ts, type, SCALE_NS, co_sleep_cb, sleep_state);
45
#endif
105
*sleep_state = &state;
106
timer_mod(&state.ts, qemu_clock_get_ns(type) + ns);
107
qemu_coroutine_yield();
46
--
108
--
47
2.26.2
109
2.31.1
48
110
diff view generated by jsdifflib
1
Polling only monitors the ctx->notified field and does not need the
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
ctx->notifier EventNotifier to be signalled. Keep ctx->aio_notify_me
3
disabled while polling to avoid unnecessary EventNotifier syscalls.
4
2
5
This optimization improves virtio-blk 4KB random read performance by
3
This simplification is enabled by the previous patch. Now aio_co_wake
6
18%. The following results are with an IOThread and the null-co block
4
will only be called once, therefore we do not care about a spurious
7
driver:
5
firing of the timer after a qemu_co_sleep_wake.
8
6
9
Test IOPS Error
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Before 244518.62 ± 1.20%
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
11
After 290706.11 ± 0.44%
9
Message-id: 20210517100548.28806-5-pbonzini@redhat.com
12
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
15
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
16
Message-id: 20200806131802.569478-4-stefanha@redhat.com
17
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
18
---
11
---
19
util/aio-posix.c | 47 +++++++++++++++++++++++++----------------------
12
util/qemu-coroutine-sleep.c | 8 ++++----
20
1 file changed, 25 insertions(+), 22 deletions(-)
13
1 file changed, 4 insertions(+), 4 deletions(-)
21
14
22
diff --git a/util/aio-posix.c b/util/aio-posix.c
15
diff --git a/util/qemu-coroutine-sleep.c b/util/qemu-coroutine-sleep.c
23
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
24
--- a/util/aio-posix.c
17
--- a/util/qemu-coroutine-sleep.c
25
+++ b/util/aio-posix.c
18
+++ b/util/qemu-coroutine-sleep.c
26
@@ -XXX,XX +XXX,XX @@ static bool remove_idle_poll_handlers(AioContext *ctx, int64_t now)
19
@@ -XXX,XX +XXX,XX @@ static const char *qemu_co_sleep_ns__scheduled = "qemu_co_sleep_ns";
27
*
20
28
* Polls for a given time.
21
struct QemuCoSleepState {
29
*
22
Coroutine *co;
30
- * Note that ctx->notify_me must be non-zero so this function can detect
23
- QEMUTimer ts;
31
- * aio_notify().
24
QemuCoSleepState **user_state_pointer;
32
- *
25
};
33
* Note that the caller must have incremented ctx->list_lock.
26
34
*
27
@@ -XXX,XX +XXX,XX @@ void qemu_co_sleep_wake(QemuCoSleepState *sleep_state)
35
* Returns: true if progress was made, false otherwise
28
36
@@ -XXX,XX +XXX,XX @@ static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout)
29
assert(scheduled == qemu_co_sleep_ns__scheduled);
37
bool progress;
30
*sleep_state->user_state_pointer = NULL;
38
int64_t start_time, elapsed_time;
31
- timer_del(&sleep_state->ts);
39
32
aio_co_wake(sleep_state->co);
40
- assert(ctx->notify_me);
41
assert(qemu_lockcnt_count(&ctx->list_lock) > 0);
42
43
trace_run_poll_handlers_begin(ctx, max_ns, *timeout);
44
@@ -XXX,XX +XXX,XX @@ static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout)
45
* @timeout: timeout for blocking wait, computed by the caller and updated if
46
* polling succeeds.
47
*
48
- * ctx->notify_me must be non-zero so this function can detect aio_notify().
49
- *
50
* Note that the caller must have incremented ctx->list_lock.
51
*
52
* Returns: true if progress was made, false otherwise
53
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
54
AioHandlerList ready_list = QLIST_HEAD_INITIALIZER(ready_list);
55
int ret = 0;
56
bool progress;
57
+ bool use_notify_me;
58
int64_t timeout;
59
int64_t start = 0;
60
61
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
62
*/
63
assert(in_aio_context_home_thread(ctx));
64
65
- /* aio_notify can avoid the expensive event_notifier_set if
66
+ qemu_lockcnt_inc(&ctx->list_lock);
67
+
68
+ if (ctx->poll_max_ns) {
69
+ start = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
70
+ }
71
+
72
+ timeout = blocking ? aio_compute_timeout(ctx) : 0;
73
+ progress = try_poll_mode(ctx, &timeout);
74
+ assert(!(timeout && progress));
75
+
76
+ /*
77
+ * aio_notify can avoid the expensive event_notifier_set if
78
* everything (file descriptors, bottom halves, timers) will
79
* be re-evaluated before the next blocking poll(). This is
80
* already true when aio_poll is called with blocking == false;
81
* if blocking == true, it is only true after poll() returns,
82
* so disable the optimization now.
83
*/
84
- if (blocking) {
85
+ use_notify_me = timeout != 0;
86
+ if (use_notify_me) {
87
atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) + 2);
88
/*
89
- * Write ctx->notify_me before computing the timeout
90
- * (reading bottom half flags, etc.). Pairs with
91
+ * Write ctx->notify_me before reading ctx->notified. Pairs with
92
* smp_mb in aio_notify().
93
*/
94
smp_mb();
95
- }
96
-
97
- qemu_lockcnt_inc(&ctx->list_lock);
98
99
- if (ctx->poll_max_ns) {
100
- start = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
101
+ /* Don't block if aio_notify() was called */
102
+ if (atomic_read(&ctx->notified)) {
103
+ timeout = 0;
104
+ }
105
}
33
}
106
34
}
107
- timeout = blocking ? aio_compute_timeout(ctx) : 0;
35
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
108
- progress = try_poll_mode(ctx, &timeout);
36
QemuCoSleepState **sleep_state)
109
- assert(!(timeout && progress));
37
{
110
-
38
AioContext *ctx = qemu_get_current_aio_context();
111
/* If polling is allowed, non-blocking aio_poll does not need the
39
+ QEMUTimer ts;
112
* system call---a single round of run_poll_handlers_once suffices.
40
QemuCoSleepState state = {
113
*/
41
.co = qemu_coroutine_self(),
114
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
42
.user_state_pointer = sleep_state,
115
ret = ctx->fdmon_ops->wait(ctx, &ready_list, timeout);
43
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
44
abort();
116
}
45
}
117
46
118
- if (blocking) {
47
- aio_timer_init(ctx, &state.ts, type, SCALE_NS, co_sleep_cb, sleep_state);
119
+ if (use_notify_me) {
48
+ aio_timer_init(ctx, &ts, type, SCALE_NS, co_sleep_cb, sleep_state);
120
/* Finish the poll before clearing the flag. */
49
*sleep_state = &state;
121
- atomic_store_release(&ctx->notify_me, atomic_read(&ctx->notify_me) - 2);
50
- timer_mod(&state.ts, qemu_clock_get_ns(type) + ns);
122
- aio_notify_accept(ctx);
51
+ timer_mod(&ts, qemu_clock_get_ns(type) + ns);
123
+ atomic_store_release(&ctx->notify_me,
52
qemu_coroutine_yield();
124
+ atomic_read(&ctx->notify_me) - 2);
53
+ timer_del(&ts);
125
}
54
126
55
/* qemu_co_sleep_wake clears *sleep_state before resuming this coroutine. */
127
+ aio_notify_accept(ctx);
56
assert(*sleep_state == NULL);
128
+
129
/* Adjust polling time */
130
if (ctx->poll_max_ns) {
131
int64_t block_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - start;
132
--
57
--
133
2.26.2
58
2.31.1
134
59
diff view generated by jsdifflib
New patch
1
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
3
Right now, users of qemu_co_sleep_ns_wakeable are simply passing
4
a pointer to QemuCoSleepState by reference to the function. But
5
QemuCoSleepState really is just a Coroutine*; making the
6
content of the struct public is just as efficient and lets us
7
skip the user_state_pointer indirection.
8
9
Since the usage is changed, take the occasion to rename the
10
struct to QemuCoSleep.
11
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
14
Message-id: 20210517100548.28806-6-pbonzini@redhat.com
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
---
17
include/qemu/coroutine.h | 23 +++++++++++----------
18
block/block-copy.c | 8 ++++----
19
block/nbd.c | 10 ++++-----
20
util/qemu-coroutine-sleep.c | 41 ++++++++++++++++---------------------
21
4 files changed, 39 insertions(+), 43 deletions(-)
22
23
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/qemu/coroutine.h
26
+++ b/include/qemu/coroutine.h
27
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_wrlock(CoRwlock *lock);
28
*/
29
void qemu_co_rwlock_unlock(CoRwlock *lock);
30
31
-typedef struct QemuCoSleepState QemuCoSleepState;
32
+typedef struct QemuCoSleep {
33
+ Coroutine *to_wake;
34
+} QemuCoSleep;
35
36
/**
37
- * Yield the coroutine for a given duration. During this yield, @sleep_state
38
- * is set to an opaque pointer, which may be used for
39
- * qemu_co_sleep_wake(). Be careful, the pointer is set back to zero when the
40
- * timer fires. Don't save the obtained value to other variables and don't call
41
- * qemu_co_sleep_wake from another aio context.
42
+ * Yield the coroutine for a given duration. Initializes @w so that,
43
+ * during this yield, it can be passed to qemu_co_sleep_wake() to
44
+ * terminate the sleep.
45
*/
46
-void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
47
- QemuCoSleepState **sleep_state);
48
+void coroutine_fn qemu_co_sleep_ns_wakeable(QemuCoSleep *w,
49
+ QEMUClockType type, int64_t ns);
50
+
51
static inline void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, int64_t ns)
52
{
53
- QemuCoSleepState *unused = NULL;
54
- qemu_co_sleep_ns_wakeable(type, ns, &unused);
55
+ QemuCoSleep w = { 0 };
56
+ qemu_co_sleep_ns_wakeable(&w, type, ns);
57
}
58
59
/**
60
@@ -XXX,XX +XXX,XX @@ static inline void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, int64_t ns)
61
* qemu_co_sleep_ns() and should be checked to be non-NULL before calling
62
* qemu_co_sleep_wake().
63
*/
64
-void qemu_co_sleep_wake(QemuCoSleepState *sleep_state);
65
+void qemu_co_sleep_wake(QemuCoSleep *w);
66
67
/**
68
* Yield until a file descriptor becomes readable
69
diff --git a/block/block-copy.c b/block/block-copy.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/block/block-copy.c
72
+++ b/block/block-copy.c
73
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyCallState {
74
/* State */
75
int ret;
76
bool finished;
77
- QemuCoSleepState *sleep_state;
78
+ QemuCoSleep sleep;
79
bool cancelled;
80
81
/* OUT parameters */
82
@@ -XXX,XX +XXX,XX @@ block_copy_dirty_clusters(BlockCopyCallState *call_state)
83
if (ns > 0) {
84
block_copy_task_end(task, -EAGAIN);
85
g_free(task);
86
- qemu_co_sleep_ns_wakeable(QEMU_CLOCK_REALTIME, ns,
87
- &call_state->sleep_state);
88
+ qemu_co_sleep_ns_wakeable(&call_state->sleep,
89
+ QEMU_CLOCK_REALTIME, ns);
90
continue;
91
}
92
}
93
@@ -XXX,XX +XXX,XX @@ out:
94
95
void block_copy_kick(BlockCopyCallState *call_state)
96
{
97
- qemu_co_sleep_wake(call_state->sleep_state);
98
+ qemu_co_sleep_wake(&call_state->sleep);
99
}
100
101
/*
102
diff --git a/block/nbd.c b/block/nbd.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/block/nbd.c
105
+++ b/block/nbd.c
106
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVNBDState {
107
CoQueue free_sema;
108
Coroutine *connection_co;
109
Coroutine *teardown_co;
110
- QemuCoSleepState *connection_co_sleep_ns_state;
111
+ QemuCoSleep reconnect_sleep;
112
bool drained;
113
bool wait_drained_end;
114
int in_flight;
115
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn nbd_client_co_drain_begin(BlockDriverState *bs)
116
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
117
118
s->drained = true;
119
- qemu_co_sleep_wake(s->connection_co_sleep_ns_state);
120
+ qemu_co_sleep_wake(&s->reconnect_sleep);
121
122
nbd_co_establish_connection_cancel(bs, false);
123
124
@@ -XXX,XX +XXX,XX @@ static void nbd_teardown_connection(BlockDriverState *bs)
125
126
s->state = NBD_CLIENT_QUIT;
127
if (s->connection_co) {
128
- qemu_co_sleep_wake(s->connection_co_sleep_ns_state);
129
+ qemu_co_sleep_wake(&s->reconnect_sleep);
130
nbd_co_establish_connection_cancel(bs, true);
131
}
132
if (qemu_in_coroutine()) {
133
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void nbd_co_reconnect_loop(BDRVNBDState *s)
134
}
135
bdrv_inc_in_flight(s->bs);
136
} else {
137
- qemu_co_sleep_ns_wakeable(QEMU_CLOCK_REALTIME, timeout,
138
- &s->connection_co_sleep_ns_state);
139
+ qemu_co_sleep_ns_wakeable(&s->reconnect_sleep,
140
+ QEMU_CLOCK_REALTIME, timeout);
141
if (s->drained) {
142
continue;
143
}
144
diff --git a/util/qemu-coroutine-sleep.c b/util/qemu-coroutine-sleep.c
145
index XXXXXXX..XXXXXXX 100644
146
--- a/util/qemu-coroutine-sleep.c
147
+++ b/util/qemu-coroutine-sleep.c
148
@@ -XXX,XX +XXX,XX @@
149
150
static const char *qemu_co_sleep_ns__scheduled = "qemu_co_sleep_ns";
151
152
-struct QemuCoSleepState {
153
+void qemu_co_sleep_wake(QemuCoSleep *w)
154
+{
155
Coroutine *co;
156
- QemuCoSleepState **user_state_pointer;
157
-};
158
159
-void qemu_co_sleep_wake(QemuCoSleepState *sleep_state)
160
-{
161
- if (sleep_state) {
162
+ co = w->to_wake;
163
+ w->to_wake = NULL;
164
+ if (co) {
165
/* Write of schedule protected by barrier write in aio_co_schedule */
166
- const char *scheduled = qatomic_cmpxchg(&sleep_state->co->scheduled,
167
+ const char *scheduled = qatomic_cmpxchg(&co->scheduled,
168
qemu_co_sleep_ns__scheduled, NULL);
169
170
assert(scheduled == qemu_co_sleep_ns__scheduled);
171
- *sleep_state->user_state_pointer = NULL;
172
- aio_co_wake(sleep_state->co);
173
+ aio_co_wake(co);
174
}
175
}
176
177
static void co_sleep_cb(void *opaque)
178
{
179
- QemuCoSleepState **sleep_state = opaque;
180
- qemu_co_sleep_wake(*sleep_state);
181
+ QemuCoSleep *w = opaque;
182
+ qemu_co_sleep_wake(w);
183
}
184
185
-void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
186
- QemuCoSleepState **sleep_state)
187
+void coroutine_fn qemu_co_sleep_ns_wakeable(QemuCoSleep *w,
188
+ QEMUClockType type, int64_t ns)
189
{
190
+ Coroutine *co = qemu_coroutine_self();
191
AioContext *ctx = qemu_get_current_aio_context();
192
QEMUTimer ts;
193
- QemuCoSleepState state = {
194
- .co = qemu_coroutine_self(),
195
- .user_state_pointer = sleep_state,
196
- };
197
198
- const char *scheduled = qatomic_cmpxchg(&state.co->scheduled, NULL,
199
- qemu_co_sleep_ns__scheduled);
200
+ const char *scheduled = qatomic_cmpxchg(&co->scheduled, NULL,
201
+ qemu_co_sleep_ns__scheduled);
202
if (scheduled) {
203
fprintf(stderr,
204
"%s: Co-routine was already scheduled in '%s'\n",
205
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns,
206
abort();
207
}
208
209
- aio_timer_init(ctx, &ts, type, SCALE_NS, co_sleep_cb, sleep_state);
210
- *sleep_state = &state;
211
+ w->to_wake = co;
212
+ aio_timer_init(ctx, &ts, type, SCALE_NS, co_sleep_cb, w),
213
timer_mod(&ts, qemu_clock_get_ns(type) + ns);
214
qemu_coroutine_yield();
215
timer_del(&ts);
216
217
- /* qemu_co_sleep_wake clears *sleep_state before resuming this coroutine. */
218
- assert(*sleep_state == NULL);
219
+ /* w->to_wake is cleared before resuming this coroutine. */
220
+ assert(w->to_wake == NULL);
221
}
222
--
223
2.31.1
224
diff view generated by jsdifflib
1
aio_notify() does not set ctx->notified when called with
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
ctx->aio_notify_me disabled. Therefore aio_notify_me needs to be enabled
3
during polling.
4
2
5
This is suboptimal since expensive event_notifier_set(&ctx->notifier)
3
Allow using QemuCoSleep to sleep forever until woken by qemu_co_sleep_wake.
6
and event_notifier_test_and_clear(&ctx->notifier) calls are required
4
This makes the logic of qemu_co_sleep_ns_wakeable easy to understand.
7
when ctx->aio_notify_me is enabled.
8
5
9
Change aio_notify() so that aio->notified is always set, regardless of
6
In the future we will introduce an API that can work even if the
10
ctx->aio_notify_me. This will make polling cheaper since
7
sleep and wake happen from different threads. For now, initializing
11
ctx->aio_notify_me can remain disabled. Move the
8
w->to_wake after timer_mod is fine because the timer can only fire in
12
event_notifier_test_and_clear() to the fd handler function (which is now
9
the same AioContext.
13
no longer an empty function so "dummy" has been dropped from its name).
14
10
15
The next patch takes advantage of this by optimizing polling in
11
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
16
util/aio-posix.c.
12
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
17
13
Message-id: 20210517100548.28806-7-pbonzini@redhat.com
18
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
19
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
20
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
21
Message-id: 20200806131802.569478-3-stefanha@redhat.com
22
23
[Paolo Bonzini pointed out that the smp_wmb() in aio_notify_accept()
24
should be smp_wb() but the comment should be smp_wmb() instead of
25
smp_wb(). Fixed.
26
--Stefan]
27
28
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
29
---
15
---
30
util/async.c | 32 +++++++++++++++++++++-----------
16
include/qemu/coroutine.h | 5 +++++
31
1 file changed, 21 insertions(+), 11 deletions(-)
17
util/qemu-coroutine-sleep.c | 26 +++++++++++++++++++-------
18
2 files changed, 24 insertions(+), 7 deletions(-)
32
19
33
diff --git a/util/async.c b/util/async.c
20
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
34
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
35
--- a/util/async.c
22
--- a/include/qemu/coroutine.h
36
+++ b/util/async.c
23
+++ b/include/qemu/coroutine.h
37
@@ -XXX,XX +XXX,XX @@ LuringState *aio_get_linux_io_uring(AioContext *ctx)
24
@@ -XXX,XX +XXX,XX @@ typedef struct QemuCoSleep {
38
25
void coroutine_fn qemu_co_sleep_ns_wakeable(QemuCoSleep *w,
39
void aio_notify(AioContext *ctx)
26
QEMUClockType type, int64_t ns);
27
28
+/**
29
+ * Yield the coroutine until the next call to qemu_co_sleep_wake.
30
+ */
31
+void coroutine_fn qemu_co_sleep(QemuCoSleep *w);
32
+
33
static inline void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, int64_t ns)
40
{
34
{
41
- /* Write e.g. bh->scheduled before reading ctx->notify_me. Pairs
35
QemuCoSleep w = { 0 };
42
+ /*
36
diff --git a/util/qemu-coroutine-sleep.c b/util/qemu-coroutine-sleep.c
43
+ * Write e.g. bh->flags before writing ctx->notified. Pairs with smp_mb in
37
index XXXXXXX..XXXXXXX 100644
44
+ * aio_notify_accept.
38
--- a/util/qemu-coroutine-sleep.c
45
+ */
39
+++ b/util/qemu-coroutine-sleep.c
46
+ smp_wmb();
40
@@ -XXX,XX +XXX,XX @@ static void co_sleep_cb(void *opaque)
47
+ atomic_set(&ctx->notified, true);
41
qemu_co_sleep_wake(w);
42
}
43
44
-void coroutine_fn qemu_co_sleep_ns_wakeable(QemuCoSleep *w,
45
- QEMUClockType type, int64_t ns)
46
+void coroutine_fn qemu_co_sleep(QemuCoSleep *w)
47
{
48
Coroutine *co = qemu_coroutine_self();
49
- AioContext *ctx = qemu_get_current_aio_context();
50
- QEMUTimer ts;
51
52
const char *scheduled = qatomic_cmpxchg(&co->scheduled, NULL,
53
qemu_co_sleep_ns__scheduled);
54
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QemuCoSleep *w,
55
}
56
57
w->to_wake = co;
58
- aio_timer_init(ctx, &ts, type, SCALE_NS, co_sleep_cb, w),
59
- timer_mod(&ts, qemu_clock_get_ns(type) + ns);
60
qemu_coroutine_yield();
61
- timer_del(&ts);
62
63
/* w->to_wake is cleared before resuming this coroutine. */
64
assert(w->to_wake == NULL);
65
}
66
+
67
+void coroutine_fn qemu_co_sleep_ns_wakeable(QemuCoSleep *w,
68
+ QEMUClockType type, int64_t ns)
69
+{
70
+ AioContext *ctx = qemu_get_current_aio_context();
71
+ QEMUTimer ts;
72
+
73
+ aio_timer_init(ctx, &ts, type, SCALE_NS, co_sleep_cb, w);
74
+ timer_mod(&ts, qemu_clock_get_ns(type) + ns);
48
+
75
+
49
+ /*
76
+ /*
50
+ * Write ctx->notified before reading ctx->notify_me. Pairs
77
+ * The timer will fire in the current AiOContext, so the callback
51
* with smp_mb in aio_ctx_prepare or aio_poll.
78
+ * must happen after qemu_co_sleep yields and there is no race
52
*/
79
+ * between timer_mod and qemu_co_sleep.
53
smp_mb();
54
if (atomic_read(&ctx->notify_me)) {
55
event_notifier_set(&ctx->notifier);
56
- atomic_mb_set(&ctx->notified, true);
57
}
58
}
59
60
void aio_notify_accept(AioContext *ctx)
61
{
62
- if (atomic_xchg(&ctx->notified, false)
63
-#ifdef WIN32
64
- || true
65
-#endif
66
- ) {
67
- event_notifier_test_and_clear(&ctx->notifier);
68
- }
69
+ atomic_set(&ctx->notified, false);
70
+
71
+ /*
72
+ * Write ctx->notified before reading e.g. bh->flags. Pairs with smp_wmb
73
+ * in aio_notify.
74
+ */
80
+ */
75
+ smp_mb();
81
+ qemu_co_sleep(w);
76
}
82
+ timer_del(&ts);
77
83
+}
78
static void aio_timerlist_notify(void *opaque, QEMUClockType type)
79
@@ -XXX,XX +XXX,XX @@ static void aio_timerlist_notify(void *opaque, QEMUClockType type)
80
aio_notify(opaque);
81
}
82
83
-static void aio_context_notifier_dummy_cb(EventNotifier *e)
84
+static void aio_context_notifier_cb(EventNotifier *e)
85
{
86
+ AioContext *ctx = container_of(e, AioContext, notifier);
87
+
88
+ event_notifier_test_and_clear(&ctx->notifier);
89
}
90
91
/* Returns true if aio_notify() was called (e.g. a BH was scheduled) */
92
@@ -XXX,XX +XXX,XX @@ AioContext *aio_context_new(Error **errp)
93
94
aio_set_event_notifier(ctx, &ctx->notifier,
95
false,
96
- aio_context_notifier_dummy_cb,
97
+ aio_context_notifier_cb,
98
aio_context_notifier_poll);
99
#ifdef CONFIG_LINUX_AIO
100
ctx->linux_aio = NULL;
101
--
84
--
102
2.26.2
85
2.31.1
103
86
diff view generated by jsdifflib