1 /*
  2  * Copyright (c) 2020, 2021, 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 package sun.nio.ch;
 26 
 27 import java.io.IOException;
 28 import jdk.internal.misc.Unsafe;
 29 
 30 /**
 31  * Provides access to WSAPoll.
 32  */
 33 class WSAPoll {
 34     private static final Unsafe UNSAFE = Unsafe.getUnsafe();
 35     private static final int ADDRESS_SIZE = UNSAFE.addressSize();
 36     
 37     private WSAPoll() { }
 38 
 39     /**
 40      * typedef struct pollfd {
 41      *   SOCKET fd;
 42      *   SHORT events;
 43      *   SHORT revents;
 44      * } WSAPOLLFD;
 45      */
 46     private static final int SIZE_POLLFD    = pollfdSize();
 47     private static final int FD_OFFSET      = fdOffset();
 48     private static final int EVENTS_OFFSET  = eventsOffset();
 49     private static final int REVENTS_OFFSET = reventsOffset();
 50 
 51     /**
 52      * Allocates a poll array of {@code size} WSAPOLLFD structures.
 53      */
 54     static long allocatePollArray(int size) {
 55         if (size <= 0)
 56             throw new IllegalArgumentException();
 57         return UNSAFE.allocateMemory(size * SIZE_POLLFD);
 58     }
 59 
 60     /**
 61      * Reallocates a poll array from {@code size} to {@code newSize}
 62      * WSAPOLLFD structures.
 63      */
 64     static long reallocatePollArray(long address, int size, int newSize) {
 65         if (newSize < size)
 66             throw new IllegalArgumentException();
 67         long newAddress = allocatePollArray(newSize);
 68         UNSAFE.copyMemory(address, newAddress, size * SIZE_POLLFD);
 69         UNSAFE.freeMemory(address);
 70         return newAddress;
 71     }
 72 
 73     /**
 74      * Free a poll array.
 75      */
 76     static void freePollArray(long address) {
 77         UNSAFE.freeMemory(address);
 78     }
 79 
 80     static void putDescriptor(long address, int i, int fd) {
 81         int offset = SIZE_POLLFD * i + FD_OFFSET;
 82         if (ADDRESS_SIZE == 8) {
 83             UNSAFE.putLong(address + offset, fd);
 84         } else {
 85             UNSAFE.putInt(address + offset, fd);
 86         }
 87     }
 88 
 89     static int getDescriptor(long address, int i) {
 90         int offset = SIZE_POLLFD * i + FD_OFFSET;
 91         long s;
 92         if (ADDRESS_SIZE == 8) {
 93             s = UNSAFE.getLong(address + offset);
 94         } else {
 95             s = UNSAFE.getInt(address + offset);
 96         }
 97         int fd = (int) s;
 98         assert ((long) fd) == s;
 99         return fd;
100     }
101 
102     static void putEvents(long address, int i, short events) {
103         int offset = SIZE_POLLFD * i + EVENTS_OFFSET;
104         UNSAFE.putShort(address + offset, events);
105     }
106 
107     static short getEvents(long address, int i) {
108         int offset = SIZE_POLLFD * i + EVENTS_OFFSET;
109         return UNSAFE.getShort(address + offset);
110     }
111 
112     static void putRevents(long address, int i, short revents) {
113         int offset = SIZE_POLLFD * i + REVENTS_OFFSET;
114         UNSAFE.putShort(address + offset, revents);
115     }
116 
117     static short getRevents(long address, int i) {
118         int offset = SIZE_POLLFD * i + REVENTS_OFFSET;
119         return UNSAFE.getShort(address + offset);
120     }
121 
122     // -- Native methods --
123 
124     private static native int pollfdSize();
125 
126     private static native int fdOffset();
127 
128     private static native int eventsOffset();
129 
130     private static native int reventsOffset();
131 
132     static native int poll(long pollAddress, int numfds, int timeout)
133         throws IOException;
134 
135     static {
136         IOUtil.load();
137     }
138 }