mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-11-11 20:17:05 +00:00
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:
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)
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
Reference in new issue
Block a user