Dead
[official-gcc.git] / gomp-20050608-branch / libjava / classpath / native / jni / java-nio / gnu_java_nio_VMSelector.c
blobf8a40aa7a15d4e9f43b213cafbf425d529160a52
1 /* gnu_java_nio_VMSelector.c - Native methods for SelectorImpl class
2 Copyright (C) 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 #include "config.h"
40 /* <sys/types.h> needs to be included on OSX before <sys/select.h> */
41 #if defined(HAVE_SYS_TYPES_H)
42 #include <sys/types.h>
43 #endif
45 #include <sys/select.h>
46 #include <sys/time.h>
48 #include <string.h>
50 #include <errno.h>
52 #include <jni.h>
53 #include <jcl.h>
55 #include "gnu_java_nio_VMSelector.h"
57 /* Amount of characters in the error message buffer for strerror_r. */
58 #define BUF_SIZE 250
60 void helper_put_filedescriptors (JNIEnv *, jintArray, fd_set *, int *);
62 void helper_get_filedescriptors (JNIEnv *, jintArray *, fd_set *);
64 void helper_reset (JNIEnv *, jintArray *);
66 int
67 helper_select (JNIEnv *, jclass, jmethodID,
68 int, fd_set *, fd_set *, fd_set *, struct timeval *);
70 void
71 helper_put_filedescriptors (JNIEnv * env, jintArray fdArray, fd_set * fds,
72 int *max_fd)
74 jint *tmpFDArray = (*env)->GetIntArrayElements (env, fdArray, 0);
75 int size = (*env)->GetArrayLength (env, fdArray);
76 int index, fd;
78 for (index = 0; index < size; index++)
80 fd = tmpFDArray[index];
82 if (fd > 0)
84 FD_SET (tmpFDArray[index], fds);
86 if (tmpFDArray[index] > (*max_fd))
87 (*max_fd) = tmpFDArray[index];
92 void
93 helper_get_filedescriptors (JNIEnv * env, jintArray * fdArray, fd_set * fds)
95 jint *tmpFDArray = (*env)->GetIntArrayElements (env, fdArray, 0);
96 int size = (*env)->GetArrayLength (env, fdArray);
97 int index, fd;
99 for (index = 0; index < size; index++)
101 fd = tmpFDArray[index];
102 if (fd < 0 || !FD_ISSET (fd, fds))
103 tmpFDArray[index] = 0;
107 void
108 helper_reset (JNIEnv * env, jintArray * fdArray)
110 jint *tmpFDArray = (*env)->GetIntArrayElements (env, fdArray, 0);
111 int size = (*env)->GetArrayLength (env, fdArray);
112 int index;
114 for (index = 0; index < size; index++)
115 tmpFDArray[index] = 0;
118 /* A wrapper for select() which ignores EINTR.
119 * Taken from gclib's posix.cc
122 helper_select (JNIEnv * env, jclass thread_class,
123 jmethodID thread_interrupted, int n, fd_set * readfds,
124 fd_set * writefds, fd_set * exceptfds, struct timeval *timeout)
126 #ifdef HAVE_SYS_SELECT_H
127 /* If we have a timeout, compute the absolute ending time. */
128 struct timeval end, delay, after;
129 int r;
131 if (timeout)
133 gettimeofday (&end, NULL);
135 end.tv_usec += timeout->tv_usec;
137 if (end.tv_usec >= 1000000)
139 ++end.tv_sec;
140 end.tv_usec -= 1000000;
143 end.tv_sec += timeout->tv_sec;
144 delay = *timeout;
146 else
148 /* Placate compiler. */
149 delay.tv_sec = delay.tv_usec = 0;
152 while (1)
154 r = select (n, readfds, writefds, exceptfds, timeout ? &delay : NULL);
156 if (r < 0 && errno != EINTR)
157 return -errno;
158 else if (r >= 0)
159 return r;
161 /* Here we know we got EINTR. */
162 if ((*env)->
163 CallStaticBooleanMethod (env, thread_class, thread_interrupted))
165 return -EINTR;
168 if (timeout)
170 gettimeofday (&after, NULL);
172 /* Now compute new timeout argument. */
173 delay.tv_usec = end.tv_usec - after.tv_usec;
174 delay.tv_sec = end.tv_sec - after.tv_sec;
176 if (delay.tv_usec < 0)
178 --delay.tv_sec;
179 delay.tv_usec += 1000000;
182 if (delay.tv_sec < 0)
184 /* We assume that the user wants a valid select() call
185 * more than precise timing. So if we get a series of
186 * EINTR we just keep trying with delay 0 until we get a
187 * valid result.
189 delay.tv_sec = 0;
193 #else /* HAVE_SYS_SELECT_H */
194 return 0;
195 #endif
199 JNIEXPORT jint JNICALL
200 Java_gnu_java_nio_VMSelector_select (JNIEnv * env,
201 jclass obj __attribute__ ((__unused__)),
202 jintArray read,
203 jintArray write,
204 jintArray except, jlong timeout)
206 jint result;
207 jclass thread_class = (*env)->FindClass (env, "java/lang/Thread");
208 jmethodID thread_current_thread =
209 (*env)->GetStaticMethodID (env, thread_class, "currentThread",
210 "()Ljava/lang/Thread;");
211 jmethodID thread_interrupt =
212 (*env)->GetMethodID (env, thread_class, "interrupt", "()V");
213 jmethodID thread_interrupted =
214 (*env)->GetStaticMethodID (env, thread_class, "interrupted", "()Z");
215 jobject current_thread;
216 int max_fd = 0;
217 fd_set read_fds;
218 fd_set write_fds;
219 fd_set except_fds;
220 struct timeval real_time_data;
221 struct timeval *time_data = NULL;
222 char message_buf[BUF_SIZE + 1];
224 /* If a legal timeout value isn't given, use NULL.
225 * This means an infinite timeout. The specification
226 * also says that a zero timeout should be treated
227 * as infinite. Otherwise (if the timeout value is legal),
228 * fill our timeval struct and use it for the select.
230 if (timeout > 0)
232 real_time_data.tv_sec = timeout / 1000;
233 real_time_data.tv_usec = (timeout % 1000) * 1000;
234 time_data = &real_time_data;
237 /* Reset all fd_set structures */
238 FD_ZERO (&read_fds);
239 FD_ZERO (&write_fds);
240 FD_ZERO (&except_fds);
242 /* Fill the fd_set data structures for the _Jv_select() call. */
243 helper_put_filedescriptors (env, read, &read_fds, &max_fd);
244 helper_put_filedescriptors (env, write, &write_fds, &max_fd);
245 helper_put_filedescriptors (env, except, &except_fds, &max_fd);
247 /* Actually do the select */
248 result =
249 helper_select (env, thread_class, thread_interrupted, max_fd + 1,
250 &read_fds, &write_fds, &except_fds, time_data);
252 if (result == -EINTR)
254 /* The behavior of JRE 1.4.1 is that no exception is thrown
255 * when the thread is interrupted, but the thread's interrupt
256 * status is set. Clear all of our select sets and return 0,
257 * indicating that nothing was selected.
259 current_thread =
260 (*env)->CallStaticObjectMethod (env, thread_class,
261 thread_current_thread);
262 (*env)->CallVoidMethod (env, current_thread, thread_interrupt);
264 helper_reset (env, read);
265 helper_reset (env, write);
266 helper_reset (env, except);
268 return 0;
271 if (result < 0)
274 int errorcode = -result;
276 if (strerror_r (errorcode, message_buf, BUF_SIZE))
278 /* This would mean that message_buf was to small
279 * to hold the error message.
281 JCL_ThrowException (env, "java/lang/InternalError",
282 "Not enough space in message buffer.");
283 return 0;
286 JCL_ThrowException (env, "java/io/IOException", message_buf);
287 return 0;
290 /* Set the file descriptors according to the values returned from select(). */
291 helper_get_filedescriptors (env, read, &read_fds);
292 helper_get_filedescriptors (env, write, &write_fds);
293 helper_get_filedescriptors (env, except, &except_fds);
295 return result;