1 /*
2 * Copyright (c) 2011, 2013, 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
49 * The implementation works in 32-bit and 64-bit world. We do this by calling a
50 * native function that actually sets the sizes and offsets of the fields based
51 * on which mode we're in.
52 */
53
54 class KQueueArrayWrapper {
55 // kevent filters
56 static short EVFILT_READ;
57 static short EVFILT_WRITE;
58
59 // kevent struct
60 // These fields are now set by initStructSizes in the static initializer.
61 static short SIZEOF_KEVENT;
62 static short FD_OFFSET;
63 static short FILTER_OFFSET;
64
65 // kevent array size
66 static final int NUM_KEVENTS = 128;
67
68 // Are we in a 64-bit VM?
69 static boolean is64bit = false;
70
71 // The kevent array (used for outcoming events only)
72 private AllocatedNativeObject keventArray = null;
73 private long keventArrayAddress;
74
75 // The kqueue fd
76 private int kq = -1;
77
78 // The fd of the interrupt line going out
79 private int outgoingInterruptFD;
80
81 // The fd of the interrupt line coming in
82 private int incomingInterruptFD;
83
84 static {
85 IOUtil.load();
86 initStructSizes();
87 String datamodel =
88 GetPropertyAction.privilegedGetProperty("sun.arch.data.model");
89 is64bit = "64".equals(datamodel);
90 }
91
92 KQueueArrayWrapper() {
93 int allocationSize = SIZEOF_KEVENT * NUM_KEVENTS;
94 keventArray = new AllocatedNativeObject(allocationSize, true);
95 keventArrayAddress = keventArray.address();
96 kq = init();
97 }
98
99 // Used to update file description registrations
100 private static class Update {
101 SelChImpl channel;
102 int events;
103 Update(SelChImpl channel, int events) {
104 this.channel = channel;
105 this.events = events;
106 }
107 }
108
109 private LinkedList<Update> updateList = new LinkedList<Update>();
110
111 void initInterrupt(int fd0, int fd1) {
112 outgoingInterruptFD = fd1;
113 incomingInterruptFD = fd0;
114 register0(kq, fd0, 1, 0);
115 }
116
117 int getReventOps(int index) {
118 int result = 0;
119 int offset = SIZEOF_KEVENT*index + FILTER_OFFSET;
120 short filter = keventArray.getShort(offset);
121
122 // This is all that's necessary based on inspection of usage:
123 // SinkChannelImpl, SourceChannelImpl, DatagramChannelImpl,
124 // ServerSocketChannelImpl, SocketChannelImpl
125 if (filter == EVFILT_READ) {
126 result |= Net.POLLIN;
127 } else if (filter == EVFILT_WRITE) {
128 result |= Net.POLLOUT;
129 }
130
131 return result;
132 }
133
134 int getDescriptor(int index) {
135 int offset = SIZEOF_KEVENT*index + FD_OFFSET;
136 /* The ident field is 8 bytes in 64-bit world, however the API wants us
151 updateList.add(new Update(channel, events));
152 }
153 }
154
155 void release(SelChImpl channel) {
156 synchronized (updateList) {
157 // flush any pending updates
158 for (Iterator<Update> it = updateList.iterator(); it.hasNext();) {
159 if (it.next().channel == channel) {
160 it.remove();
161 }
162 }
163
164 // remove
165 register0(kq, channel.getFDVal(), 0, 0);
166 }
167 }
168
169 void updateRegistrations() {
170 synchronized (updateList) {
171 Update u = null;
172 while ((u = updateList.poll()) != null) {
173 SelChImpl ch = u.channel;
174 if (!ch.isOpen())
175 continue;
176
177 register0(kq, ch.getFDVal(), u.events & Net.POLLIN, u.events & Net.POLLOUT);
178 }
179 }
180 }
181
182
183 void close() throws IOException {
184 if (keventArray != null) {
185 keventArray.free();
186 keventArray = null;
187 }
188 if (kq >= 0) {
189 FileDispatcherImpl.closeIntFD(kq);
190 kq = -1;
191 }
192 }
193
194 int poll(long timeout) {
195 updateRegistrations();
196 int updated = kevent0(kq, keventArrayAddress, NUM_KEVENTS, timeout);
197 return updated;
198 }
199
200 void interrupt() {
201 interrupt(outgoingInterruptFD);
202 }
203
204 private native int init();
205 private static native void initStructSizes();
206
207 private native void register0(int kq, int fd, int read, int write);
208 private native int kevent0(int kq, long keventAddress, int keventCount,
209 long timeout);
210 private static native void interrupt(int fd);
211 }
|
1 /*
2 * Copyright (c) 2011, 2018, 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
49 * The implementation works in 32-bit and 64-bit world. We do this by calling a
50 * native function that actually sets the sizes and offsets of the fields based
51 * on which mode we're in.
52 */
53
54 class KQueueArrayWrapper {
55 // kevent filters
56 static short EVFILT_READ;
57 static short EVFILT_WRITE;
58
59 // kevent struct
60 // These fields are now set by initStructSizes in the static initializer.
61 static short SIZEOF_KEVENT;
62 static short FD_OFFSET;
63 static short FILTER_OFFSET;
64
65 // kevent array size
66 static final int NUM_KEVENTS = 128;
67
68 // Are we in a 64-bit VM?
69 static boolean is64bit;
70
71 // The kevent array (used for outcoming events only)
72 private final AllocatedNativeObject keventArray;
73 private final long keventArrayAddress;
74
75 // The kqueue fd
76 private final int kq;
77
78 // The fd of the interrupt line going out
79 private final int outgoingInterruptFD;
80
81
82 static {
83 IOUtil.load();
84 initStructSizes();
85 String datamodel =
86 GetPropertyAction.privilegedGetProperty("sun.arch.data.model");
87 is64bit = "64".equals(datamodel);
88 }
89
90 KQueueArrayWrapper(int fd0, int fd1) throws IOException {
91 int allocationSize = SIZEOF_KEVENT * NUM_KEVENTS;
92 keventArray = new AllocatedNativeObject(allocationSize, true);
93 keventArrayAddress = keventArray.address();
94 kq = init();
95 register0(kq, fd0, 1, 0);
96 outgoingInterruptFD = fd1;
97 }
98
99 // Used to update file description registrations
100 private static class Update {
101 SelChImpl channel;
102 int events;
103 Update(SelChImpl channel, int events) {
104 this.channel = channel;
105 this.events = events;
106 }
107 }
108
109 private LinkedList<Update> updateList = new LinkedList<Update>();
110
111 int getReventOps(int index) {
112 int result = 0;
113 int offset = SIZEOF_KEVENT*index + FILTER_OFFSET;
114 short filter = keventArray.getShort(offset);
115
116 // This is all that's necessary based on inspection of usage:
117 // SinkChannelImpl, SourceChannelImpl, DatagramChannelImpl,
118 // ServerSocketChannelImpl, SocketChannelImpl
119 if (filter == EVFILT_READ) {
120 result |= Net.POLLIN;
121 } else if (filter == EVFILT_WRITE) {
122 result |= Net.POLLOUT;
123 }
124
125 return result;
126 }
127
128 int getDescriptor(int index) {
129 int offset = SIZEOF_KEVENT*index + FD_OFFSET;
130 /* The ident field is 8 bytes in 64-bit world, however the API wants us
145 updateList.add(new Update(channel, events));
146 }
147 }
148
149 void release(SelChImpl channel) {
150 synchronized (updateList) {
151 // flush any pending updates
152 for (Iterator<Update> it = updateList.iterator(); it.hasNext();) {
153 if (it.next().channel == channel) {
154 it.remove();
155 }
156 }
157
158 // remove
159 register0(kq, channel.getFDVal(), 0, 0);
160 }
161 }
162
163 void updateRegistrations() {
164 synchronized (updateList) {
165 Update u;
166 while ((u = updateList.poll()) != null) {
167 SelChImpl ch = u.channel;
168 if (!ch.isOpen())
169 continue;
170
171 register0(kq, ch.getFDVal(), u.events & Net.POLLIN, u.events & Net.POLLOUT);
172 }
173 }
174 }
175
176 void close() throws IOException {
177 FileDispatcherImpl.closeIntFD(kq);
178 keventArray.free();
179 }
180
181 int poll(long timeout) {
182 updateRegistrations();
183 return kevent0(kq, keventArrayAddress, NUM_KEVENTS, timeout);
184 }
185
186 void interrupt() {
187 interrupt(outgoingInterruptFD);
188 }
189
190 private native int init();
191 private static native void initStructSizes();
192
193 private native void register0(int kq, int fd, int read, int write);
194 private native int kevent0(int kq, long keventAddress, int keventCount,
195 long timeout);
196 private static native void interrupt(int fd);
197 }
|