Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/sun/nio/ch/WindowsSelectorImpl.c
32288 views
/*1* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26*/2728/* Maximum number of sockets per select() */29/* This number should be equal to WindowsSelectorImpl.MAX_SELECTABLE_FDS */30/* This definition MUST precede the inclusion of winsock2.h */3132#define FD_SETSIZE 10243334#include <stdlib.h>35#include <winsock2.h>3637#include "jvm.h"38#include "jni.h"39#include "jni_util.h"40#include "nio.h"41#include "sun_nio_ch_WindowsSelectorImpl.h"42#include "sun_nio_ch_PollArrayWrapper.h"4344#include "nio_util.h" /* Needed for POLL* constants (includes "winsock2.h") */4546typedef struct {47jint fd;48jshort events;49} pollfd;5051#define WAKEUP_SOCKET_BUF_SIZE 16525354JNIEXPORT jint JNICALL55Java_sun_nio_ch_WindowsSelectorImpl_00024SubSelector_poll0(JNIEnv *env, jobject this,56jlong pollAddress, jint numfds,57jintArray returnReadFds, jintArray returnWriteFds,58jintArray returnExceptFds, jlong timeout, jlong fdsBuffer)59{60DWORD result = 0;61pollfd *fds = (pollfd *) pollAddress;62int i;63FD_SET *readfds = (FD_SET *) jlong_to_ptr(fdsBuffer);64FD_SET *writefds = (FD_SET *) jlong_to_ptr(fdsBuffer + sizeof(FD_SET));65FD_SET *exceptfds = (FD_SET *) jlong_to_ptr(fdsBuffer + sizeof(FD_SET) * 2);66struct timeval timevalue, *tv;67static struct timeval zerotime = {0, 0};68int read_count = 0, write_count = 0, except_count = 0;6970#ifdef _WIN6471int resultbuf[FD_SETSIZE + 1];72#endif7374if (timeout == 0) {75tv = &zerotime;76} else if (timeout < 0) {77tv = NULL;78} else {79tv = &timevalue;80tv->tv_sec = (long)(timeout / 1000);81tv->tv_usec = (long)((timeout % 1000) * 1000);82}8384/* Set FD_SET structures required for select */85for (i = 0; i < numfds; i++) {86if (fds[i].events & POLLIN) {87readfds->fd_array[read_count] = fds[i].fd;88read_count++;89}90if (fds[i].events & (POLLOUT | POLLCONN))91{92writefds->fd_array[write_count] = fds[i].fd;93write_count++;94}95exceptfds->fd_array[except_count] = fds[i].fd;96except_count++;97}9899readfds->fd_count = read_count;100writefds->fd_count = write_count;101exceptfds->fd_count = except_count;102103/* Call select */104if ((result = select(0 , readfds, writefds, exceptfds, tv))105== SOCKET_ERROR) {106/* Bad error - this should not happen frequently */107/* Iterate over sockets and call select() on each separately */108FD_SET *errreadfds = (FD_SET *) jlong_to_ptr(fdsBuffer + sizeof(FD_SET) * 3);109FD_SET *errwritefds = (FD_SET *) jlong_to_ptr(fdsBuffer + sizeof(FD_SET) * 4);110FD_SET *errexceptfds = (FD_SET *) jlong_to_ptr(fdsBuffer + sizeof(FD_SET) * 5);111readfds->fd_count = 0;112writefds->fd_count = 0;113exceptfds->fd_count = 0;114for (i = 0; i < numfds; i++) {115/* prepare select structures for the i-th socket */116errreadfds->fd_count = 0;117errwritefds->fd_count = 0;118if (fds[i].events & POLLIN) {119errreadfds->fd_array[0] = fds[i].fd;120errreadfds->fd_count = 1;121}122if (fds[i].events & (POLLOUT | POLLCONN))123{124errwritefds->fd_array[0] = fds[i].fd;125errwritefds->fd_count = 1;126}127errexceptfds->fd_array[0] = fds[i].fd;128errexceptfds->fd_count = 1;129130/* call select on the i-th socket */131if (select(0, errreadfds, errwritefds, errexceptfds, &zerotime)132== SOCKET_ERROR) {133/* This socket causes an error. Add it to exceptfds set */134exceptfds->fd_array[exceptfds->fd_count] = fds[i].fd;135exceptfds->fd_count++;136} else {137/* This socket does not cause an error. Process result */138if (errreadfds->fd_count == 1) {139readfds->fd_array[readfds->fd_count] = fds[i].fd;140readfds->fd_count++;141}142if (errwritefds->fd_count == 1) {143writefds->fd_array[writefds->fd_count] = fds[i].fd;144writefds->fd_count++;145}146if (errexceptfds->fd_count == 1) {147exceptfds->fd_array[exceptfds->fd_count] = fds[i].fd;148exceptfds->fd_count++;149}150}151}152}153154/* Return selected sockets. */155/* Each Java array consists of sockets count followed by sockets list */156157#ifdef _WIN64158resultbuf[0] = readfds->fd_count;159for (i = 0; i < (int)readfds->fd_count; i++) {160resultbuf[i + 1] = (int)readfds->fd_array[i];161}162(*env)->SetIntArrayRegion(env, returnReadFds, 0,163readfds->fd_count + 1, resultbuf);164165resultbuf[0] = writefds->fd_count;166for (i = 0; i < (int)writefds->fd_count; i++) {167resultbuf[i + 1] = (int)writefds->fd_array[i];168}169(*env)->SetIntArrayRegion(env, returnWriteFds, 0,170writefds->fd_count + 1, resultbuf);171172resultbuf[0] = exceptfds->fd_count;173for (i = 0; i < (int)exceptfds->fd_count; i++) {174resultbuf[i + 1] = (int)exceptfds->fd_array[i];175}176(*env)->SetIntArrayRegion(env, returnExceptFds, 0,177exceptfds->fd_count + 1, resultbuf);178#else179(*env)->SetIntArrayRegion(env, returnReadFds, 0,180readfds->fd_count + 1, (jint *)readfds);181182(*env)->SetIntArrayRegion(env, returnWriteFds, 0,183writefds->fd_count + 1, (jint *)writefds);184(*env)->SetIntArrayRegion(env, returnExceptFds, 0,185exceptfds->fd_count + 1, (jint *)exceptfds);186#endif187return 0;188}189190JNIEXPORT void JNICALL191Java_sun_nio_ch_WindowsSelectorImpl_setWakeupSocket0(JNIEnv *env, jclass this,192jint scoutFd)193{194/* Write one byte into the pipe */195const char byte = 1;196send(scoutFd, &byte, 1, 0);197}198199JNIEXPORT void JNICALL200Java_sun_nio_ch_WindowsSelectorImpl_resetWakeupSocket0(JNIEnv *env, jclass this,201jint scinFd)202{203char bytes[WAKEUP_SOCKET_BUF_SIZE];204long bytesToRead;205206/* Drain socket */207/* Find out how many bytes available for read */208ioctlsocket (scinFd, FIONREAD, &bytesToRead);209if (bytesToRead == 0) {210return;211}212/* Prepare corresponding buffer if needed, and then read */213if (bytesToRead > WAKEUP_SOCKET_BUF_SIZE) {214char* buf = (char*)malloc(bytesToRead);215if (buf == NULL) {216JNU_ThrowOutOfMemoryError(env, NULL);217return;218}219recv(scinFd, buf, bytesToRead, 0);220free(buf);221} else {222recv(scinFd, bytes, WAKEUP_SOCKET_BUF_SIZE, 0);223}224}225226JNIEXPORT jboolean JNICALL227Java_sun_nio_ch_WindowsSelectorImpl_discardUrgentData(JNIEnv* env, jobject this,228jint s)229{230char data[8];231jboolean discarded = JNI_FALSE;232int n;233do {234n = recv(s, (char*)&data, sizeof(data), MSG_OOB);235if (n > 0) {236discarded = JNI_TRUE;237}238} while (n > 0);239return discarded;240}241242243