Re: [PATCH 2/2] dm: iothread: fix bug in iothread handler


Conghui Chen
 

-----Original Message-----
From: Wang, Yu1 <yu1.wang@...>
Sent: Tuesday, September 20, 2022 8:18 AM
To: Chen, Conghui <conghui.chen@...>
Cc: acrn-dev@...
Subject: Re: [PATCH 2/2] dm: iothread: fix bug in iothread handler

On Mon, Sep 19, 2022 at 11:03:08PM +0800, Chen, Conghui wrote:


-----Original Message-----
From: Wang, Yu1 <yu1.wang@...>
Sent: Monday, September 19, 2022 2:42 PM
To: Chen, Conghui <conghui.chen@...>
Cc: acrn-dev@...
Subject: Re: [PATCH 2/2] dm: iothread: fix bug in iothread handler

On Fri, Sep 16, 2022 at 04:35:29PM +0800, Conghui wrote:
Fix the bug in iothread handler, the event should be read out so that the
next epoll_wait not return directly as the fd can still readable.

Signed-off-by: Conghui <conghui.chen@...>
---
devicemodel/core/iothread.c | 11 +++++++++--
devicemodel/hw/pci/virtio/virtio.c | 1 +
devicemodel/include/iothread.h | 1 +
3 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/devicemodel/core/iothread.c b/devicemodel/core/iothread.c
index 238ecb375..7fbce2b07 100644
--- a/devicemodel/core/iothread.c
+++ b/devicemodel/core/iothread.c
@@ -21,6 +21,7 @@


#define MEVENT_MAX 64
+#define MAX_EVENT_NUM 64
struct iothread_ctx {
pthread_t tid;
int epfd;
@@ -34,7 +35,8 @@ io_thread(void *arg)
{
struct epoll_event eventlist[MEVENT_MAX];
struct iothread_mevent *aevp;
- int i, n;
+ int i, n, status;
+ char buf[MAX_EVENT_NUM];

while(ioctx.started) {
n = epoll_wait(ioctx.epfd, eventlist, MEVENT_MAX, -1);
@@ -47,8 +49,13 @@ io_thread(void *arg)
}
for (i = 0; i < n; i++) {
aevp = eventlist[i].data.ptr;
- if (aevp && aevp->run)
+ if (aevp && aevp->run) {
+ /* dry the events in the fd */
+ do {
+ status = read(aevp->fd, buf,
sizeof(buf));
+ } while (status == MAX_EVENT_NUM);
I don't quite understand the point. There still has race to pop events
after this loop. We can not guarrante that. And what is the real impact
if the next epoll_wait return directly?
When kernel call event_signal(fd, 1), we can read 1 byte from aevp->fd. So,
we have to read the data out before we run the handler. Otherwise, in the
next loop, it will be treated as a new event_signal(fd, 1).
Then why do we need to read in loop? read on time is enough?
As kernel may invoke eventfd_signal (fd, 1) more than MAX_EVENT_NUM times, then iothread is scheduled.
So, need to make sure all data is read out.






(*aevp->run)(aevp->arg);
+ }
}
}

diff --git a/devicemodel/hw/pci/virtio/virtio.c
b/devicemodel/hw/pci/virtio/virtio.c
index 6b5646269..546ec6f31 100644
--- a/devicemodel/hw/pci/virtio/virtio.c
+++ b/devicemodel/hw/pci/virtio/virtio.c
@@ -104,6 +104,7 @@ virtio_set_iothread(struct virtio_base *base,
vq->viothrd.idx = idx;
vq->viothrd.iomvt.arg = &vq->viothrd;
vq->viothrd.iomvt.run = iothread_handler;
+ vq->viothrd.iomvt.fd = vq->viothrd.kick_fd;

if (!iothread_add(vq->viothrd.kick_fd, &vq-
viothrd.iomvt))
if (!virtio_register_ioeventfd(base, idx, true))
diff --git a/devicemodel/include/iothread.h
b/devicemodel/include/iothread.h
index 6a3cc7167..fb76e9baa 100644
--- a/devicemodel/include/iothread.h
+++ b/devicemodel/include/iothread.h
@@ -10,6 +10,7 @@
struct iothread_mevent {
void (*run)(void *);
void *arg;
+ int fd;
};
int iothread_add(int fd, struct iothread_mevent *aevt);
int iothread_del(int fd);
--
2.25.1

Join {acrn-dev@lists.projectacrn.org to automatically receive all group messages.