1 /* 2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.nio.ch; 27 28 import java.io.IOException; 29 import java.nio.channels.*; 30 import java.nio.channels.spi.*; 31 import java.util.*; 32 import sun.misc.*; 33 34 35 /** 36 * An implementation of Selector for Solaris. 37 */ 38 class DevPollSelectorImpl 39 extends SelectorImpl 40 { 41 42 // File descriptors used for interrupt 43 protected int fd0; 44 protected int fd1; 45 46 // The poll object 47 DevPollArrayWrapper pollWrapper; 48 49 // Maps from file descriptors to keys 50 private Map<Integer,SelectionKeyImpl> fdToKey; 51 52 // True if this Selector has been closed 53 private boolean closed = false; 54 55 // Lock for close/cleanup 56 private Object closeLock = new Object(); 57 58 // Lock for interrupt triggering and clearing 59 private Object interruptLock = new Object(); 60 private boolean interruptTriggered = false; 61 62 /** 63 * Package private constructor called by factory method in 64 * the abstract superclass Selector. 65 */ 66 DevPollSelectorImpl(SelectorProvider sp) { 67 super(sp); 68 long pipeFds = IOUtil.makePipe(false); 69 fd0 = (int) (pipeFds >>> 32); 70 fd1 = (int) pipeFds; 71 pollWrapper = new DevPollArrayWrapper(); 72 pollWrapper.initInterrupt(fd0, fd1); 73 fdToKey = new HashMap<Integer,SelectionKeyImpl>(); 74 } 75 76 protected int doSelect(long timeout) 77 throws IOException 78 { 79 if (closed) 80 throw new ClosedSelectorException(); 81 processDeregisterQueue(); 82 try { 83 begin(); 84 pollWrapper.poll(timeout); 85 } finally { 86 end(); 87 } 88 processDeregisterQueue(); 89 int numKeysUpdated = updateSelectedKeys(); 90 if (pollWrapper.interrupted()) { 91 // Clear the wakeup pipe 92 pollWrapper.putReventOps(pollWrapper.interruptedIndex(), 0); 93 synchronized (interruptLock) { 94 pollWrapper.clearInterrupted(); 95 IOUtil.drain(fd0); 96 interruptTriggered = false; 97 } 98 } 99 return numKeysUpdated; 100 } 101 102 /** 103 * Update the keys whose fd's have been selected by the devpoll 104 * driver. Add the ready keys to the ready queue. 105 */ 106 private int updateSelectedKeys() { 107 int entries = pollWrapper.updated; 108 int numKeysUpdated = 0; 109 for (int i=0; i<entries; i++) { 110 int nextFD = pollWrapper.getDescriptor(i); 111 SelectionKeyImpl ski = fdToKey.get(Integer.valueOf(nextFD)); 112 // ski is null in the case of an interrupt 113 if (ski != null) { 114 int rOps = pollWrapper.getReventOps(i); 115 if (selectedKeys.contains(ski)) { 116 if (ski.channel.translateAndSetReadyOps(rOps, ski)) { 117 numKeysUpdated++; 118 } 119 } else { 120 ski.channel.translateAndSetReadyOps(rOps, ski); 121 if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) { 122 selectedKeys.add(ski); 123 numKeysUpdated++; 124 } 125 } 126 } 127 } 128 return numKeysUpdated; 129 } 130 131 protected void implClose() throws IOException { 132 if (closed) 133 return; 134 closed = true; 135 136 // prevent further wakeup 137 synchronized (interruptLock) { 138 interruptTriggered = true; 139 } 140 141 FileDispatcherImpl.closeIntFD(fd0); 142 FileDispatcherImpl.closeIntFD(fd1); 143 144 pollWrapper.release(fd0); 145 pollWrapper.closeDevPollFD(); 146 selectedKeys = null; 147 148 // Deregister channels 149 Iterator<SelectionKey> i = keys.iterator(); 150 while (i.hasNext()) { 151 SelectionKeyImpl ski = (SelectionKeyImpl)i.next(); 152 deregister(ski); 153 SelectableChannel selch = ski.channel(); 154 if (!selch.isOpen() && !selch.isRegistered()) 155 ((SelChImpl)selch).kill(); 156 i.remove(); 157 } 158 fd0 = -1; 159 fd1 = -1; 160 } 161 162 protected void implRegister(SelectionKeyImpl ski) { 163 int fd = IOUtil.fdVal(ski.channel.getFD()); 164 fdToKey.put(Integer.valueOf(fd), ski); 165 keys.add(ski); 166 } 167 168 protected void implDereg(SelectionKeyImpl ski) throws IOException { 169 int i = ski.getIndex(); 170 assert (i >= 0); 171 int fd = ski.channel.getFDVal(); 172 fdToKey.remove(Integer.valueOf(fd)); 173 pollWrapper.release(fd); 174 ski.setIndex(-1); 175 keys.remove(ski); 176 selectedKeys.remove(ski); 177 deregister((AbstractSelectionKey)ski); 178 SelectableChannel selch = ski.channel(); 179 if (!selch.isOpen() && !selch.isRegistered()) 180 ((SelChImpl)selch).kill(); 181 } 182 183 public void putEventOps(SelectionKeyImpl sk, int ops) { 184 if (closed) 185 throw new ClosedSelectorException(); 186 int fd = IOUtil.fdVal(sk.channel.getFD()); 187 pollWrapper.setInterest(fd, ops); 188 } 189 190 public Selector wakeup() { 191 synchronized (interruptLock) { 192 if (!interruptTriggered) { 193 pollWrapper.interrupt(); 194 interruptTriggered = true; 195 } 196 } 197 return this; 198 } 199 200 static { 201 Util.load(); 202 } 203 204 }