Skip to contentSkip to conversation

New iohandler API

PATCH In review Amit Shah 4 participants 22 messages Feb 22, 2011 – Feb 23, 2011

lore
Share & tools
lore

Amit Shah

author
#0 lore raw

cover New iohandler API

Hello,

This is a new iohandler API implementation. It gets rid of the multiple callbacks and switches to just one callback with an event mask that triggered the callback.

qemu-char.c has been trivially updated to replace all usage of qemu_set_fd_handler* functions to the new api.

Future work includes removing the qemu_set_fd_handler* functions and getting rid of #include "qemu-char.h" from all the src files that don't need it (most of them).

The users of the char api can then be also converted over to a new api in similar fashion, deprecating the usage of can_read callbacks altogether.

I tested this series in two scenarios: monitor on stdio and by running the virtio-serial testsuite, which uses unix sockets and does open/close/read/write/poll calls on the sockets. It all works fine.

Please review and apply.

Amit Shah (7):
iohandlers: Mark current implementation as 'old'
iohandlers: Introduce a new API
char: tcp: Use new iohandler api
char: udp: Use new iohandler api
char: fd: Use new iohandler api
char: stdio: Use new iohandler api
char: pty: Use new iohandler api

 iohandler.h |   28 +++++++++++
 qemu-char.c |  140 +++++++++++++++++++++++++++++++++++++++++++----------
 vl.c        |  154 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 291 insertions(+), 31 deletions(-)
 create mode 100644 iohandler.h
Signature · 1 line
1.7.4
author
#1 lore raw

PATCH 1/7 iohandlers: Mark current implementation as 'old'

Mark the current iohandler list as 'old'. In the next commit we'll introduce a new iohandler api that will replace the list name.

The 'old' list will eventually be completely replaced by the new implementation.

---
 vl.c |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)
vl.c +7 -7
index b436952..e248ec4 100644
@@ -1037,8 +1037,8 @@ typedef struct IOHandlerRecord {
     QLIST_ENTRY(IOHandlerRecord) next;
 } IOHandlerRecord;
 
-static QLIST_HEAD(, IOHandlerRecord) io_handlers =
-    QLIST_HEAD_INITIALIZER(io_handlers);
+static QLIST_HEAD(, IOHandlerRecord) io_handlers_old =
+    QLIST_HEAD_INITIALIZER(io_handlers_old);
 
 
 /* XXX: fd_read_poll should be suppressed, but an API change is
@@ -1052,19 +1052,19 @@ int qemu_set_fd_handler2(int fd,
     IOHandlerRecord *ioh;
 
     if (!fd_read && !fd_write) {
-        QLIST_FOREACH(ioh, &io_handlers, next) {
+        QLIST_FOREACH(ioh, &io_handlers_old, next) {
             if (ioh->fd == fd) {
                 ioh->deleted = 1;
                 break;
             }
         }
     } else {
-        QLIST_FOREACH(ioh, &io_handlers, next) {
+        QLIST_FOREACH(ioh, &io_handlers_old, next) {
             if (ioh->fd == fd)
                 goto found;
         }
         ioh = qemu_mallocz(sizeof(IOHandlerRecord));
-        QLIST_INSERT_HEAD(&io_handlers, ioh, next);
+        QLIST_INSERT_HEAD(&io_handlers_old, ioh, next);
     found:
         ioh->fd = fd;
         ioh->fd_read_poll = fd_read_poll;
@@ -1347,7 +1347,7 @@ void main_loop_wait(int nonblocking)
     FD_ZERO(&rfds);
     FD_ZERO(&wfds);
     FD_ZERO(&xfds);
-    QLIST_FOREACH(ioh, &io_handlers, next) {
+    QLIST_FOREACH(ioh, &io_handlers_old, next) {
         if (ioh->deleted)
             continue;
         if (ioh->fd_read &&
@@ -1375,7 +1375,7 @@ void main_loop_wait(int nonblocking)
     if (ret > 0) {
         IOHandlerRecord *pioh;
 
-        QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
+        QLIST_FOREACH_SAFE(ioh, &io_handlers_old, next, pioh) {
             if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) {
                 ioh->fd_read(ioh->opaque);
             }
Signature · 1 line
1.7.4
#2 lore raw

Re: [Qemu-devel] [PATCH 1/7] iohandlers: Mark current implementation as 'old'

Quoted 6 lines · Amit Shah

Mark the current iohandler list as 'old'. In the next commit we'll introduce a new iohandler api that will replace the list name.

The 'old' list will eventually be completely replaced by the new implementation.

A better way to do this is to implement the old API in terms of the new API. This ensures you don't lose any functionality, and reduces the amount of low-level infrastructure.

Signature · 1 line
error compiling committee.c: too many arguments to function
author
#3 lore raw

Re: [Qemu-devel] [PATCH 1/7] iohandlers: Mark current implementation as 'old'

Quoted 10 lines · Avi Kivity
Quoted 5 lines · Amit Shah

Mark the current iohandler list as 'old'. In the next commit we'll introduce a new iohandler api that will replace the list name.

The 'old' list will eventually be completely replaced by the new implementation.

A better way to do this is to implement the old API in terms of the new API. This ensures you don't lose any functionality, and reduces the amount of low-level infrastructure.

With this new approach of switching to just one callback, that is more work for little gain as we'll just deprecate the older API soon. (The previous patches used this approach, btw.)

Would you still prefer to have an old->new mapping?

Amit

#4 lore raw

Re: [Qemu-devel] [PATCH 1/7] iohandlers: Mark current implementation as 'old'

Quoted 8 lines · Amit Shah
Quoted 7 lines · Avi Kivity
Quoted 5 lines · Amit Shah

Mark the current iohandler list as 'old'. In the next commit we'll introduce a new iohandler api that will replace the list name.

The 'old' list will eventually be completely replaced by the new implementation.

Quoted 7 lines
Quoted 3 lines

A better way to do this is to implement the old API in terms of the new API. This ensures you don't lose any functionality, and reduces the amount of low-level infrastructure.

With this new approach of switching to just one callback, that is more work for little gain as we'll just deprecate the older API soon. (The previous patches used this approach, btw.)

Does "deprecate" mean "completely remove"?

If so I agree.

Quoted 2 lines

Would you still prefer to have an old->new mapping?

If you don't remove the old API, yes.

Signature · 1 line
error compiling committee.c: too many arguments to function
author
#5 lore raw

Re: [Qemu-devel] [PATCH 1/7] iohandlers: Mark current implementation as 'old'

Quoted 13 lines · Avi Kivity
Quoted 12 lines · Amit Shah
Quoted 10 lines · Avi Kivity
Quoted 5 lines · Amit Shah

Mark the current iohandler list as 'old'. In the next commit we'll introduce a new iohandler api that will replace the list name.

The 'old' list will eventually be completely replaced by the new implementation.

A better way to do this is to implement the old API in terms of the new API. This ensures you don't lose any functionality, and reduces the amount of low-level infrastructure.

Quoted 7 lines
Quoted 3 lines

With this new approach of switching to just one callback, that is more work for little gain as we'll just deprecate the older API soon. (The previous patches used this approach, btw.)

Does "deprecate" mean "completely remove"?

If so I agree.

Yes, completely removing the older API is the plan (as noted in message 00).

Amit

#6 lore raw

Re: [Qemu-devel] [PATCH 1/7] iohandlers: Mark current implementation as 'old'

Quoted 18 lines · Amit Shah
Quoted 17 lines · Avi Kivity
Quoted 15 lines · Amit Shah
Quoted 10 lines · Avi Kivity
Quoted 5 lines · Amit Shah

Mark the current iohandler list as 'old'. In the next commit we'll introduce a new iohandler api that will replace the list name.

The 'old' list will eventually be completely replaced by the new implementation.

A better way to do this is to implement the old API in terms of the new API. This ensures you don't lose any functionality, and reduces the amount of low-level infrastructure.

With this new approach of switching to just one callback, that is more work for little gain as we'll just deprecate the older API soon. (The previous patches used this approach, btw.)

Quoted 6 lines
Quoted 3 lines

Does "deprecate" mean "completely remove"?

If so I agree.

Yes, completely removing the older API is the plan (as noted in message 00).

Great. That's a much better deprecate than "add the new thing and let the old thing rot" (which I've been guilty of a few times).

Signature · 1 line
error compiling committee.c: too many arguments to function
author
#7 lore raw

PATCH 2/7 iohandlers: Introduce a new API

In reply to Amit Shah

Introduce a new iohandler api that doesn't have multiple callbacks. Instead, a single callback and a mask of events that got set will be passed on to the handler. This will ease our transition to a poll() interface instead of the current select() that happens on the fds.

---
 iohandler.h |   28 +++++++++++
 vl.c        |  144 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 172 insertions(+), 0 deletions(-)
 create mode 100644 iohandler.h
iohandler.h new file +28 -0
new file mode 100644
index 0000000..6553835
@@ -0,0 +1,28 @@
+/*
+ * Declarations for iohandler functions
+ *
+ * Copyright Red Hat, Inc. 2011
+ * Copyright Amit Shah <[email protected]> 2011
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef _QEMU_IOHANDLER_H
+#define _QEMU_IOHANDLER_H
+
+/* iohandler masks */
+#define IOH_MASK_CAN_READ	(1U << 0)
+#define IOH_MASK_READ		(1U << 1)
+#define IOH_MASK_WRITE		(1U << 2)
+
+typedef int IOAllHandler(void *opaque, unsigned int mask);
+
+int assign_iohandler(int fd, IOAllHandler *handler, unsigned int mask,
+                     void *opaque);
+int remove_iohandler(int fd);
+int update_fd_mask(int fd, unsigned int mask);
+int get_fd_mask(int fd, unsigned int *mask);
+
+
+#endif /* _QEMU_IOHANDLER_H */
vl.c +144 -0

180 lines not on this page · raw message

Signature · 1 line
1.7.4
#8 lore raw

Re: [Qemu-devel] [PATCH 2/7] iohandlers: Introduce a new API

Quoted 5 lines · Amit Shah

Introduce a new iohandler api that doesn't have multiple callbacks. Instead, a single callback and a mask of events that got set will be passed on to the handler. This will ease our transition to a poll() interface instead of the current select() that happens on the fds.

Is the mask argument to the callback indicative of a real mask, or is this an enum when passed to the clients? i.e. you seem to use a switch in all handlers, so is it actually meant that each callback has a single possible value, not an or'ed one?

Quoted 235 lines
---
 iohandler.h |   28 +++++++++++
 vl.c        |  144 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 172 insertions(+), 0 deletions(-)
 create mode 100644 iohandler.h
iohandler.h new file +28 -0
new file mode 100644
index 0000000..6553835
@@ -0,0 +1,28 @@
+/*
+ * Declarations for iohandler functions
+ *
+ * Copyright Red Hat, Inc. 2011
+ * Copyright Amit Shah <[email protected]> 2011
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef _QEMU_IOHANDLER_H
+#define _QEMU_IOHANDLER_H
+
+/* iohandler masks */
+#define IOH_MASK_CAN_READ	(1U << 0)
+#define IOH_MASK_READ		(1U << 1)
+#define IOH_MASK_WRITE		(1U << 2)
+
+typedef int IOAllHandler(void *opaque, unsigned int mask);
+
+int assign_iohandler(int fd, IOAllHandler *handler, unsigned int mask,
+                     void *opaque);
+int remove_iohandler(int fd);
+int update_fd_mask(int fd, unsigned int mask);
+int get_fd_mask(int fd, unsigned int *mask);
+
+
+#endif /* _QEMU_IOHANDLER_H */
vl.c +144 -0
index e248ec4..9dabee2 100644
@@ -2,6 +2,8 @@
  * QEMU System Emulator
  *
  * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2011 Amit Shah, <[email protected]>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -136,6 +138,7 @@ int main(int argc, char **argv)
 #include "gdbstub.h"
 #include "qemu-timer.h"
 #include "qemu-char.h"
+#include "iohandler.h"
 #include "cache-utils.h"
 #include "block.h"
 #include "blockdev.h"
@@ -1030,6 +1033,8 @@ typedef struct IOHandlerRecord {
     IOCanReadHandler *fd_read_poll;
     IOHandler *fd_read;
     IOHandler *fd_write;
+    IOAllHandler *fd_iohandler;
+    unsigned int mask;
     int deleted;
     void *opaque;
     /* temporary data */
@@ -1040,6 +1045,97 @@ typedef struct IOHandlerRecord {
 static QLIST_HEAD(, IOHandlerRecord) io_handlers_old =
     QLIST_HEAD_INITIALIZER(io_handlers_old);
 
+static QLIST_HEAD(, IOHandlerRecord) io_handlers =
+    QLIST_HEAD_INITIALIZER(io_handlers);
+
+static IOHandlerRecord *find_iohandler(int fd)
+{
+    IOHandlerRecord *ioh;
+
+    QLIST_FOREACH(ioh, &io_handlers, next) {
+        if (ioh->fd == fd) {
+            return ioh;
+        }
+    }
+    return NULL;
+}
+
+static int update_iohandler_mask(IOHandlerRecord *ioh, unsigned int mask)
+{
+    assert(ioh);
+
+    ioh->mask = mask;
+    return 0;
+}
+
+/*
+ * Updates the mask for the fd.  Returns 0 on success.
+ */
+int update_fd_mask(int fd, unsigned int mask)
+{
+    IOHandlerRecord *ioh;
+
+    ioh = find_iohandler(fd);
+    if (!ioh) {
+        return -1;
+    }
+
+    return update_iohandler_mask(ioh, mask);
+}
+
+/*
+ * Populates the mask registered in *mask.  Only valid if return value
+ * is 0.
+ */
+int get_fd_mask(int fd, unsigned int *mask)
+{
+    IOHandlerRecord *ioh;
+
+    ioh = find_iohandler(fd);
+    if (!ioh) {
+        return -1;
+    }
+    *mask = ioh->mask;
+
+    return 0;
+}
+
+/*
+ * Assign an iohandler to an fd.  Can also be used to update the mask
+ * or handler or the opaque pointer and also to delete the iohandler.
+ * Returns 0 on success.
+ */
+int assign_iohandler(int fd, IOAllHandler *handler, unsigned int mask,
+                     void *opaque)
+{
+    IOHandlerRecord *ioh;
+
+    ioh = find_iohandler(fd);
+
+    if (!handler) {
+        if (ioh) {
+            ioh->deleted = 1;
+        }
+        return 0;
+    }
+
+    if (!ioh) {
+        ioh = qemu_mallocz(sizeof(IOHandlerRecord));
+        QLIST_INSERT_HEAD(&io_handlers, ioh, next);
+        ioh->fd = fd;
+    }
+    ioh->fd_iohandler = handler;
+    ioh->opaque = opaque;
+    update_iohandler_mask(ioh, mask);
+    ioh->deleted = 0;
+
+    return 0;
+}
+
+int remove_iohandler(int fd)
+{
+    return assign_iohandler(fd, NULL, 0, NULL);
+}
 
 /* XXX: fd_read_poll should be suppressed, but an API change is
    necessary in the character devices to suppress fd_can_read(). */
@@ -1363,6 +1459,26 @@ void main_loop_wait(int nonblocking)
                 nfds = ioh->fd;
         }
     }
+    QLIST_FOREACH(ioh, &io_handlers, next) {
+        if (ioh->deleted) {
+            continue;
+        }
+        if (ioh->mask & IOH_MASK_READ &&
+            (!(ioh->mask & IOH_MASK_CAN_READ) ||
+             (ioh->fd_iohandler(ioh->opaque, IOH_MASK_CAN_READ) != 0))) {
+
+            FD_SET(ioh->fd, &rfds);
+            if (ioh->fd > nfds) {
+                nfds = ioh->fd;
+            }
+        }
+        if (ioh->mask & IOH_MASK_WRITE) {
+            FD_SET(ioh->fd, &wfds);
+            if (ioh->fd > nfds) {
+                nfds = ioh->fd;
+            }
+        }
+    }
 
     tv.tv_sec = timeout / 1000;
     tv.tv_usec = (timeout % 1000) * 1000;
@@ -1389,6 +1505,34 @@ void main_loop_wait(int nonblocking)
                 qemu_free(ioh);
             }
         }
+        QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
+            unsigned int mask;
+
+            mask = 0;
+            if (!ioh->deleted) {
+                if (FD_ISSET(ioh->fd, &rfds)) {
+                    mask |= IOH_MASK_READ;
+                }
+                if (FD_ISSET(ioh->fd, &wfds)) {
+                    mask |= IOH_MASK_WRITE;
+                }
+            }
+            /*
+             * Strip out flags the caller didn't ask for -- shouldn't
+             * happen since we set rfds and wfds based on the value of
+             * ioh->mask anyway.
+             */
+            mask &= ioh->mask;
+            if (mask) {
+                ioh->fd_iohandler(ioh->opaque, mask);
+            }
+            /* Do this last in case the handler marked it for deletion */
+            if (ioh->deleted) {
+                QLIST_REMOVE(ioh, next);
+                qemu_free(ioh);
+                continue;
+            }
+        }
     }
 
     slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0));
Signature · 1 line
1.7.4
author
#9 lore raw

Re: [Qemu-devel] [PATCH 2/7] iohandlers: Introduce a new API

Quoted 10 lines · Alon Levy
Quoted 4 lines · Amit Shah

Introduce a new iohandler api that doesn't have multiple callbacks. Instead, a single callback and a mask of events that got set will be passed on to the handler. This will ease our transition to a poll() interface instead of the current select() that happens on the fds.

Is the mask argument to the callback indicative of a real mask, or is this an enum when passed to the clients? i.e. you seem to use a switch in all handlers, so is it actually meant that each callback has a single possible value, not an or'ed one?

Hm, this will actually be a bug when we get rid of the _can_read callbacks. So the switch will have to change to something else for sure.

Amit

#10 lore raw

Re: [Qemu-devel] [PATCH 2/7] iohandlers: Introduce a new API

In reply to Amit Shah

iohandler.h line 19

Quoted 13 lines · Amit Shah

Introduce a new iohandler api that doesn't have multiple callbacks. Instead, a single callback and a mask of events that got set will be passed on to the handler. This will ease our transition to a poll() interface instead of the current select() that happens on the fds.

iohandler.h new file +7 -0
+
+/* iohandler masks */
+#define IOH_MASK_CAN_READ	(1U<<  0)
+#define IOH_MASK_READ		(1U<<  1)
+#define IOH_MASK_WRITE		(1U<<  2)
+
+typedef int IOAllHandler(void *opaque, unsigned int mask);

Strange name.

Drop the opaque, instead put the IOHandler in there (or maybe the CharDev?) and use container_of().

iohandler.h line 26

Quoted 7 lines
iohandler.h new file +7 -0
+
+int assign_iohandler(int fd, IOAllHandler *handler, unsigned int mask,
+                     void *opaque);
+int remove_iohandler(int fd);
+int update_fd_mask(int fd, unsigned int mask);
+int get_fd_mask(int fd, unsigned int *mask);
+

iohandler_init(IOHandler *ioh, int fd, IOEventHandler *handler, unsigned mask) iohandler_del(IOHandler *ioh)
iohandler_set_event_mask(IOHandler *ioh, unsigned mask) iohandler_event_mask(IOHandler *ioh)

No opaques, use an object as a key so you don't have to search for it.

Signature · 1 line
error compiling committee.c: too many arguments to function
author
#11 lore raw

Re: [Qemu-devel] [PATCH 2/7] iohandlers: Introduce a new API

Quoted 7 lines · Avi Kivity
Quoted 6 lines · Amit Shah

Introduce a new iohandler api that doesn't have multiple callbacks. Instead, a single callback and a mask of events that got set will be passed on to the handler. This will ease our transition to a poll() interface instead of the current select() that happens on the fds.

Quoted 9 lines

iohandler.h line 19

Quoted 7 lines
iohandler.h new file +7 -0
+
+/* iohandler masks */
+#define IOH_MASK_CAN_READ	(1U<<  0)
+#define IOH_MASK_READ		(1U<<  1)
+#define IOH_MASK_WRITE		(1U<<  2)
+
+typedef int IOAllHandler(void *opaque, unsigned int mask);

Strange name.

IOHandler is taken. I plan to switch back to IOHandler when the older one is removed.

Quoted 2 lines

Drop the opaque, instead put the IOHandler in there (or maybe the CharDev?) and use container_of().

Can put the IOHandler there; the chardev is just one user of iohandlers, and there are others.

Quoted 14 lines

iohandler.h line 26

Quoted 7 lines
iohandler.h new file +7 -0
+
+int assign_iohandler(int fd, IOAllHandler *handler, unsigned int mask,
+                     void *opaque);
+int remove_iohandler(int fd);
+int update_fd_mask(int fd, unsigned int mask);
+int get_fd_mask(int fd, unsigned int *mask);
+

iohandler_init(IOHandler *ioh, int fd, IOEventHandler *handler, unsigned mask)
iohandler_del(IOHandler *ioh) iohandler_set_event_mask(IOHandler *ioh, unsigned mask) iohandler_event_mask(IOHandler *ioh)

Quoted 1 line

No opaques, use an object as a key so you don't have to search for it.

Thanks!

Amit

#12 lore raw

Re: [Qemu-devel] [PATCH 2/7] iohandlers: Introduce a new API

In reply to Avi Kivity
Quoted 17 lines · Avi Kivity

iohandler.h line 19

Quoted 13 lines · Amit Shah

Introduce a new iohandler api that doesn't have multiple callbacks. Instead, a single callback and a mask of events that got set will be passed on to the handler. This will ease our transition to a poll() interface instead of the current select() that happens on the fds.

iohandler.h new file +7 -0
+
+/* iohandler masks */
+#define IOH_MASK_CAN_READ    (1U<<  0)
+#define IOH_MASK_READ        (1U<<  1)
+#define IOH_MASK_WRITE        (1U<<  2)
+
+typedef int IOAllHandler(void *opaque, unsigned int mask);

Strange name.

Quoted 1 line

Drop the opaque, instead put the IOHandler in there (or maybe the CharDev?) and use container_of().

You know, I'm not there that this is automatically better.

Quoted 13 lines

iohandler.h line 26

Quoted 7 lines
iohandler.h new file +7 -0
+
+int assign_iohandler(int fd, IOAllHandler *handler, unsigned int mask,
+                     void *opaque);
+int remove_iohandler(int fd);
+int update_fd_mask(int fd, unsigned int mask);
+int get_fd_mask(int fd, unsigned int *mask);
+

iohandler_init(IOHandler *ioh, int fd, IOEventHandler *handler, unsigned mask) iohandler_del(IOHandler *ioh)
iohandler_set_event_mask(IOHandler *ioh, unsigned mask) iohandler_event_mask(IOHandler *ioh)

Quoted 1 line

No opaques, use an object as a key so you don't have to search for it.

I don't think there should be a setter/getter for the event mask. Just delete the handler and re-add it.

Why is there an IOHandler and an IOEventHandler argument for init?

Regards,

Anthony Liguori

#13 lore raw

Re: [Qemu-devel] [PATCH 2/7] iohandlers: Introduce a new API

Quoted 5 lines · Anthony Liguori
Quoted 2 lines

Drop the opaque, instead put the IOHandler in there (or maybe the CharDev?) and use container_of().

You know, I'm not there that this is automatically better.

Why not? One less unsafe cast.

Quoted 14 lines
Quoted 14 lines

iohandler.h line 26

Quoted 8 lines
iohandler.h new file +7 -0
+
+int assign_iohandler(int fd, IOAllHandler *handler, unsigned int mask,
+                     void *opaque);
+int remove_iohandler(int fd);
+int update_fd_mask(int fd, unsigned int mask);
+int get_fd_mask(int fd, unsigned int *mask);
+

iohandler_init(IOHandler *ioh, int fd, IOEventHandler *handler, unsigned mask) iohandler_del(IOHandler *ioh)
iohandler_set_event_mask(IOHandler *ioh, unsigned mask) iohandler_event_mask(IOHandler *ioh)

Quoted 4 lines
Quoted 1 line

No opaques, use an object as a key so you don't have to search for it.

I don't think there should be a setter/getter for the event mask. Just delete the handler and re-add it.

It's more epoll() compatible to update it. I'm fine with reregistering though.

Quoted 1 line

Why is there an IOHandler and an IOEventHandler argument for init?

IOHandler is the object, IOEventHandler is the function call.

Basically this is a 1:1 translation of

class IOHandler {
public:

    IOHandler(int fd, unsigned mask);
    ~IOHandler();
    virtual void io_event_handler() = 0;
    unsigned event_mask();
    void set_event_mask(unsigned mask);
}
class MyClient : private IOHandler {
    virtual void io_event_handler();
}

where the compiler automatically generates the container_of() to get to the actual MyClient pointer.

#14 lore raw

Re: [Qemu-devel] [PATCH 2/7] iohandlers: Introduce a new API

Quoted 8 lines · Avi Kivity
Quoted 5 lines · Anthony Liguori
Quoted 2 lines

Drop the opaque, instead put the IOHandler in there (or maybe the CharDev?) and use container_of().

You know, I'm not there that this is automatically better.

Why not? One less unsafe cast.

It turns out there are a lot of cases in QEMU where there isn't an obvious data structure to piggy back on.

Quoted 1 line
Quoted 1 line

Why is there an IOHandler and an IOEventHandler argument for init?

So wouldn't you set the IOEventHandler directly in the IOHandler as part of initialization? IOW:

struct MyDevice {
    IOHandler iohandler;
};

iohandler.func = my_io_function;
io_handler_init(&iohandler, fd, event_mask);

That's the paradigm I'm used to at least.

Regards,

Anthony Liguori

Quoted 19 lines

IOHandler is the object, IOEventHandler is the function call.

Basically this is a 1:1 translation of

class IOHandler {
public:

    IOHandler(int fd, unsigned mask);
    ~IOHandler();
    virtual void io_event_handler() = 0;
    unsigned event_mask();
    void set_event_mask(unsigned mask);
}
class MyClient : private IOHandler {
    virtual void io_event_handler();
}

where the compiler automatically generates the container_of() to get to the actual MyClient pointer.

#15 lore raw

Re: [Qemu-devel] [PATCH 2/7] iohandlers: Introduce a new API

Quoted 11 lines · Anthony Liguori
Quoted 8 lines · Avi Kivity
Quoted 5 lines · Anthony Liguori
Quoted 2 lines

Drop the opaque, instead put the IOHandler in there (or maybe the CharDev?) and use container_of().

You know, I'm not there that this is automatically better.

Why not? One less unsafe cast.

It turns out there are a lot of cases in QEMU where there isn't an obvious data structure to piggy back on.

Examples?

In that case you can always make a structure with a void * and a IOHandler, and you get your opaque. But I don't really see how it can happen, the void * always points to a structure (or is ignored if there's a static instance), and you can add that IOHandler to the structure.

Quoted 5 lines
Quoted 2 lines
Quoted 2 lines

Why is there an IOHandler and an IOEventHandler argument for init?

So wouldn't you set the IOEventHandler directly in the IOHandler as part of initialization? IOW:

Quoted 8 lines
struct MyDevice {
    IOHandler iohandler;
};

iohandler.func = my_io_function;
io_handler_init(&iohandler, fd, event_mask);

That's the paradigm I'm used to at least.

You mean instead of passing .func to io_handler_init()? I slightly prefer my version (less chance to forget the assignment) but I'm okay with either.

Signature · 1 line
error compiling committee.c: too many arguments to function
#16 lore raw

[Qemu-devel] Re: [PATCH 2/7] iohandlers: Introduce a new API

In reply to Amit Shah
Quoted 34 lines · Amit Shah

Introduce a new iohandler api that doesn't have multiple callbacks. Instead, a single callback and a mask of events that got set will be passed on to the handler. This will ease our transition to a poll() interface instead of the current select() that happens on the fds.

---
  iohandler.h |   28 +++++++++++
  vl.c        |  144 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2 files changed, 172 insertions(+), 0 deletions(-)

create mode 100644 iohandler.h

iohandler.h new file +15 -0
new file mode 100644
index 0000000..6553835
@@ -0,0 +1,28 @@
+/*
+ * Declarations for iohandler functions
+ *
+ * Copyright Red Hat, Inc. 2011
+ * Copyright Amit Shah<[email protected]>  2011
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef _QEMU_IOHANDLER_H
+#define _QEMU_IOHANDLER_H
+
+/* iohandler masks */
+#define IOH_MASK_CAN_READ	(1U<<  0)

iohandler.h line 25

Quoted 10 lines
iohandler.h new file +10 -0
+#define IOH_MASK_READ		(1U<<  1)
+#define IOH_MASK_WRITE		(1U<<  2)
+
+typedef int IOAllHandler(void *opaque, unsigned int mask);
+
+int assign_iohandler(int fd, IOAllHandler *handler, unsigned int mask,
+                     void *opaque);
+int remove_iohandler(int fd);
+int update_fd_mask(int fd, unsigned int mask);
+int get_fd_mask(int fd, unsigned int *mask);

As I previously suggested, we should return a connection handle instead of using an fd as an implicit handle.

Regards,

Anthony Liguori

Quoted 194 lines
iohandler.h new file +3 -0
+
+
+#endif /* _QEMU_IOHANDLER_H */
vl.c +144 -0
index e248ec4..9dabee2 100644
@@ -2,6 +2,8 @@
   * QEMU System Emulator
   *
   * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2011 Amit Shah,<[email protected]>
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to deal
@@ -136,6 +138,7 @@ int main(int argc, char **argv)
  #include "gdbstub.h"
  #include "qemu-timer.h"
  #include "qemu-char.h"
+#include "iohandler.h"
  #include "cache-utils.h"
  #include "block.h"
  #include "blockdev.h"
@@ -1030,6 +1033,8 @@ typedef struct IOHandlerRecord {
      IOCanReadHandler *fd_read_poll;
      IOHandler *fd_read;
      IOHandler *fd_write;
+    IOAllHandler *fd_iohandler;
+    unsigned int mask;
      int deleted;
      void *opaque;
      /* temporary data */
@@ -1040,6 +1045,97 @@ typedef struct IOHandlerRecord {
  static QLIST_HEAD(, IOHandlerRecord) io_handlers_old =
      QLIST_HEAD_INITIALIZER(io_handlers_old);
 
+static QLIST_HEAD(, IOHandlerRecord) io_handlers =
+    QLIST_HEAD_INITIALIZER(io_handlers);
+
+static IOHandlerRecord *find_iohandler(int fd)
+{
+    IOHandlerRecord *ioh;
+
+    QLIST_FOREACH(ioh,&io_handlers, next) {
+        if (ioh->fd == fd) {
+            return ioh;
+        }
+    }
+    return NULL;
+}
+
+static int update_iohandler_mask(IOHandlerRecord *ioh, unsigned int mask)
+{
+    assert(ioh);
+
+    ioh->mask = mask;
+    return 0;
+}
+
+/*
+ * Updates the mask for the fd.  Returns 0 on success.
+ */
+int update_fd_mask(int fd, unsigned int mask)
+{
+    IOHandlerRecord *ioh;
+
+    ioh = find_iohandler(fd);
+    if (!ioh) {
+        return -1;
+    }
+
+    return update_iohandler_mask(ioh, mask);
+}
+
+/*
+ * Populates the mask registered in *mask.  Only valid if return value
+ * is 0.
+ */
+int get_fd_mask(int fd, unsigned int *mask)
+{
+    IOHandlerRecord *ioh;
+
+    ioh = find_iohandler(fd);
+    if (!ioh) {
+        return -1;
+    }
+    *mask = ioh->mask;
+
+    return 0;
+}
+
+/*
+ * Assign an iohandler to an fd.  Can also be used to update the mask
+ * or handler or the opaque pointer and also to delete the iohandler.
+ * Returns 0 on success.
+ */
+int assign_iohandler(int fd, IOAllHandler *handler, unsigned int mask,
+                     void *opaque)
+{
+    IOHandlerRecord *ioh;
+
+    ioh = find_iohandler(fd);
+
+    if (!handler) {
+        if (ioh) {
+            ioh->deleted = 1;
+        }
+        return 0;
+    }
+
+    if (!ioh) {
+        ioh = qemu_mallocz(sizeof(IOHandlerRecord));
+        QLIST_INSERT_HEAD(&io_handlers, ioh, next);
+        ioh->fd = fd;
+    }
+    ioh->fd_iohandler = handler;
+    ioh->opaque = opaque;
+    update_iohandler_mask(ioh, mask);
+    ioh->deleted = 0;
+
+    return 0;
+}
+
+int remove_iohandler(int fd)
+{
+    return assign_iohandler(fd, NULL, 0, NULL);
+}
 
  /* XXX: fd_read_poll should be suppressed, but an API change is
     necessary in the character devices to suppress fd_can_read(). */
@@ -1363,6 +1459,26 @@ void main_loop_wait(int nonblocking)
                  nfds = ioh->fd;
          }
      }
+    QLIST_FOREACH(ioh,&io_handlers, next) {
+        if (ioh->deleted) {
+            continue;
+        }
+        if (ioh->mask&  IOH_MASK_READ&&
+            (!(ioh->mask&  IOH_MASK_CAN_READ) ||
+             (ioh->fd_iohandler(ioh->opaque, IOH_MASK_CAN_READ) != 0))) {
+
+            FD_SET(ioh->fd,&rfds);
+            if (ioh->fd>  nfds) {
+                nfds = ioh->fd;
+            }
+        }
+        if (ioh->mask&  IOH_MASK_WRITE) {
+            FD_SET(ioh->fd,&wfds);
+            if (ioh->fd>  nfds) {
+                nfds = ioh->fd;
+            }
+        }
+    }
 
      tv.tv_sec = timeout / 1000;
      tv.tv_usec = (timeout % 1000) * 1000;
@@ -1389,6 +1505,34 @@ void main_loop_wait(int nonblocking)
                  qemu_free(ioh);
              }
          }
+        QLIST_FOREACH_SAFE(ioh,&io_handlers, next, pioh) {
+            unsigned int mask;
+
+            mask = 0;
+            if (!ioh->deleted) {
+                if (FD_ISSET(ioh->fd,&rfds)) {
+                    mask |= IOH_MASK_READ;
+                }
+                if (FD_ISSET(ioh->fd,&wfds)) {
+                    mask |= IOH_MASK_WRITE;
+                }
+            }
+            /*
+             * Strip out flags the caller didn't ask for -- shouldn't
+             * happen since we set rfds and wfds based on the value of
+             * ioh->mask anyway.
+             */
+            mask&= ioh->mask;
+            if (mask) {
+                ioh->fd_iohandler(ioh->opaque, mask);
+            }
+            /* Do this last in case the handler marked it for deletion */
+            if (ioh->deleted) {
+                QLIST_REMOVE(ioh, next);
+                qemu_free(ioh);
+                continue;
+            }
+        }
      }
 
      slirp_select_poll(&rfds,&wfds,&xfds, (ret<  0));
author
#17 lore raw

PATCH 3/7 char: tcp: Use new iohandler api

In reply to Amit Shah

Update the tcp code to use the new iohandler api. The change is mostly mechanical with a new iohandler function calling the older functions depending on the value of the 'mask' field.

---
 qemu-char.c |   48 ++++++++++++++++++++++++++++++++++++------------
 1 files changed, 36 insertions(+), 12 deletions(-)
qemu-char.c +36 -12
index bd4e944..ba58c18 100644
@@ -21,6 +21,7 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+#include "iohandler.h"
 #include "qemu-common.h"
 #include "net.h"
 #include "monitor.h"
@@ -1909,7 +1910,7 @@ typedef struct {
     int msgfd;
 } TCPCharDriver;
 
-static void tcp_chr_accept(void *opaque);
+static int tcp_accept_handler(void *opaque, unsigned int mask);
 
 static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
@@ -2064,9 +2065,10 @@ static void tcp_chr_read(void *opaque)
         /* connection closed */
         s->connected = 0;
         if (s->listen_fd >= 0) {
-            qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
+            assign_iohandler(s->listen_fd, tcp_accept_handler, IOH_MASK_READ,
+                             chr);
         }
-        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+        remove_iohandler(s->fd);
         closesocket(s->fd);
         s->fd = -1;
         qemu_chr_event(chr, CHR_EVENT_CLOSED);
@@ -2078,6 +2080,22 @@ static void tcp_chr_read(void *opaque)
     }
 }
 
+static int tcp_iohandler(void *opaque, unsigned int mask)
+{
+    int ret;
+
+    ret = 0;
+    switch(mask) {
+    case IOH_MASK_CAN_READ:
+        ret = tcp_chr_read_poll(opaque);
+        break;
+    case IOH_MASK_READ:
+        tcp_chr_read(opaque);
+        break;
+    }
+    return ret;
+}
+
 #ifndef _WIN32
 CharDriverState *qemu_chr_open_eventfd(int eventfd)
 {
@@ -2091,8 +2109,8 @@ static void tcp_chr_connect(void *opaque)
     TCPCharDriver *s = chr->opaque;
 
     s->connected = 1;
-    qemu_set_fd_handler2(s->fd, tcp_chr_read_poll,
-                         tcp_chr_read, NULL, chr);
+    assign_iohandler(s->fd, tcp_iohandler, IOH_MASK_CAN_READ|IOH_MASK_READ,
+                     chr);
     qemu_chr_generic_open(chr);
 }
 
@@ -2117,7 +2135,7 @@ static void socket_set_nodelay(int fd)
     setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
 }
 
-static void tcp_chr_accept(void *opaque)
+static int tcp_accept_handler(void *opaque, unsigned int mask)
 {
     CharDriverState *chr = opaque;
     TCPCharDriver *s = chr->opaque;
@@ -2129,6 +2147,10 @@ static void tcp_chr_accept(void *opaque)
     socklen_t len;
     int fd;
 
+    if (!(mask & IOH_MASK_READ)) {
+        return 0;
+    }
+
     for(;;) {
 #ifndef _WIN32
 	if (s->is_unix) {
@@ -2142,7 +2164,7 @@ static void tcp_chr_accept(void *opaque)
 	}
         fd = qemu_accept(s->listen_fd, addr, &len);
         if (fd < 0 && errno != EINTR) {
-            return;
+            return 0;
         } else if (fd >= 0) {
             if (s->do_telnetopt)
                 tcp_chr_telnet_init(fd);
@@ -2153,19 +2175,21 @@ static void tcp_chr_accept(void *opaque)
     if (s->do_nodelay)
         socket_set_nodelay(fd);
     s->fd = fd;
-    qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
+    remove_iohandler(s->listen_fd);
     tcp_chr_connect(chr);
+
+    return 0;
 }
 
 static void tcp_chr_close(CharDriverState *chr)
 {
     TCPCharDriver *s = chr->opaque;
     if (s->fd >= 0) {
-        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+        remove_iohandler(s->fd);
         closesocket(s->fd);
     }
     if (s->listen_fd >= 0) {
-        qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
+        remove_iohandler(s->listen_fd);
         closesocket(s->listen_fd);
     }
     qemu_free(s);
@@ -2227,7 +2251,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
 
     if (is_listen) {
         s->listen_fd = fd;
-        qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
+        assign_iohandler(s->listen_fd, tcp_accept_handler, IOH_MASK_READ, chr);
         if (is_telnet)
             s->do_telnetopt = 1;
 
@@ -2257,7 +2281,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     if (is_listen && is_waitconnect) {
         printf("QEMU waiting for connection on: %s\n",
                chr->filename);
-        tcp_chr_accept(chr);
+        tcp_accept_handler(chr, IOH_MASK_READ);
         socket_set_nonblock(s->listen_fd);
     }
     return chr;
Signature · 1 line
1.7.4
author
#18 lore raw

PATCH 4/7 char: udp: Use new iohandler api

In reply to Amit Shah

Update the udp code to use the new iohandler api. The change is mostly mechanical with a new iohandler function calling the older functions depending on the value of the 'mask' field.

---
 qemu-char.c |   22 +++++++++++++++++++---
 1 files changed, 19 insertions(+), 3 deletions(-)
qemu-char.c +19 -3
index ba58c18..61f8358 100644
@@ -1842,13 +1842,29 @@ static void udp_chr_read(void *opaque)
     }
 }
 
+static int udp_iohandler(void *opaque, unsigned int mask)
+{
+    int ret;
+
+    ret = 0;
+    switch(mask) {
+    case IOH_MASK_CAN_READ:
+        ret = udp_chr_read_poll(opaque);
+        break;
+    case IOH_MASK_READ:
+        udp_chr_read(opaque);
+        break;
+    }
+    return ret;
+}
+
 static void udp_chr_update_read_handler(CharDriverState *chr)
 {
     NetCharDriver *s = chr->opaque;
 
     if (s->fd >= 0) {
-        qemu_set_fd_handler2(s->fd, udp_chr_read_poll,
-                             udp_chr_read, NULL, chr);
+        assign_iohandler(s->fd, udp_iohandler,
+                          IOH_MASK_CAN_READ|IOH_MASK_READ, chr);
     }
 }
 
@@ -1856,7 +1872,7 @@ static void udp_chr_close(CharDriverState *chr)
 {
     NetCharDriver *s = chr->opaque;
     if (s->fd >= 0) {
-        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+        remove_iohandler(s->fd);
         closesocket(s->fd);
     }
     qemu_free(s);
Signature · 1 line
1.7.4
author
#19 lore raw

PATCH 5/7 char: fd: Use new iohandler api

In reply to Amit Shah

Update the fd code to use the new iohandler api. The change is mostly mechanical with a new iohandler function calling the older functions depending on the value of the 'mask' field.

---
 qemu-char.c |   24 ++++++++++++++++++++----
 1 files changed, 20 insertions(+), 4 deletions(-)
qemu-char.c +20 -4
index 61f8358..d93820e 100644
@@ -572,7 +572,7 @@ static void fd_chr_read(void *opaque)
     size = read(s->fd_in, buf, len);
     if (size == 0) {
         /* FD has been closed. Remove it from the active list.  */
-        qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL);
+        remove_iohandler(s->fd_in);
         qemu_chr_event(chr, CHR_EVENT_CLOSED);
         return;
     }
@@ -581,6 +581,22 @@ static void fd_chr_read(void *opaque)
     }
 }
 
+static int fd_iohandler(void *opaque, unsigned int mask)
+{
+    int ret;
+
+    ret = 0;
+    switch(mask) {
+    case IOH_MASK_CAN_READ:
+        ret = fd_chr_read_poll(opaque);
+        break;
+    case IOH_MASK_READ:
+        fd_chr_read(opaque);
+        break;
+    }
+    return ret;
+}
+
 static void fd_chr_update_read_handler(CharDriverState *chr)
 {
     FDCharDriver *s = chr->opaque;
@@ -588,8 +604,8 @@ static void fd_chr_update_read_handler(CharDriverState *chr)
     if (s->fd_in >= 0) {
         if (display_type == DT_NOGRAPHIC && s->fd_in == 0) {
         } else {
-            qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll,
-                                 fd_chr_read, NULL, chr);
+            assign_iohandler(s->fd_in, fd_iohandler,
+                             IOH_MASK_CAN_READ|IOH_MASK_READ, chr);
         }
     }
 }
@@ -601,7 +617,7 @@ static void fd_chr_close(struct CharDriverState *chr)
     if (s->fd_in >= 0) {
         if (display_type == DT_NOGRAPHIC && s->fd_in == 0) {
         } else {
-            qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL);
+            remove_iohandler(s->fd_in);
         }
     }
 
Signature · 1 line
1.7.4
author
#20 lore raw

PATCH 6/7 char: stdio: Use new iohandler api

In reply to Amit Shah

Update the stdio code to use the new iohandler api. The change is mostly mechanical with a new iohandler function calling the older functions depending on the value of the 'mask' field.

---
 qemu-char.c |   22 +++++++++++++++++++---
 1 files changed, 19 insertions(+), 3 deletions(-)
qemu-char.c +19 -3
index d93820e..ade28ba 100644
@@ -717,7 +717,7 @@ static void stdio_read(void *opaque)
     size = read(0, buf, 1);
     if (size == 0) {
         /* stdin has been closed. Remove it from the active list.  */
-        qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL);
+        remove_iohandler(0);
         qemu_chr_event(chr, CHR_EVENT_CLOSED);
         return;
     }
@@ -730,6 +730,22 @@ static void stdio_read(void *opaque)
     }
 }
 
+static int stdio_iohandler(void *opaque, unsigned int mask)
+{
+    int ret;
+
+    ret = 0;
+    switch(mask) {
+    case IOH_MASK_CAN_READ:
+        ret = stdio_read_poll(opaque);
+        break;
+    case IOH_MASK_READ:
+        stdio_read(opaque);
+        break;
+    }
+    return ret;
+}
+
 /* init terminal so that we can grab keys */
 static struct termios oldtty;
 static int old_fd0_flags;
@@ -767,7 +783,7 @@ static void qemu_chr_close_stdio(struct CharDriverState *chr)
 {
     term_exit();
     stdio_nb_clients--;
-    qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL);
+    remove_iohandler(0);
     fd_chr_close(chr);
 }
 
@@ -787,7 +803,7 @@ static CharDriverState *qemu_chr_open_stdio(QemuOpts *opts)
     chr = qemu_chr_open_fd(0, 1);
     chr->chr_close = qemu_chr_close_stdio;
     chr->chr_set_echo = qemu_chr_set_echo_stdio;
-    qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr);
+    assign_iohandler(0, stdio_iohandler, IOH_MASK_CAN_READ|IOH_MASK_READ, chr);
     stdio_nb_clients++;
     stdio_allow_signal = qemu_opt_get_bool(opts, "signal",
                                            display_type != DT_NOGRAPHIC);
Signature · 1 line
1.7.4
author
#21 lore raw

PATCH 7/7 char: pty: Use new iohandler api

In reply to Amit Shah

Update the pty code to use the new iohandler api. The change is mostly mechanical with a new iohandler function calling the older functions depending on the value of the 'mask' field.

---
 qemu-char.c |   24 ++++++++++++++++++++----
 1 files changed, 20 insertions(+), 4 deletions(-)
qemu-char.c +20 -4
index ade28ba..6875b00 100644
@@ -929,12 +929,28 @@ static void pty_chr_read(void *opaque)
     }
 }
 
+static int pty_iohandler(void *opaque, unsigned int mask)
+{
+    int ret;
+
+    ret = 0;
+    switch(mask) {
+    case IOH_MASK_CAN_READ:
+        ret = pty_chr_read_poll(opaque);
+        break;
+    case IOH_MASK_READ:
+        pty_chr_read(opaque);
+        break;
+    }
+    return ret;
+}
+
 static void pty_chr_update_read_handler(CharDriverState *chr)
 {
     PtyCharDriver *s = chr->opaque;
 
-    qemu_set_fd_handler2(s->fd, pty_chr_read_poll,
-                         pty_chr_read, NULL, chr);
+    assign_iohandler(s->fd, pty_iohandler, IOH_MASK_CAN_READ|IOH_MASK_READ,
+                     chr);
     s->polling = 1;
     /*
      * Short timeout here: just need wait long enougth that qemu makes
@@ -952,7 +968,7 @@ static void pty_chr_state(CharDriverState *chr, int connected)
     PtyCharDriver *s = chr->opaque;
 
     if (!connected) {
-        qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+        remove_iohandler(s->fd);
         s->connected = 0;
         s->polling = 0;
         /* (re-)connect poll interval for idle guests: once per second.
@@ -988,7 +1004,7 @@ static void pty_chr_close(struct CharDriverState *chr)
 {
     PtyCharDriver *s = chr->opaque;
 
-    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+    remove_iohandler(s->fd);
     close(s->fd);
     qemu_del_timer(s->timer);
     qemu_free_timer(s->timer);
Signature · 1 line
1.7.4