Save This Page
Home » openjdk-7 » sun » nio » ch » [javadoc | source]
    1   /*
    2    * Copyright (c) 2001, 2009, 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 sun.misc;
   29   import java.io.IOException;
   30   import java.util.LinkedList;
   31   
   32   
   33   /**
   34    * Manipulates a native array of pollfd structs on Solaris:
   35    *
   36    * typedef struct pollfd {
   37    *    int fd;
   38    *    short events;
   39    *    short revents;
   40    * } pollfd_t;
   41    *
   42    * @author Mike McCloskey
   43    * @since 1.4
   44    */
   45   
   46   class DevPollArrayWrapper {
   47   
   48       // Event masks
   49       static final short POLLIN       = 0x0001;
   50       static final short POLLPRI      = 0x0002;
   51       static final short POLLOUT      = 0x0004;
   52       static final short POLLRDNORM   = 0x0040;
   53       static final short POLLWRNORM   = POLLOUT;
   54       static final short POLLRDBAND   = 0x0080;
   55       static final short POLLWRBAND   = 0x0100;
   56       static final short POLLNORM     = POLLRDNORM;
   57       static final short POLLERR      = 0x0008;
   58       static final short POLLHUP      = 0x0010;
   59       static final short POLLNVAL     = 0x0020;
   60       static final short POLLREMOVE   = 0x0800;
   61       static final short POLLCONN     = POLLOUT;
   62   
   63       // Miscellaneous constants
   64       static final short SIZE_POLLFD   = 8;
   65       static final short FD_OFFSET     = 0;
   66       static final short EVENT_OFFSET  = 4;
   67       static final short REVENT_OFFSET = 6;
   68   
   69       // Maximum number of open file descriptors
   70       static final int   OPEN_MAX      = fdLimit();
   71   
   72       // Number of pollfd structures to create.
   73       // DP_POLL ioctl allows up to OPEN_MAX-1
   74       static final int   NUM_POLLFDS   = Math.min(OPEN_MAX-1, 8192);
   75   
   76       // Base address of the native pollArray
   77       private long pollArrayAddress;
   78   
   79       // Array of pollfd structs used for driver updates
   80       private AllocatedNativeObject updatePollArray;
   81   
   82       // Maximum number of POLL_FD structs to update at once
   83       private int MAX_UPDATE_SIZE = Math.min(OPEN_MAX, 10000);
   84   
   85       DevPollArrayWrapper() {
   86           int allocationSize = NUM_POLLFDS * SIZE_POLLFD;
   87           pollArray = new AllocatedNativeObject(allocationSize, true);
   88           pollArrayAddress = pollArray.address();
   89           allocationSize = MAX_UPDATE_SIZE * SIZE_POLLFD;
   90           updatePollArray = new AllocatedNativeObject(allocationSize, true);
   91           wfd = init();
   92       }
   93   
   94       // Machinery for remembering fd registration changes
   95       // A hashmap could be used but the number of changes pending
   96       // is expected to be small
   97       private static class Updator {
   98           int fd;
   99           int mask;
  100           Updator(int fd, int mask) {
  101               this.fd = fd;
  102               this.mask = mask;
  103           }
  104       }
  105       private LinkedList<Updator> updateList = new LinkedList<Updator>();
  106   
  107       // The pollfd array for results from devpoll driver
  108       private AllocatedNativeObject pollArray;
  109   
  110       // The fd of the devpoll driver
  111       int wfd;
  112   
  113       // The fd of the interrupt line going out
  114       int outgoingInterruptFD;
  115   
  116       // The fd of the interrupt line coming in
  117       int incomingInterruptFD;
  118   
  119       // The index of the interrupt FD
  120       int interruptedIndex;
  121   
  122       // Number of updated pollfd entries
  123       int updated;
  124   
  125       void initInterrupt(int fd0, int fd1) {
  126           outgoingInterruptFD = fd1;
  127           incomingInterruptFD = fd0;
  128           register(wfd, fd0, POLLIN);
  129       }
  130   
  131       void putReventOps(int i, int revent) {
  132           int offset = SIZE_POLLFD * i + REVENT_OFFSET;
  133           pollArray.putShort(offset, (short)revent);
  134       }
  135   
  136       int getEventOps(int i) {
  137           int offset = SIZE_POLLFD * i + EVENT_OFFSET;
  138           return pollArray.getShort(offset);
  139       }
  140   
  141       int getReventOps(int i) {
  142           int offset = SIZE_POLLFD * i + REVENT_OFFSET;
  143           return pollArray.getShort(offset);
  144       }
  145   
  146       int getDescriptor(int i) {
  147           int offset = SIZE_POLLFD * i + FD_OFFSET;
  148           return pollArray.getInt(offset);
  149       }
  150   
  151       void setInterest(int fd, int mask) {
  152           synchronized (updateList) {
  153               updateList.add(new Updator(fd, mask));
  154           }
  155       }
  156   
  157       void release(int fd) {
  158           synchronized (updateList) {
  159               updateList.add(new Updator(fd, POLLREMOVE));
  160           }
  161       }
  162   
  163       void closeDevPollFD() throws IOException {
  164           FileDispatcherImpl.closeIntFD(wfd);
  165           pollArray.free();
  166           updatePollArray.free();
  167       }
  168   
  169       int poll(long timeout) throws IOException {
  170           updateRegistrations();
  171           updated = poll0(pollArrayAddress, NUM_POLLFDS, timeout, wfd);
  172           for (int i=0; i<updated; i++) {
  173               if (getDescriptor(i) == incomingInterruptFD) {
  174                   interruptedIndex = i;
  175                   interrupted = true;
  176                   break;
  177               }
  178           }
  179           return updated;
  180       }
  181   
  182       void updateRegistrations() throws IOException {
  183           // Populate pollfd array with updated masks
  184           synchronized (updateList) {
  185               while (updateList.size() > 0) {
  186                   // We have to insert a dummy node in between each
  187                   // real update to use POLLREMOVE on the fd first because
  188                   // otherwise the changes are simply OR'd together
  189                   int index = 0;
  190                   Updator u = null;
  191                   while ((u = updateList.poll()) != null) {
  192                       // First add pollfd struct to clear out this fd
  193                       putPollFD(updatePollArray, index, u.fd, POLLREMOVE);
  194                       index++;
  195                       // Now add pollfd to update this fd, if necessary
  196                       if (u.mask != POLLREMOVE) {
  197                           putPollFD(updatePollArray, index, u.fd, (short)u.mask);
  198                           index++;
  199                       }
  200   
  201                       // Check against the max update size; these are
  202                       // all we will process. Valid index ranges from 0 to
  203                       // (MAX_UPDATE_SIZE - 1) and we can use up to 2 per loop
  204                       if (index >  MAX_UPDATE_SIZE - 2)
  205                           break;
  206                   }
  207                   // Register the changes with /dev/poll
  208                   registerMultiple(wfd, updatePollArray.address(), index);
  209                }
  210           }
  211       }
  212   
  213       private void putPollFD(AllocatedNativeObject array, int index, int fd,
  214                              short event)
  215       {
  216           int structIndex = SIZE_POLLFD * index;
  217           array.putInt(structIndex + FD_OFFSET, fd);
  218           array.putShort(structIndex + EVENT_OFFSET, event);
  219           array.putShort(structIndex + REVENT_OFFSET, (short)0);
  220       }
  221   
  222       boolean interrupted = false;
  223   
  224       public void interrupt() {
  225           interrupt(outgoingInterruptFD);
  226       }
  227   
  228       public int interruptedIndex() {
  229           return interruptedIndex;
  230       }
  231   
  232       boolean interrupted() {
  233           return interrupted;
  234       }
  235   
  236       void clearInterrupted() {
  237           interrupted = false;
  238       }
  239   
  240       private native int init();
  241       private native void register(int wfd, int fd, int mask);
  242       private native void registerMultiple(int wfd, long address, int len)
  243           throws IOException;
  244       private native int poll0(long pollAddress, int numfds, long timeout,
  245                                int wfd);
  246       private static native void interrupt(int fd);
  247       private static native int fdLimit();
  248   
  249   }

Save This Page
Home » openjdk-7 » sun » nio » ch » [javadoc | source]