Path: blob/master/src/java.base/windows/native/libnio/ch/WindowsSelectorImpl.c
41134 views
/*1* Copyright (c) 2002, 2021, 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 <limits.h>35#include <stdlib.h>36#include <winsock2.h>3738#include "jvm.h"39#include "jni.h"40#include "jni_util.h"41#include "nio.h"42#include "sun_nio_ch_WindowsSelectorImpl.h"43#include "sun_nio_ch_PollArrayWrapper.h"4445#include "nio_util.h" /* Needed for POLL* constants (includes "winsock2.h") */4647typedef struct {48jint fd;49jshort events;50} pollfd;5152#define WAKEUP_SOCKET_BUF_SIZE 16535455JNIEXPORT jint JNICALL56Java_sun_nio_ch_WindowsSelectorImpl_00024SubSelector_poll0(JNIEnv *env, jobject this,57jlong pollAddress, jint numfds,58jintArray returnReadFds, jintArray returnWriteFds,59jintArray returnExceptFds, jlong timeout, jlong fdsBuffer)60{61DWORD result = 0;62pollfd *fds = (pollfd *) pollAddress;63int i;64FD_SET *readfds = (FD_SET *) jlong_to_ptr(fdsBuffer);65FD_SET *writefds = (FD_SET *) jlong_to_ptr(fdsBuffer + sizeof(FD_SET));66FD_SET *exceptfds = (FD_SET *) jlong_to_ptr(fdsBuffer + sizeof(FD_SET) * 2);67struct timeval timevalue, *tv;68static struct timeval zerotime = {0, 0};69int read_count = 0, write_count = 0, except_count = 0;7071#ifdef _WIN6472int resultbuf[FD_SETSIZE + 1];73#endif7475if (timeout == 0) {76tv = &zerotime;77} else if (timeout < 0) {78tv = NULL;79} else {80jlong sec = timeout / 1000;81tv = &timevalue;82//83// struct timeval members are signed 32-bit integers so the84// signed 64-bit jlong needs to be clamped85//86if (sec > INT_MAX) {87tv->tv_sec = INT_MAX;88tv->tv_usec = 0;89} else {90tv->tv_sec = (long)sec;91tv->tv_usec = (long)((timeout % 1000) * 1000);92}93}9495/* Set FD_SET structures required for select */96for (i = 0; i < numfds; i++) {97if (fds[i].events & POLLIN) {98readfds->fd_array[read_count] = fds[i].fd;99read_count++;100}101if (fds[i].events & POLLOUT) {102writefds->fd_array[write_count] = fds[i].fd;103write_count++;104}105exceptfds->fd_array[except_count] = fds[i].fd;106except_count++;107}108109readfds->fd_count = read_count;110writefds->fd_count = write_count;111exceptfds->fd_count = except_count;112113/* Call select */114if ((result = select(0 , readfds, writefds, exceptfds, tv))115== SOCKET_ERROR) {116JNU_ThrowIOExceptionWithLastError(env, "Select failed");117return IOS_THROWN;118}119120/* Return selected sockets. */121/* Each Java array consists of sockets count followed by sockets list */122123#ifdef _WIN64124resultbuf[0] = readfds->fd_count;125for (i = 0; i < (int)readfds->fd_count; i++) {126resultbuf[i + 1] = (int)readfds->fd_array[i];127}128(*env)->SetIntArrayRegion(env, returnReadFds, 0,129readfds->fd_count + 1, resultbuf);130131resultbuf[0] = writefds->fd_count;132for (i = 0; i < (int)writefds->fd_count; i++) {133resultbuf[i + 1] = (int)writefds->fd_array[i];134}135(*env)->SetIntArrayRegion(env, returnWriteFds, 0,136writefds->fd_count + 1, resultbuf);137138resultbuf[0] = exceptfds->fd_count;139for (i = 0; i < (int)exceptfds->fd_count; i++) {140resultbuf[i + 1] = (int)exceptfds->fd_array[i];141}142(*env)->SetIntArrayRegion(env, returnExceptFds, 0,143exceptfds->fd_count + 1, resultbuf);144#else145(*env)->SetIntArrayRegion(env, returnReadFds, 0,146readfds->fd_count + 1, (jint *)readfds);147148(*env)->SetIntArrayRegion(env, returnWriteFds, 0,149writefds->fd_count + 1, (jint *)writefds);150(*env)->SetIntArrayRegion(env, returnExceptFds, 0,151exceptfds->fd_count + 1, (jint *)exceptfds);152#endif153return 0;154}155156JNIEXPORT void JNICALL157Java_sun_nio_ch_WindowsSelectorImpl_setWakeupSocket0(JNIEnv *env, jclass this,158jint scoutFd)159{160/* Write one byte into the pipe */161const char byte = 1;162send(scoutFd, &byte, 1, 0);163}164165JNIEXPORT void JNICALL166Java_sun_nio_ch_WindowsSelectorImpl_resetWakeupSocket0(JNIEnv *env, jclass this,167jint scinFd)168{169char bytes[WAKEUP_SOCKET_BUF_SIZE];170long bytesToRead;171172/* Drain socket */173/* Find out how many bytes available for read */174ioctlsocket (scinFd, FIONREAD, &bytesToRead);175if (bytesToRead == 0) {176return;177}178/* Prepare corresponding buffer if needed, and then read */179if (bytesToRead > WAKEUP_SOCKET_BUF_SIZE) {180char* buf = (char*)malloc(bytesToRead);181if (buf == NULL) {182JNU_ThrowOutOfMemoryError(env, NULL);183return;184}185recv(scinFd, buf, bytesToRead, 0);186free(buf);187} else {188recv(scinFd, bytes, WAKEUP_SOCKET_BUF_SIZE, 0);189}190}191192193