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