1 /* 2 * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. 3 * Copyright 2012 SAP AG. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 #include "jni.h" 28 #include "jni_util.h" 29 #include "jvm.h" 30 #include "jlong.h" 31 32 #include "sun_nio_ch_AixPollPort.h" 33 34 #include <unistd.h> 35 #include <sys/types.h> 36 #include <sys/socket.h> 37 #include <sys/poll.h> 38 #include <sys/pollset.h> 39 #include <fcntl.h> 40 #include <stddef.h> 41 #include <dlfcn.h> 42 #include <errno.h> 43 44 /* Initially copied from src/solaris/native/sun/nio/ch/nio_util.h */ 45 #define RESTARTABLE(_cmd, _result) do { \ 46 do { \ 47 _result = _cmd; \ 48 } while((_result == -1) && (errno == EINTR)); \ 49 } while(0) 50 51 typedef pollset_t pollset_create_func(int maxfd); 52 typedef int pollset_destroy_func(pollset_t ps); 53 typedef int pollset_ctl_func(pollset_t ps, struct poll_ctl *pollctl_array, int array_length); 54 typedef int pollset_poll_func(pollset_t ps, struct pollfd *polldata_array, int array_length, int timeout); 55 static pollset_create_func* _pollset_create = NULL; 56 static pollset_destroy_func* _pollset_destroy = NULL; 57 static pollset_ctl_func* _pollset_ctl = NULL; 58 static pollset_poll_func* _pollset_poll = NULL; 59 60 JNIEXPORT void JNICALL 61 Java_sun_nio_ch_AixPollPort_init(JNIEnv* env, jclass this) { 62 _pollset_create = (pollset_create_func*) dlsym(RTLD_DEFAULT, "pollset_create"); 63 _pollset_destroy = (pollset_destroy_func*) dlsym(RTLD_DEFAULT, "pollset_destroy"); 64 _pollset_ctl = (pollset_ctl_func*) dlsym(RTLD_DEFAULT, "pollset_ctl"); 65 _pollset_poll = (pollset_poll_func*) dlsym(RTLD_DEFAULT, "pollset_poll"); 66 if (_pollset_create == NULL || _pollset_destroy == NULL || 67 _pollset_ctl == NULL || _pollset_poll == NULL) { 68 JNU_ThrowInternalError(env, "unable to get address of pollset functions"); 69 } 70 } 71 72 JNIEXPORT jint JNICALL 73 Java_sun_nio_ch_AixPollPort_eventSize(JNIEnv* env, jclass this) { 74 return sizeof(struct pollfd); 75 } 76 77 JNIEXPORT jint JNICALL 78 Java_sun_nio_ch_AixPollPort_eventsOffset(JNIEnv* env, jclass this) { 79 return offsetof(struct pollfd, events); 80 } 81 82 JNIEXPORT jint JNICALL 83 Java_sun_nio_ch_AixPollPort_reventsOffset(JNIEnv* env, jclass this) { 84 return offsetof(struct pollfd, revents); 85 } 86 87 JNIEXPORT jint JNICALL 88 Java_sun_nio_ch_AixPollPort_fdOffset(JNIEnv* env, jclass this) { 89 return offsetof(struct pollfd, fd); 90 } 91 92 JNIEXPORT jint JNICALL 93 Java_sun_nio_ch_AixPollPort_pollsetCreate(JNIEnv *env, jclass c) { 94 /* pollset_create can take the maximum number of fds, but we 95 * cannot predict this number so we leave it at OPEN_MAX. */ 96 pollset_t ps = _pollset_create(-1); 97 if (ps < 0) { 98 JNU_ThrowIOExceptionWithLastError(env, "pollset_create failed"); 99 } 100 return (int)ps; 101 } 102 103 JNIEXPORT jint JNICALL 104 Java_sun_nio_ch_AixPollPort_pollsetCtl(JNIEnv *env, jclass c, jint ps, 105 jint opcode, jint fd, jint events) { 106 struct poll_ctl event; 107 int res; 108 109 event.cmd = opcode; 110 event.events = events; 111 event.fd = fd; 112 113 RESTARTABLE(_pollset_ctl((pollset_t)ps, &event, 1 /* length */), res); 114 115 return (res == 0) ? 0 : errno; 116 } 117 118 JNIEXPORT jint JNICALL 119 Java_sun_nio_ch_AixPollPort_pollsetPoll(JNIEnv *env, jclass c, 120 jint ps, jlong address, jint numfds) { 121 struct pollfd *events = jlong_to_ptr(address); 122 int res; 123 124 RESTARTABLE(_pollset_poll(ps, events, numfds, -1), res); 125 if (res < 0) { 126 JNU_ThrowIOExceptionWithLastError(env, "pollset_poll failed"); 127 } 128 return res; 129 } 130 131 JNIEXPORT void JNICALL 132 Java_sun_nio_ch_AixPollPort_pollsetDestroy(JNIEnv *env, jclass c, jint ps) { 133 int res; 134 RESTARTABLE(_pollset_destroy((pollset_t)ps), res); 135 } 136 137 JNIEXPORT void JNICALL 138 Java_sun_nio_ch_AixPollPort_socketpair(JNIEnv* env, jclass clazz, jintArray sv) { 139 int sp[2]; 140 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) { 141 JNU_ThrowIOExceptionWithLastError(env, "socketpair failed"); 142 } else { 143 jint res[2]; 144 res[0] = (jint)sp[0]; 145 res[1] = (jint)sp[1]; 146 (*env)->SetIntArrayRegion(env, sv, 0, 2, &res[0]); 147 } 148 } 149 150 JNIEXPORT void JNICALL 151 Java_sun_nio_ch_AixPollPort_interrupt(JNIEnv *env, jclass c, jint fd) { 152 int res; 153 int buf[1]; 154 buf[0] = 1; 155 RESTARTABLE(write(fd, buf, 1), res); 156 if (res < 0) { 157 JNU_ThrowIOExceptionWithLastError(env, "write failed"); 158 } 159 } 160 161 JNIEXPORT void JNICALL 162 Java_sun_nio_ch_AixPollPort_drain1(JNIEnv *env, jclass cl, jint fd) { 163 int res; 164 char buf[1]; 165 RESTARTABLE(read(fd, buf, 1), res); 166 if (res < 0) { 167 JNU_ThrowIOExceptionWithLastError(env, "drain1 failed"); 168 } 169 } 170 171 JNIEXPORT void JNICALL 172 Java_sun_nio_ch_AixPollPort_close0(JNIEnv *env, jclass c, jint fd) { 173 int res; 174 RESTARTABLE(close(fd), res); 175 }