[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 5/6] net: defer nested call to BH
From: |
Liu Ping Fan |
Subject: |
[Qemu-devel] [PATCH v2 5/6] net: defer nested call to BH |
Date: |
Thu, 13 Jun 2013 17:03:05 +0800 |
From: Liu Ping Fan <address@hidden>
Nested call caused by ->receive() will raise issue like deadlock,
so postphone it to BH.
Signed-off-by: Liu Ping Fan <address@hidden>
---
net/queue.c | 40 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 38 insertions(+), 2 deletions(-)
diff --git a/net/queue.c b/net/queue.c
index 58222b0..9c343ab 100644
--- a/net/queue.c
+++ b/net/queue.c
@@ -24,6 +24,8 @@
#include "net/queue.h"
#include "qemu/queue.h"
#include "net/net.h"
+#include "block/aio.h"
+#include "qemu/main-loop.h"
/* The delivery handler may only return zero if it will call
* qemu_net_queue_flush() when it determines that it is once again able
@@ -183,6 +185,22 @@ static ssize_t qemu_net_queue_deliver_iov(NetQueue *queue,
return ret;
}
+typedef struct NetQueBH {
+ QEMUBH *bh;
+ NetClientState *nc;
+} NetQueBH;
+
+static void qemu_net_queue_send_bh(void *opaque)
+{
+ NetQueBH *q_bh = opaque;
+ NetQueue *queue = q_bh->nc->send_queue;
+
+ qemu_net_queue_flush(queue);
+ netclient_unref(q_bh->nc);
+ qemu_bh_delete(q_bh->bh);
+ g_slice_free(NetQueBH, q_bh);
+}
+
ssize_t qemu_net_queue_send(NetQueue *queue,
NetClientState *sender,
unsigned flags,
@@ -192,8 +210,17 @@ ssize_t qemu_net_queue_send(NetQueue *queue,
{
ssize_t ret;
- if (queue->delivering || !qemu_can_send_packet_nolock(sender)) {
+ if (queue->delivering || !qemu_can_send_packet_nolock(sender)
+ || sender->send_queue->delivering) {
qemu_net_queue_append(queue, sender, flags, data, size, sent_cb);
+ /* Nested call will be deferred to BH */
+ if (sender->send_queue->delivering) {
+ NetQueBH *que_bh = g_slice_new(NetQueBH);
+ que_bh->bh = qemu_bh_new(qemu_net_queue_send_bh, que_bh);
+ que_bh->nc = queue->opaque;
+ netclient_ref(queue->opaque);
+ qemu_bh_schedule(que_bh->bh);
+ }
return 0;
}
@@ -217,8 +244,17 @@ ssize_t qemu_net_queue_send_iov(NetQueue *queue,
{
ssize_t ret;
- if (queue->delivering || !qemu_can_send_packet_nolock(sender)) {
+ if (queue->delivering || !qemu_can_send_packet_nolock(sender)
+ || sender->send_queue->delivering) {
qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt, sent_cb);
+ /* Nested call will be deferred to BH */
+ if (sender->send_queue->delivering) {
+ NetQueBH *que_bh = g_slice_new(NetQueBH);
+ que_bh->bh = qemu_bh_new(qemu_net_queue_send_bh, que_bh);
+ que_bh->nc = queue->opaque;
+ netclient_ref(queue->opaque);
+ qemu_bh_schedule(que_bh->bh);
+ }
return 0;
}
--
1.8.1.4
[Qemu-devel] [PATCH v2 6/6] net: hub use lock to protect ports list, Liu Ping Fan, 2013/06/13
Re: [Qemu-devel] [PATCH v2 0/6] port network layer onto glib, Stefan Hajnoczi, 2013/06/18