Author: mturk
Date: Tue May 17 07:46:51 2011
New Revision: 1104038
URL: http://svn.apache.org/viewvc?rev=1104038&view=rev
Log:
Add native implementation for posix pollset
Added:
commons/sandbox/runtime/trunk/src/main/native/os/unix/poll.c (with props)
Modified:
commons/sandbox/runtime/trunk/src/main/native/Makefile.unx.in
commons/sandbox/runtime/trunk/src/main/native/include/acr/error.h
commons/sandbox/runtime/trunk/src/main/native/include/acr/iodefs.h
commons/sandbox/runtime/trunk/src/main/native/include/acr/table.h
commons/sandbox/runtime/trunk/src/main/native/os/unix/arch_opts.h
commons/sandbox/runtime/trunk/src/main/native/os/unix/util.c
commons/sandbox/runtime/trunk/src/main/native/shared/error.c
commons/sandbox/runtime/trunk/src/main/native/shared/table.c
Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.unx.in
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/Makefile.unx.in?rev=1104038&r1=1104037&r2=1104038&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/Makefile.unx.in (original)
+++ commons/sandbox/runtime/trunk/src/main/native/Makefile.unx.in Tue May 17
07:46:51 2011
@@ -66,6 +66,7 @@ UNIX_SOURCES=\
$(TOPDIR)/os/unix/inetsock.c \
$(TOPDIR)/os/unix/init.c \
$(TOPDIR)/os/unix/platform.c \
+ $(TOPDIR)/os/unix/poll.c \
$(TOPDIR)/os/unix/posixapi.c \
$(TOPDIR)/os/unix/procmutex.c \
$(TOPDIR)/os/unix/shmem.c \
Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr/error.h
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr/error.h?rev=1104038&r1=1104037&r2=1104038&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr/error.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr/error.h Tue May
17 07:46:51 2011
@@ -36,6 +36,7 @@
/* Exception class enums */
enum {
+ ACR_EX_EILLEGAL, /* java/lang/IllegalStateException */
ACR_EX_ENOINST, /* java/lang/InstatiationException */
ACR_EX_ERUNTIME, /* java/lang/RuntimeException */
ACR_EX_ENOMEM, /* java/lang/OutOfMemoryError */
Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr/iodefs.h
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr/iodefs.h?rev=1104038&r1=1104037&r2=1104038&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr/iodefs.h
(original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr/iodefs.h Tue May
17 07:46:51 2011
@@ -35,4 +35,12 @@
#define ACR_FOPEN_NOINHERIT 0x010000 /**< Do not inherit files on exec */
#define ACR_FOPEN_INFO 0x020000 /**< Open without READ or WRITE access
*/
+#define ACR_POLLIN 0x01
+#define ACR_POLLPRI 0x02
+#define ACR_POLLOUT 0x04
+#define ACR_POLLERR 0x08
+#define ACR_POLLHUP 0x10
+#define ACR_POLLNVAL 0x20
+#define ACR_POLLTTL 0x40
+
#endif /* _ACR_IODEFS_H */
Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr/table.h
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr/table.h?rev=1104038&r1=1104037&r2=1104038&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr/table.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr/table.h Tue May
17 07:46:51 2011
@@ -90,6 +90,15 @@ void *
AcrTableTop(acr_table_t *arr);
/**
+ * Delete an element from the table.
+ * @param arr The table to use.
+ * @param e Element index to delete..
+ * @return zero on success, ACR_EOF if not found or if array is empty.
+ */
+int
+AcrTableDel(acr_table_t *arr, int e);
+
+/**
* Remove all elements from an table.
* @param arr The table to remove all elements from.
* @remark No memory is freed by this operation,
Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/arch_opts.h
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/arch_opts.h?rev=1104038&r1=1104037&r2=1104038&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/arch_opts.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/arch_opts.h Tue May
17 07:46:51 2011
@@ -151,6 +151,7 @@ int AcrNullPipe(int flags, int fd);
int AcrPipePair(int pd[2], int flags);
int AcrSigIgnore(int signo);
int AcrSigDefault(int signo);
+void AcrDrainPipe(int fd);
#endif /* _ACR_ARCH_OPTS_H_ */
Added: commons/sandbox/runtime/trunk/src/main/native/os/unix/poll.c
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/poll.c?rev=1104038&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/poll.c (added)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/poll.c Tue May 17
07:46:51 2011
@@ -0,0 +1,376 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "acr/clazz.h"
+#include "acr/memory.h"
+#include "acr/jniapi.h"
+#include "acr/port.h"
+#include "acr/time.h"
+#include "acr/iodefs.h"
+#include "arch_opts.h"
+#include <poll.h>
+
+/* pollset operation states */
+#define PSS_DESTROY 1
+#define PSS_POLL 2
+#define PSS_WAIT 3
+#define PSS_WAKEUP 4
+
+typedef struct acr_pollfd_t {
+ jobject obj;
+ acr_time_t ttl;
+} acr_pollfd_t;
+
+typedef struct acr_pollset_t {
+ struct pollfd *fdset;
+ acr_pollfd_t *ooset;
+ int used;
+ int size;
+ volatile int state;
+ int wpipe[2];
+ pthread_mutex_t mutex;
+ pthread_cond_t wakeup;
+} acr_pollset_t;
+
+static short ieventt(int event)
+{
+ short rv = 0;
+
+ if (event & ACR_POLLIN)
+ rv |= POLLIN;
+ if (event & ACR_POLLPRI)
+ rv |= POLLPRI;
+ if (event & ACR_POLLOUT)
+ rv |= POLLOUT;
+ /* POLLERR, POLLHUP, and POLLNVAL aren't valid as requested events
+ */
+ return rv;
+}
+
+static short reventt(short event)
+{
+ short rv = 0;
+
+ if (event & POLLIN)
+ rv |= ACR_POLLIN;
+ if (event & POLLPRI)
+ rv |= ACR_POLLPRI;
+ if (event & POLLOUT)
+ rv |= ACR_POLLOUT;
+ if (event & POLLERR)
+ rv |= ACR_POLLERR;
+ if (event & POLLHUP)
+ rv |= ACR_POLLHUP;
+ if (event & POLLNVAL)
+ rv |= ACR_POLLNVAL;
+ return rv;
+}
+
+
+ACR_NET_EXPORT(jlong, Poll, create0)(JNI_STDARGS, jint size)
+{
+ int rc;
+ acr_pollset_t *ps;
+
+ ps = ACR_TALLOC(acr_pollset_t);
+ if (ps == 0)
+ return 0;
+ ps->wpipe[0] = -1;
+ ps->wpipe[1] = -1;
+ ps->size = size;
+ ps->used = 1;
+
+ ps->fdset = ACR_MALLOC(struct pollfd, size);
+ if (ps->fdset == 0)
+ return 0;
+ ps->ooset = ACR_MALLOC(acr_pollfd_t, size);
+ if (ps->fdset == 0) {
+ AcrFree(ps->fdset);
+ return 0;
+ }
+ if ((rc = AcrPipePair(ps->wpipe, 0)) != 0) {
+ ACR_THROW_NET_ERROR(rc);
+ goto cleanup;
+ }
+ /* Add the wakeup pipe to the pset
+ */
+ ps->fdset[0].fd = ps->wpipe[0];
+ ps->fdset[0].events = POLLIN;
+ ps->fdset[0].revents = 0;
+ ps->ooset[0].obj = 0;
+ ps->ooset[0].ttl = ACR_INFINITE;
+
+ if (pthread_cond_init(&ps->wakeup, 0) != 0) {
+ ACR_THROW_NET_ERRNO();
+ goto cleanup;
+ }
+ if (pthread_mutex_init(&ps->mutex, 0) != 0) {
+ ACR_THROW_NET_ERRNO();
+ pthread_cond_destroy(&ps->wakeup);
+ goto cleanup;
+ }
+ return P2J(ps);
+
+cleanup:
+ AcrFree(ps->fdset);
+ AcrFree(ps->ooset);
+ AcrFree(ps);
+ return 0;
+}
+
+ACR_NET_EXPORT(void, Poll, free0)(JNI_STDARGS, jlong pollset)
+{
+ int i;
+ acr_pollset_t *ps = J2P(pollset, acr_pollset_t *);
+
+ pthread_mutex_lock(&ps->mutex);
+ if (ps->state != 0) {
+ int state = ps->state;
+ ps->state = PSS_DESTROY;
+ if (state == PSS_POLL) {
+ char ch = 1;
+ r_write(ps->wpipe[1], &ch, 1);
+ }
+ /* Wait until the wait0 call breaks.
+ * Since we set the state to DESTROY
+ * wait0 will return 0.
+ */
+ if (pthread_cond_wait(&ps->wakeup, &ps->mutex) != 0) {
+ pthread_mutex_unlock(&ps->mutex);
+ ACR_THROW(ACR_EX_EILLEGAL, 0);
+ return;
+ }
+ }
+ ps->state = PSS_DESTROY;
+ pthread_mutex_unlock(&ps->mutex);
+ for (i = 0; i < ps->used; i++) {
+ if (ps->ooset[i].obj != 0) {
+ /* XXX: Invalidate the container. */
+ }
+ }
+ r_close(ps->wpipe[0]);
+ r_close(ps->wpipe[1]);
+ pthread_cond_destroy(&ps->wakeup);
+ pthread_mutex_destroy(&ps->mutex);
+ AcrFree(ps->fdset);
+ AcrFree(ps->ooset);
+ AcrFree(ps);
+}
+
+ACR_NET_EXPORT(jint, Poll, clear0)(JNI_STDARGS, jlong pollset,
+ jobjectArray rs)
+{
+ int i;
+ int cnt = 0;
+ acr_pollset_t *ps = J2P(pollset, acr_pollset_t *);
+
+ pthread_mutex_lock(&ps->mutex);
+ while (ps->state != 0) {
+ if (ps->state == PSS_DESTROY) {
+ /* Interrupted by free0 */
+ pthread_mutex_unlock(&ps->mutex);
+ return 0;
+ }
+ if (ps->state == PSS_POLL) {
+ char ch = 1;
+ ps->state = PSS_WAKEUP;
+ r_write(ps->wpipe[1], &ch, 1);
+ }
+ /* Wait until the wait0 call breaks.
+ * Since we set the state to DESTROY
+ * wait0 will return 0.
+ */
+ if (pthread_cond_wait(&ps->wakeup, &ps->mutex) != 0) {
+ pthread_mutex_unlock(&ps->mutex);
+ ACR_THROW(ACR_EX_EILLEGAL, 0);
+ return 0;
+ }
+ }
+ for (i = 1; i < ps->used; i++) {
+ (*env)->SetObjectArrayElement(env, rs, cnt++, ps->ooset[i].obj);
+ }
+ ps->used = 1;
+ pthread_mutex_unlock(&ps->mutex);
+ return cnt;
+}
+
+ACR_NET_EXPORT(void, Poll, wakeup0)(JNI_STDARGS, jlong pollset)
+{
+ acr_pollset_t *ps = J2P(pollset, acr_pollset_t *);
+
+ pthread_mutex_lock(&ps->mutex);
+ if (ps->state == PSS_POLL) {
+ char ch = 1;
+ ps->state = PSS_WAKEUP;
+ r_write(ps->wpipe[1], &ch, 1);
+ }
+ pthread_mutex_unlock(&ps->mutex);
+}
+
+ACR_NET_EXPORT(jint, Poll, wait0)(JNI_STDARGS, jlong pollset, jobjectArray rs,
+ jshortArray revents, jint timeout,
+ jboolean rmsignaled)
+{
+ int i, ns, rc = 0;
+ int rv = 0;
+ jshort *pevents;
+ acr_time_t now = 0;
+ acr_pollset_t *ps = J2P(pollset, acr_pollset_t *);
+
+ pthread_mutex_lock(&ps->mutex);
+ if (ps->state != 0) {
+ /* Note that this should never happen if api is correctly used.
+ * wait cannot be run from multiple threads and cannot be run
+ * after destroy.
+ */
+ pthread_mutex_unlock(&ps->mutex);
+ return 0;
+ }
+ if (ps->used == 1) {
+ /* We only have the wakeup pipe in the pollset
+ * so there is no point to wait.
+ */
+ pthread_mutex_unlock(&ps->mutex);
+ return 0;
+ }
+
+ ps->state = PSS_POLL;
+ pthread_mutex_unlock(&ps->mutex);
+ do {
+ ns = poll(ps->fdset, ps->used, timeout);
+ } while (ns == -1 && errno == EINTR);
+
+ if (ns == -1)
+ rc = ACR_GET_OS_ERROR();
+ pthread_mutex_lock(&ps->mutex);
+ if (ps->state == PSS_DESTROY) {
+ /* Interrupted by free0 */
+ pthread_cond_broadcast(&ps->wakeup);
+ pthread_mutex_unlock(&ps->mutex);
+ return 0;
+ }
+ if (rc != 0) {
+ /* Error during poll */
+ ps->state = 0;
+ pthread_cond_broadcast(&ps->wakeup);
+ pthread_mutex_unlock(&ps->mutex);
+ ACR_THROW_NET_ERROR(rc);
+ return 0;
+ }
+ if (ns == 0) {
+ /* Timeout occured */
+ ps->state = 0;
+ pthread_cond_broadcast(&ps->wakeup);
+ pthread_mutex_unlock(&ps->mutex);
+ return 0;
+ }
+ ps->state = PSS_WAIT;
+ pevents = JARRAY_CRITICAL(jshort, revents);
+ /* Cycle trough the descriptors */
+ for (i = 0; i < ps->used; i++) {
+ if (ps->fdset[i].revents != 0) {
+ if (i == 0) {
+ /* Drain the wakeup pipe.
+ * Wakeup pipe is always at index zero.
+ */
+ AcrDrainPipe(ps->wpipe[0]);
+ continue;
+ }
+ else {
+ pevents[rv] = reventt(ps->fdset[i].revents);
+ (*env)->SetObjectArrayElement(env, rs, rv++, ps->ooset[i].obj);
+ }
+ }
+ else {
+ if (now == 0)
+ now = AcrTimeNow();
+ if (ps->ooset[i].ttl > 0 && ps->ooset[i].ttl > now) {
+ /* Expired descriptor */
+ ps->fdset[i].revents = POLLHUP;
+ pevents[rv] = ACR_POLLTTL;
+ (*env)->SetObjectArrayElement(env, rs, rv++, ps->ooset[i].obj);
+ }
+ }
+ }
+ RELEASE_CRITICAL(revents, pevents);
+ if (rmsignaled == JNI_TRUE && rv > 0) {
+ /* Remove all descriptors with revents set except
+ * the wakeup pipe at index zero.
+ */
+ for (i = 1; i < ps->used; i++) {
+ if (ps->fdset[i].revents != 0) {
+ int dest = i;
+ int used = ps->used;
+ ps->used--;
+ for (++i; i < used; i++) {
+ if (ps->fdset[i].revents != 0) {
+ /* Skip signaled descriptor */
+ ps->used--;
+ }
+ else {
+ ps->fdset[dest] = ps->fdset[i];
+ ps->ooset[dest] = ps->ooset[i];
+ dest++;
+ }
+ }
+ }
+ }
+ }
+ ps->state = 0;
+ pthread_cond_broadcast(&ps->wakeup);
+ pthread_mutex_unlock(&ps->mutex);
+ return rv;
+}
+
+ACR_NET_EXPORT(jint, Poll, add0)(JNI_STDARGS, jlong pollset, jobject fo,
+ jint f, jint events, jint ttlms)
+{
+ int rc = 0;
+ acr_pollset_t *ps = J2P(pollset, acr_pollset_t *);
+
+ pthread_mutex_lock(&ps->mutex);
+ while (ps->state != 0) {
+ if (ps->state == PSS_DESTROY) {
+ rc = 0;
+ goto cleanup;
+ }
+ if (ps->state == PSS_POLL) {
+ char ch = 1;
+ ps->state = PSS_WAKEUP;
+ r_write(ps->wpipe[1], &ch, 1);
+ }
+ if ((rc = pthread_cond_wait(&ps->wakeup, &ps->mutex)) != 0)
+ goto cleanup;
+ }
+ if (ps->used == ps->size) {
+ /* Overflow
+ */
+ rc = ACR_EOVERFLOW;
+ goto cleanup;
+ }
+ ps->fdset[ps->used].fd = f;
+ ps->fdset[ps->used].events = ieventt(events);
+ ps->fdset[ps->used].revents = 0;
+ ps->ooset[ps->used].obj = fo;
+ if (ttlms > 0)
+ ps->ooset[ps->used].ttl = AcrTimeNow() + AcrTimeFromMsec(ttlms);
+ else
+ ps->ooset[ps->used].ttl = ACR_INFINITE;
+ ps->used++;
+cleanup:
+ pthread_mutex_unlock(&ps->mutex);
+ return rc;
+}
Propchange: commons/sandbox/runtime/trunk/src/main/native/os/unix/poll.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/util.c
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/util.c?rev=1104038&r1=1104037&r2=1104038&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/util.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/util.c Tue May 17
07:46:51 2011
@@ -297,6 +297,23 @@ finally:
return rc;
}
+void
+AcrDrainPipe(int fd)
+{
+ char rb[512];
+ ssize_t rd;
+
+ while ((rd = r_read(fd, rb, sizeof(rb))) > 0) {
+ /* Although we write just one byte to the other end of the pipe
+ * during wakeup, multiple threads could call the wakeup.
+ * So simply drain out from the input side of the pipe all
+ * the data.
+ */
+ if (rd != sizeof(rb))
+ break;
+ }
+}
+
#if defined(__NETBSD) || defined(__DARWIN)
static void avoid_zombies(int signo)
{
Modified: commons/sandbox/runtime/trunk/src/main/native/shared/error.c
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/error.c?rev=1104038&r1=1104037&r2=1104038&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/shared/error.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/shared/error.c Tue May 17
07:46:51 2011
@@ -30,6 +30,7 @@ static struct {
jclass clazz;
const char *name;
} _throw_classes[ACR_EX_LEN] = {
+ { 0, "java/lang/IllegalStateException" },
{ 0, "java/lang/InstatiationException" }, /* ENOINIT
*/
{ 0, "java/lang/RuntimeException" }, /* EGENERAL
*/
{ 0, "java/lang/OutOfMemoryError" }, /* ENOMEM
*/
Modified: commons/sandbox/runtime/trunk/src/main/native/shared/table.c
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/table.c?rev=1104038&r1=1104037&r2=1104038&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/shared/table.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/shared/table.c Tue May 17
07:46:51 2011
@@ -28,13 +28,11 @@ AcrTableInit(acr_table_t *arr, int nelts
celts = 8;
else
celts = ACR_ALIGN_DEFAULT(celts);
- if (celts > INT_MAX) {
- ACR_SET_OS_ERROR(ACR_ERANGE);
- return 0;
- }
+ if (celts > INT_MAX)
+ return ACR_ERANGE;
arr->elts = (char *)malloc(celts * esize);
if (arr->elts == 0)
- return ACR_GET_OS_ERROR();
+ return ACR_ENOMEM;
arr->nalloc = celts;
arr->esize = esize;
arr->nelts = 0;
@@ -77,14 +75,12 @@ AcrTableAdd(acr_table_t *arr)
arr->nalloc = 0;
}
if (arr->nelts == arr->nalloc) {
- acr_u32_t ns;
+ acr_u32_t ns = 4096 / arr->esize;
char *nd;
- if (arr->nalloc == 0)
+
+ if (ns < 8)
ns = 8;
- else if (arr->nalloc < 65536)
- ns = arr->nalloc * 2;
- else
- ns = arr->nalloc + 65536;
+ ns += arr->nalloc;
if (ns > INT_MAX) {
ACR_SET_OS_ERROR(ACR_ERANGE);
return 0;
@@ -126,15 +122,28 @@ AcrTableTop(acr_table_t *arr)
}
}
+int
+AcrTableDel(acr_table_t *arr, int e)
+{
+ if (arr == 0)
+ return ACR_EINVAL;
+ if (e >= arr->nelts)
+ return ACR_EOF;
+ if ((arr->nelts - e - 1) > 0)
+ memmove(arr->elts + (e * arr->esize),
+ arr->elts + ((e + 1) * arr->esize),
+ arr->esize * (arr->nelts - e - 1));
+ --arr->nelts;
+ return 0;
+}
+
void
AcrTableClear(acr_table_t *arr)
{
if (arr != 0) {
arr->nelts = 0;
- if ((arr->nalloc * arr->esize) > 65536) {
- AcrFree(arr->elts);
- arr->nalloc = 0;
- arr->elts = 0;
- }
+ AcrFree(arr->elts);
+ arr->nalloc = 0;
+ arr->elts = 0;
}
}