Problems persist in KQueueSelectorProvider (Mac) in 7u6 ea

David Schlosnagle schlosna at gmail.com
Mon Aug 13 14:24:59 PDT 2012


On Mon, Aug 13, 2012 at 3:13 PM, Jason T. Greene
<jason.greene at redhat.com> wrote:
> I threw together a quick patch (attached below against 7u-dev), and it
> appears to resolve the issues on 6 and 7. Although it needs more testing.
>
> The preClose problem disappears as well with this change. My hunch is that
> the tight spin loop on kqueue makes it impossible for close/dup2 to ever
> complete.

Hi Jason,

A few minor comments/questions in KQueueArrayWrapper.java:

Should the updateList and Update instance fields all be final?
Is there any reason not to avoid the continue in updateRegistrations()?
    while ((u = updateList.poll()) != null) {
        SelChImpl ch = u.channel;
        if (ch.isOpen()) {
            register0(kq, ch.getFDVal(), u.events & POLLIN, u.events & POLLOUT);
        }
    }

Do you foresee any lock contention issues with the synchronization on
updateList? Would using a java.util.concurrent.LinkedBlockingQueue
rather than the LinkedList with synchronization violate the API
semantics of batching the updates? I was thinking something along the
lines of the KQueueArrayWrapper.java diff below would work (but I
haven't tested at all).

Thanks,
Dave


diff --git a/KQueueArrayWrapper.java b/KQueueArrayWrapper.java
index 5a7020c..936f086 100644
--- a/KQueueArrayWrapper.java
+++ b/KQueueArrayWrapper.java
@@ -34,7 +34,9 @@ package sun.nio.ch;
 import sun.misc.*;
 import java.io.IOException;
 import java.io.FileDescriptor;
-
+import java.util.Iterator;
+import java.util.Queue;
+import java.util.concurrent.LinkedBlockingQueue;

 /*
  * struct kevent {           // 32-bit    64-bit
@@ -85,6 +87,9 @@ class KQueueArrayWrapper {
     // The fd of the interrupt line coming in
     private int incomingInterruptFD;

+    // The queue of file descriptor registration updates to process
+    private final Queue<Update> updateQueue = new LinkedBlockingQueue<>();
+
     static {
         initStructSizes();
         String datamodel = java.security.AccessController.doPrivileged(
@@ -100,6 +105,16 @@ class KQueueArrayWrapper {
         kq = init();
     }

+    // Used to update file description registrations
+    private static class Update {
+        final SelChImpl channel;
+        final int events;
+        Update(SelChImpl channel, int events) {
+            this.channel = channel;
+            this.events = events;
+        }
+    }
+
     void initInterrupt(int fd0, int fd1) {
         outgoingInterruptFD = fd1;
         incomingInterruptFD = fd0;
@@ -137,12 +152,31 @@ class KQueueArrayWrapper {
         }
     }

-    void setInterest(int fd, int events) {
-        register0(kq, fd, events & POLLIN, events & POLLOUT);
+    void setInterest(SelChImpl channel, int events) {
+        // update existing registration
+        updateQueue.add(new Update(channel, events));
     }

-    void release(int fd) {
-        register0(kq, fd, 0, 0);
+    void release(SelChImpl channel) {
+        // flush any pending updates
+        for (Iterator<Update> it = updateQueue.iterator(); it.hasNext();) {
+            if (it.next().channel == channel) {
+                it.remove();
+            }
+        }
+
+        // remove
+        register0(kq, channel.getFDVal(), 0, 0);
+    }
+
+    void updateRegistrations() {
+        Update u = null;
+        while ((u = updateQueue.poll()) != null) {
+            SelChImpl ch = u.channel;
+            if (ch.isOpen()) {
+                register0(kq, ch.getFDVal(), u.events & POLLIN,
u.events & POLLOUT);
+            }
+        }
     }

     void close() throws IOException {
@@ -157,6 +191,7 @@ class KQueueArrayWrapper {
     }

     int poll(long timeout) {
+        updateRegistrations();
         int updated = kevent0(kq, keventArrayAddress, NUM_KEVENTS, timeout);
         return updated;
     }


More information about the nio-dev mailing list