sync back up again with sofia tree prior to their release

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@4177 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Michael Jerris committed 2007-02-09 17:32:17 +00:00
1 parent f359f847f7
commit 666bd3bec3
55 files changed
+1807 -2097

No files matched your search

@@ -79,7 +79,7 @@ libsu_la_SOURCES = \
su_time.c su_time0.c \
su_wait.c su_root.c su_timer.c \
su_port.c su_port.h \
su_base_port.c su_pthread_port.c \
su_base_port.c su_pthread_port.c su_socket_port.c \
su_poll_port.c su_epoll_port.c su_select_port.c \
su_localinfo.c \
su_os_nw.c \
@@ -94,6 +94,7 @@ EXTRA_libsu_la_SOURCES = \
inet_ntop.c inet_pton.c poll.c getopt.c \
su_tag_ref.c su_win32_port.c
libsu_la_CFLAGS = $(AM_CFLAGS) $(SOFIA_CFLAGS)
libsu_la_LIBADD = $(REPLACE_LIBADD)
libsu_la_DEPENDENCIES = $(REPLACE_LIBADD)
+166 -171
View File
@@ -1,13 +1,20 @@
/* Copyright (C) 1994,1996,1997,1998,1999,2001,2002
Free Software Foundation, Inc.
This file is part of the GNU C Library.
/* This file is part of the Sofia-SIP package.
The GNU C Library is free software; you can redistribute it and/or
Copyright (C) 2005 Nokia Corporation.
Contact: Pekka Pessi <pekka.pessi@nokia.com>
This file is originally from GNU C library.
Copyright (C) 1994,1996,1997,1998,1999,2001,2002
Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
@@ -19,237 +26,225 @@
#include "config.h"
#if !HAVE_POLL && HAVE_SELECT && HAVE_POLL_PORT
#if HAVE_SELECT
#include "sofia-sip/su.h"
//extern __typeof(poll) __libc_poll;
#if 1
#include <alloca.h>
#include <string.h>
#include "sofia-sip/su_wait.h"
#ifndef __NFDBITS
#define NBBY 8 /* bits in a byte */
#define __NFDBITS (sizeof(__int32_t) * NBBY) /* bits per mask */
#endif
#undef NBBY
#undef NFDBITS
#undef FDSETSIZE
#undef roundup
#define NBBY 8 /* bits in a byte */
#define NFDBITS (sizeof(long) * NBBY) /* bits per mask */
#undef howmany
#define FDSETSIZE(n) (((n) + NFDBITS - 1) / NFDBITS * (NFDBITS / NBBY))
#define roundup(n, x) (((n) + (x) - 1) / (x) * (x))
#ifndef howmany
#define howmany(x, y) (((x)+((y)-1))/(y)) * sizeof(uint32_t)
#endif
/* Emulated poll() using select().
//libc_hidden_proto(memcpy)
//libc_hidden_proto(memset)
//libc_hidden_proto(getdtablesize)
//libc_hidden_proto(select)
This is used by su_wait().
/* uClinux 2.0 doesn't have poll, emulate it using select */
/* Poll the file descriptors described by the NFDS structures starting at
FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
an event to occur; if TIMEOUT is -1, block until an event occurs.
Returns the number of file descriptors with events, zero if timed out,
or -1 for errors. */
Poll the file descriptors described by the NFDS structures starting at
FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
an event to occur; if TIMEOUT is -1, block until an event occurs.
Returns the number of file descriptors with events, zero if timed out,
or -1 for errors. */
int poll(struct pollfd *fds, nfds_t nfds, int timeout)
{
struct timeval tv;
#if HAVE_ALLOCA_H
static int max_fd_size;
int bytes;
fd_set *rset, *wset, *xset;
#else
fd_set rset[1], wset[1], xset[1];
#endif
struct pollfd *f;
int ready;
int maxfd = 0;
struct timeval tv;
struct pollfd *f;
int ready;
int maxfd = 0;
#if HAVE_ALLOCA_H
if (!max_fd_size)
max_fd_size = getdtablesize ();
static int max_fd_size;
int bytes;
fd_set *rset, *wset, *xset;
bytes = howmany (max_fd_size, __NFDBITS);
if (!max_fd_size)
max_fd_size = getdtablesize ();
rset = alloca (bytes);
wset = alloca (bytes);
xset = alloca (bytes);
bytes = FDSETSIZE (max_fd_size);
/* We can't call FD_ZERO, since FD_ZERO only works with sets
of exactly __FD_SETSIZE size. */
memset (rset, 0, bytes);
memset (wset, 0, bytes);
memset (xset, 0, bytes);
rset = alloca (bytes);
wset = alloca (bytes);
xset = alloca (bytes);
/* We can't call FD_ZERO, since FD_ZERO only works with sets
of exactly __FD_SETSIZE size. */
memset (rset, 0, bytes);
memset (wset, 0, bytes);
memset (xset, 0, bytes);
#else
FD_ZERO(rset);
FD_ZERO(wset);
FD_ZERO(xset);
fd_set rset[1], wset[1], xset[1];
FD_ZERO(rset);
FD_ZERO(wset);
FD_ZERO(xset);
#endif
for (f = fds; f < &fds[nfds]; ++f)
for (f = fds; f < &fds[nfds]; ++f)
{
f->revents = 0;
if (f->fd >= 0)
f->revents = 0;
if (f->fd >= 0)
{
#if HAVE_ALLOCA_H
if (f->fd >= max_fd_size)
if (f->fd >= max_fd_size)
{
/* The user provides a file descriptor number which is higher
than the maximum we got from the `getdtablesize' call.
Maybe this is ok so enlarge the arrays. */
fd_set *nrset, *nwset, *nxset;
int nbytes;
/* The user provides a file descriptor number which is higher
than the maximum we got from the `getdtablesize' call.
Maybe this is ok so enlarge the arrays. */
fd_set *nrset, *nwset, *nxset;
int nbytes;
max_fd_size = roundup (f->fd, __NFDBITS);
nbytes = howmany (max_fd_size, __NFDBITS);
max_fd_size = roundup (f->fd, NFDBITS);
nbytes = FDSETSIZE (max_fd_size);
nrset = alloca (nbytes);
nwset = alloca (nbytes);
nxset = alloca (nbytes);
nrset = alloca (nbytes);
nwset = alloca (nbytes);
nxset = alloca (nbytes);
memset ((char *) nrset + bytes, 0, nbytes - bytes);
memset ((char *) nwset + bytes, 0, nbytes - bytes);
memset ((char *) nxset + bytes, 0, nbytes - bytes);
memset ((char *) nrset + bytes, 0, nbytes - bytes);
memset ((char *) nwset + bytes, 0, nbytes - bytes);
memset ((char *) nxset + bytes, 0, nbytes - bytes);
rset = memcpy (nrset, rset, bytes);
wset = memcpy (nwset, wset, bytes);
xset = memcpy (nxset, xset, bytes);
rset = memcpy (nrset, rset, bytes);
wset = memcpy (nwset, wset, bytes);
xset = memcpy (nxset, xset, bytes);
bytes = nbytes;
bytes = nbytes;
}
#else
if (f->fd >= FD_SETSIZE) {
errno = EBADF;
return -1;
}
if (f->fd >= FD_SETSIZE) {
errno = EBADF;
return -1;
}
#endif /* HAVE_ALLOCA_H */
if (f->events & POLLIN)
FD_SET (f->fd, rset);
if (f->events & POLLOUT)
FD_SET (f->fd, wset);
if (f->events & POLLPRI)
FD_SET (f->fd, xset);
if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
maxfd = f->fd;
if (f->events & POLLIN)
FD_SET (f->fd, rset);
if (f->events & POLLOUT)
FD_SET (f->fd, wset);
if (f->events & POLLPRI)
FD_SET (f->fd, xset);
if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
maxfd = f->fd;
}
}
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
while (1)
while (1)
{
ready = select (maxfd + 1, rset, wset, xset,
timeout == -1 ? NULL : &tv);
ready = select (maxfd + 1, rset, wset, xset,
timeout == -1 ? NULL : &tv);
/* It might be that one or more of the file descriptors is invalid.
We now try to find and mark them and then try again. */
if (ready == -1 && errno == EBADF)
/* It might be that one or more of the file descriptors is invalid.
We now try to find and mark them and then try again. */
if (ready == -1 && errno == EBADF)
{
struct timeval sngl_tv;
struct timeval sngl_tv;
#if HAVE_ALLOCA_H
fd_set *sngl_rset = alloca (bytes);
fd_set *sngl_wset = alloca (bytes);
fd_set *sngl_xset = alloca (bytes);
fd_set *sngl_rset = alloca (bytes);
fd_set *sngl_wset = alloca (bytes);
fd_set *sngl_xset = alloca (bytes);
/* Clear the original set. */
memset (rset, 0, bytes);
memset (wset, 0, bytes);
memset (xset, 0, bytes);
/* Clear the original set. */
memset (rset, 0, bytes);
memset (wset, 0, bytes);
memset (xset, 0, bytes);
#else
fd_set sngl_rset[1];
fd_set sngl_wset[1];
fd_set sngl_xset[1];
fd_set sngl_rset[1];
fd_set sngl_wset[1];
fd_set sngl_xset[1];
FD_ZERO(rset);
FD_ZERO(wset);
FD_ZERO(xset);
FD_ZERO(rset);
FD_ZERO(wset);
FD_ZERO(xset);
#endif
/* This means we don't wait for input. */
sngl_tv.tv_sec = 0;
sngl_tv.tv_usec = 0;
/* This means we don't wait for input. */
sngl_tv.tv_sec = 0;
sngl_tv.tv_usec = 0;
maxfd = -1;
maxfd = -1;
/* Reset the return value. */
ready = 0;
/* Reset the return value. */
ready = 0;
for (f = fds; f < &fds[nfds]; ++f)
if (f->fd != -1 && (f->events & (POLLIN|POLLOUT|POLLPRI))
&& (f->revents & POLLNVAL) == 0)
{
int n;
for (f = fds; f < &fds[nfds]; ++f)
if (f->fd != -1 && (f->events & (POLLIN|POLLOUT|POLLPRI))
&& (f->revents & POLLNVAL) == 0)
{
int n;
#if HAVE_ALLOCA_H
memset (sngl_rset, 0, bytes);
memset (sngl_wset, 0, bytes);
memset (sngl_xset, 0, bytes);
memset (sngl_rset, 0, bytes);
memset (sngl_wset, 0, bytes);
memset (sngl_xset, 0, bytes);
#else
FD_ZERO(rset);
FD_ZERO(wset);
FD_ZERO(xset);
FD_ZERO(rset);
FD_ZERO(wset);
FD_ZERO(xset);
#endif
if (f->events & POLLIN)
FD_SET (f->fd, sngl_rset);
if (f->events & POLLOUT)
FD_SET (f->fd, sngl_wset);
if (f->events & POLLPRI)
FD_SET (f->fd, sngl_xset);
if (f->events & POLLIN)
FD_SET (f->fd, sngl_rset);
if (f->events & POLLOUT)
FD_SET (f->fd, sngl_wset);
if (f->events & POLLPRI)
FD_SET (f->fd, sngl_xset);
n = select (f->fd + 1, sngl_rset, sngl_wset, sngl_xset,
n = select (f->fd + 1, sngl_rset, sngl_wset, sngl_xset,
&sngl_tv);
if (n != -1)
{
/* This descriptor is ok. */
if (f->events & POLLIN)
FD_SET (f->fd, rset);
if (f->events & POLLOUT)
FD_SET (f->fd, wset);
if (f->events & POLLPRI)
FD_SET (f->fd, xset);
if (f->fd > maxfd)
maxfd = f->fd;
if (n > 0)
/* Count it as being available. */
++ready;
}
else if (errno == EBADF)
f->revents |= POLLNVAL;
}
/* Try again. */
continue;
if (n != -1)
{
/* This descriptor is ok. */
if (f->events & POLLIN)
FD_SET (f->fd, rset);
if (f->events & POLLOUT)
FD_SET (f->fd, wset);
if (f->events & POLLPRI)
FD_SET (f->fd, xset);
if (f->fd > maxfd)
maxfd = f->fd;
if (n > 0)
/* Count it as being available. */
++ready;
}
else if (errno == EBADF)
f->revents |= POLLNVAL;
}
/* Try again. */
continue;
}
break;
break;
}
if (ready > 0)
for (f = fds; f < &fds[nfds]; ++f)
{
if (f->fd >= 0)
{
if (FD_ISSET (f->fd, rset))
f->revents |= POLLIN;
if (FD_ISSET (f->fd, wset))
f->revents |= POLLOUT;
if (FD_ISSET (f->fd, xset))
f->revents |= POLLPRI;
}
}
if (ready > 0)
for (f = fds; f < &fds[nfds]; ++f)
{
if (f->fd >= 0)
{
if (FD_ISSET (f->fd, rset))
f->revents |= POLLIN;
if (FD_ISSET (f->fd, wset))
f->revents |= POLLOUT;
if (FD_ISSET (f->fd, xset))
f->revents |= POLLPRI;
}
}
return ready;
return ready;
}
#endif
#endif
+19 -4
View File
@@ -2,18 +2,33 @@
rc=0
run=no
for SU_PORT in select epoll poll ; do
export SU_PORT
grep -q -i '^#define have_'$SU_PORT ../../config.h ||
continue
run=yes
if $VALGRIND ./test_su ; then
echo PASS: multithread test_su
echo PASS: multithread test_su with $SU_PORT
else
echo FAIL: multithread test_su failed
echo FAIL: multithread test_su with $SU_PORT failed
rc=1
fi
if $VALGRIND ./test_su -s ; then
echo PASS: singlethread test_su
echo PASS: singlethread test_su with $SU_PORT
else
echo FAIL: singlethread test_su failed
echo FAIL: singlethread test_su with $SU_PORT failed
rc=1
fi
done
test $run = no && exit 77
exit $rc
@@ -512,6 +512,31 @@ SOFIAPUBFUN void su_clone_wait(su_root_t *root, su_clone_r clone);
SOFIAPUBFUN int su_clone_pause(su_clone_r);
SOFIAPUBFUN int su_clone_resume(su_clone_r);
/* ---------------------------------------------------------------------- */
/* Different su_root_t implementations */
typedef su_port_t *su_port_create_f(void);
typedef int su_clone_start_f(su_root_t *parent,
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit);
SOFIAPUBFUN void su_port_prefer(su_port_create_f *f, su_clone_start_f *);
SOFIAPUBFUN su_port_create_f su_default_port_create;
SOFIAPUBFUN su_port_create_f su_epoll_port_create;
SOFIAPUBFUN su_port_create_f su_poll_port_create;
SOFIAPUBFUN su_port_create_f su_wsaevent_port_create;
SOFIAPUBFUN su_port_create_f su_select_port_create;
SOFIAPUBFUN su_clone_start_f su_default_clone_start;
SOFIAPUBFUN su_clone_start_f su_epoll_clone_start;
SOFIAPUBFUN su_clone_start_f su_poll_clone_start;
SOFIAPUBFUN su_clone_start_f su_wsaevent_clone_start;
SOFIAPUBFUN su_clone_start_f su_select_clone_start;
SOFIA_END_DECLS
#endif /* SU_WAIT_H */
@@ -1,7 +1,7 @@
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2005 Nokia Corporation.
* Copyright (C) 2005, 2006, 2007 Nokia Corporation.
*
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
*
@@ -23,18 +23,28 @@
*/
/**@ingroup su_wait
* @CFILE su_poll_port.c
* @CFILE su_epoll_port.c
*
* Port implementation using poll()
* Port implementation using epoll(7)
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Kai Vehmanen <kai.vehmanen@nokia.com>
*
* @date Created: Tue Sep 14 15:51:04 1999 ppessi
* @date Created: Fri Jan 26 20:44:14 2007 ppessi
* @date Original: Tue Sep 14 15:51:04 1999 ppessi
*/
#include "config.h"
#define su_port_s su_epoll_port_s
#include "su_port.h"
#if HAVE_EPOLL
#include "sofia-sip/su.h"
#include "sofia-sip/su_alloc.h"
#include <stdlib.h>
#include <assert.h>
#include <stdarg.h>
@@ -43,14 +53,6 @@
#include <limits.h>
#include <errno.h>
#define su_port_s su_poll_port_s
#include "sofia-sip/su.h"
#include "su_port.h"
#include "sofia-sip/su_alloc.h"
#if HAVE_EPOLL
#include <sys/epoll.h>
#define POLL2EPOLL_NEEDED \
@@ -62,8 +64,8 @@
/** Port based on epoll(). */
struct su_poll_port_s {
su_pthread_port_t sup_base[1];
struct su_epoll_port_s {
su_socket_port_t sup_base[1];
/** epoll fd */
int sup_epoll;
@@ -88,7 +90,9 @@ struct su_poll_port_s {
} **sup_indices;
};
static void su_epoll_port_decref(su_port_t *self, int blocking, char const *who);
static void su_epoll_port_decref(su_port_t *self,
int blocking,
char const *who);
static int su_epoll_port_register(su_port_t *self,
su_root_t *root,
su_wait_t *wait,
@@ -118,7 +122,7 @@ su_port_vtable_t const su_epoll_port_vtable[1] =
su_base_port_incref,
su_epoll_port_decref,
su_base_port_gsource,
su_pthread_port_send,
su_socket_port_send,
su_epoll_port_register,
su_epoll_port_unregister,
su_epoll_port_deregister,
@@ -159,7 +163,7 @@ static void su_epoll_port_deinit(void *arg)
SU_DEBUG_9(("%s(%p) called\n", "su_epoll_port_deinit", (void* )self));
su_pthread_port_deinit(self);
su_socket_port_deinit(self->sup_base);
close(self->sup_epoll), self->sup_epoll = -1;
}
@@ -434,9 +438,9 @@ int su_epoll_port_eventmask(su_port_t *self, int index, int socket, int events)
ev.data.u64 = (uint64_t)0;
ev.data.u32 = (uint32_t)index;
if (epoll_ctl(self->sup_epoll, EPOLL_CTL_MOD, ser->ser_wait->fd, &ev) == -1) {
if (epoll_ctl(self->sup_epoll, EPOLL_CTL_MOD, socket, &ev) == -1) {
SU_DEBUG_1(("su_port(%p): EPOLL_CTL_MOD(%u): %s\n", (void *)self,
ser->ser_wait->fd, su_strerror(su_errno())));
socket, su_strerror(su_errno())));
return -1;
}
@@ -449,7 +453,7 @@ int su_epoll_port_eventmask(su_port_t *self, int index, int socket, int events)
* multishot mode determines how the events are scheduled by port. If
* multishot mode is enabled, port serves all the sockets that have received
* network events. If it is disabled, only first socket event is served.
p *
*
* @param self pointer to port object
* @param multishot multishot mode (0 => disables, 1 => enables, -1 => query)
*
@@ -547,7 +551,7 @@ su_port_t *su_epoll_port_create(void)
self->sup_epoll = epoll;
self->sup_multishot = SU_ENABLE_MULTISHOT_POLL;
if (su_pthread_port_init(self, su_epoll_port_vtable) < 0)
if (su_socket_port_init(self->sup_base, su_epoll_port_vtable) < 0)
return su_home_unref(su_port_home(self)), NULL;
return self;
@@ -562,22 +566,21 @@ int su_epoll_clone_start(su_root_t *parent,
return su_pthreaded_port_start(su_epoll_port_create,
parent, return_clone, magic, init, deinit);
}
#else
su_port_t *su_epoll_port_create(void)
{
return su_poll_port_create();
return su_default_port_create();
}
int su_epoll_clone_start(su_root_t *parent,
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit)
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit)
{
return su_pthreaded_port_start(su_poll_port_create,
parent, return_clone, magic, init, deinit);
return su_default_clone_start(parent, return_clone, magic, init, deinit);
}
#endif /* HAVE_EPOLL */
@@ -1199,7 +1199,7 @@ static
int win_localinfo(su_localinfo_t const hints[1], su_localinfo_t **rresult)
{
/* This is Windows XP code, for both IPv6 and IPv4. */
size_t iaa_size = 2048;
ULONG iaa_size = 2048;
IP_ADAPTER_ADDRESSES *iaa0, *iaa;
int error, loopback_seen = 0;
int v4_mapped = (hints->li_flags & LI_V4MAPPED) != 0;
@@ -1208,7 +1208,7 @@ int win_localinfo(su_localinfo_t const hints[1], su_localinfo_t **rresult)
int flags = GAA_FLAG_SKIP_MULTICAST;
*rresult = NULL; next = rresult;
iaa0 = malloc(iaa_size);
iaa0 = malloc((size_t)iaa_size);
if (!iaa0) {
SU_DEBUG_1(("su_localinfo: memory exhausted\n"));
error = ELI_MEMORY;
@@ -1229,7 +1229,7 @@ int win_localinfo(su_localinfo_t const hints[1], su_localinfo_t **rresult)
IP_ADAPTER_UNICAST_ADDRESS *ua;
IP_ADAPTER_UNICAST_ADDRESS lua[1];
int if_index = iaa->IfIndex;
int ifnamelen = 0;
size_t ifnamelen = 0;
char ifname[16];
for (ua = iaa->FirstUnicastAddress; ;ua = ua->Next) {
File diff suppressed because it is too large. Load diff
@@ -30,12 +30,19 @@
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Kai Vehmanen <kai.vehmanen@nokia.com>
*
* @date Created: Tue Sep 14 15:51:04 1999 ppessi
* @date Create: Fri Jan 26 20:44:14 2007 ppessi
* @date Original: Tue Sep 14 15:51:04 1999 ppessi
*/
#include "config.h"
#if HAVE_POLL || HAVE_SELECT
#define su_port_s su_poll_port_s
#include "su_port.h"
#include "sofia-sip/su_alloc.h"
#include "sofia-sip/su.h"
#if HAVE_POLL_PORT
#include <stdlib.h>
#include <assert.h>
@@ -45,18 +52,12 @@
#include <limits.h>
#include <errno.h>
#define su_port_s su_poll_port_s
#include "sofia-sip/su.h"
#include "su_port.h"
#include "sofia-sip/su_alloc.h"
/** Port based on poll(). */
struct su_poll_port_s {
su_pthread_port_t sup_base[1];
su_socket_port_t sup_base[1];
#define sup_home sup_base->sup_base->sup_home
#define sup_home sup_base->sup_base->sup_base->sup_home
unsigned sup_multishot; /**< Multishot operation? */
@@ -69,12 +70,7 @@ struct su_poll_port_s {
int sup_size_waits; /**< Size of allocated su_waits */
int sup_pri_offset; /**< Offset to prioritized waits */
#if !SU_HAVE_WINSOCK
#define INDEX_MAX (0x7fffffff)
#else
/* We use WSAWaitForMultipleEvents() */
#define INDEX_MAX (64)
#endif
/** Indices from index returned by su_root_register() to tables below.
*
@@ -124,7 +120,7 @@ su_port_vtable_t const su_poll_port_vtable[1] =
su_base_port_incref,
su_poll_port_decref,
su_base_port_gsource,
su_pthread_port_send,
su_socket_port_send,
su_poll_port_register,
su_poll_port_unregister,
su_poll_port_deregister,
@@ -160,7 +156,7 @@ static void su_poll_port_deinit(void *arg)
SU_DEBUG_9(("%s(%p) called\n", "su_poll_port_deinit", (void *)self));
su_pthread_port_deinit(self);
su_socket_port_deinit(self->sup_base);
}
static void su_poll_port_decref(su_port_t *self, int blocking, char const *who)
@@ -516,8 +512,8 @@ int su_poll_port_unregister_all(su_port_t *self,
/**Set mask for a registered event. @internal
*
* The function su_poll_port_eventmask() sets the mask describing events that can
* signal the registered callback.
* The function su_poll_port_eventmask() sets the mask describing events
* that can signal the registered callback.
*
* @param port pointer to port object
* @param index registration index
@@ -663,7 +659,7 @@ su_port_t *su_poll_port_create(void)
self->sup_multishot = SU_ENABLE_MULTISHOT_POLL;
if (su_pthread_port_init(self, su_poll_port_vtable) < 0)
if (su_socket_port_init(self->sup_base, su_poll_port_vtable) < 0)
return su_home_unref(su_port_home(self)), NULL;
return self;
@@ -675,8 +671,25 @@ int su_poll_clone_start(su_root_t *parent,
su_root_init_f init,
su_root_deinit_f deinit)
{
return su_pthreaded_port_start(su_poll_port_create,
return su_pthreaded_port_start(su_default_port_create,
parent, return_clone, magic, init, deinit);
}
#endif /* HAVE_POLL || HAVE_SELECT */
#else
su_port_t *su_poll_port_create(void)
{
return su_default_port_create();
}
int su_poll_clone_start(su_root_t *parent,
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit)
{
return su_default_clone_start(parent, return_clone, magic, init, deinit);
}
#endif /* HAVE_POLL_PORT */
+58 -28
View File
@@ -48,7 +48,43 @@
#include <string.h>
#include <stdlib.h>
static su_port_create_f *preferred_su_port_create;
/** Create the default su_port_t implementation. */
su_port_t *su_default_port_create(void)
{
#if HAVE_EPOLL
return su_epoll_port_create();
#elif HAVE_POLL_PORT
return su_poll_port_create();
#elif HAVE_WIN32
return su_wsaevent_port_create();
#elif HAVE_SELECT
return su_select_port_create();
#else
return NULL;
#endif
}
int su_default_clone_start(su_root_t *parent,
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit)
{
#if HAVE_EPOLL
return su_epoll_clone_start(parent, return_clone, magic, init, deinit);;
#elif HAVE_POLL_PORT
return su_poll_clone_start(parent, return_clone, magic, init, deinit);;
#elif HAVE_WIN32
return su_wsaevent_clone_start(parent, return_clone, magic, init, deinit);;
#elif HAVE_SELECT
return su_select_clone_start(parent, return_clone, magic, init, deinit);;
#else
errno = ENOSYS;
return -1;
#endif
}
static su_port_create_f *preferred_su_port_create = su_default_port_create;
static su_clone_start_f *preferred_su_clone_start;
/** Explicitly set the preferred su_port_t implementation.
@@ -69,45 +105,44 @@ void su_port_set_system_preferences(char const *name)
if (name == NULL)
;
#if HAVE_POLL_PORT
#if HAVE_EPOLL
else if (strcmp(name, "epoll") == 0) {
create = su_epoll_port_create;
start = su_epoll_clone_start;
}
#endif
#if HAVE_POLL_PORT
else if (strcmp(name, "poll") == 0) {
create = su_poll_port_create;
start = su_poll_clone_start;
}
#else
/* select port does not work yet */
#error no poll!
#endif
#if HAVE_SELECT
#if HAVE_WIN32
else if (strcasecmp(name, "wsaevent") == 0) {
create = su_wsaevent_port_create;
start = su_wsaevent_clone_start;
}
#endif
#if HAVE_SELECT && !HAVE_WIN32
else if (strcmp(name, "select") == 0) {
create = su_select_port_create;
start = su_select_clone_start;
}
#endif
#if HAVE_POLL_PORT
#if HAVE_EPOLL
if (create == NULL) create = su_epoll_port_create;
if (start == NULL) start = su_epoll_clone_start;
#else
if (create == NULL) create = su_poll_port_create;
if (start == NULL) start = su_poll_clone_start;
#endif
#else
#if HAVE_SELECT
if (create == NULL) create = su_select_port_create;
if (start == NULL) start = su_select_clone_start;
#endif
#endif
if (create == NULL)
create = su_default_port_create;
if (preferred_su_port_create == NULL) preferred_su_port_create = create;
if (preferred_su_clone_start == NULL) preferred_su_clone_start = start;
if (!preferred_su_port_create ||
preferred_su_port_create == su_default_port_create)
preferred_su_port_create = create;
if (start == NULL)
start = su_default_clone_start;
if (!preferred_su_clone_start ||
preferred_su_clone_start == su_default_clone_start)
preferred_su_clone_start = start;
}
/** Create the preferred su_port_t implementation. */
@@ -116,10 +151,7 @@ su_port_t *su_port_create(void)
if (preferred_su_port_create == NULL)
su_port_set_system_preferences(getenv("SU_PORT"));
if (preferred_su_port_create)
return preferred_su_port_create();
return NULL;
return preferred_su_port_create();
}
/* ========================================================================
@@ -244,8 +276,6 @@ int su_clone_start(su_root_t *parent,
if (parent == NULL || parent->sur_threading) {
if (preferred_su_clone_start == NULL)
su_port_set_system_preferences(getenv("SU_PORT"));
if (preferred_su_clone_start == NULL)
return -1;
return preferred_su_clone_start(parent, return_clone, magic, init, deinit);
}
+18 -27
View File
@@ -152,26 +152,6 @@ SOFIAPUBFUN su_port_t *su_port_create(void)
/* Extension from >= 1.12.5 */
typedef su_port_t *su_port_create_f(void);
typedef int su_clone_start_f(su_root_t *parent,
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit);
SOFIAPUBFUN void su_port_prefer(su_port_create_f *f, su_clone_start_f *);
SOFIAPUBFUN su_port_t *su_epoll_port_create(void)
__attribute__((__malloc__));
SOFIAPUBFUN su_port_t *su_poll_port_create(void)
__attribute__((__malloc__));
SOFIAPUBFUN su_port_t *su_select_port_create(void)
__attribute__((__malloc__));
SOFIAPUBFUN su_clone_start_f su_epoll_clone_start;
SOFIAPUBFUN su_clone_start_f su_poll_clone_start;
SOFIAPUBFUN su_clone_start_f su_select_clone_start;
SOFIAPUBFUN void su_msg_delivery_report(su_msg_r msg);
SOFIAPUBFUN su_duration_t su_timer_next_expires(su_timer_t const * t,
su_time_t now);
@@ -518,22 +498,18 @@ SOFIAPUBFUN void su_base_port_wait(su_clone_r rclone);
#include <pthread.h>
#define SU_MBOX_SIZE 2
/** Pthread port object */
typedef struct su_pthread_port_s {
su_base_port_t sup_base[1];
struct su_pthread_port_waiting_parent
*sup_waiting_parent;
pthread_t sup_tid;
pthread_mutex_t sup_runlock[1];
#if 0
pthread_mutex_t sup_runlock[1];
pthread_cond_t sup_resume[1];
short sup_paused; /**< True if thread is paused */
#endif
short sup_thread; /**< True if thread is active */
short sup_mbox_index;
su_socket_t sup_mbox[SU_MBOX_SIZE];
} su_pthread_port_t;
/* Pthread methods */
@@ -546,9 +522,9 @@ SOFIAPUBFUN void su_pthread_port_unlock(su_port_t *self, char const *who);
SOFIAPUBFUN int su_pthread_port_own_thread(su_port_t const *self);
#if 0 /* not yet */
SOFIAPUBFUN int su_pthread_port_send(su_port_t *self, su_msg_r rmsg);
#if 0 /* not yet */
SOFIAPUBFUN su_port_t *su_pthread_port_create(void);
SOFIAPUBFUN su_port_t *su_pthread_port_start(su_root_t *parent,
su_clone_r return_clone,
@@ -584,12 +560,27 @@ typedef su_base_port_t su_pthread_port_t;
#define su_pthread_port_lock su_base_port_lock
#define su_pthread_port_unlock su_base_port_unlock
#define su_pthread_port_own_thread su_base_port_own_thread
#define su_pthread_port_send su_base_port_send
#define su_pthread_port_wait su_base_port_wait
#define su_pthread_port_execute su_base_port_execute
#endif
/* ====================================================================== */
/* Mailbox port using sockets */
#define SU_MBOX_SIZE 2
typedef struct su_socket_port_s {
su_pthread_port_t sup_base[1];
int sup_mbox_index;
su_socket_t sup_mbox[SU_MBOX_SIZE];
} su_socket_port_t;
SOFIAPUBFUN int su_socket_port_init(su_socket_port_t *,
su_port_vtable_t const *);
SOFIAPUBFUN void su_socket_port_deinit(su_socket_port_t *self);
SOFIAPUBFUN int su_socket_port_send(su_port_t *self, su_msg_r rmsg);
SOFIA_END_DECLS
#endif /* SU_PORT_H */
@@ -61,24 +61,6 @@
#define SU_TASK_COPY(d, s, by) (void)((d)[0]=(s)[0], \
(s)->sut_port?(void)su_port_incref(s->sut_port, #by):(void)0)
#if HAVE_SOCKETPAIR
#define SU_MBOX_SEND 1
#else
#define SU_MBOX_SEND 0
#endif
/** @internal Message box wakeup function. */
static int su_mbox_port_wakeup(su_root_magic_t *magic, /* NULL */
su_wait_t *w,
su_wakeup_arg_t *arg)
{
char buf[32];
su_socket_t socket = *(su_socket_t*)arg;
su_wait_events(w, socket);
recv(socket, buf, sizeof(buf), 0);
return 0;
}
/**@internal
*
* Initializes a message port. It creates a mailbox used to wake up the
@@ -90,93 +72,14 @@ int su_pthread_port_init(su_port_t *self, su_port_vtable_t const *vtable)
SU_DEBUG_9(("su_pthread_port_init(%p, %p) called\n",
(void *)self, (void *)vtable));
self->sup_tid = pthread_self();
if (su_base_port_init(self, vtable) == 0 &&
su_base_port_threadsafe(self) == 0) {
int af;
su_socket_t mb = INVALID_SOCKET;
su_wait_t wait[1] = { SU_WAIT_INIT };
char const *why;
self->sup_tid = pthread_self();
#if 0
pthread_mutex_init(self->sup_runlock, NULL);
pthread_mutex_lock(self->sup_runlock);
pthread_cond_init(self->sup_resume, NULL);
#endif
#if HAVE_SOCKETPAIR
#if defined(AF_LOCAL)
af = AF_LOCAL;
#else
af = AF_UNIX;
#endif
if (socketpair(af, SOCK_STREAM, 0, self->sup_mbox) == -1) {
why = "socketpair"; goto error;
}
mb = self->sup_mbox[0];
su_setblocking(self->sup_mbox[1], 0);
#else
{
struct sockaddr_in sin = { sizeof(struct sockaddr_in), 0 };
socklen_t sinsize = sizeof sin;
struct sockaddr *sa = (struct sockaddr *)&sin;
af = PF_INET;
self->sup_mbox[0] = mb = su_socket(af, SOCK_DGRAM, IPPROTO_UDP);
if (mb == INVALID_SOCKET) {
why = "socket"; goto error;
}
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* 127.1 */
/* Get a port for us */
if (bind(mb, sa, sizeof sin) == -1) {
why = "bind"; goto error;
}
if (getsockname(mb, sa, &sinsize) == -1) {
why = "getsockname"; goto error;
}
if (connect(mb, sa, sinsize) == -1) {
why = "connect"; goto error;
}
}
#endif
su_setblocking(mb, 0);
if (su_wait_create(wait, mb, SU_WAIT_IN) == -1) {
why = "su_wait_create";
goto error;
}
self->sup_mbox_index = su_port_register(self, NULL, wait,
su_mbox_port_wakeup,
(void *)self->sup_mbox, 0);
if (self->sup_mbox_index <= 0) {
why = "su_port_register";
su_wait_destroy(wait);
goto error;
}
SU_DEBUG_9(("%s() returns %d\n", "su_pthread_port_init", 0));
return 0;
error:
su_log("%s: %s: %s\n",
"su_pthread_port_init", why, su_strerror(su_errno()));
su_pthread_port_deinit(self);
}
SU_DEBUG_9(("%s() returns %d\n", "su_pthread_port_init", -1));
else
su_base_port_deinit(self);
return -1;
}
@@ -187,17 +90,6 @@ void su_pthread_port_deinit(su_port_t *self)
{
assert(self);
if (self->sup_mbox_index > 0)
su_port_deregister(self, self->sup_mbox_index);
self->sup_mbox_index = 0;
if (self->sup_mbox[0] && self->sup_mbox[0] != INVALID_SOCKET)
su_close(self->sup_mbox[0]); self->sup_mbox[0] = INVALID_SOCKET;
#if HAVE_SOCKETPAIR
if (self->sup_mbox[1] && self->sup_mbox[1] != INVALID_SOCKET)
su_close(self->sup_mbox[1]); self->sup_mbox[1] = INVALID_SOCKET;
#endif
#if 0
pthread_mutex_destroy(self->sup_runlock);
pthread_cond_destroy(self->sup_resume);
@@ -225,27 +117,6 @@ void su_pthread_port_unlock(su_port_t *self, char const *who)
(void *)pthread_self(), who, self));
}
/** @internal Send a message to the port. */
int su_pthread_port_send(su_port_t *self, su_msg_r rmsg)
{
int wakeup = su_base_port_send(self, rmsg);
if (wakeup < 0)
return -1;
if (wakeup == 0)
return 0;
assert(self->sup_mbox[SU_MBOX_SEND] != INVALID_SOCKET);
if (send(self->sup_mbox[SU_MBOX_SEND], "X", 1, 0) == -1) {
#if HAVE_SOCKETPAIR
if (su_errno() != EWOULDBLOCK)
#endif
su_perror("su_msg_send: send()");
}
return 0;
}
/** @internal
* Checks if the calling thread owns the port object.
*
+334 -344
View File
@@ -25,12 +25,12 @@
/**@ingroup su_wait
* @CFILE su_select_port.c
*
* Port implementation using select(). NOT IMPLEMENTED YET!
* Port implementation using select().
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Kai Vehmanen <kai.vehmanen@nokia.com>
*
* @date Created: Tue Sep 14 15:51:04 1999 ppessi
* @date Created: Fri Jan 26 17:56:34 2007 ppessi
*/
#include "config.h"
@@ -51,63 +51,82 @@
#include <limits.h>
#include <errno.h>
#if HAVE_WIN32
#error winsock select() not supported yet
#else
#if HAVE_SYS_SELECT_H
#include <sys/select.h>
#elif HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <sys/types.h>
#include <unistd.h>
#ifndef __NFDBITS
#define __NFDBITS (8 * sizeof (long int))
#endif
#undef FDSETSIZE
/* Size of fd set in bytes */
#define FDSETSIZE(n) (((n) + __NFDBITS - 1) / __NFDBITS * (__NFDBITS / 8))
#endif
/** Port based on select(). */
struct su_select_port_s {
su_pthread_port_t sup_base[1];
su_socket_port_t sup_base[1];
#define sup_home sup_base->sup_base->sup_base->sup_home
/** epoll fd */
int sup_epoll;
unsigned sup_multishot; /**< Multishot operation? */
unsigned sup_registers; /** Counter incremented by
su_port_register() or
su_port_unregister()
*/
int sup_n_registrations;
int sup_max_index; /**< Indexes are equal or smaller than this */
int sup_size_indices; /**< Size of allocated index table */
int sup_n_waits; /**< Active su_wait_t in su_waits */
int sup_size_waits; /**< Size of allocated su_waits */
int sup_pri_offset; /**< Offset to prioritized waits */
/** Structure containing registration data */
struct su_select_register {
struct su_select_register *ser_next; /* Next in free list */
su_wakeup_f ser_cb;
su_wakeup_arg_t*ser_arg;
su_root_t *ser_root;
int ser_id; /** registration identifier */
su_wait_t ser_wait[1];
} **sup_indices;
/** Indices from index returned by su_root_register() to tables below.
*
* Free elements are negative. Free elements form a list, value of free
* element is (0 - index of next free element).
*
* First element sup_indices[0] points to first free element.
*/
int *sup_indices;
int *sup_reverses; /** Reverse index */
su_wakeup_f *sup_wait_cbs;
su_wakeup_arg_t**sup_wait_args;
su_root_t **sup_wait_roots;
su_wait_t *sup_waits;
int sup_maxfd, sup_allocfd;
fd_set *sup_readfds, *sup_readfds2;
fd_set *sup_writefds, *sup_writefds2;
};
static void su_select_port_decref(su_port_t *, int blocking, char const *who);
static void su_select_port_decref(su_port_t *self,
int blocking,
char const *who);
static int su_select_port_register(su_port_t *self,
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback,
su_wakeup_arg_t *arg,
int priority);
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback,
su_wakeup_arg_t *arg,
int priority);
static int su_select_port_unregister(su_port_t *port,
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback,
su_wakeup_arg_t *arg);
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback,
su_wakeup_arg_t *arg);
static int su_select_port_deregister(su_port_t *self, int i);
static int su_select_port_unregister_all(su_port_t *self, su_root_t *root);
static int su_select_port_eventmask(su_port_t *self,
int index,
int socket,
int events);
int index,
int socket,
int events);
static int su_select_port_multishot(su_port_t *self, int multishot);
static int su_select_port_wait_events(su_port_t *self, su_duration_t tout);
static char const *su_select_port_name(su_port_t const *self);
@@ -120,7 +139,7 @@ su_port_vtable_t const su_select_port_vtable[1] =
su_base_port_incref,
su_select_port_decref,
su_base_port_gsource,
su_pthread_port_send,
su_socket_port_send,
su_select_port_register,
su_select_port_unregister,
su_select_port_deregister,
@@ -142,7 +161,7 @@ su_port_vtable_t const su_select_port_vtable[1] =
su_select_port_name,
su_base_port_start_shared,
su_pthread_port_wait,
su_pthread_port_execute
su_pthread_port_execute,
}};
static char const *su_select_port_name(su_port_t const *self)
@@ -150,39 +169,23 @@ static char const *su_select_port_name(su_port_t const *self)
return "select";
}
static void su_select_port_decref(su_port_t *self, int blocking, char const *who)
{
(void)su_base_port_decref(self, blocking, who);
}
static void su_select_port_deinit(void *arg)
{
su_port_t *self = arg;
SU_DEBUG_9(("%s(%p) called\n", "su_select_port_deinit", (void *)self));
su_pthread_port_deinit(self);
if (self->sup_waits)
free(self->sup_waits), self->sup_waits = NULL;
if (self->sup_wait_cbs)
free(self->sup_wait_cbs), self->sup_wait_cbs = NULL;
if (self->sup_wait_args)
free(self->sup_wait_args), self->sup_wait_args = NULL;
if (self->sup_wait_roots)
free(self->sup_wait_roots), self->sup_wait_roots = NULL;
if (self->sup_reverses)
free(self->sup_reverses), self->sup_reverses = NULL;
if (self->sup_indices)
free(self->sup_indices), self->sup_indices = NULL;
SU_DEBUG_9(("%s(%p) freed registrations\n",
"su_select_port_deinit", (void *)self));
}
static void su_select_port_decref(su_port_t *self, int blocking, char const *who)
{
su_base_port_decref(self, blocking, who);
su_socket_port_deinit(self->sup_base);
}
/** @internal
*
* Register a @c su_wait_t object. The wait object, a callback function and
* Register a #su_wait_t object. The wait object, a callback function and
* an argument pointer is stored in the port object. The callback function
* will be called when the wait object is signaled.
*
@@ -202,179 +205,154 @@ static void su_select_port_decref(su_port_t *self, int blocking, char const *who
* or -1 upon an error.
*/
int su_select_port_register(su_port_t *self,
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback,
su_wakeup_arg_t *arg,
int priority)
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback,
su_wakeup_arg_t *arg,
int priority)
{
int i, j, n;
struct su_select_register *ser;
struct su_select_register **indices = self->sup_indices;
int allocfd = self->sup_allocfd;
fd_set *readfds = self->sup_readfds, *readfds2 = self->sup_readfds2;
fd_set *writefds = self->sup_writefds, *writefds2 = self->sup_writefds2;
assert(su_port_own_thread(self));
n = self->sup_n_waits;
n = self->sup_size_indices;
if (n >= SU_WAIT_MAX)
return su_seterrno(ENOMEM);
if (n >= self->sup_size_waits) {
/* Reallocate size arrays */
int size;
int *indices;
int *reverses;
su_wait_t *waits;
su_wakeup_f *wait_cbs;
su_wakeup_arg_t **wait_args;
su_root_t **wait_tasks;
if (self->sup_size_waits == 0)
size = su_root_size_hint;
else
size = 2 * self->sup_size_waits;
if (size < SU_WAIT_MIN)
size = SU_WAIT_MIN;
/* Too large */
if (-3 - size > 0)
return (errno = ENOMEM), -1;
indices = realloc(self->sup_indices, (size + 1) * sizeof(*indices));
if (indices) {
self->sup_indices = indices;
if (self->sup_size_waits == 0)
indices[0] = -1;
for (i = self->sup_size_waits + 1; i <= size; i++)
indices[i] = -1 - i;
}
reverses = realloc(self->sup_reverses, size * sizeof(*waits));
if (reverses) {
for (i = self->sup_size_waits; i < size; i++)
reverses[i] = -1;
self->sup_reverses = reverses;
}
waits = realloc(self->sup_waits, size * sizeof(*waits));
if (waits)
self->sup_waits = waits;
wait_cbs = realloc(self->sup_wait_cbs, size * sizeof(*wait_cbs));
if (wait_cbs)
self->sup_wait_cbs = wait_cbs;
wait_args = realloc(self->sup_wait_args, size * sizeof(*wait_args));
if (wait_args)
self->sup_wait_args = wait_args;
/* Add sup_wait_roots array, if needed */
wait_tasks = realloc(self->sup_wait_roots, size * sizeof(*wait_tasks));
if (wait_tasks)
self->sup_wait_roots = wait_tasks;
if (!(indices &&
reverses && waits && wait_cbs && wait_args && wait_tasks)) {
return -1;
}
self->sup_size_waits = size;
}
i = -self->sup_indices[0]; assert(i <= self->sup_size_waits);
if (priority > 0) {
/* Insert */
for (n = self->sup_n_waits; n > 0; n--) {
j = self->sup_reverses[n-1]; assert(self->sup_indices[j] == n - 1);
self->sup_indices[j] = n;
self->sup_reverses[n] = j;
self->sup_waits[n] = self->sup_waits[n-1];
self->sup_wait_cbs[n] = self->sup_wait_cbs[n-1];
self->sup_wait_args[n] = self->sup_wait_args[n-1];
self->sup_wait_roots[n] = self->sup_wait_roots[n-1];
}
self->sup_pri_offset++;
}
else {
/* Append - no need to move anything */
n = self->sup_n_waits;
}
self->sup_n_waits++;
self->sup_indices[0] = self->sup_indices[i]; /* Free index */
self->sup_indices[i] = n;
self->sup_reverses[n] = i;
self->sup_waits[n] = *wait;
self->sup_wait_cbs[n] = callback;
self->sup_wait_args[n] = arg;
self->sup_wait_roots[n] = root;
self->sup_registers++;
/* We return -1 or positive integer */
if (wait->fd >= allocfd)
allocfd += __NFDBITS; /* long at a time */
return i;
if (allocfd >= self->sup_allocfd) {
size_t bytes = FDSETSIZE(allocfd);
size_t bytes0 = FDSETSIZE(self->sup_allocfd);
/* (Re)allocate fd_sets */
readfds = su_realloc(self->sup_home, readfds, bytes);
if (readfds) self->sup_readfds = readfds;
readfds2 = su_realloc(self->sup_home, readfds2, bytes);
if (readfds2) self->sup_readfds2 = readfds2;
if (!readfds || !readfds2)
return -1;
writefds = su_realloc(self->sup_home, writefds, bytes);
if (writefds) self->sup_writefds = writefds;
writefds2 = su_realloc(self->sup_home, writefds2, bytes);
if (writefds2) self->sup_writefds2 = writefds2;
if (!writefds || !writefds2)
return -1;
memset((char *)readfds + bytes0, 0, bytes - bytes0);
memset((char *)writefds + bytes0, 0, bytes - bytes0);
self->sup_allocfd = allocfd;
}
ser = indices[0];
if (!ser) {
su_home_t *h = su_port_home(self);
i = self->sup_max_index, j = i == 0 ? 15 : i + 16;
if (j >= self->sup_size_indices) {
/* Reallocate index table */
n = n < 1024 ? 2 * n : n + 1024;
indices = su_realloc(h, indices, n * sizeof(indices[0]));
if (!indices)
return -1;
self->sup_indices = indices;
self->sup_size_indices = n;
}
/* Allocate registrations */
ser = su_zalloc(h, (j - i) * (sizeof *ser));
if (!ser)
return -1;
indices[0] = ser;
for (i++; i <= j; i++) {
ser->ser_id = i;
ser->ser_next = i < j ? ser + 1 : NULL;
indices[i] = ser++;
}
self->sup_max_index = j;
ser = indices[0];
}
i = ser->ser_id;
indices[0] = ser->ser_next;
ser->ser_next = NULL;
*ser->ser_wait = *wait;
ser->ser_cb = callback;
ser->ser_arg = arg;
ser->ser_root = root;
if (wait->events & SU_WAIT_IN)
FD_SET(wait->fd, readfds);
if (wait->events & SU_WAIT_OUT)
FD_SET(wait->fd, writefds);
if (wait->fd >= self->sup_maxfd)
self->sup_maxfd = wait->fd + 1;
self->sup_n_registrations++;
return i; /* return index */
}
static void su_select_port_update_maxfd(su_port_t *self)
{
int i;
su_socket_t maxfd = 0;
for (i = 1; i <= self->sup_max_index; i++) {
if (!self->sup_indices[i]->ser_cb)
continue;
if (maxfd <= self->sup_indices[i]->ser_wait->fd)
maxfd = self->sup_indices[i]->ser_wait->fd + 1;
}
self->sup_maxfd = maxfd;
}
/** Deregister a su_wait_t object. */
static int su_select_port_deregister0(su_port_t *self, int i, int destroy_wait)
{
int n, N, *indices, *reverses;
struct su_select_register **indices = self->sup_indices;
struct su_select_register *ser;
indices = self->sup_indices;
reverses = self->sup_reverses;
n = indices[i]; assert(n >= 0);
if (destroy_wait)
su_wait_destroy(&self->sup_waits[n]);
N = --self->sup_n_waits;
if (n < self->sup_pri_offset) {
int j = --self->sup_pri_offset;
if (n != j) {
assert(reverses[j] > 0);
assert(indices[reverses[j]] == j);
indices[reverses[j]] = n;
reverses[n] = reverses[j];
self->sup_waits[n] = self->sup_waits[j];
self->sup_wait_cbs[n] = self->sup_wait_cbs[j];
self->sup_wait_args[n] = self->sup_wait_args[j];
self->sup_wait_roots[n] = self->sup_wait_roots[j];
n = j;
}
ser = self->sup_indices[i];
if (ser == NULL || ser->ser_cb == NULL) {
su_seterrno(ENOENT);
return -1;
}
if (n < N) {
assert(reverses[N] > 0);
assert(indices[reverses[N]] == N);
assert(ser->ser_id == i);
indices[reverses[N]] = n;
reverses[n] = reverses[N];
FD_CLR(ser->ser_wait->fd, self->sup_readfds);
FD_CLR(ser->ser_wait->fd, self->sup_writefds);
self->sup_waits[n] = self->sup_waits[N];
self->sup_wait_cbs[n] = self->sup_wait_cbs[N];
self->sup_wait_args[n] = self->sup_wait_args[N];
self->sup_wait_roots[n] = self->sup_wait_roots[N];
n = N;
}
if (ser->ser_wait->fd + 1 >= self->sup_maxfd)
self->sup_maxfd = 0;
reverses[n] = -1;
memset(&self->sup_waits[n], 0, sizeof self->sup_waits[n]);
self->sup_wait_cbs[n] = NULL;
self->sup_wait_args[n] = NULL;
self->sup_wait_roots[n] = NULL;
indices[i] = indices[0];
indices[0] = -i;
memset(ser, 0, sizeof *ser);
ser->ser_id = i;
ser->ser_next = indices[0], indices[0] = ser;
self->sup_n_registrations--;
self->sup_registers++;
return i;
@@ -383,9 +361,9 @@ static int su_select_port_deregister0(su_port_t *self, int i, int destroy_wait)
/** Unregister a su_wait_t object.
*
* The function su_select_port_unregister() unregisters a su_wait_t object. The
* wait object, a callback function and a argument are removed from the
* port object.
* The function su_select_port_unregister() unregisters a su_wait_t object.
* The registration defined by the wait object, the callback function and
* the argument pointer are removed from the port object.
*
* @param self - pointer to port object
* @param root - pointer to root object
@@ -399,22 +377,27 @@ static int su_select_port_deregister0(su_port_t *self, int i, int destroy_wait)
* @return Nonzero index of the wait object, or -1 upon an error.
*/
int su_select_port_unregister(su_port_t *self,
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback, /* XXX - ignored */
su_wakeup_arg_t *arg)
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback, /* XXX - ignored */
su_wakeup_arg_t *arg)
{
int n, N;
int i, I;
struct su_select_register *ser;
assert(self);
assert(su_port_own_thread(self));
N = self->sup_n_waits;
I = self->sup_max_index;
for (n = 0; n < N; n++) {
if (SU_WAIT_CMP(wait[0], self->sup_waits[n]) == 0) {
return su_select_port_deregister0(self, self->sup_reverses[n], 0);
}
for (i = 1; i <= I; i++) {
ser = self->sup_indices[i];
if (ser->ser_cb &&
arg == ser->ser_arg &&
SU_WAIT_CMP(wait[0], ser->ser_wait[0]) == 0)
return su_select_port_deregister0(self, ser->ser_id, 0);
}
su_seterrno(ENOENT);
@@ -435,100 +418,56 @@ int su_select_port_unregister(su_port_t *self,
*/
int su_select_port_deregister(su_port_t *self, int i)
{
su_wait_t wait[1] = { SU_WAIT_INIT };
int retval;
struct su_select_register *ser;
assert(self);
assert(su_port_own_thread(self));
if (i <= 0 || i > self->sup_size_waits)
if (i <= 0 || i > self->sup_max_index)
return su_seterrno(EBADF);
if (self->sup_indices[i] < 0)
ser = self->sup_indices[i];
if (!ser->ser_cb)
return su_seterrno(EBADF);
retval = su_select_port_deregister0(self, i, 1);
su_wait_destroy(wait);
return retval;
return su_select_port_deregister0(self, i, 1);
}
/** @internal
* Unregister all su_wait_t objects.
* Unregister all su_wait_t objects of given su_root_t instance.
*
* The function su_select_port_unregister_all() unregisters all su_wait_t objects
* and destroys all queued timers associated with given root object.
* The function su_select_port_unregister_all() unregisters all su_wait_t
* objects associated with given root object.
*
* @param self - pointer to port object
* @param root - pointer to root object
*
* @return Number of wait objects removed.
*/
int su_select_port_unregister_all(su_port_t *self,
su_root_t *root)
int su_select_port_unregister_all(su_port_t *self, su_root_t *root)
{
int i, j, index, N;
int *indices, *reverses;
su_wait_t *waits;
su_wakeup_f *wait_cbs;
su_wakeup_arg_t**wait_args;
su_root_t **wait_roots;
int i, I, n;
struct su_select_register *ser;
assert(self); assert(root);
assert(su_port_own_thread(self));
N = self->sup_n_waits;
indices = self->sup_indices;
reverses = self->sup_reverses;
waits = self->sup_waits;
wait_cbs = self->sup_wait_cbs;
wait_args = self->sup_wait_args;
wait_roots = self->sup_wait_roots;
for (i = j = 0; i < N; i++) {
index = reverses[i]; assert(index > 0 && indices[index] == i);
I = self->sup_max_index;
if (wait_roots[i] == root) {
/* XXX - we should free all resources associated with this, too */
if (i < self->sup_pri_offset)
self->sup_pri_offset--;
indices[index] = indices[0];
indices[0] = -index;
for (i = 1, n = 0; i <= I; i++) {
ser = self->sup_indices[i];
if (ser->ser_root != root)
continue;
}
if (i != j) {
indices[index] = j;
reverses[j] = reverses[i];
waits[j] = waits[i];
wait_cbs[j] = wait_cbs[i];
wait_args[j] = wait_args[i];
wait_roots[j] = wait_roots[i];
}
j++;
su_select_port_deregister0(self, ser->ser_id, 0);
n++;
}
for (i = j; i < N; i++) {
reverses[i] = -1;
wait_cbs[i] = NULL;
wait_args[i] = NULL;
wait_roots[i] = NULL;
}
memset(&waits[j], 0, (char *)&waits[N] - (char *)&waits[j]);
self->sup_n_waits = j;
self->sup_registers++;
return N - j;
return n;
}
/**Set mask for a registered event. @internal
*
* The function su_select_port_eventmask() sets the mask describing events that can
* signal the registered callback.
* The function su_select_port_eventmask() sets the mask describing events
* that can signal the registered callback.
*
* @param port pointer to port object
* @param index registration index
@@ -538,19 +477,41 @@ int su_select_port_unregister_all(su_port_t *self,
* @retval 0 when successful,
* @retval -1 upon an error.
*/
int su_select_port_eventmask(su_port_t *self, int index, int socket, int events)
int su_select_port_eventmask(su_port_t *self,
int index,
int socket, int events)
{
int n;
assert(self);
assert(su_port_own_thread(self));
struct su_select_register *ser;
if (index <= 0 || index > self->sup_size_waits)
return su_seterrno(EBADF);
n = self->sup_indices[index];
if (n < 0)
if (index <= 0 || index > self->sup_max_index)
return su_seterrno(EBADF);
return su_wait_mask(&self->sup_waits[n], socket, events);
ser = self->sup_indices[index];
if (!ser->ser_cb)
return su_seterrno(EBADF);
if (self->sup_maxfd == 0)
su_select_port_update_maxfd(self);
if (socket >= self->sup_maxfd)
return su_seterrno(EBADF);
if (su_wait_mask(ser->ser_wait, socket, events) < 0)
return -1;
assert(socket < self->sup_maxfd);
if (events & SU_WAIT_IN)
FD_SET(socket, self->sup_readfds);
else
FD_CLR(socket, self->sup_readfds);
if (events & SU_WAIT_OUT)
FD_SET(socket, self->sup_writefds);
else
FD_CLR(socket, self->sup_writefds);
return 0;
}
/** @internal Enable multishot mode.
@@ -580,7 +541,7 @@ int su_select_port_multishot(su_port_t *self, int multishot)
/** @internal
* Wait (select()) for wait objects in port.
* Wait (poll()) for wait objects in port.
*
* @param self pointer to port
* @param tout timeout in milliseconds
@@ -590,78 +551,107 @@ int su_select_port_multishot(su_port_t *self, int multishot)
static
int su_select_port_wait_events(su_port_t *self, su_duration_t tout)
{
/* NOT IMPLEMENTED */
(void)su_select_port_deinit;
int j, n, events = 0;
unsigned version = self->sup_registers;
size_t bytes;
struct timeval tv;
fd_set *rset = NULL, *wset = NULL;
return -1;
}
if (self->sup_maxfd == 0)
su_select_port_update_maxfd(self);
#if 0
/** @internal
* Prints out the contents of the port.
*
* @param self pointer to a port
* @param f pointer to a file (if @c NULL, uses @c stdout).
*/
void su_port_dump(su_port_t const *self, FILE *f)
{
int i;
#define IS_WAIT_IN(x) (((x)->events & SU_WAIT_IN) ? "IN" : "")
#define IS_WAIT_OUT(x) (((x)->events & SU_WAIT_OUT) ? "OUT" : "")
#define IS_WAIT_ACCEPT(x) (((x)->events & SU_WAIT_ACCEPT) ? "ACCEPT" : "")
bytes = self->sup_maxfd ? FDSETSIZE(self->sup_maxfd - 1) : 0;
if (f == NULL)
f = stdout;
if (bytes) {
rset = memcpy(self->sup_readfds2, self->sup_readfds, bytes);
wset = memcpy(self->sup_writefds2, self->sup_writefds, bytes);
}
fprintf(f, "su_port_t at %p:\n", self);
fprintf(f, "\tport is%s running\n", self->sup_running ? "" : "not ");
#if SU_HAVE_PTHREADS
fprintf(f, "\tport tid %p\n", (void *)self->sup_tid);
fprintf(f, "\tport mbox %d (%s%s%s)\n", self->sup_mbox[0],
IS_WAIT_IN(&self->sup_mbox_wait),
IS_WAIT_OUT(&self->sup_mbox_wait),
IS_WAIT_ACCEPT(&self->sup_mbox_wait));
#endif
fprintf(f, "\t%d wait objects\n", self->sup_n_waits);
for (i = 0; i < self->sup_n_waits; i++) {
tv.tv_sec = tout / 1000;
tv.tv_usec = (tout % 1000) * 1000;
n = select(self->sup_maxfd, rset, wset, NULL, &tv);
if (n <= 0) {
SU_DEBUG_0(("su_select_port_wait_events(%p): %s (%d)\n",
(void *)self, su_strerror(su_errno()), su_errno()));
return 0;
}
for (j = 1; j < self->sup_max_index; j++) {
struct su_select_register *ser;
su_root_magic_t *magic;
int fd;
ser = self->sup_indices[j];
if (!ser->ser_cb)
continue;
fd = ser->ser_wait->fd;
ser->ser_wait->revents = 0;
if (ser->ser_wait->events & SU_WAIT_IN)
if (FD_ISSET(fd, rset)) ser->ser_wait->revents |= SU_WAIT_IN, n--;
if (ser->ser_wait->events & SU_WAIT_OUT)
if (FD_ISSET(fd, wset)) ser->ser_wait->revents |= SU_WAIT_OUT, n--;
if (ser->ser_wait->revents) {
magic = ser->ser_root ? su_root_magic(ser->ser_root) : NULL;
ser->ser_cb(magic, ser->ser_wait, ser->ser_arg);
events++;
if (version != self->sup_registers)
/* Callback function used su_register()/su_deregister() */
return events;
if (!self->sup_multishot)
/* Callback function used su_register()/su_deregister() */
return events;
}
if (n == 0)
break;
}
assert(n == 0);
return events;
}
#endif
/** Create a port using select().
/** Create a port using epoll() or poll().
*/
su_port_t *su_select_port_create(void)
{
#if notyet
su_port_t *self = su_home_new(sizeof *self);
su_port_t *self;
self = su_home_new(sizeof *self);
if (!self)
return self;
return NULL;
if (su_home_destructor(su_port_home(self), su_select_port_deinit) < 0)
return su_home_unref(su_port_home(self)), NULL;
if (su_home_destructor(su_port_home(self), su_select_port_deinit) < 0 ||
!(self->sup_indices =
su_zalloc(su_port_home(self),
(sizeof self->sup_indices[0]) *
(self->sup_size_indices = __NFDBITS)))) {
su_home_unref(su_port_home(self));
return NULL;
}
self->sup_multishot = SU_ENABLE_MULTISHOT_POLL;
if (su_pthread_port_init(self, su_select_port_vtable) < 0)
if (su_socket_port_init(self->sup_base, su_select_port_vtable) < 0)
return su_home_unref(su_port_home(self)), NULL;
return self;
#else
return NULL;
#endif
}
int su_select_clone_start(su_root_t *parent,
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit)
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit)
{
return su_pthreaded_port_start(su_select_port_create,
parent, return_clone, magic, init, deinit);
}
#endif
+68 -100
View File
@@ -193,7 +193,10 @@ RBTREE_BODIES(static inline, timers, su_timer_t,
IS_RED, SET_RED, IS_BLACK, SET_BLACK, COPY_COLOR,
CMP, INSERT, REMOVE);
/** Set the timer. */
/**@internal Set the timer.
*
* @retval 0 when successful (always)
*/
static inline int
su_timer_set0(su_timer_t **timers,
su_timer_t *t,
@@ -212,7 +215,10 @@ su_timer_set0(su_timer_t **timers,
return timers_append(timers, t);
}
/** Reset the timer. */
/**@internal Reset the timer.
*
* @retval 0 when successful (always)
*/
static inline int
su_timer_reset0(su_timer_t **timers,
su_timer_t *t)
@@ -229,6 +235,40 @@ su_timer_reset0(su_timer_t **timers,
return 0;
}
/**@internal Validate timer @a t and return pointer to per-port timer tree.
*
* @retval pointer to pointer to timer tree when successful
* @retval NULL upon an error
*/
static
su_timer_t **su_timer_tree(su_timer_t const *t,
int use_sut_duration,
char const *caller)
{
su_timer_t **timers;
if (t == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", caller, (void *)t,
"NULL argument"));
return NULL;
}
timers = su_task_timers(t->sut_task);
if (timers == NULL)
SU_DEBUG_1(("%s(%p): %s\n", caller, (void *)t,
"invalid timer"));
if (use_sut_duration && t->sut_duration == 0) {
assert(t->sut_duration > 0);
SU_DEBUG_1(("%s(%p): %s\n", caller, (void *)t,
"timer without default duration"));
return NULL;
}
return timers;
}
/**Create a timer.
*
@@ -291,23 +331,12 @@ int su_timer_set_interval(su_timer_t *t,
su_timer_arg_t *arg,
su_duration_t interval)
{
char const *func = "su_timer_set_interval";
su_timer_t **timers;
su_timer_t **timers = su_timer_tree(t, 0, "su_timer_set_interval");
if (t == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
if (t == NULL)
return -1;
}
timers = su_task_timers(t->sut_task);
if (timers == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "invalid timer"));
return -1;
}
su_timer_set0(timers, t, wakeup, arg, su_now(), interval);
return 0;
return su_timer_set0(timers, t, wakeup, arg, su_now(), interval);
}
/** Set the timer for the default interval.
@@ -326,19 +355,12 @@ int su_timer_set(su_timer_t *t,
su_timer_f wakeup,
su_timer_arg_t *arg)
{
char const *func = "su_timer_set";
su_timer_t **timers = su_timer_tree(t, 1, "su_timer_set");
if (t == NULL)
if (timers == NULL)
return -1;
assert(t->sut_duration > 0);
if (t->sut_duration == 0) {
SU_DEBUG_0(("%s(%p): %s\n", func, (void *)t,
"timer without default duration"));
return -1;
}
return su_timer_set_interval(t, wakeup, arg, t->sut_duration);
return su_timer_set0(timers, t, wakeup, arg, su_now(), t->sut_duration);
}
/** Set timer at known time.
@@ -357,23 +379,12 @@ int su_timer_set_at(su_timer_t *t,
su_wakeup_arg_t *arg,
su_time_t when)
{
char const *func = "su_timer_set_at";
su_timer_t **timers;
su_timer_t **timers = su_timer_tree(t, 0, "su_timer_set_at");
if (t == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
if (timers == NULL)
return -1;
}
timers = su_task_timers(t->sut_task);
if (timers == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "invalid timer"));
return -1;
}
su_timer_set0(timers, t, wakeup, arg, when, 0);
return 0;
return su_timer_set0(timers, t, wakeup, arg, when, 0);
}
/** Set the timer for regular intervals.
@@ -398,35 +409,17 @@ int su_timer_run(su_timer_t *t,
su_timer_f wakeup,
su_timer_arg_t *arg)
{
char const *func = "su_timer_run";
su_timer_t **timers;
su_time_t now = su_now();
su_timer_t **timers = su_timer_tree(t, 1, "su_timer_run");
su_time_t now;
if (t == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
if (timers == NULL)
return -1;
}
assert(t->sut_duration > 0);
if (t->sut_duration == 0) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t,
"timer without default duration"));
return -1;
}
timers = su_task_timers(t->sut_task);
if (timers == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "invalid timer"));
return -1;
}
t->sut_running = run_at_intervals;
t->sut_run = now;
t->sut_run = now = su_now();
t->sut_woken = 0;
su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration);
return 0;
return su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration);
}
/**Set the timer for regular intervals.
@@ -449,35 +442,17 @@ int su_timer_set_for_ever(su_timer_t *t,
su_timer_f wakeup,
su_timer_arg_t *arg)
{
char const *func = "su_timer_set_for_ever";
su_timer_t **timers;
su_time_t now = su_now();
su_timer_t **timers = su_timer_tree(t, 1, "su_timer_set_for_ever");
su_time_t now;
if (t == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
if (timers == NULL)
return -1;
}
assert(t->sut_duration > 0);
if (t->sut_duration == 0) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t,
"timer without default duration"));
return -1;
}
timers = su_task_timers(t->sut_task);
if (timers == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "invalid timer"));
return -1;
}
t->sut_running = run_for_ever;
t->sut_run = now;
t->sut_run = now = su_now();
t->sut_woken = 0;
su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration);
return 0;
return su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration);
}
/**Reset the timer.
@@ -490,19 +465,12 @@ int su_timer_set_for_ever(su_timer_t *t,
*/
int su_timer_reset(su_timer_t *t)
{
char const *func = "su_timer_reset";
su_timer_t **timers;
su_timer_t **timers = su_timer_tree(t, 0, "su_timer_reset");
if (t == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
if (timers == NULL)
return -1;
}
timers = su_task_timers(t->sut_task);
su_timer_reset0(timers, t);
return 0;
return su_timer_reset0(timers, t);
}
/** @internal Check for expired timers in queue.
@@ -576,6 +544,7 @@ int su_timer_expire(su_timer_t ** const timers,
}
/** Calculate duration in milliseconds until next timer expires. */
su_duration_t su_timer_next_expires(su_timer_t const * t, su_time_t now)
{
su_duration_t tout;
@@ -625,14 +594,13 @@ int su_timer_reset_all(su_timer_t **timers, su_task_r task)
/** Get the root object owning the timer.
*
* The function su_timer_root() return pointer to the root object owning the
* timer.
* Return pointer to the root object owning the timer.
*
* @param t pointer to the timer
*
* @return Pointer to the root object owning the timer.
* @return Pointer to the root object.
*/
su_root_t *su_timer_root(su_timer_t const *t)
{
return su_task_root(t->sut_task);
return t ? su_task_root(t->sut_task) : NULL;
}
+66 -110
View File
@@ -23,19 +23,24 @@
*/
/**@ingroup su_wait
* @CFILE su_poll_port.c
* @CFILE su_win32_port.c
*
* Port implementation using poll()
* Port implementation using WSAEVENTs
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Kai Vehmanen <kai.vehmanen@nokia.com>
*
* @date Created: Tue Sep 14 15:51:04 1999 ppessi
* @date Created: Mon Feb 5 20:29:21 2007 ppessi
* @date Original: Tue Sep 14 15:51:04 1999 ppessi
*/
#include "config.h"
#if HAVE_POLL || HAVE_WIN32
#define su_port_s su_wsaevent_port_s
#include "sofia-sip/su.h"
#include "su_port.h"
#include "sofia-sip/su_alloc.h"
#include <stdlib.h>
#include <assert.h>
@@ -45,18 +50,14 @@
#include <limits.h>
#include <errno.h>
#define su_port_s su_poll_port_s
/** Port based on su_wait() aka WSAWaitForMultipleEvents. */
#include "sofia-sip/su.h"
#include "su_port.h"
#include "sofia-sip/su_alloc.h"
#define INDEX_MAX (64)
/** Port based on poll(). */
struct su_wsaevent_port_s {
su_socket_port_t sup_base[1];
struct su_poll_port_s {
su_pthread_port_t sup_base[1];
#define sup_home sup_base->sup_base->sup_home
#define sup_home sup_base->sup_base->sup_base->sup_home
unsigned sup_multishot; /**< Multishot operation? */
@@ -69,13 +70,6 @@ struct su_poll_port_s {
int sup_size_waits; /**< Size of allocated su_waits */
int sup_pri_offset; /**< Offset to prioritized waits */
#if !SU_HAVE_WINSOCK
#define INDEX_MAX (0x7fffffff)
#else
/* We use WSAWaitForMultipleEvents() */
#define INDEX_MAX (64)
#endif
/** Indices from index returned by su_root_register() to tables below.
*
* Free elements are negative. Free elements form a list, value of free
@@ -93,43 +87,43 @@ struct su_poll_port_s {
};
static void su_poll_port_decref(su_port_t *, int blocking, char const *who);
static void su_wsevent_port_decref(su_port_t *, int blocking, char const *who);
static int su_poll_port_register(su_port_t *self,
static int su_wsevent_port_register(su_port_t *self,
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback,
su_wakeup_arg_t *arg,
int priority);
static int su_poll_port_unregister(su_port_t *port,
static int su_wsevent_port_unregister(su_port_t *port,
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback,
su_wakeup_arg_t *arg);
static int su_poll_port_deregister(su_port_t *self, int i);
static int su_poll_port_unregister_all(su_port_t *self, su_root_t *root);
static int su_poll_port_eventmask(su_port_t *self,
static int su_wsevent_port_deregister(su_port_t *self, int i);
static int su_wsevent_port_unregister_all(su_port_t *self, su_root_t *root);
static int su_wsevent_port_eventmask(su_port_t *self,
int index,
int socket,
int events);
static int su_poll_port_multishot(su_port_t *self, int multishot);
static int su_poll_port_wait_events(su_port_t *self, su_duration_t tout);
static char const *su_poll_port_name(su_port_t const *self);
static int su_wsevent_port_multishot(su_port_t *self, int multishot);
static int su_wsevent_port_wait_events(su_port_t *self, su_duration_t tout);
static char const *su_wsevent_port_name(su_port_t const *self);
su_port_vtable_t const su_poll_port_vtable[1] =
su_port_vtable_t const su_wsevent_port_vtable[1] =
{{
/* su_vtable_size: */ sizeof su_poll_port_vtable,
/* su_vtable_size: */ sizeof su_wsevent_port_vtable,
su_pthread_port_lock,
su_pthread_port_unlock,
su_base_port_incref,
su_poll_port_decref,
su_wsevent_port_decref,
su_base_port_gsource,
su_pthread_port_send,
su_poll_port_register,
su_poll_port_unregister,
su_poll_port_deregister,
su_poll_port_unregister_all,
su_poll_port_eventmask,
su_socket_port_send,
su_wsevent_port_register,
su_wsevent_port_unregister,
su_wsevent_port_deregister,
su_wsevent_port_unregister_all,
su_wsevent_port_eventmask,
su_base_port_run,
su_base_port_break,
su_base_port_step,
@@ -137,33 +131,33 @@ su_port_vtable_t const su_poll_port_vtable[1] =
su_base_port_add_prepoll,
su_base_port_remove_prepoll,
su_base_port_timers,
su_poll_port_multishot,
su_wsevent_port_multishot,
su_base_port_threadsafe,
su_base_port_yield,
su_poll_port_wait_events,
su_wsevent_port_wait_events,
su_base_port_getmsgs,
su_base_port_getmsgs_from,
su_poll_port_name,
su_wsevent_port_name,
su_base_port_start_shared,
su_pthread_port_wait,
su_pthread_port_execute,
}};
static char const *su_poll_port_name(su_port_t const *self)
static char const *su_wsevent_port_name(su_port_t const *self)
{
return "poll";
}
static void su_poll_port_deinit(void *arg)
static void su_wsevent_port_deinit(void *arg)
{
su_port_t *self = arg;
SU_DEBUG_9(("%s(%p) called\n", "su_poll_port_deinit", self));
SU_DEBUG_9(("%s(%p) called\n", "su_wsevent_port_deinit", self));
su_pthread_port_deinit(self);
su_socket_port_deinit(self->sup_base);
}
static void su_poll_port_decref(su_port_t *self, int blocking, char const *who)
static void su_wsevent_port_decref(su_port_t *self, int blocking, char const *who)
{
su_base_port_decref(self, blocking, who);
}
@@ -189,7 +183,7 @@ static void su_poll_port_decref(su_port_t *self, int blocking, char const *who)
* Positive index of the wait object,
* or -1 upon an error.
*/
int su_poll_port_register(su_port_t *self,
int su_wsevent_port_register(su_port_t *self,
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback,
@@ -311,7 +305,7 @@ int su_poll_port_register(su_port_t *self,
}
/** Deregister a su_wait_t object. */
static int su_poll_port_deregister0(su_port_t *self, int i, int destroy_wait)
static int su_wsevent_port_deregister0(su_port_t *self, int i, int destroy_wait)
{
int n, N, *indices, *reverses;
@@ -372,9 +366,8 @@ static int su_poll_port_deregister0(su_port_t *self, int i, int destroy_wait)
/** Unregister a su_wait_t object.
*
* The function su_poll_port_unregister() unregisters a su_wait_t object. The
* wait object, a callback function and a argument are removed from the
* port object.
* Unregisters a su_wait_t object. The wait object, a callback function and
* a argument are removed from the port object.
*
* @param self - pointer to port object
* @param root - pointer to root object
@@ -383,11 +376,11 @@ static int su_poll_port_deregister0(su_port_t *self, int i, int destroy_wait)
* @param arg - argument given to callback function when it is invoked
* (may be NULL)
*
* @deprecated Use su_poll_port_deregister() instead.
* @deprecated Use su_wsevent_port_deregister() instead.
*
* @return Nonzero index of the wait object, or -1 upon an error.
*/
int su_poll_port_unregister(su_port_t *self,
int su_wsevent_port_unregister(su_port_t *self,
su_root_t *root,
su_wait_t *wait,
su_wakeup_f callback, /* XXX - ignored */
@@ -402,7 +395,7 @@ int su_poll_port_unregister(su_port_t *self,
for (n = 0; n < N; n++) {
if (SU_WAIT_CMP(wait[0], self->sup_waits[n]) == 0) {
return su_poll_port_deregister0(self, self->sup_reverses[n], 0);
return su_wsevent_port_deregister0(self, self->sup_reverses[n], 0);
}
}
@@ -422,7 +415,7 @@ int su_poll_port_unregister(su_port_t *self,
*
* @return Index of the wait object, or -1 upon an error.
*/
int su_poll_port_deregister(su_port_t *self, int i)
int su_wsevent_port_deregister(su_port_t *self, int i)
{
su_wait_t wait[1] = { SU_WAIT_INIT };
int retval;
@@ -436,7 +429,7 @@ int su_poll_port_deregister(su_port_t *self, int i)
if (self->sup_indices[i] < 0)
return su_seterrno(EBADF);
retval = su_poll_port_deregister0(self, i, 1);
retval = su_wsevent_port_deregister0(self, i, 1);
su_wait_destroy(wait);
@@ -447,15 +440,15 @@ int su_poll_port_deregister(su_port_t *self, int i)
/** @internal
* Unregister all su_wait_t objects.
*
* The function su_poll_port_unregister_all() unregisters all su_wait_t objects
* and destroys all queued timers associated with given root object.
* Unregisters all su_wait_t objects and destroys all queued timers
* associated with given root object.
*
* @param self - pointer to port object
* @param root - pointer to root object
*
* @return Number of wait objects removed.
*/
int su_poll_port_unregister_all(su_port_t *self,
int su_wsevent_port_unregister_all(su_port_t *self,
su_root_t *root)
{
int i, j, index, N;
@@ -516,8 +509,7 @@ int su_poll_port_unregister_all(su_port_t *self,
/**Set mask for a registered event. @internal
*
* The function su_poll_port_eventmask() sets the mask describing events that can
* signal the registered callback.
* Sets the mask describing events that can signal the registered callback.
*
* @param port pointer to port object
* @param index registration index
@@ -527,7 +519,7 @@ int su_poll_port_unregister_all(su_port_t *self,
* @retval 0 when successful,
* @retval -1 upon an error.
*/
int su_poll_port_eventmask(su_port_t *self, int index, int socket, int events)
int su_wsevent_port_eventmask(su_port_t *self, int index, int socket, int events)
{
int n;
assert(self);
@@ -557,7 +549,7 @@ int su_poll_port_eventmask(su_port_t *self, int index, int socket, int events)
* @retval -1 an error occurred
*/
static
int su_poll_port_multishot(su_port_t *self, int multishot)
int su_wsevent_port_multishot(su_port_t *self, int multishot)
{
if (multishot < 0)
return self->sup_multishot;
@@ -577,7 +569,7 @@ int su_poll_port_multishot(su_port_t *self, int multishot)
* @return number of events handled
*/
static
int su_poll_port_wait_events(su_port_t *self, su_duration_t tout)
int su_wsevent_port_wait_events(su_port_t *self, su_duration_t tout)
{
int i, events = 0;
su_wait_t *waits = self->sup_waits;
@@ -620,68 +612,32 @@ int su_poll_port_wait_events(su_port_t *self, su_duration_t tout)
return events;
}
#if 0
/** @internal
* Prints out the contents of the port.
*
* @param self pointer to a port
* @param f pointer to a file (if @c NULL, uses @c stdout).
*/
void su_port_dump(su_port_t const *self, FILE *f)
{
int i;
#define IS_WAIT_IN(x) (((x)->events & SU_WAIT_IN) ? "IN" : "")
#define IS_WAIT_OUT(x) (((x)->events & SU_WAIT_OUT) ? "OUT" : "")
#define IS_WAIT_ACCEPT(x) (((x)->events & SU_WAIT_ACCEPT) ? "ACCEPT" : "")
if (f == NULL)
f = stdout;
fprintf(f, "su_port_t at %p:\n", self);
fprintf(f, "\tport is%s running\n", self->sup_running ? "" : "not ");
#if SU_HAVE_PTHREADS
fprintf(f, "\tport tid %p\n", (void *)self->sup_tid);
fprintf(f, "\tport mbox %d (%s%s%s)\n", self->sup_mbox[0],
IS_WAIT_IN(&self->sup_mbox_wait),
IS_WAIT_OUT(&self->sup_mbox_wait),
IS_WAIT_ACCEPT(&self->sup_mbox_wait));
#endif
fprintf(f, "\t%d wait objects\n", self->sup_n_waits);
for (i = 0; i < self->sup_n_waits; i++) {
}
}
#endif
/** Create a port using epoll() or poll().
*/
su_port_t *su_poll_port_create(void)
/** Create a port using WSAEVENTs and WSAWaitForMultipleEvents. */
su_port_t *su_wsaevent_port_create(void)
{
su_port_t *self = su_home_new(sizeof *self);
if (!self)
return self;
if (su_home_destructor(su_port_home(self), su_poll_port_deinit) < 0)
if (su_home_destructor(su_port_home(self), su_wsevent_port_deinit) < 0)
return su_home_unref(su_port_home(self)), NULL;
self->sup_multishot = SU_ENABLE_MULTISHOT_POLL;
if (su_pthread_port_init(self, su_poll_port_vtable) < 0)
if (su_socket_port_init(self->sup_base, su_wsevent_port_vtable) < 0)
return su_home_unref(su_port_home(self)), NULL;
return self;
}
int su_poll_clone_start(su_root_t *parent,
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit)
int su_wsaevent_clone_start(su_root_t *parent,
su_clone_r return_clone,
su_root_magic_t *magic,
su_root_init_f init,
su_root_deinit_f deinit)
{
return su_pthreaded_port_start(su_poll_port_create,
return su_pthreaded_port_start(su_wsaevent_port_create,
parent, return_clone, magic, init, deinit);
}
#endif /* HAVE_POLL */
+121 -6
View File
@@ -100,7 +100,7 @@ int test_sockaddr(void)
TEST(su_setblocking(s, 1), 0);
TEST(su_close(s), 0);
su_freelocalinfo(res);
su_freelocalinfo(res), res = NULL;
#if SU_HAVE_IN6
hints->li_family = AF_INET6;
@@ -111,16 +111,17 @@ int test_sockaddr(void)
for (li = res; li; li = li->li_next)
TEST(li->li_family, AF_INET6);
su_freelocalinfo(res);
su_freelocalinfo(res), res = NULL;
#endif
hints->li_flags |= LI_NUMERIC;
TEST(su_getlocalinfo(hints, &res), 0);
su_freelocalinfo(res), res = NULL;
hints->li_flags |= LI_NAMEREQD;
res = NULL;
hints->li_flags |= LI_NAMEREQD;
su_getlocalinfo(hints, &res);
su_freelocalinfo(res);
su_freelocalinfo(res), res = NULL;
memset(a, 0, sizeof *a);
memset(b, 0, sizeof *b);
@@ -161,7 +162,7 @@ int test_sockaddr(void)
int test_sendrecv(void)
{
int s, l, a;
su_socket_t s, l, a;
int n;
su_sockaddr_t su, csu;
socklen_t sulen = sizeof su.su_sin, csulen = sizeof csu.su_sin;
@@ -260,6 +261,120 @@ int test_sendrecv(void)
END();
}
#if HAVE_SELECT
#if HAVE_WIN32
int test_select(void)
{
return 0;
}
#else
#if HAVE_SYS_SELECT_H
#include <sys/select.h>
#elif HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <sys/types.h>
#include <unistd.h>
#ifndef __NFDBITS
#define __NFDBITS (8 * sizeof (long int))
#endif
#undef howmany
/* Size of fd set in bytes. Sorry, octets. */
#define howmany(n) (((n) + __NFDBITS - 1) / __NFDBITS * (__NFDBITS / 8))
#define FD_ZERO_TO(maxfd, set) \
memset((set), 0, howmany(maxfd))
/* Test assumptions in su_select_port implementation */
int test_select(void)
{
su_socket_t s;
su_sockaddr_t su;
socklen_t sulen = sizeof su.su_sin;
size_t bytes;
fd_set *rset, *wset;
struct timeval tv;
BEGIN();
s = su_socket(AF_INET, SOCK_DGRAM, 0); TEST_1(s != -1);
memset(&su, 0, sulen);
su.su_len = sulen;
su.su_family = AF_INET;
TEST(inet_pton(AF_INET, "127.0.0.1", &su.su_sin.sin_addr), 1);
TEST(bind(s, &su.su_sa, sulen), 0);
TEST(getsockname(s, &su.su_sa, &sulen), 0);
tv.tv_sec = 0; tv.tv_usec = 1000;
TEST(select(0, NULL, NULL, NULL, &tv), 0);
bytes = howmany(s);
TEST_1(rset = malloc(bytes));
TEST_1(wset = malloc(bytes));
FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset); FD_SET(s, wset);
tv.tv_sec = 0, tv.tv_usec = 1000;
TEST(select(s + 1, NULL, wset, NULL, &tv), 1);
TEST_1(FD_ISSET(s, wset));
FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset);
FD_SET(s, rset); FD_SET(s, wset);
tv.tv_sec = 0, tv.tv_usec = 1000;
TEST(select(s + 1, rset, wset, NULL, &tv), 1);
TEST_1(!FD_ISSET(s, rset));
TEST_1(FD_ISSET(s, wset));
FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset);
FD_SET(s, rset); FD_SET(s, wset);
tv.tv_sec = 0, tv.tv_usec = 1000;
TEST(select(s + 1, rset, NULL, NULL, &tv), 0);
TEST_1(!FD_ISSET(s, rset));
FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset);
FD_SET(s, rset); FD_CLR(s, wset);
tv.tv_sec = 0, tv.tv_usec = 1000;
TEST(select(s + 1, rset, wset, NULL, &tv), 0);
TEST_1(!FD_ISSET(s, rset));
TEST_1(!FD_ISSET(s, wset));
TEST(su_sendto(s, "foo", 3, 0, &su, sulen), 3);
FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset);
FD_SET(s, rset); FD_CLR(s, wset);
tv.tv_sec = 0, tv.tv_usec = 1000;
TEST(select(s + 1, rset, wset, NULL, &tv), 1);
TEST_1(FD_ISSET(s, rset));
TEST_1(!FD_ISSET(s, wset));
FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset);
FD_SET(s, rset); FD_SET(s, wset);
tv.tv_sec = 0, tv.tv_usec = 1000;
TEST(select(s + 1, rset, wset, NULL, &tv), 2);
TEST_1(FD_ISSET(s, rset));
TEST_1(FD_ISSET(s, wset));
su_close(s);
free(wset);
free(rset);
END();
}
#endif
#else
int test_select(void)
{
return 0;
}
#endif
#include <sofia-sip/su_md5.h>
int test_md5(void)
@@ -395,10 +510,10 @@ int main(int argc, char *argv[])
retval |= test_sockaddr();
retval |= test_sendrecv();
retval |= test_select();
retval |= test_md5(); fflush(stdout);
su_deinit();
return retval;
}
@@ -533,10 +533,30 @@ void usage(void)
int main(int argc, char *argv[])
{
root_test_t rt[1] = {{{ SU_HOME_INIT(rt) }}};
root_test_t *rt, rt0[1] = {{{ SU_HOME_INIT(rt0) }}}, rt1[1];
int retval = 0;
int i;
struct {
su_port_create_f *create;
su_clone_start_f *start;
char const *preference;
} prefer[] =
{
{ NULL, NULL, "default" },
#if HAVE_POLL_PORT
#if HAVE_EPOLL
{ su_epoll_port_create, su_epoll_clone_start, "epoll", },
#endif
{ su_poll_port_create, su_poll_clone_start, "poll" },
#endif
#if HAVE_SELECT
{ su_select_port_create, su_select_clone_start, "select" },
#endif
{ NULL, NULL }
};
rt = rt0;
rt->rt_family = AF_INET;
for (i = 1; argv[i]; i++) {
@@ -550,14 +570,23 @@ int main(int argc, char *argv[])
usage();
}
retval |= init_test(rt);
retval |= register_test(rt);
retval |= event_test(rt);
su_root_threading(rt->rt_root, 1);
retval |= clone_test(rt);
su_root_threading(rt->rt_root, 0);
retval |= clone_test(rt);
retval |= deinit_test(rt);
i = 0;
do {
rt = rt1, *rt = *rt0;
printf("%s: testing %s implementation\n",
name, prefer[i].preference);
su_port_prefer(prefer[i].create, prefer[i].start);
retval |= init_test(rt);
retval |= register_test(rt);
retval |= event_test(rt);
su_root_threading(rt->rt_root, 1);
retval |= clone_test(rt);
su_root_threading(rt->rt_root, 0);
retval |= clone_test(rt);
retval |= deinit_test(rt);
} while (prefer[++i].create);
return retval;
}