/* * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ #include "jni.h" #include "jni_util.h" #include "jvm.h" #include "jlong.h" #include <poll.h> #include <unistd.h> #include <sys/time.h> #define RESTARTABLE(_cmd, _result) do { \ do { \ _result = _cmd; \ } while((_result == -1) && (errno == EINTR)); \ } while(0) #include "JNIHelp.h" #define NATIVE_METHOD(className, functionName, signature) \ { #functionName, signature, (void*)(Java_sun_nio_ch_ ## className ## _ ## functionName) } static int ipoll(struct pollfd fds[], unsigned int nfds, int timeout) { jlong start, now; int remaining = timeout; struct timeval t; int diff; gettimeofday(&t, NULL); start = t.tv_sec * 1000 + t.tv_usec / 1000; for (;;) { int res = poll(fds, nfds, remaining); if (res < 0 && errno == EINTR) { if (remaining >= 0) { gettimeofday(&t, NULL); now = t.tv_sec * 1000 + t.tv_usec / 1000; diff = now - start; remaining -= diff; if (diff < 0 || remaining <= 0) { return 0; } start = now; } } else { return res; } } } JNIEXPORT jint JNICALL Java_sun_nio_ch_PollArrayWrapper_poll0(JNIEnv *env, jobject this, jlong address, jint numfds, jlong timeout) { struct pollfd *a; int err = 0; a = (struct pollfd *) jlong_to_ptr(address); if (timeout <= 0) { /* Indefinite or no wait */ RESTARTABLE (poll(a, numfds, timeout), err); } else { /* Bounded wait; bounded restarts */ err = ipoll(a, numfds, timeout); } if (err < 0) { JNU_ThrowIOExceptionWithLastError(env, "Poll failed"); } return (jint)err; } JNIEXPORT void JNICALL Java_sun_nio_ch_PollArrayWrapper_interrupt(JNIEnv *env, jobject this, jint fd) { int fakebuf[1]; fakebuf[0] = 1; if (write(fd, fakebuf, 1) < 0) { JNU_ThrowIOExceptionWithLastError(env, "Write to interrupt fd failed"); } } static JNINativeMethod gMethods[] = { NATIVE_METHOD(PollArrayWrapper, poll0, "(JIJ)I"), NATIVE_METHOD(PollArrayWrapper, interrupt, "(I)V"), }; void register_sun_nio_ch_PollArrayWrapper(JNIEnv* env) { jniRegisterNativeMethods(env, "sun/nio/ch/PollArrayWrapper", gMethods, NELEM(gMethods)); }