Patchwork [RFC,11/13] rcuify iohandlers

login
register
mail settings
Submitter Paolo Bonzini
Date Aug. 15, 2011, 9:08 p.m.
Message ID <1313442520-12062-12-git-send-email-pbonzini@redhat.com>
Download mbox | patch
Permalink /patch/110099/
State New
Headers show

Comments

Paolo Bonzini - Aug. 15, 2011, 9:08 p.m.
Just a proof of concept, with the write-side still under the global
lock, in order to test the call_rcu code.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 iohandler.c |   45 ++++++++++++++++++++-------------------------
 1 files changed, 20 insertions(+), 25 deletions(-)

Patch

diff --git a/iohandler.c b/iohandler.c
index 2b82421..4c1f68f 100644
--- a/iohandler.c
+++ b/iohandler.c
@@ -26,17 +26,18 @@ 
 #include "qemu-common.h"
 #include "qemu-char.h"
 #include "qemu-queue.h"
+#include "rcu.h"
 
 #ifndef _WIN32
 #include <sys/wait.h>
 #endif
 
 typedef struct IOHandlerRecord {
+    struct rcu_head h;
     int fd;
     IOCanReadHandler *fd_read_poll;
     IOHandler *fd_read;
     IOHandler *fd_write;
-    int deleted;
     void *opaque;
     QLIST_ENTRY(IOHandlerRecord) next;
 } IOHandlerRecord;
@@ -55,28 +56,26 @@  int qemu_set_fd_handler2(int fd,
 {
     IOHandlerRecord *ioh;
 
-    if (!fd_read && !fd_write) {
-        QLIST_FOREACH(ioh, &io_handlers, next) {
-            if (ioh->fd == fd) {
-                ioh->deleted = 1;
-                break;
-            }
-        }
-    } else {
-        QLIST_FOREACH(ioh, &io_handlers, next) {
-            if (ioh->fd == fd)
-                goto found;
+    //qemu_mutex_lock(&iohandler_lock);
+    QLIST_FOREACH(ioh, &io_handlers, next) {
+        if (ioh->fd == fd) {
+            break;
         }
+    }
+    if (ioh) {
+        QLIST_REMOVE(ioh, next);
+        call_rcu(&ioh->h, rcu_free);
+    }
+    if (fd_read || fd_write) {
         ioh = qemu_mallocz(sizeof(IOHandlerRecord));
-        QLIST_INSERT_HEAD(&io_handlers, ioh, next);
-    found:
         ioh->fd = fd;
         ioh->fd_read_poll = fd_read_poll;
         ioh->fd_read = fd_read;
         ioh->fd_write = fd_write;
         ioh->opaque = opaque;
-        ioh->deleted = 0;
+        QLIST_INSERT_HEAD(&io_handlers, ioh, next);
     }
+    //qemu_mutex_lock(&iohandler_unlock);
     return 0;
 }
 
@@ -92,9 +91,8 @@  void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *
 {
     IOHandlerRecord *ioh;
 
+    rcu_read_lock();
     QLIST_FOREACH(ioh, &io_handlers, next) {
-        if (ioh->deleted)
-            continue;
         if (ioh->fd_read &&
             (!ioh->fd_read_poll ||
              ioh->fd_read_poll(ioh->opaque) != 0)) {
@@ -108,6 +106,7 @@  void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *
                 *pnfds = ioh->fd;
         }
     }
+    rcu_read_unlock();
 }
 
 void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int ret)
@@ -115,20 +114,16 @@  void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int re
     if (ret > 0) {
         IOHandlerRecord *pioh, *ioh;
 
+        rcu_read_lock();
         QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
-            if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, readfds)) {
+            if (ioh->fd_read && FD_ISSET(ioh->fd, readfds)) {
                 ioh->fd_read(ioh->opaque);
             }
-            if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, writefds)) {
+            if (ioh->fd_write && FD_ISSET(ioh->fd, writefds)) {
                 ioh->fd_write(ioh->opaque);
             }
-
-            /* Do this last in case read/write handlers marked it for deletion */
-            if (ioh->deleted) {
-                QLIST_REMOVE(ioh, next);
-                qemu_free(ioh);
-            }
         }
+        rcu_read_unlock();
     }
 }