jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java
changeset 12844 883981db17b3
parent 5506 202f599c92aa
child 12868 8ab4f225fc94
equal deleted inserted replaced
12843:f785258dea60 12844:883981db17b3
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package sun.nio.ch;
    26 package sun.nio.ch;
    27 
    27 
    28 import sun.misc.*;
       
    29 import java.io.IOException;
    28 import java.io.IOException;
    30 import java.util.LinkedList;
       
    31 
    29 
    32 
    30 
    33 /**
    31 /**
    34  * Manipulates a native array of pollfd structs on Solaris:
    32  * Manipulates a native array of pollfd structs on Solaris:
    35  *
    33  *
    64     static final short SIZE_POLLFD   = 8;
    62     static final short SIZE_POLLFD   = 8;
    65     static final short FD_OFFSET     = 0;
    63     static final short FD_OFFSET     = 0;
    66     static final short EVENT_OFFSET  = 4;
    64     static final short EVENT_OFFSET  = 4;
    67     static final short REVENT_OFFSET = 6;
    65     static final short REVENT_OFFSET = 6;
    68 
    66 
       
    67     // Special value to indicate that an update should be ignored
       
    68     static final byte  CANCELLED     = (byte)-1;
       
    69 
    69     // Maximum number of open file descriptors
    70     // Maximum number of open file descriptors
    70     static final int   OPEN_MAX      = fdLimit();
    71     static final int   OPEN_MAX      = fdLimit();
    71 
    72 
    72     // Number of pollfd structures to create.
    73     // Number of pollfd structures to create.
    73     // DP_POLL ioctl allows up to OPEN_MAX-1
    74     // DP_POLL ioctl allows up to OPEN_MAX-1
    74     static final int   NUM_POLLFDS   = Math.min(OPEN_MAX-1, 8192);
    75     static final int   NUM_POLLFDS   = Math.min(OPEN_MAX-1, 8192);
    75 
    76 
    76     // Base address of the native pollArray
    77     // Base address of the native pollArray
    77     private long pollArrayAddress;
    78     private final long pollArrayAddress;
    78 
    79 
    79     // Array of pollfd structs used for driver updates
    80     // Array of pollfd structs used for driver updates
    80     private AllocatedNativeObject updatePollArray;
    81     private final AllocatedNativeObject updatePollArray;
    81 
    82 
    82     // Maximum number of POLL_FD structs to update at once
    83     // Maximum number of POLL_FD structs to update at once
    83     private int MAX_UPDATE_SIZE = Math.min(OPEN_MAX, 10000);
    84     private final int MAX_UPDATE_SIZE = Math.min(OPEN_MAX, 512);
       
    85 
       
    86     // Initial size of arrays for fd registration changes
       
    87     private final int INITIAL_PENDING_UPDATE_SIZE = 64;
    84 
    88 
    85     DevPollArrayWrapper() {
    89     DevPollArrayWrapper() {
    86         int allocationSize = NUM_POLLFDS * SIZE_POLLFD;
    90         int allocationSize = NUM_POLLFDS * SIZE_POLLFD;
    87         pollArray = new AllocatedNativeObject(allocationSize, true);
    91         pollArray = new AllocatedNativeObject(allocationSize, true);
    88         pollArrayAddress = pollArray.address();
    92         pollArrayAddress = pollArray.address();
    89         allocationSize = MAX_UPDATE_SIZE * SIZE_POLLFD;
    93         allocationSize = MAX_UPDATE_SIZE * SIZE_POLLFD;
    90         updatePollArray = new AllocatedNativeObject(allocationSize, true);
    94         updatePollArray = new AllocatedNativeObject(allocationSize, true);
    91         wfd = init();
    95         wfd = init();
    92     }
    96     }
    93 
    97 
    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
    98     // The pollfd array for results from devpoll driver
   108     private AllocatedNativeObject pollArray;
    99     private AllocatedNativeObject pollArray;
   109 
   100 
   110     // The fd of the devpoll driver
   101     // The fd of the devpoll driver
   111     int wfd;
   102     int wfd;
   119     // The index of the interrupt FD
   110     // The index of the interrupt FD
   120     int interruptedIndex;
   111     int interruptedIndex;
   121 
   112 
   122     // Number of updated pollfd entries
   113     // Number of updated pollfd entries
   123     int updated;
   114     int updated;
       
   115 
       
   116     // object to synchronize fd registration changes
       
   117     private final Object updateLock = new Object();
       
   118 
       
   119     // number of file descriptors with registration changes pending
       
   120     private int updateCount;
       
   121 
       
   122     // file descriptors with registration changes pending
       
   123     private int[] updateDescriptors = new int[INITIAL_PENDING_UPDATE_SIZE];
       
   124 
       
   125     // events for file descriptors with registration changes pending, indexed
       
   126     // by file descriptor and stored as bytes for efficiency reasons.
       
   127     private byte[] updateEvents = new byte[OPEN_MAX];
       
   128 
   124 
   129 
   125     void initInterrupt(int fd0, int fd1) {
   130     void initInterrupt(int fd0, int fd1) {
   126         outgoingInterruptFD = fd1;
   131         outgoingInterruptFD = fd1;
   127         incomingInterruptFD = fd0;
   132         incomingInterruptFD = fd0;
   128         register(wfd, fd0, POLLIN);
   133         register(wfd, fd0, POLLIN);
   147         int offset = SIZE_POLLFD * i + FD_OFFSET;
   152         int offset = SIZE_POLLFD * i + FD_OFFSET;
   148         return pollArray.getInt(offset);
   153         return pollArray.getInt(offset);
   149     }
   154     }
   150 
   155 
   151     void setInterest(int fd, int mask) {
   156     void setInterest(int fd, int mask) {
   152         synchronized (updateList) {
   157         synchronized (updateLock) {
   153             updateList.add(new Updator(fd, mask));
   158             // record the file descriptor and events, expanding the
       
   159             // respective arrays first if necessary.
       
   160             int oldCapacity = updateDescriptors.length;
       
   161             if (updateCount >= oldCapacity) {
       
   162                 int newCapacity = oldCapacity + INITIAL_PENDING_UPDATE_SIZE;
       
   163                 int[] newDescriptors = new int[newCapacity];
       
   164                 System.arraycopy(updateDescriptors, 0, newDescriptors, 0, oldCapacity);
       
   165                 updateDescriptors = newDescriptors;
       
   166             }
       
   167             updateDescriptors[updateCount++] = fd;
       
   168 
       
   169             // events are stored as bytes for efficiency reasons
       
   170             byte b = (byte)mask;
       
   171             assert (b == mask) && (b != CANCELLED);
       
   172             updateEvents[fd] = b;
   154         }
   173         }
   155     }
   174     }
   156 
   175 
   157     void release(int fd) {
   176     void release(int fd) {
   158         synchronized (updateList) {
   177         synchronized (updateLock) {
   159             updateList.add(new Updator(fd, POLLREMOVE));
   178             // cancel any pending update for this file descriptor
       
   179             updateEvents[fd] = CANCELLED;
       
   180 
       
   181             // remove from /dev/poll
       
   182             register(wfd, fd, POLLREMOVE);
   160         }
   183         }
   161     }
   184     }
   162 
   185 
   163     void closeDevPollFD() throws IOException {
   186     void closeDevPollFD() throws IOException {
   164         FileDispatcherImpl.closeIntFD(wfd);
   187         FileDispatcherImpl.closeIntFD(wfd);
   179         return updated;
   202         return updated;
   180     }
   203     }
   181 
   204 
   182     void updateRegistrations() throws IOException {
   205     void updateRegistrations() throws IOException {
   183         // Populate pollfd array with updated masks
   206         // Populate pollfd array with updated masks
   184         synchronized (updateList) {
   207         synchronized (updateLock) {
   185             while (updateList.size() > 0) {
   208 
   186                 // We have to insert a dummy node in between each
   209             int j = 0;
   187                 // real update to use POLLREMOVE on the fd first because
   210             int index = 0;
   188                 // otherwise the changes are simply OR'd together
   211             while (j < updateCount) {
   189                 int index = 0;
   212                 int fd = updateDescriptors[j];
   190                 Updator u = null;
   213                 short events = updateEvents[fd];
   191                 while ((u = updateList.poll()) != null) {
   214 
   192                     // First add pollfd struct to clear out this fd
   215                 // skip update if key has been cancelled
   193                     putPollFD(updatePollArray, index, u.fd, POLLREMOVE);
   216                 if (events != CANCELLED) {
       
   217                     // remove from /dev/poll when the interest ops changes to 0
       
   218                     if (events == 0)
       
   219                         events = POLLREMOVE;
       
   220 
       
   221                     // populate pollfd array with updated event
       
   222                     putPollFD(updatePollArray, index, fd, events);
   194                     index++;
   223                     index++;
   195                     // Now add pollfd to update this fd, if necessary
   224                     if (index >= MAX_UPDATE_SIZE) {
   196                     if (u.mask != POLLREMOVE) {
   225                         registerMultiple(wfd, updatePollArray.address(), index);
   197                         putPollFD(updatePollArray, index, u.fd, (short)u.mask);
   226                         index = 0;
   198                         index++;
       
   199                     }
   227                     }
   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                 }
   228                 }
   207                 // Register the changes with /dev/poll
   229                 j++;
       
   230 
       
   231             }
       
   232 
       
   233             // write any remaining updates
       
   234             if (index > 0)
   208                 registerMultiple(wfd, updatePollArray.address(), index);
   235                 registerMultiple(wfd, updatePollArray.address(), index);
   209              }
   236 
       
   237             updateCount = 0;
   210         }
   238         }
   211     }
   239     }
   212 
   240 
   213     private void putPollFD(AllocatedNativeObject array, int index, int fd,
   241     private void putPollFD(AllocatedNativeObject array, int index, int fd,
   214                            short event)
   242                            short event)