1/* 2 * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2012 SAP SE. 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 <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 51typedef pollset_t pollset_create_func(int maxfd); 52typedef int pollset_destroy_func(pollset_t ps); 53typedef int pollset_ctl_func(pollset_t ps, struct poll_ctl *pollctl_array, int array_length); 54typedef int pollset_poll_func(pollset_t ps, struct pollfd *polldata_array, int array_length, int timeout); 55static pollset_create_func* _pollset_create = NULL; 56static pollset_destroy_func* _pollset_destroy = NULL; 57static pollset_ctl_func* _pollset_ctl = NULL; 58static pollset_poll_func* _pollset_poll = NULL; 59 60JNIEXPORT void JNICALL 61Java_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 72JNIEXPORT jint JNICALL 73Java_sun_nio_ch_AixPollPort_eventSize(JNIEnv* env, jclass this) { 74 return sizeof(struct pollfd); 75} 76 77JNIEXPORT jint JNICALL 78Java_sun_nio_ch_AixPollPort_eventsOffset(JNIEnv* env, jclass this) { 79 return offsetof(struct pollfd, events); 80} 81 82JNIEXPORT jint JNICALL 83Java_sun_nio_ch_AixPollPort_reventsOffset(JNIEnv* env, jclass this) { 84 return offsetof(struct pollfd, revents); 85} 86 87JNIEXPORT jint JNICALL 88Java_sun_nio_ch_AixPollPort_fdOffset(JNIEnv* env, jclass this) { 89 return offsetof(struct pollfd, fd); 90} 91 92JNIEXPORT jint JNICALL 93Java_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 103JNIEXPORT jint JNICALL 104Java_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 118JNIEXPORT jint JNICALL 119Java_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 131JNIEXPORT void JNICALL 132Java_sun_nio_ch_AixPollPort_pollsetDestroy(JNIEnv *env, jclass c, jint ps) { 133 int res; 134 RESTARTABLE(_pollset_destroy((pollset_t)ps), res); 135} 136 137JNIEXPORT void JNICALL 138Java_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 150JNIEXPORT void JNICALL 151Java_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 161JNIEXPORT void JNICALL 162Java_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 171JNIEXPORT void JNICALL 172Java_sun_nio_ch_AixPollPort_close0(JNIEnv *env, jclass c, jint fd) { 173 int res; 174 RESTARTABLE(close(fd), res); 175} 176