--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/demo/solaris/jni/Poller/Poller.c Sun Aug 17 15:54:13 2014 +0100
@@ -0,0 +1,753 @@
+/*
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This source code is provided to illustrate the usage of a given feature
+ * or technique and has been deliberately simplified. Additional steps
+ * required for a production-quality application, such as security checks,
+ * input validation and proper error handling, might not be present in
+ * this sample code.
+ */
+
+
+/*
+ **********************************************************************
+ * Poller.c :
+ * JNI code for use with Poller.java, principally to take advantage
+ * of poll() or /dev/poll multiplexing.
+ *
+ * One will need Solaris 8 or Solaris 7 with adequate patches to take
+ * advantage of the /dev/poll performance enhancements, though any
+ * version of Solaris 7 will automatically use the kernel poll()
+ * caching. And poll() will function in 2.5.1 and 2.6 as well, but
+ * will not perform well for large numbers of file descriptors.
+ *
+ * Several assumptions have been made to simplify this code :
+ * 1> At most MAX_HANDLES (32) separate pollable entities are currently
+ * supported.
+ * 2> Global synchronization from Java is assumed for all init, create
+ * and destroy routines. Per Object (handle passed in) synchronization
+ * is required for all AddFd, RemoveFd, IsMember, and Wait routines.
+ * 3> It is currently up to the user to handle waking up an
+ * existing nativeWait() call to do an addfd or removefd on
+ * that set...could implement that here with an extra pipe, or
+ * with a pair of loopback sockets in Poller.java or user code.
+ * In most cases interruption is not necessary for deletions,
+ * so long as deletions are queued up outside the Poller class
+ * and then executed the next time waitMultiple() returns.
+ * 4> /dev/poll performance could be slightly improved by coalescing
+ * adds/removes so that a write() is only done before the ioctl
+ * (DP_POLL), but this complicates exception handling and sees
+ * only modest performance gains so wasn't done.
+ * 5> /dev/poll does not report errors on attempts to remove non-
+ * extant fds, but a future bug fix to the /dev/poll device driver
+ * should solve this problem.
+ * 6> Could add simpler code for pre-Solaris 7 releases which will
+ * perform slightly better on those OSs. But again there
+ * are only modest gains to be had from these new code paths,
+ * so they've been omitted here.
+ *
+ * Compile "cc -G -o <dest_dir>/libpoller.so -I ${JAVA_HOME}/include " \
+ * -I ${JAVA_HOME}/include/solaris Poller.c" and place the <dest_dir>
+ * in your LD_LIBRARY_PATH
+ *
+ **********************************************************************
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <poll.h>
+#include <malloc.h>
+#include <fcntl.h>
+
+
+/*
+ * Remove "_NOT"s to turn on features
+ * Append "_NOT" to turn off features.
+ * Use of /dev/poll requires both the include file and kernel driver.
+ */
+#define DEBUG_NOT
+#define DEVPOLL_NOT
+
+#ifdef DEVPOLL
+#include <sys/devpoll.h>
+#endif
+
+#include "Poller.h"
+
+#define MAX_HANDLES 32
+
+
+#ifdef DEBUG
+#define DBGMSG(x) printf x
+#define ASSERT(x) {if (!(x)) \
+ printf("assertion(%s) failed at line : %d\n",#x,__LINE__);}
+#define CHECK_HANDLE(x) check_handle(x)
+#else
+#define DBGMSG(x)
+#define ASSERT(x)
+#define CHECK_HANDLE(x)
+#endif
+
+/*
+ * Globals ...protect all with a global synchronization object.
+ */
+
+static int Current_handle = 0;
+static int Use_devpoll = 0;
+static int Max_index = 0;
+
+/*
+ * Per Poller object data.
+ * Must be synchronized on a per Poller object basis.
+ */
+
+typedef struct ioevent {
+ int inuse;
+ int devpollfd;
+ int last_index;
+ int total_free;
+ int left_events;
+ int max_index;
+ pollfd_t *pfd;
+} ioevent_t;
+
+static ioevent_t IOE_handles[MAX_HANDLES];
+
+/*
+ * Exceptions to be thrown.
+ * Note : assuming all illegal argument and NULL pointer checks
+ * have already been done by the Java calling methods.
+ */
+static jint throwOutOfMemoryError(JNIEnv *env, const char * cause)
+{
+ (*env)->ThrowNew(env, (*env)->FindClass(env,"java/lang/OutOfMemoryError"),
+ cause);
+ return -1;
+}
+static jint throwInterruptedIOException(JNIEnv *env, const char * cause)
+{
+ (*env)->ThrowNew(env,
+ (*env)->FindClass(env,"java/io/InterruptedIOException"),
+ cause);
+ return -1;
+}
+static jint throwIllegalStateException(JNIEnv *env, const char * cause)
+{
+ (*env)->ThrowNew(env,
+ (*env)->FindClass(env,"java/lang/IllegalStateException"),
+ cause);
+ return -1;
+}
+
+#define MEMORY_EXCEPTION(str) throwOutOfMemoryError(env, "Poller:" str)
+#define STATE_EXCEPTION(str) throwIllegalStateException(env, "Poller:" str)
+#define INTERRUPT_EXCEPTION(str) throwInterruptedIOException(env, \
+ "Poller:" str)
+jint addfd(JNIEnv *, ioevent_t *, jint, jshort);
+jint removefd(JNIEnv *, ioevent_t *, jint);
+
+/*
+ * Class Poller
+ * Method: nativeInit
+ * Signature: ()I
+ *
+ * Only to be called once, right after this library is loaded,
+ * so no need to deal with reentrancy here.
+ * Could do as a pragma ini, but that isn't as portable.
+ */
+JNIEXPORT jint JNICALL Java_Poller_nativeInit(JNIEnv *env, jclass cls)
+{
+ int testdevpollfd;
+ int i;
+
+#ifdef DEVPOLL
+ /*
+ * See if we can use this much faster method
+ * Note : must have fix for BUGID # 4223353 or OS can crash!
+ */
+ testdevpollfd = open("/dev/poll",O_RDWR);
+ if (testdevpollfd >= 0) {
+ /*
+ * If Solaris 7, we need a patch
+ * Until we know what string to search for, we'll play it
+ * safe and disable this for Solaris 7.
+ */
+
+ if (!strcmp(name.release,"5.7"))
+ {
+ Use_devpoll = 0;
+ }
+ else
+ {
+ Use_devpoll = 1;
+ }
+ }
+
+ DBGMSG(("Use_devpoll=%d\n" ,Use_devpoll));
+ close(testdevpollfd);
+#endif
+
+ /*
+ * For now, we optimize for Solaris 7 if /dev/poll isn't
+ * available, as it is only a small % hit for Solaris < 7.
+ * if ( (Use_devpoll == 0) && !strcmp(name.release,"5.6") )
+ * Use_sol7opt = 0;
+ */
+ Current_handle = 0;
+ for (i = 0; i < MAX_HANDLES; i++) {
+ IOE_handles[i].devpollfd = -1;
+ IOE_handles[i].pfd = NULL;
+ }
+
+ /*
+ * this tells me the max number of open filedescriptors
+ */
+ Max_index = sysconf(_SC_OPEN_MAX);
+ if (Max_index < 0) {
+ Max_index = 1024;
+ }
+
+ DBGMSG(("got sysconf(_SC_OPEN_MAX)=%d file desc\n",Max_index));
+
+ return 0;
+}
+
+JNIEXPORT jint JNICALL Java_Poller_getNumCPUs(JNIEnv *env, jclass cls)
+{
+ return sysconf(_SC_NPROCESSORS_ONLN);
+}
+
+/*
+ * Class: Poller
+ * Method: nativeCreatePoller
+ * Signature: (I)I
+ * Note : in the case where /dev/poll doesn't exist,
+ * using more than one poll array could hurt
+ * Solaris 7 performance due to kernel caching.
+ */
+
+JNIEXPORT jint JNICALL Java_Poller_nativeCreatePoller
+ (JNIEnv *env, jobject obj, jint maximum_fds)
+{
+ int handle, retval, i;
+ ioevent_t *ioeh;
+
+ if (maximum_fds == -1) {
+ maximum_fds = Max_index;
+ }
+ handle = Current_handle;
+ if (Current_handle >= MAX_HANDLES) {
+ for (i = 0; i < MAX_HANDLES; i++) {
+ if (IOE_handles[i].inuse == 0) {
+ handle = i;
+ break;
+ }
+ }
+ if (handle >= MAX_HANDLES) {
+ return MEMORY_EXCEPTION("CreatePoller - MAX_HANDLES exceeded");
+ }
+ } else {
+ Current_handle++;
+ }
+
+ ioeh = &IOE_handles[handle];
+
+ ioeh->inuse = 1;
+
+ ioeh->last_index = 0;
+ ioeh->total_free = 0;
+ ioeh->left_events = 0;
+ ioeh->max_index = maximum_fds;
+
+ retval = handle;
+ if (Use_devpoll) {
+ ioeh->devpollfd = open("/dev/poll",O_RDWR);
+ DBGMSG(("Opened /dev/poll, set devpollfd = %d\n",ioeh->devpollfd));
+ if (ioeh->devpollfd < 0) {
+ Current_handle--;
+ return MEMORY_EXCEPTION("CreatePoller - can\'t open /dev/poll");
+ }
+ }
+ ioeh->pfd = malloc(maximum_fds * sizeof(pollfd_t));
+ if (ioeh->pfd == NULL) {
+ Current_handle--;
+ return MEMORY_EXCEPTION("CreatePoller - malloc failure");
+ }
+
+ return retval;
+}
+
+/*
+ * Class: Poller
+ * Method: nativeDestroyPoller
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_Poller_nativeDestroyPoller
+ (JNIEnv *env, jobject obj, jint handle)
+{
+
+ ioevent_t *ioeh;
+
+ if (handle < 0 || handle >= MAX_HANDLES)
+ {
+ STATE_EXCEPTION("DestroyPoller - handle out of range");
+ return;
+ }
+
+ ioeh = &IOE_handles[handle];
+ ioeh->inuse = 0;
+ if (Use_devpoll) {
+ close(ioeh->devpollfd);
+ }
+ free(ioeh->pfd);
+}
+
+#ifdef DEBUG
+static void check_handle(ioevent_t *ioeh)
+{
+ int i,used,unused;
+
+ used=unused=0;
+ for (i = 0; i < ioeh->last_index; i++)
+ {
+ if (ioeh->pfd[i].fd == -1)
+ unused++;
+ else
+ used++;
+ }
+ if (unused != ioeh->total_free)
+ printf("WARNING : found %d free, claimed %d. Used : %d\n",
+ unused, ioeh->total_free, used);
+}
+#endif
+
+/*
+ * Class: Poller
+ * Method: nativeAddFd
+ * Signature: (IIS)I
+ *
+ * Currently doesn't check to make sure we aren't adding
+ * an fd already added (no problem for /dev/poll...just
+ * an array waster for poll()).
+ */
+JNIEXPORT jint JNICALL Java_Poller_nativeAddFd
+ (JNIEnv *env, jobject obj, jint handle, jint fd, jshort events)
+{
+ int retval;
+ ioevent_t *ioeh;
+
+ if (handle < 0 || handle >= MAX_HANDLES)
+ return STATE_EXCEPTION("AddFd - handle out of range");
+
+ ioeh = &IOE_handles[handle];
+
+ CHECK_HANDLE(ioeh);
+
+ #ifdef DEVPOLL
+ if (Use_devpoll)
+ {
+ int i;
+ pollfd_t pollelt;
+
+ /*
+ * use /dev/poll
+ */
+ pollelt.fd = fd;
+ pollelt.events = events;
+ if ((i = write(ioeh->devpollfd, &pollelt, sizeof(pollfd_t))) !=
+ sizeof(pollfd_t)) {
+ DBGMSG(("write to devpollfd=%d showed %d bytes out of %d\n",
+ ioeh->devpollfd,i,sizeof(pollfd_t)));
+ return STATE_EXCEPTION("AddFd - /dev/poll add failure");
+ }
+ else
+ {
+ retval = fd;
+ }
+ }
+ else
+ #endif
+ { /* no /dev/poll available */
+ retval = addfd(env, ioeh, fd, events);
+ }
+ return retval;
+}
+
+/*
+ * Addfd to pollfd array...optimized for Solaris 7
+ */
+jint addfd(JNIEnv *env, ioevent_t *ioeh, jint fd, jshort events)
+{
+ int idx;
+
+ if (ioeh->total_free)
+ {
+ /*
+ * Traversing from end because that's where we pad.
+ */
+ ioeh->total_free--;
+ for (idx = ioeh->last_index - 1; idx >= 0; idx--) {
+ if (ioeh->pfd[idx].fd == -1)
+ break;
+ }
+ }
+ else if (ioeh->last_index >= ioeh->max_index)
+ {
+ return MEMORY_EXCEPTION("AddFd - too many fds");
+ }
+ else
+ {
+ int i;
+ int new_total;
+ /*
+ * For Solaris 7, want to add some growth space
+ * and fill extras with fd=-1. This allows for
+ * kernel poll() implementation to perform optimally.
+ */
+ new_total = ioeh->last_index;
+ new_total += (new_total/10) + 1; /* bump size by 10% */
+ if (new_total > ioeh->max_index)
+ new_total = ioeh->max_index;
+ for (i = ioeh->last_index; i <= new_total; i++)
+ {
+ ioeh->pfd[i].fd = -1;
+ }
+ idx = ioeh->last_index;
+ ioeh->total_free = new_total - ioeh->last_index - 1;
+ DBGMSG(("Just grew from %d to %d in size\n",
+ ioeh->last_index, new_total));
+ ioeh->last_index = new_total;
+ }
+ ASSERT((idx >= 0) && (idx <= ioeh->max_index));
+ ASSERT(ioeh->pfd[idx].fd == -1);
+ ioeh->pfd[idx].fd = fd;
+ ioeh->pfd[idx].events = events;
+ ioeh->pfd[idx].revents = 0;
+
+ CHECK_HANDLE(ioeh);
+
+ return fd;
+}
+
+/*
+ * Class: Poller
+ * Method: nativeRemoveFd
+ * Signature: (II)I
+ */
+JNIEXPORT jint JNICALL Java_Poller_nativeRemoveFd
+ (JNIEnv *env, jobject obj, jint handle, jint fd)
+{
+ ioevent_t *ioeh;
+
+ if (handle < 0 || handle >= MAX_HANDLES)
+ return STATE_EXCEPTION("RemoveFd - handle out of range");
+
+ ioeh = &IOE_handles[handle];
+
+ #ifdef DEVPOLL
+ if (Use_devpoll)
+ {
+ /*
+ * use /dev/poll - currently no need for locking here.
+ */
+ pollfd_t pollelt;
+
+ pollelt.fd = fd;
+ pollelt.events = POLLREMOVE;
+ if (write(ioeh->devpollfd, &pollelt,
+ sizeof(pollfd_t) ) != sizeof(pollfd_t))
+ {
+ return STATE_EXCEPTION("RemoveFd - /dev/poll failure");
+ }
+ }
+ else
+ #endif DEVPOLL
+ {
+ return removefd(env, ioeh,fd);
+ }
+}
+/*
+ * remove from pollfd array...optimize for Solaris 7
+ */
+jint removefd(JNIEnv *env, ioevent_t *ioeh, jint fd)
+{
+ int i;
+ int found = 0;
+
+ { /* !Use_devpoll */
+ for (i = 0; i < ioeh->last_index; i++)
+ {
+ if (ioeh->pfd[i].fd == fd)
+ {
+ ioeh->pfd[i].fd = -1;
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ {
+ return STATE_EXCEPTION("RemoveFd - no such fd");
+ }
+ ioeh->left_events = 0; /* Have to go back to the kernel */
+ ioeh->total_free++;
+ /*
+ * Shrinking pool if > 33% empty. Just don't do this often!
+ */
+ if ( (ioeh->last_index > 100) &&
+ (ioeh->total_free > (ioeh->last_index / 3)) )
+ {
+ int j;
+ /*
+ * we'll just bite the bullet here, since we're > 33% empty.
+ * walk through and eliminate -1 fd values, shrink total
+ * size to still have ~ 10 fd==-1 values at end.
+ * Start at end (since we pad here) and, when we find fd != -1,
+ * swap with an earlier fd == -1 until we have all -1 values
+ * at the end.
+ */
+ CHECK_HANDLE(ioeh);
+ for (i = ioeh->last_index - 1, j = 0; i > j; i--)
+ {
+ if (ioeh->pfd[i].fd != -1)
+ {
+ while ( (j < i) && (ioeh->pfd[j].fd != -1) )
+ j++;
+ DBGMSG( ("i=%d,j=%d,ioeh->pfd[j].fd=%d\n",
+ i, j, ioeh->pfd[j].fd) );
+ if (j < i)
+ {
+ ASSERT(ioeh->pfd[j].fd == -1);
+ ioeh->pfd[j].fd = ioeh->pfd[i].fd;
+ ioeh->pfd[j].events = ioeh->pfd[i].events;
+ ioeh->pfd[i].fd = -1;
+ }
+ }
+ }
+ DBGMSG(("Just shrunk from %d to %d in size\n",
+ ioeh->last_index, j+11));
+ ioeh->last_index = j + 11; /* last_index always 1 greater */
+ ioeh->total_free = 10;
+ CHECK_HANDLE(ioeh);
+ }
+ } /* !Use_devpoll */
+
+ return 1;
+}
+
+/*
+ * Class: Poller
+ * Method: nativeIsMember
+ * Signature: (II)I
+ */
+JNIEXPORT jint JNICALL Java_Poller_nativeIsMember
+ (JNIEnv *env, jobject obj, jint handle, jint fd)
+{
+ int found = 0;
+ int i;
+ ioevent_t *ioeh;
+
+ if (handle < 0 || handle >= MAX_HANDLES)
+ return STATE_EXCEPTION("IsMember - handle out of range");
+
+ ioeh = &IOE_handles[handle];
+
+ #ifdef DEVPOLL
+ if (Use_devpoll)
+ {
+ pollfd_t pfd;
+ /*
+ * DEVPOLL ioctl DP_ISPOLLED call to determine if fd is polled.
+ */
+ pfd.fd = fd;
+ pfd.events = 0;
+ pfd.revents = 0;
+ found = ioctl(ioeh->devpollfd, DP_ISPOLLED, &pfd);
+ if (found == -1)
+ {
+ return STATE_EXCEPTION("IsMember - /dev/poll failure");
+ }
+ }
+ else
+ #endif
+ {
+ for (i = 0; i < ioeh->last_index; i++)
+ {
+ if (fd == ioeh->pfd[i].fd)
+ {
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ return found;
+}
+
+/*
+ * Class: Poller
+ * Method: nativeWait
+ * Signature: (II[I[SJ)I
+ */
+JNIEXPORT jint JNICALL Java_Poller_nativeWait
+ (JNIEnv *env, jobject obj, jint handle, jint maxEvents,
+ jintArray jfds, jshortArray jrevents, jlong timeout)
+{
+ int useEvents, count, idx;
+ short *reventp;
+ jint *fdp;
+ int retval;
+ ioevent_t *ioeh;
+ jboolean isCopy1,isCopy2;
+
+ if (handle < 0 || handle >= MAX_HANDLES)
+ return STATE_EXCEPTION("nativeWait - handle out of range");
+
+ ioeh = &IOE_handles[handle];
+
+ if (maxEvents == 0) /* just doing a kernel delay! */
+ {
+ useEvents = poll(NULL,0L,timeout);
+ return 0;
+ }
+
+ #ifdef DEVPOLL
+ if (Use_devpoll)
+ {
+ struct dvpoll dopoll;
+ /*
+ * DEVPOLL ioctl DP_POLL call, reading
+ */
+ dopoll.dp_timeout = timeout;
+ dopoll.dp_nfds=maxEvents;
+ dopoll.dp_fds=ioeh->pfd;
+
+ useEvents = ioctl(ioeh->devpollfd, DP_POLL, &dopoll);
+ while ((useEvents == -1) && (errno == EAGAIN))
+ useEvents = ioctl(ioeh->devpollfd, DP_POLL, &dopoll);
+
+ if (useEvents == -1)
+ {
+ if (errno == EINTR)
+ return INTERRUPT_EXCEPTION("nativeWait - /dev/poll failure EINTR");
+ else
+ return STATE_EXCEPTION("nativeWait - /dev/poll failure");
+ }
+
+ reventp =(*env)->GetShortArrayElements(env,jrevents,&isCopy1);
+ fdp =(*env)->GetIntArrayElements(env,jfds,&isCopy2);
+ for (idx = 0,count = 0; idx < useEvents; idx++)
+ {
+ if (ioeh->pfd[idx].revents)
+ {
+ fdp[count] = ioeh->pfd[idx].fd;
+ reventp[count] = ioeh->pfd[idx].revents;
+ count++;
+ }
+ }
+ if (count < useEvents)
+ return STATE_EXCEPTION("Wait - Corrupted internals");
+
+ if (isCopy1 == JNI_TRUE)
+ (*env)->ReleaseShortArrayElements(env,jrevents,reventp,0);
+ if (isCopy2 == JNI_TRUE)
+ (*env)->ReleaseIntArrayElements(env,jfds,fdp,0);
+ }
+ else
+ #endif
+ { /* !Use_devpoll */
+
+ /* no leftovers=>go to kernel */
+ if (ioeh->left_events == 0)
+ {
+ useEvents = poll(ioeh->pfd,ioeh->last_index, timeout);
+ while ((useEvents == -1) && (errno == EAGAIN))
+ useEvents = poll(ioeh->pfd,ioeh->last_index, timeout);
+ if (useEvents == -1)
+ {
+ if (errno == EINTR)
+ return INTERRUPT_EXCEPTION("Wait - poll() failure EINTR-" \
+ "IO interrupted.");
+ else if (errno == EINVAL)
+ return STATE_EXCEPTION("Wait - poll() failure EINVAL-" \
+ "invalid args (is fdlim cur < max?)");
+ else
+ return STATE_EXCEPTION("Wait - poll() failure");
+ }
+ ioeh->left_events = useEvents;
+ DBGMSG(("waitnative : poll returns : %d\n",useEvents));
+ }
+ else
+ { /* left over from last call */
+ useEvents = ioeh->left_events;
+ }
+
+ if (useEvents > maxEvents)
+ {
+ useEvents = maxEvents;
+ }
+
+ ioeh->left_events -= useEvents; /* left to process */
+
+ DBGMSG(("waitnative : left %d, use %d, max %d\n",ioeh->left_events,
+ useEvents,maxEvents));
+
+ if (useEvents > 0)
+ {
+ reventp =(*env)->GetShortArrayElements(env,jrevents,&isCopy1);
+ fdp =(*env)->GetIntArrayElements(env,jfds,&isCopy2);
+ for (idx = 0,count = 0; (idx < ioeh->last_index) &&
+ (count < useEvents); idx++)
+ {
+ if (ioeh->pfd[idx].revents)
+ {
+ fdp[count] = ioeh->pfd[idx].fd;
+ reventp[count] = ioeh->pfd[idx].revents;
+ /* in case of leftover for next walk */
+ ioeh->pfd[idx].revents = 0;
+ count++;
+ }
+ }
+ if (count < useEvents)
+ {
+ ioeh->left_events = 0;
+ return STATE_EXCEPTION("Wait - Corrupted internals");
+ }
+ if (isCopy1 == JNI_TRUE)
+ (*env)->ReleaseShortArrayElements(env,jrevents,reventp,0);
+ if (isCopy2 == JNI_TRUE)
+ (*env)->ReleaseIntArrayElements(env,jfds,fdp,0);
+ }
+ } /* !Use_devpoll */
+
+ return useEvents;
+}