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
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <signal.h>
29 #include <pthread.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <sys/select.h>
33 #include <sys/time.h>
34 #include <sys/resource.h>
35 #include <sys/uio.h>
36 #include <unistd.h>
37 #include <errno.h>
38
39 #include <sys/poll.h>
40
41 /*
42 * Stack allocated by thread when doing blocking operation
43 */
44 typedef struct threadEntry {
45 pthread_t thr; /* this thread */
46 struct threadEntry *next; /* next thread */
47 int intr; /* interrupted */
48 } threadEntry_t;
49
50 /*
51 * Heap allocated during initialized - one entry per fd
52 */
53 typedef struct {
54 pthread_mutex_t lock; /* fd lock */
55 threadEntry_t *threads; /* threads blocked on fd */
56 } fdEntry_t;
57
58 /*
59 * Signal to unblock thread
60 */
322 BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
323 }
324
325 #ifndef USE_SELECT
326 int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
327 BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
328 }
329 #else
330 int NET_Select(int s, fd_set *readfds, fd_set *writefds,
331 fd_set *exceptfds, struct timeval *timeout) {
332 BLOCKING_IO_RETURN_INT( s-1,
333 select(s, readfds, writefds, exceptfds, timeout) );
334 }
335 #endif
336
337 /*
338 * Wrapper for select(s, timeout). We are using select() on Mac OS due to Bug 7131399.
339 * Auto restarts with adjusted timeout if interrupted by
340 * signal other than our wakeup signal.
341 */
342 int NET_Timeout(int s, long timeout) {
343 long prevtime = 0, newtime;
344 struct timeval t, *tp = &t;
345 fdEntry_t *fdEntry = getFdEntry(s);
346
347 /*
348 * Check that fd hasn't been closed.
349 */
350 if (fdEntry == NULL) {
351 errno = EBADF;
352 return -1;
353 }
354
355 /*
356 * Pick up current time as may need to adjust timeout
357 */
358 if (timeout > 0) {
359 /* Timed */
360 struct timeval now;
361 gettimeofday(&now, NULL);
362 prevtime = now.tv_sec * 1000 + now.tv_usec / 1000;
363 t.tv_sec = timeout / 1000;
364 t.tv_usec = (timeout % 1000) * 1000;
365 } else if (timeout < 0) {
366 /* Blocking */
367 tp = 0;
368 } else {
369 /* Poll */
370 t.tv_sec = 0;
371 t.tv_usec = 0;
372 }
373
374 for(;;) {
375 fd_set rfds;
376 int rv;
377 threadEntry_t self;
378
379 /*
380 * call select on the fd. If interrupted by our wakeup signal
381 * errno will be set to EBADF.
382 */
383 FD_ZERO(&rfds);
384 FD_SET(s, &rfds);
385
386 startOp(fdEntry, &self);
387 rv = select(s+1, &rfds, 0, 0, tp);
388 endOp(fdEntry, &self);
389
390 /*
391 * If interrupted then adjust timeout. If timeout
392 * has expired return 0 (indicating timeout expired).
393 */
394 if (rv < 0 && errno == EINTR) {
395 if (timeout > 0) {
396 struct timeval now;
397 gettimeofday(&now, NULL);
398 newtime = now.tv_sec * 1000 + now.tv_usec / 1000;
399 timeout -= newtime - prevtime;
400 if (timeout <= 0) {
401 return 0;
402 }
403 prevtime = newtime;
404 t.tv_sec = timeout / 1000;
405 t.tv_usec = (timeout % 1000) * 1000;
406 }
407 } else {
408 return rv;
409 }
410
411 }
412 }
|
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
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <signal.h>
30 #include <pthread.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <sys/select.h>
34 #include <sys/time.h>
35 #include <sys/resource.h>
36 #include <sys/uio.h>
37 #include <unistd.h>
38 #include <errno.h>
39 #include <sys/poll.h>
40
41 #include "jni_util.h"
42
43 /*
44 * Stack allocated by thread when doing blocking operation
45 */
46 typedef struct threadEntry {
47 pthread_t thr; /* this thread */
48 struct threadEntry *next; /* next thread */
49 int intr; /* interrupted */
50 } threadEntry_t;
51
52 /*
53 * Heap allocated during initialized - one entry per fd
54 */
55 typedef struct {
56 pthread_mutex_t lock; /* fd lock */
57 threadEntry_t *threads; /* threads blocked on fd */
58 } fdEntry_t;
59
60 /*
61 * Signal to unblock thread
62 */
324 BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
325 }
326
327 #ifndef USE_SELECT
328 int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
329 BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
330 }
331 #else
332 int NET_Select(int s, fd_set *readfds, fd_set *writefds,
333 fd_set *exceptfds, struct timeval *timeout) {
334 BLOCKING_IO_RETURN_INT( s-1,
335 select(s, readfds, writefds, exceptfds, timeout) );
336 }
337 #endif
338
339 /*
340 * Wrapper for select(s, timeout). We are using select() on Mac OS due to Bug 7131399.
341 * Auto restarts with adjusted timeout if interrupted by
342 * signal other than our wakeup signal.
343 */
344 int NET_Timeout(JNIEnv *env, int s, long timeout) {
345 long prevtime = 0, newtime;
346 struct timeval t, *tp = &t;
347 fd_set fds;
348 fd_set* fdsp = NULL;
349 int allocated = 0;
350 threadEntry_t self;
351 fdEntry_t *fdEntry = getFdEntry(s);
352
353 /*
354 * Check that fd hasn't been closed.
355 */
356 if (fdEntry == NULL) {
357 errno = EBADF;
358 return -1;
359 }
360
361 /*
362 * Pick up current time as may need to adjust timeout
363 */
364 if (timeout > 0) {
365 /* Timed */
366 struct timeval now;
367 gettimeofday(&now, NULL);
368 prevtime = now.tv_sec * 1000 + now.tv_usec / 1000;
369 t.tv_sec = timeout / 1000;
370 t.tv_usec = (timeout % 1000) * 1000;
371 } else if (timeout < 0) {
372 /* Blocking */
373 tp = 0;
374 } else {
375 /* Poll */
376 t.tv_sec = 0;
377 t.tv_usec = 0;
378 }
379
380 if (s < FD_SETSIZE) {
381 fdsp = &fds;
382 FD_ZERO(fdsp);
383 } else {
384 int length = (howmany(s+1, NFDBITS)) * sizeof(int);
385 fdsp = (fd_set *) calloc(1, length);
386 if (fdsp == NULL) {
387 JNU_ThrowOutOfMemoryError(env, "NET_Select native heap allocation failed");
388 return 0;
389 }
390 allocated = 1;
391 }
392 FD_SET(s, fdsp);
393
394 for(;;) {
395 int rv;
396
397 /*
398 * call select on the fd. If interrupted by our wakeup signal
399 * errno will be set to EBADF.
400 */
401
402 startOp(fdEntry, &self);
403 rv = select(s+1, fdsp, 0, 0, tp);
404 endOp(fdEntry, &self);
405
406 /*
407 * If interrupted then adjust timeout. If timeout
408 * has expired return 0 (indicating timeout expired).
409 */
410 if (rv < 0 && errno == EINTR) {
411 if (timeout > 0) {
412 struct timeval now;
413 gettimeofday(&now, NULL);
414 newtime = now.tv_sec * 1000 + now.tv_usec / 1000;
415 timeout -= newtime - prevtime;
416 if (timeout <= 0) {
417 if (allocated != 0)
418 free(fdsp);
419 return 0;
420 }
421 prevtime = newtime;
422 t.tv_sec = timeout / 1000;
423 t.tv_usec = (timeout % 1000) * 1000;
424 }
425 } else {
426 if (allocated != 0)
427 free(fdsp);
428 return rv;
429 }
430
431 }
432 }
|