Merge in rest of event library update branch, updating the event library to
libevent-1.1a. svn merge -r10917:11006 https://svn.open-mpi.org/svn/ompi/tmp/libevent-update This commit was SVN r11022. The following SVN revisions from the original message are invalid or inconsistent and therefore were not cross-referenced: r10917 r11006
Этот коммит содержится в:
родитель
7c2ca73a1b
Коммит
7ea33eac02
1
NEWS
1
NEWS
@ -25,6 +25,7 @@ version 1.0.
|
||||
1.2
|
||||
---
|
||||
|
||||
- Update event library to libevent-1.1a
|
||||
- Fixed standards conformance issues with MPI_ERR_TRUNCATED and
|
||||
setting MPI_ERROR during MPI_TEST/MPI_WAIT.
|
||||
- Added support for building the Fortran 90 bindings library as
|
||||
|
@ -32,7 +32,7 @@ dnl AC_CHECK_LIB(socket, socket)
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS(inttypes.h stdint.h poll.h signal.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h)
|
||||
AC_CHECK_HEADERS(fcntl.h stdarg.h inttypes.h stdint.h poll.h signal.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h sys/ioctl.h sys/devpoll.h)
|
||||
if test "x$ac_cv_header_sys_queue_h" = "xyes"; then
|
||||
AC_MSG_CHECKING(for TAILQ_FOREACH in sys/queue.h)
|
||||
AC_EGREP_CPP(yes,
|
||||
@ -66,7 +66,19 @@ dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_HEADER_TIME
|
||||
|
||||
dnl Checks for library functions.
|
||||
AC_CHECK_FUNCS(gettimeofday)
|
||||
AC_CHECK_FUNCS(gettimeofday vasprintf fcntl)
|
||||
|
||||
AC_MSG_CHECKING(for F_SETFD in fcntl.h)
|
||||
AC_EGREP_CPP(yes,
|
||||
[
|
||||
#define _GNU_SOURCE
|
||||
#include <fcntl.h>
|
||||
#ifdef F_SETFD
|
||||
yes
|
||||
#endif
|
||||
], [ AC_DEFINE(HAVE_SETFD, 1,
|
||||
[Define if F_SETFD is defined in <fcntl.h>])
|
||||
AC_MSG_RESULT(yes) ], AC_MSG_RESULT(no))
|
||||
|
||||
needsignal=no
|
||||
haveselect=no
|
||||
@ -189,6 +201,15 @@ if test "x$haveepoll" = "xyes" ; then
|
||||
needsignal=yes
|
||||
fi
|
||||
|
||||
havedevpoll=no
|
||||
if test "x$ac_cv_header_sys_devpoll_h" = "xyes"; then
|
||||
AC_DEFINE(HAVE_DEVPOLL, 1,
|
||||
[Define if /dev/poll is available])
|
||||
# OMPI: Don't use AC_LIBOBJ(devpoll)
|
||||
sources="devpoll.c $sources"
|
||||
needsignal=yes
|
||||
fi
|
||||
|
||||
havekqueue=no
|
||||
if test "x$ac_cv_header_sys_event_h" = "xyes"; then
|
||||
AC_CHECK_FUNCS(kqueue, [havekqueue=yes], )
|
||||
@ -292,7 +313,6 @@ fi
|
||||
# OMPI: AC_REPLACE_FUNCS doesn't have much meaning here because it
|
||||
# uses AC_LIBOBJ; use our own test
|
||||
#AC_REPLACE_FUNCS(err)
|
||||
AC_CHECK_FUNC(err, [], [sources="err.c $sources"])
|
||||
|
||||
AC_TYPE_PID_T
|
||||
AC_TYPE_SIZE_T
|
||||
|
@ -568,7 +568,7 @@ AC_CHECK_HEADERS([alloca.h aio.h arpa/inet.h dirent.h \
|
||||
string.h strings.h stropts.h sys/fcntl.h sys/ipc.h \
|
||||
sys/ioctl.h sys/mman.h sys/param.h sys/queue.h \
|
||||
sys/resource.h sys/select.h sys/socket.h sys/sockio.h \
|
||||
sys/stat.h sys/statvfs.h sys/time.h sys/tree.h \
|
||||
stdarg.h sys/stat.h sys/statvfs.h sys/time.h sys/tree.h \
|
||||
sys/types.h sys/uio.h sys/utsname.h sys/wait.h syslog.h \
|
||||
time.h termios.h ulimit.h unistd.h util.h utmp.h malloc.h \
|
||||
ucontext.h])
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "orte/runtime/runtime.h"
|
||||
#include "ompi/tools/ompi_info/ompi_info.h"
|
||||
|
||||
#include "opal/event/event.h"
|
||||
#include "opal/mca/base/base.h"
|
||||
#include "opal/mca/memory/memory.h"
|
||||
#include "opal/mca/paffinity/paffinity.h"
|
||||
@ -139,6 +140,10 @@ void ompi_info::open_components()
|
||||
}
|
||||
}
|
||||
|
||||
// some components require the event library be active, so activate
|
||||
// it.
|
||||
opal_event_init();
|
||||
|
||||
// Open the DPS
|
||||
|
||||
if (ORTE_SUCCESS != orte_dss_open()) {
|
||||
|
@ -38,6 +38,7 @@
|
||||
|
||||
#include "opal/install_dirs.h"
|
||||
#include "opal/class/opal_object.h"
|
||||
#include "opal/runtime/opal.h"
|
||||
#include "orte/runtime/runtime.h"
|
||||
#include "opal/util/output.h"
|
||||
#include "opal/util/cmd_line.h"
|
||||
@ -78,6 +79,12 @@ int main(int argc, char *argv[])
|
||||
int i, len;
|
||||
|
||||
// Initialize the argv parsing handle
|
||||
if (OMPI_SUCCESS != opal_init_util()) {
|
||||
opal_show_help("help-ompi_info.txt", "lib-call-fail", true,
|
||||
"opal_init_util", __FILE__, __LINE__, NULL);
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
|
||||
cmd_line = OBJ_NEW(opal_cmd_line_t);
|
||||
if (NULL == cmd_line) {
|
||||
@ -259,6 +266,8 @@ int main(int argc, char *argv[])
|
||||
ompi_info::close_components();
|
||||
OBJ_RELEASE(cmd_line);
|
||||
mca_base_close();
|
||||
opal_class_finalize();
|
||||
|
||||
opal_finalize_util();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
4
opal/event/.compile_files
Обычный файл
4
opal/event/.compile_files
Обычный файл
@ -0,0 +1,4 @@
|
||||
event.c
|
||||
err.c
|
||||
select.c
|
||||
signal.c
|
75
opal/event/Makefile.am
Обычный файл
75
opal/event/Makefile.am
Обычный файл
@ -0,0 +1,75 @@
|
||||
#
|
||||
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The University of Tennessee and The University
|
||||
# of Tennessee Research Foundation. All rights
|
||||
# reserved.
|
||||
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
# University of Stuttgart. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
|
||||
# OMPI Get the dirs where ompi_config.h and ompi_config_bottom.h live.
|
||||
# Also specify where we can find this package's config.h because some
|
||||
# of the header files in this directory get included elsewhere in OMPI.
|
||||
# #@%@#$...
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/opal/event/compat
|
||||
|
||||
# OMPI: No need to build the sample or test
|
||||
#SUBDIRS = . sample test
|
||||
SUBDIRS = compat
|
||||
|
||||
EXTRA_DIST = event.h event-internal.h evsignal.h event.3 \
|
||||
kqueue.c epoll_sub.c epoll.c select.c rtsig.c poll.c signal.c \
|
||||
devpoll.c \
|
||||
WIN32-Code/config.h WIN32-Code/misc.c \
|
||||
WIN32-Code/misc.h WIN32-Code/win32.c
|
||||
|
||||
# OMPI: This causes problems
|
||||
junk = \
|
||||
sample/Makefile.am sample/Makefile.in sample/event-test.c \
|
||||
sample/signal-test.c sample/time-test.c \
|
||||
test/Makefile.am test/Makefile.in test/bench.c test/regress.c \
|
||||
test/test-eof.c test/test-weof.c test/test-time.c \
|
||||
test/test-init.c test/test.sh \
|
||||
compat/sys/queue.h compat/sys/tree.h compat/sys/_time.h \
|
||||
WIN32-Code WIN32-Code/config.h WIN32-Code/misc.c \
|
||||
WIN32-Code/win32.c WIN32-Code/misc.h \
|
||||
WIN32-Prj WIN32-Prj/event_test WIN32-Prj/event_test/event_test.dsp \
|
||||
WIN32-Prj/event_test/test.txt WIN32-Prj/libevent.dsp \
|
||||
WIN32-Prj/libevent.dsw WIN32-Prj/signal_test \
|
||||
WIN32-Prj/signal_test/signal_test.dsp WIN32-Prj/time_test \
|
||||
WIN32-Prj/time_test/time_test.dsp
|
||||
|
||||
# OMPI: Changed to noinst and libevent.la
|
||||
noinst_LTLIBRARIES = libevent.la
|
||||
|
||||
# OMPI: Automake sillyness so that we can have variable sources
|
||||
objects = $(OMPI_LIBEVENT_SOURCES:.c=.lo)
|
||||
|
||||
# OMPI: Changed to libevent_la_*
|
||||
headers = event.h event_rename.h
|
||||
|
||||
libevent_la_SOURCES = event.c buffer.c evbuffer.c log.c $(headers)
|
||||
libevent_la_LIBADD = $(objects)
|
||||
libevent_la_DEPENDENCIES = $(objects)
|
||||
|
||||
|
||||
if WANT_INSTALL_HEADERS
|
||||
ompidir = $(includedir)/openmpi/opal/event
|
||||
ompi_HEADERS = $(headers)
|
||||
else
|
||||
ompidir = $(includedir)
|
||||
endif
|
||||
|
||||
verify: libevent.la
|
||||
cd $(srcdir)/test && make verify
|
28
opal/event/README
Обычный файл
28
opal/event/README
Обычный файл
@ -0,0 +1,28 @@
|
||||
To build libevent, type
|
||||
|
||||
$ ./configure && make
|
||||
|
||||
Install as root via
|
||||
|
||||
# make install
|
||||
|
||||
You can run the regression tests by
|
||||
|
||||
$ make verify
|
||||
|
||||
Before, reporting any problems, please run the regression tests.
|
||||
|
||||
Acknowledgements:
|
||||
-----------------
|
||||
|
||||
The following people have helped with suggestions, ideas, code or
|
||||
fixing bugs:
|
||||
|
||||
Nick Mathewson
|
||||
Andrew Danforth
|
||||
Shie Erlich
|
||||
Mike Davis
|
||||
William Ahern
|
||||
Alexander von Gernler
|
||||
|
||||
If I have forgotten your name, please contact me.
|
1
opal/event/WIN32-Code/.compile_files
Обычный файл
1
opal/event/WIN32-Code/.compile_files
Обычный файл
@ -0,0 +1 @@
|
||||
win32.c
|
5
opal/event/WIN32-Code/CVS/Entries
Обычный файл
5
opal/event/WIN32-Code/CVS/Entries
Обычный файл
@ -0,0 +1,5 @@
|
||||
/misc.h/1.1/Sat Jun 7 19:57:00 2003//
|
||||
/misc.c/1.2/Mon May 24 00:14:28 2004//
|
||||
/config.h/1.3/Tue Mar 29 06:50:51 2005//
|
||||
/win32.c/1.3/Tue Mar 29 06:50:24 2005//
|
||||
D
|
1
opal/event/WIN32-Code/CVS/Repository
Обычный файл
1
opal/event/WIN32-Code/CVS/Repository
Обычный файл
@ -0,0 +1 @@
|
||||
libevent/WIN32-Code
|
1
opal/event/WIN32-Code/CVS/Root
Обычный файл
1
opal/event/WIN32-Code/CVS/Root
Обычный файл
@ -0,0 +1 @@
|
||||
nprovos@cvs.sourceforge.net:/cvsroot/levent
|
239
opal/event/WIN32-Code/config.h
Обычный файл
239
opal/event/WIN32-Code/config.h
Обычный файл
@ -0,0 +1,239 @@
|
||||
/* config.h.in. Generated automatically from configure.in by autoheader. */
|
||||
/* Define if kqueue works correctly with pipes */
|
||||
#undef HAVE_WORKING_KQUEUE
|
||||
|
||||
/* Define to `unsigned long long' if <sys/types.h> doesn't define. */
|
||||
#undef u_int64_t
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> doesn't define. */
|
||||
#undef u_int32_t
|
||||
|
||||
/* Define to `unsigned short' if <sys/types.h> doesn't define. */
|
||||
#undef u_int16_t
|
||||
|
||||
/* Define to `unsigned char' if <sys/types.h> doesn't define. */
|
||||
#undef u_int8_t
|
||||
|
||||
/* Define if timeradd is defined in <sys/time.h> */
|
||||
#undef HAVE_TIMERADD
|
||||
#ifndef HAVE_TIMERADD
|
||||
#undef timersub
|
||||
#define timeradd(tvp, uvp, vvp) \
|
||||
do { \
|
||||
(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
|
||||
(vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
|
||||
if ((vvp)->tv_usec >= 1000000) { \
|
||||
(vvp)->tv_sec++; \
|
||||
(vvp)->tv_usec -= 1000000; \
|
||||
} \
|
||||
} while (0)
|
||||
#define timersub(tvp, uvp, vvp) \
|
||||
do { \
|
||||
(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
|
||||
(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
|
||||
if ((vvp)->tv_usec < 0) { \
|
||||
(vvp)->tv_sec--; \
|
||||
(vvp)->tv_usec += 1000000; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif /* !HAVE_TIMERADD */
|
||||
|
||||
#undef HAVE_TIMERCLEAR
|
||||
#ifndef HAVE_TIMERCLEAR
|
||||
#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
|
||||
#endif
|
||||
|
||||
#define HAVE_TIMERCMP
|
||||
#ifndef HAVE_TIMERCMP
|
||||
#undef timercmp
|
||||
#define timercmp(tvp, uvp, cmp) \
|
||||
(((tvp)->tv_sec == (uvp)->tv_sec) ? \
|
||||
((tvp)->tv_usec cmp (uvp)->tv_usec) : \
|
||||
((tvp)->tv_sec cmp (uvp)->tv_sec))
|
||||
#endif
|
||||
|
||||
#undef HAVE_TIMERISSET
|
||||
#ifndef HAVE_TIMERISSET
|
||||
#undef timerisset
|
||||
#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
|
||||
#endif
|
||||
|
||||
/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */
|
||||
#define HAVE_TAILQFOREACH
|
||||
#ifndef HAVE_TAILQFOREACH
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
#define TAILQ_END(head) NULL
|
||||
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
#define TAILQ_FOREACH(var, head, field) \
|
||||
for((var) = TAILQ_FIRST(head); \
|
||||
(var) != TAILQ_END(head); \
|
||||
(var) = TAILQ_NEXT(var, field))
|
||||
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
||||
(elm)->field.tqe_next = (listelm); \
|
||||
*(listelm)->field.tqe_prev = (elm); \
|
||||
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
|
||||
} while (0)
|
||||
#endif /* TAILQ_FOREACH */
|
||||
|
||||
/* Define if /dev/poll is available */
|
||||
#undef HAVE_DEVPOLL
|
||||
|
||||
/* Define if your system supports the epoll system calls */
|
||||
#undef HAVE_EPOLL
|
||||
|
||||
/* Define if you have the `epoll_ctl' function. */
|
||||
#undef HAVE_EPOLL_CTL
|
||||
|
||||
/* Define if you have the `err' function. */
|
||||
#undef HAVE_ERR
|
||||
|
||||
/* Define if you have the `fcntl' function. */
|
||||
#undef HAVE_FCNTL
|
||||
|
||||
/* Define if you have the <fcntl.h> header file. */
|
||||
#undef HAVE_FCNTL_H
|
||||
|
||||
/* Define if you have the `gettimeofday' function. */
|
||||
#define HAVE_GETTIMEOFDAY 1
|
||||
|
||||
/* Define if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define if you have the `kqueue' function. */
|
||||
#undef HAVE_KQUEUE
|
||||
|
||||
/* Define if you have the `socket' library (-lsocket). */
|
||||
#undef HAVE_LIBSOCKET
|
||||
|
||||
/* Define if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define if you have the `poll' function. */
|
||||
#undef HAVE_POLL
|
||||
|
||||
/* Define if you have the <poll.h> header file. */
|
||||
#undef HAVE_POLL_H
|
||||
|
||||
/* Define if your system supports POSIX realtime signals */
|
||||
#undef HAVE_RTSIG
|
||||
|
||||
/* Define if you have the `select' function. */
|
||||
#undef HAVE_SELECT
|
||||
|
||||
/* Define if F_SETFD is defined in <fcntl.h> */
|
||||
#undef HAVE_SETFD
|
||||
|
||||
/* Define if you have the <signal.h> header file. */
|
||||
#undef HAVE_SIGNAL_H
|
||||
|
||||
/* Define if you have the `sigtimedwait' function. */
|
||||
#undef HAVE_SIGTIMEDWAIT
|
||||
|
||||
/* Define if you have the <stdarg.h> header file. */
|
||||
#define HAVE_STDARG_H 1
|
||||
|
||||
/* Define if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define if you have the <sys/devpoll.h> header file. */
|
||||
#undef HAVE_SYS_DEVPOLL_H
|
||||
|
||||
/* Define if you have the <sys/epoll.h> header file. */
|
||||
#undef HAVE_SYS_EPOLL_H
|
||||
|
||||
/* Define if you have the <sys/event.h> header file. */
|
||||
#undef HAVE_SYS_EVENT_H
|
||||
|
||||
/* Define if you have the <sys/ioctl.h> header file. */
|
||||
#undef HAVE_SYS_IOCTL_H
|
||||
|
||||
/* Define if you have the <sys/queue.h> header file. */
|
||||
#undef HAVE_SYS_QUEUE_H
|
||||
|
||||
/* Define if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define if you have the <sys/time.h> header file. */
|
||||
#undef HAVE_SYS_TIME_H
|
||||
|
||||
/* Define if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */
|
||||
#undef HAVE_TAILQFOREACH
|
||||
|
||||
/* Define if timeradd is defined in <sys/time.h> */
|
||||
#undef HAVE_TIMERADD
|
||||
|
||||
/* Define if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define if you have the `vasprintf' function. */
|
||||
#undef HAVE_VASPRINTF
|
||||
|
||||
/* Define if kqueue works correctly with pipes */
|
||||
#undef HAVE_WORKING_KQUEUE
|
||||
|
||||
/* Define if realtime signals work on pipes */
|
||||
#undef HAVE_WORKING_RTSIG
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "libevent"
|
||||
|
||||
/* Define if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Define if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#undef TIME_WITH_SYS_TIME
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "1.0b"
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#undef const
|
||||
|
||||
/* Define as `__inline' if that's what the C compiler calls it, or to nothing
|
||||
if it is not supported. */
|
||||
#define inline __inline
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#undef pid_t
|
||||
|
||||
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||
#undef size_t
|
||||
|
||||
/* Define to unsigned int if you dont have it */
|
||||
#undef socklen_t
|
||||
|
||||
/* Define to `unsigned short' if <sys/types.h> does not define. */
|
||||
#undef u_int16_t
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
#undef u_int32_t
|
||||
|
||||
/* Define to `unsigned long long' if <sys/types.h> does not define. */
|
||||
/* #undef u_int64_t */
|
||||
|
||||
/* Define to `unsigned char' if <sys/types.h> does not define. */
|
||||
/* #undef u_int8_t */
|
||||
|
||||
<<<<<<< .working
|
||||
int win_read(int, void *, unsigned int);
|
||||
int win_write(int, void *, unsigned int);
|
||||
int socketpair(int d, int type, int protocol, int *sv);
|
||||
|
||||
#define __func__ __FILE__
|
||||
=======
|
||||
/* Define to __FUNCTION__ or __file__ if your compiler doesn't have __func__ */
|
||||
#define __func__ __FUNCTION__
|
||||
>>>>>>> .merge-right.r10952
|
84
opal/event/WIN32-Code/misc.c
Обычный файл
84
opal/event/WIN32-Code/misc.c
Обычный файл
@ -0,0 +1,84 @@
|
||||
#include "opal_config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
#include <sys/timeb.h>
|
||||
#include <time.h>
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Function: gettimeofday(struct timeval *, struct timezone *)
|
||||
*
|
||||
* Purpose: Get current time of day.
|
||||
*
|
||||
* Arguments: tv => Place to store the curent time of day.
|
||||
* tz => Ignored.
|
||||
*
|
||||
* Returns: 0 => Success.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int gettimeofday(struct timeval *tv, struct timezone *tz) {
|
||||
struct _timeb tb;
|
||||
|
||||
if(tv == NULL)
|
||||
return -1;
|
||||
|
||||
_ftime(&tb);
|
||||
tv->tv_sec = tb.time;
|
||||
tv->tv_usec = ((int) tb.millitm) * 1000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
win_read(int fd, void *buf, unsigned int length)
|
||||
{
|
||||
DWORD dwBytesRead;
|
||||
int res = ReadFile((HANDLE) fd, buf, length, &dwBytesRead, NULL);
|
||||
if (res == 0) {
|
||||
DWORD error = GetLastError();
|
||||
if (error == ERROR_NO_DATA)
|
||||
return (0);
|
||||
return (-1);
|
||||
} else
|
||||
return (dwBytesRead);
|
||||
}
|
||||
|
||||
int
|
||||
win_write(int fd, void *buf, unsigned int length)
|
||||
{
|
||||
DWORD dwBytesWritten;
|
||||
int res = WriteFile((HANDLE) fd, buf, length, &dwBytesWritten, NULL);
|
||||
if (res == 0) {
|
||||
DWORD error = GetLastError();
|
||||
if (error == ERROR_NO_DATA)
|
||||
return (0);
|
||||
return (-1);
|
||||
} else
|
||||
return (dwBytesWritten);
|
||||
}
|
||||
|
||||
int
|
||||
socketpair(int d, int type, int protocol, int *sv)
|
||||
{
|
||||
static int count;
|
||||
char buf[64];
|
||||
HANDLE fd;
|
||||
DWORD dwMode;
|
||||
sprintf(buf, "\\\\.\\pipe\\levent-%d", count++);
|
||||
/* Create a duplex pipe which will behave like a socket pair */
|
||||
fd = CreateNamedPipe(buf, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_NOWAIT,
|
||||
PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, NULL);
|
||||
if (fd == INVALID_HANDLE_VALUE)
|
||||
return (-1);
|
||||
sv[0] = (int)fd;
|
||||
|
||||
fd = CreateFile(buf, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (fd == INVALID_HANDLE_VALUE)
|
||||
return (-1);
|
||||
dwMode = PIPE_NOWAIT;
|
||||
SetNamedPipeHandleState(fd, &dwMode, NULL, NULL);
|
||||
sv[1] = (int)fd;
|
||||
|
||||
return (0);
|
||||
}
|
6
opal/event/WIN32-Code/misc.h
Обычный файл
6
opal/event/WIN32-Code/misc.h
Обычный файл
@ -0,0 +1,6 @@
|
||||
#ifndef MISC_H
|
||||
#define MISC_H
|
||||
|
||||
int gettimeofday(struct timeval *,struct timezone *);
|
||||
|
||||
#endif
|
406
opal/event/WIN32-Code/win32.c
Обычный файл
406
opal/event/WIN32-Code/win32.c
Обычный файл
@ -0,0 +1,406 @@
|
||||
/*
|
||||
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright 2003 Michael A. Davis <mike@datanerds.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <winsock2.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/tree.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "event.h"
|
||||
#include "event-internal.h"
|
||||
|
||||
#define XFREE(ptr) do { if (ptr) free(ptr); } while(0)
|
||||
|
||||
extern struct event_list timequeue;
|
||||
extern struct event_list addqueue;
|
||||
extern struct event_list signalqueue;
|
||||
|
||||
struct win_fd_set {
|
||||
u_int fd_count;
|
||||
SOCKET fd_array[1];
|
||||
};
|
||||
|
||||
int evsigcaught[NSIG];
|
||||
volatile sig_atomic_t signal_caught = 0;
|
||||
/* MSDN says this is required to handle SIGFPE */
|
||||
volatile double SIGFPE_REQ = 0.0f;
|
||||
|
||||
int signal_handler(int sig);
|
||||
void signal_process(void);
|
||||
int signal_recalc(void);
|
||||
|
||||
struct win32op {
|
||||
int fd_setsz;
|
||||
struct win_fd_set *readset_in;
|
||||
struct win_fd_set *writeset_in;
|
||||
struct win_fd_set *readset_out;
|
||||
struct win_fd_set *writeset_out;
|
||||
struct win_fd_set *exset_out;
|
||||
int n_events;
|
||||
int n_events_alloc;
|
||||
struct event **events;
|
||||
};
|
||||
|
||||
void *win32_init (void);
|
||||
int win32_insert (void *, struct event *);
|
||||
int win32_del (void *, struct event *);
|
||||
int win32_recalc (struct event_base *base, void *, int);
|
||||
int win32_dispatch (struct event_base *base, void *, struct timeval *);
|
||||
|
||||
struct eventop win32ops = {
|
||||
"win32",
|
||||
win32_init,
|
||||
win32_insert,
|
||||
win32_del,
|
||||
win32_recalc,
|
||||
win32_dispatch
|
||||
};
|
||||
|
||||
#define FD_SET_ALLOC_SIZE(n) ((sizeof(struct win_fd_set) + ((n)-1)*sizeof(SOCKET)))
|
||||
|
||||
static int
|
||||
realloc_fd_sets(struct win32op *op, size_t new_size)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
assert(new_size >= op->readset_in->fd_count &&
|
||||
new_size >= op->writeset_in->fd_count);
|
||||
assert(new_size >= 1);
|
||||
|
||||
size = FD_SET_ALLOC_SIZE(new_size);
|
||||
if (!(op->readset_in = realloc(op->readset_in, size)))
|
||||
return (-1);
|
||||
if (!(op->writeset_in = realloc(op->writeset_in, size)))
|
||||
return (-1);
|
||||
if (!(op->readset_out = realloc(op->readset_out, size)))
|
||||
return (-1);
|
||||
if (!(op->exset_out = realloc(op->exset_out, size)))
|
||||
return (-1);
|
||||
if (!(op->writeset_out = realloc(op->writeset_out, size)))
|
||||
return (-1);
|
||||
op->fd_setsz = new_size;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
timeval_to_ms(struct timeval *tv)
|
||||
{
|
||||
return ((tv->tv_sec * 1000) + (tv->tv_usec / 1000));
|
||||
}
|
||||
|
||||
static int
|
||||
do_fd_set(struct win32op *op, SOCKET s, int read)
|
||||
{
|
||||
unsigned int i;
|
||||
struct win_fd_set *set = read ? op->readset_in : op->writeset_in;
|
||||
for (i=0;i<set->fd_count;++i) {
|
||||
if (set->fd_array[i]==s)
|
||||
return (0);
|
||||
}
|
||||
if (set->fd_count == op->fd_setsz) {
|
||||
if (realloc_fd_sets(op, op->fd_setsz*2))
|
||||
return (-1);
|
||||
}
|
||||
set->fd_array[set->fd_count] = s;
|
||||
return (set->fd_count++);
|
||||
}
|
||||
|
||||
static int
|
||||
do_fd_clear(struct win32op *op, SOCKET s, int read)
|
||||
{
|
||||
unsigned int i;
|
||||
struct win_fd_set *set = read ? op->readset_in : op->writeset_in;
|
||||
for (i=0;i<set->fd_count;++i) {
|
||||
if (set->fd_array[i]==s) {
|
||||
if (--set->fd_count != i) {
|
||||
set->fd_array[i] = set->fd_array[set->fd_count];
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define NEVENT 64
|
||||
void *
|
||||
win32_init(void)
|
||||
{
|
||||
struct win32op *winop;
|
||||
size_t size;
|
||||
if (!(winop = calloc(1, sizeof(struct win32op))))
|
||||
return NULL;
|
||||
winop->fd_setsz = NEVENT;
|
||||
size = FD_SET_ALLOC_SIZE(NEVENT);
|
||||
if (!(winop->readset_in = malloc(size)))
|
||||
goto err;
|
||||
if (!(winop->writeset_in = malloc(size)))
|
||||
goto err;
|
||||
if (!(winop->readset_out = malloc(size)))
|
||||
goto err;
|
||||
if (!(winop->writeset_out = malloc(size)))
|
||||
goto err;
|
||||
if (!(winop->exset_out = malloc(size)))
|
||||
goto err;
|
||||
winop->n_events = 0;
|
||||
winop->n_events_alloc = NEVENT;
|
||||
if (!(winop->events = malloc(NEVENT*sizeof(struct event*))))
|
||||
goto err;
|
||||
winop->readset_in->fd_count = winop->writeset_in->fd_count = 0;
|
||||
winop->readset_out->fd_count = winop->writeset_out->fd_count
|
||||
= winop->exset_out->fd_count = 0;
|
||||
|
||||
return (winop);
|
||||
err:
|
||||
XFREE(winop->readset_in);
|
||||
XFREE(winop->writeset_in);
|
||||
XFREE(winop->readset_out);
|
||||
XFREE(winop->writeset_out);
|
||||
XFREE(winop->exset_out);
|
||||
XFREE(winop->events);
|
||||
XFREE(winop);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
win32_recalc(struct event_base *base, void *arg, int max)
|
||||
{
|
||||
return (signal_recalc());
|
||||
}
|
||||
|
||||
int
|
||||
win32_insert(struct win32op *win32op, struct event *ev)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (ev->ev_events & EV_SIGNAL) {
|
||||
if (ev->ev_events & (EV_READ|EV_WRITE))
|
||||
event_errx(1, "%s: EV_SIGNAL incompatible use",
|
||||
__func__);
|
||||
if((int)signal(EVENT_SIGNAL(ev), signal_handler) == -1)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
if (!(ev->ev_events & (EV_READ|EV_WRITE)))
|
||||
return (0);
|
||||
|
||||
for (i=0;i<win32op->n_events;++i) {
|
||||
if(win32op->events[i] == ev) {
|
||||
event_debug(("%s: Event for %d already inserted.",
|
||||
__func__, (int)ev->ev_fd));
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
event_debug(("%s: adding event for %d", __func__, (int)ev->ev_fd));
|
||||
if (ev->ev_events & EV_READ) {
|
||||
if (do_fd_set(win32op, ev->ev_fd, 1)<0)
|
||||
return (-1);
|
||||
}
|
||||
if (ev->ev_events & EV_WRITE) {
|
||||
if (do_fd_set(win32op, ev->ev_fd, 0)<0)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (win32op->n_events_alloc == win32op->n_events) {
|
||||
size_t sz;
|
||||
win32op->n_events_alloc *= 2;
|
||||
sz = sizeof(struct event*)*win32op->n_events_alloc;
|
||||
if (!(win32op->events = realloc(win32op->events, sz)))
|
||||
return (-1);
|
||||
}
|
||||
win32op->events[win32op->n_events++] = ev;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
win32_del(struct win32op *win32op, struct event *ev)
|
||||
{
|
||||
int i, found;
|
||||
|
||||
if (ev->ev_events & EV_SIGNAL)
|
||||
return ((int)signal(EVENT_SIGNAL(ev), SIG_IGN));
|
||||
|
||||
found = -1;
|
||||
for (i=0;i<win32op->n_events;++i) {
|
||||
if(win32op->events[i] == ev) {
|
||||
found = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found < 0) {
|
||||
event_debug(("%s: Unable to remove non-inserted event for %d",
|
||||
__func__, ev->ev_fd));
|
||||
return (-1);
|
||||
}
|
||||
event_debug(("%s: Removing event for %d", __func__, ev->ev_fd));
|
||||
if (ev->ev_events & EV_READ)
|
||||
do_fd_clear(win32op, ev->ev_fd, 1);
|
||||
if (ev->ev_events & EV_WRITE)
|
||||
do_fd_clear(win32op, ev->ev_fd, 0);
|
||||
|
||||
if (i != --win32op->n_events) {
|
||||
win32op->events[i] = win32op->events[win32op->n_events];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
fd_set_copy(struct win_fd_set *out, const struct win_fd_set *in)
|
||||
{
|
||||
out->fd_count = in->fd_count;
|
||||
memcpy(out->fd_array, in->fd_array, in->fd_count * (sizeof(SOCKET)));
|
||||
}
|
||||
|
||||
/*
|
||||
static void dump_fd_set(struct win_fd_set *s)
|
||||
{
|
||||
unsigned int i;
|
||||
printf("[ ");
|
||||
for(i=0;i<s->fd_count;++i)
|
||||
printf("%d ",(int)s->fd_array[i]);
|
||||
printf("]\n");
|
||||
}
|
||||
*/
|
||||
|
||||
int
|
||||
win32_dispatch(struct event_base *base, struct win32op *win32op,
|
||||
struct timeval *tv)
|
||||
{
|
||||
int res = 0;
|
||||
int i;
|
||||
int fd_count;
|
||||
|
||||
fd_set_copy(win32op->readset_out, win32op->readset_in);
|
||||
fd_set_copy(win32op->exset_out, win32op->readset_in);
|
||||
fd_set_copy(win32op->writeset_out, win32op->writeset_in);
|
||||
|
||||
fd_count =
|
||||
(win32op->readset_out->fd_count > win32op->writeset_out->fd_count) ?
|
||||
win32op->readset_out->fd_count : win32op->writeset_out->fd_count;
|
||||
|
||||
if (!fd_count) {
|
||||
/* Windows doesn't like you to call select() with no sockets */
|
||||
Sleep(timeval_to_ms(tv));
|
||||
signal_process();
|
||||
return (0);
|
||||
}
|
||||
|
||||
res = select(fd_count,
|
||||
(struct fd_set*)win32op->readset_out,
|
||||
(struct fd_set*)win32op->writeset_out,
|
||||
(struct fd_set*)win32op->exset_out, tv);
|
||||
|
||||
event_debug(("%s: select returned %d", __func__, res));
|
||||
|
||||
if(res <= 0) {
|
||||
signal_process();
|
||||
return res;
|
||||
}
|
||||
|
||||
for (i=0;i<win32op->n_events;++i) {
|
||||
struct event *ev;
|
||||
int got = 0;
|
||||
ev = win32op->events[i];
|
||||
if ((ev->ev_events & EV_READ)) {
|
||||
if (FD_ISSET(ev->ev_fd, win32op->readset_out) ||
|
||||
FD_ISSET(ev->ev_fd, win32op->exset_out)) {
|
||||
got |= EV_READ;
|
||||
}
|
||||
}
|
||||
if ((ev->ev_events & EV_WRITE)) {
|
||||
if (FD_ISSET(ev->ev_fd, win32op->writeset_out)) {
|
||||
got |= EV_WRITE;
|
||||
}
|
||||
}
|
||||
if (!got)
|
||||
continue;
|
||||
if (!(ev->ev_events & EV_PERSIST)) {
|
||||
event_del(ev);
|
||||
}
|
||||
event_active(ev,got,1);
|
||||
}
|
||||
|
||||
if (signal_recalc() == -1)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
signal_handler(int sig)
|
||||
{
|
||||
evsigcaught[sig]++;
|
||||
signal_caught = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
signal_recalc(void)
|
||||
{
|
||||
struct event *ev;
|
||||
|
||||
/* Reinstall our signal handler. */
|
||||
TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
|
||||
if((int)signal(EVENT_SIGNAL(ev), signal_handler) == -1)
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
signal_process(void)
|
||||
{
|
||||
struct event *ev;
|
||||
short ncalls;
|
||||
|
||||
TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
|
||||
ncalls = evsigcaught[EVENT_SIGNAL(ev)];
|
||||
if (ncalls) {
|
||||
if (!(ev->ev_events & EV_PERSIST))
|
||||
event_del(ev);
|
||||
event_active(ev, EV_SIGNAL, ncalls);
|
||||
}
|
||||
}
|
||||
|
||||
memset(evsigcaught, 0, sizeof(evsigcaught));
|
||||
signal_caught = 0;
|
||||
}
|
5
opal/event/WIN32-Prj/CVS/Entries
Обычный файл
5
opal/event/WIN32-Prj/CVS/Entries
Обычный файл
@ -0,0 +1,5 @@
|
||||
D/event_test////
|
||||
D/signal_test////
|
||||
D/time_test////
|
||||
/libevent.dsp/1.1/Sat Jun 7 19:57:00 2003//
|
||||
/libevent.dsw/1.1/Sat Jun 7 19:57:00 2003//
|
1
opal/event/WIN32-Prj/CVS/Repository
Обычный файл
1
opal/event/WIN32-Prj/CVS/Repository
Обычный файл
@ -0,0 +1 @@
|
||||
libevent/WIN32-Prj
|
1
opal/event/WIN32-Prj/CVS/Root
Обычный файл
1
opal/event/WIN32-Prj/CVS/Root
Обычный файл
@ -0,0 +1 @@
|
||||
nprovos@cvs.sourceforge.net:/cvsroot/levent
|
3
opal/event/WIN32-Prj/event_test/CVS/Entries
Обычный файл
3
opal/event/WIN32-Prj/event_test/CVS/Entries
Обычный файл
@ -0,0 +1,3 @@
|
||||
/event_test.dsp/1.1/Sat Jun 7 19:57:00 2003//
|
||||
/test.txt/1.1/Sat Jun 7 19:57:00 2003//
|
||||
D
|
1
opal/event/WIN32-Prj/event_test/CVS/Repository
Обычный файл
1
opal/event/WIN32-Prj/event_test/CVS/Repository
Обычный файл
@ -0,0 +1 @@
|
||||
libevent/WIN32-Prj/event_test
|
1
opal/event/WIN32-Prj/event_test/CVS/Root
Обычный файл
1
opal/event/WIN32-Prj/event_test/CVS/Root
Обычный файл
@ -0,0 +1 @@
|
||||
nprovos@cvs.sourceforge.net:/cvsroot/levent
|
100
opal/event/WIN32-Prj/event_test/event_test.dsp
Обычный файл
100
opal/event/WIN32-Prj/event_test/event_test.dsp
Обычный файл
@ -0,0 +1,100 @@
|
||||
# Microsoft Developer Studio Project File - Name="event_test" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=event_test - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "event_test.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "event_test.mak" CFG="event_test - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "event_test - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "event_test - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "event_test - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /I "..\..\\" /I "..\..\WIN32-Code" /I "..\..\compat" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "event_test - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\\" /I "..\..\WIN32-Code" /I "..\..\compat" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "event_test - Win32 Release"
|
||||
# Name "event_test - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\..\sample\event-test.c"
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
180
opal/event/WIN32-Prj/event_test/test.txt
Обычный файл
180
opal/event/WIN32-Prj/event_test/test.txt
Обычный файл
@ -0,0 +1,180 @@
|
||||
|
||||
Platform SDK: File Storage
|
||||
ReadFile
|
||||
The ReadFile function reads data from a file, starting at the position indicated by the file pointer. After the read operation has been completed, the file pointer is adjusted by the number of bytes actually read, unless the file handle is created with the overlapped attribute. If the file handle is created for overlapped input and output (I/O), the application must adjust the position of the file pointer after the read operation.
|
||||
|
||||
This function is designed for both synchronous and asynchronous operation. The ReadFileEx function is designed solely for asynchronous operation. It lets an application perform other processing during a file read operation.
|
||||
|
||||
BOOL ReadFile(
|
||||
HANDLE hFile, // handle to file
|
||||
LPVOID lpBuffer, // data buffer
|
||||
DWORD nNumberOfBytesToRead, // number of bytes to read
|
||||
LPDWORD lpNumberOfBytesRead, // number of bytes read
|
||||
LPOVERLAPPED lpOverlapped // overlapped buffer
|
||||
);
|
||||
Parameters
|
||||
hFile
|
||||
[in] Handle to the file to be read. The file handle must have been created with GENERIC_READ access to the file.
|
||||
Windows NT/2000/XP: For asynchronous read operations, hFile can be any handle opened with the FILE_FLAG_OVERLAPPED flag by the CreateFile function, or a socket handle returned by the socket or accept function.
|
||||
|
||||
Windows 95/98/Me: For asynchronous read operations, hFile can be a communications resource opened with the FILE_FLAG_OVERLAPPED flag by CreateFile, or a socket handle returned by socket or accept. You cannot perform asynchronous read operations on mailslots, named pipes, or disk files.
|
||||
|
||||
lpBuffer
|
||||
[out] Pointer to the buffer that receives the data read from the file.
|
||||
nNumberOfBytesToRead
|
||||
[in] Specifies the number of bytes to be read from the file.
|
||||
lpNumberOfBytesRead
|
||||
[out] Pointer to the variable that receives the number of bytes read. ReadFile sets this value to zero before doing any work or error checking. If this parameter is zero when ReadFile returns TRUE on a named pipe, the other end of the message-mode pipe called the WriteFile function with nNumberOfBytesToWrite set to zero.
|
||||
Windows NT/2000/XP: If lpOverlapped is NULL, lpNumberOfBytesRead cannot be NULL. If lpOverlapped is not NULL, lpNumberOfBytesRead can be NULL. If this is an overlapped read operation, you can get the number of bytes read by calling GetOverlappedResult. If hFile is associated with an I/O completion port, you can get the number of bytes read by calling GetQueuedCompletionStatus.
|
||||
|
||||
If I/O completion ports are used and you are using a callback routine to free the memory allocated to the OVERLAPPED structure pointed to by the lpOverlapped parameter, specify NULL as the value of this parameter to avoid a memory corruption problem during the deallocation. This memory corruption problem will cause an invalid number of bytes to be returned in this parameter.
|
||||
|
||||
Windows 95/98/Me: This parameter cannot be NULL.
|
||||
|
||||
lpOverlapped
|
||||
[in] Pointer to an OVERLAPPED structure. This structure is required if hFile was created with FILE_FLAG_OVERLAPPED.
|
||||
If hFile was opened with FILE_FLAG_OVERLAPPED, the lpOverlapped parameter must not be NULL. It must point to a valid OVERLAPPED structure. If hFile was created with FILE_FLAG_OVERLAPPED and lpOverlapped is NULL, the function can incorrectly report that the read operation is complete.
|
||||
|
||||
If hFile was opened with FILE_FLAG_OVERLAPPED and lpOverlapped is not NULL, the read operation starts at the offset specified in the OVERLAPPED structure and ReadFile may return before the read operation has been completed. In this case, ReadFile returns FALSE and the GetLastError function returns ERROR_IO_PENDING. This allows the calling process to continue while the read operation finishes. The event specified in the OVERLAPPED structure is set to the signaled state upon completion of the read operation.
|
||||
|
||||
If hFile was not opened with FILE_FLAG_OVERLAPPED and lpOverlapped is NULL, the read operation starts at the current file position and ReadFile does not return until the operation has been completed.
|
||||
|
||||
Windows NT/2000/XP: If hFile is not opened with FILE_FLAG_OVERLAPPED and lpOverlapped is not NULL, the read operation starts at the offset specified in the OVERLAPPED structure. ReadFile does not return until the read operation has been completed.
|
||||
|
||||
Windows 95/98/Me: For operations on files, disks, pipes, or mailslots, this parameter must be NULL; a pointer to an OVERLAPPED structure causes the call to fail. However, Windows 95/98/Me supports overlapped I/O on serial and parallel ports.
|
||||
|
||||
Return Values
|
||||
The ReadFile function returns when one of the following is true: a write operation completes on the write end of the pipe, the number of bytes requested has been read, or an error occurs.
|
||||
|
||||
If the function succeeds, the return value is nonzero.
|
||||
|
||||
If the return value is nonzero and the number of bytes read is zero, the file pointer was beyond the current end of the file at the time of the read operation. However, if the file was opened with FILE_FLAG_OVERLAPPED and lpOverlapped is not NULL, the return value is FALSE and GetLastError returns ERROR_HANDLE_EOF when the file pointer goes beyond the current end of file.
|
||||
|
||||
If the function fails, the return value is zero. To get extended error information, call GetLastError.
|
||||
|
||||
Remarks
|
||||
If part of the file is locked by another process and the read operation overlaps the locked portion, this function fails.
|
||||
|
||||
An application must meet certain requirements when working with files opened with FILE_FLAG_NO_BUFFERING:
|
||||
|
||||
File access must begin at byte offsets within the file that are integer multiples of the volume's sector size. To determine a volume's sector size, call the GetDiskFreeSpace function.
|
||||
File access must be for numbers of bytes that are integer multiples of the volume's sector size. For example, if the sector size is 512 bytes, an application can request reads and writes of 512, 1024, or 2048 bytes, but not of 335, 981, or 7171 bytes.
|
||||
Buffer addresses for read and write operations must be sector aligned (aligned on addresses in memory that are integer multiples of the volume's sector size). One way to sector align buffers is to use the VirtualAlloc function to allocate the buffers. This function allocates memory that is aligned on addresses that are integer multiples of the system's page size. Because both page and volume sector sizes are powers of 2, memory aligned by multiples of the system's page size is also aligned by multiples of the volume's sector size.
|
||||
Accessing the input buffer while a read operation is using the buffer may lead to corruption of the data read into that buffer. Applications must not read from, write to, reallocate, or free the input buffer that a read operation is using until the read operation completes.
|
||||
|
||||
Characters can be read from the console input buffer by using ReadFile with a handle to console input. The console mode determines the exact behavior of the ReadFile function.
|
||||
|
||||
If a named pipe is being read in message mode and the next message is longer than the nNumberOfBytesToRead parameter specifies, ReadFile returns FALSE and GetLastError returns ERROR_MORE_DATA. The remainder of the message may be read by a subsequent call to the ReadFile or PeekNamedPipe function.
|
||||
|
||||
When reading from a communications device, the behavior of ReadFile is governed by the current communication time-outs as set and retrieved using the SetCommTimeouts and GetCommTimeouts functions. Unpredictable results can occur if you fail to set the time-out values. For more information about communication time-outs, see COMMTIMEOUTS.
|
||||
|
||||
If ReadFile attempts to read from a mailslot whose buffer is too small, the function returns FALSE and GetLastError returns ERROR_INSUFFICIENT_BUFFER.
|
||||
|
||||
If the anonymous write pipe handle has been closed and ReadFile attempts to read using the corresponding anonymous read pipe handle, the function returns FALSE and GetLastError returns ERROR_BROKEN_PIPE.
|
||||
|
||||
The ReadFile function may fail and return ERROR_INVALID_USER_BUFFER or ERROR_NOT_ENOUGH_MEMORY whenever there are too many outstanding asynchronous I/O requests.
|
||||
|
||||
The ReadFile code to check for the end-of-file condition (eof) differs for synchronous and asynchronous read operations.
|
||||
|
||||
When a synchronous read operation reaches the end of a file, ReadFile returns TRUE and sets *lpNumberOfBytesRead to zero. The following sample code tests for end-of-file for a synchronous read operation:
|
||||
|
||||
// Attempt a synchronous read operation.
|
||||
bResult = ReadFile(hFile, &inBuffer, nBytesToRead, &nBytesRead, NULL) ;
|
||||
// Check for end of file.
|
||||
if (bResult && nBytesRead == 0, )
|
||||
{
|
||||
// we're at the end of the file
|
||||
}
|
||||
An asynchronous read operation can encounter the end of a file during the initiating call to ReadFile, or during subsequent asynchronous operation.
|
||||
|
||||
If EOF is detected at ReadFile time for an asynchronous read operation, ReadFile returns FALSE and GetLastError returns ERROR_HANDLE_EOF.
|
||||
|
||||
If EOF is detected during subsequent asynchronous operation, the call to GetOverlappedResult to obtain the results of that operation returns FALSE and GetLastError returns ERROR_HANDLE_EOF.
|
||||
|
||||
To cancel all pending asynchronous I/O operations, use the CancelIo function. This function only cancels operations issued by the calling thread for the specified file handle. I/O operations that are canceled complete with the error ERROR_OPERATION_ABORTED.
|
||||
|
||||
If you are attempting to read from a floppy drive that does not have a floppy disk, the system displays a message box prompting the user to retry the operation. To prevent the system from displaying this message box, call the SetErrorMode function with SEM_NOOPENFILEERRORBOX.
|
||||
|
||||
The following sample code illustrates testing for end-of-file for an asynchronous read operation:
|
||||
|
||||
// set up overlapped structure fields
|
||||
gOverLapped.Offset = 0;
|
||||
gOverLapped.OffsetHigh = 0;
|
||||
gOverLapped.hEvent = hEvent;
|
||||
|
||||
// attempt an asynchronous read operation
|
||||
bResult = ReadFile(hFile, &inBuffer, nBytesToRead, &nBytesRead,
|
||||
&gOverlapped) ;
|
||||
|
||||
// if there was a problem, or the async. operation's still pending ...
|
||||
if (!bResult)
|
||||
{
|
||||
// deal with the error code
|
||||
switch (dwError = GetLastError())
|
||||
{
|
||||
case ERROR_HANDLE_EOF:
|
||||
{
|
||||
// we have reached the end of the file
|
||||
// during the call to ReadFile
|
||||
|
||||
// code to handle that
|
||||
}
|
||||
|
||||
case ERROR_IO_PENDING:
|
||||
{
|
||||
// asynchronous i/o is still in progress
|
||||
|
||||
// do something else for a while
|
||||
GoDoSomethingElse() ;
|
||||
|
||||
// check on the results of the asynchronous read
|
||||
bResult = GetOverlappedResult(hFile, &gOverlapped,
|
||||
&nBytesRead, FALSE) ;
|
||||
|
||||
// if there was a problem ...
|
||||
if (!bResult)
|
||||
{
|
||||
// deal with the error code
|
||||
switch (dwError = GetLastError())
|
||||
{
|
||||
case ERROR_HANDLE_EOF:
|
||||
{
|
||||
// we have reached the end of
|
||||
// the file during asynchronous
|
||||
// operation
|
||||
}
|
||||
|
||||
// deal with other error cases
|
||||
}
|
||||
}
|
||||
} // end case
|
||||
|
||||
// deal with other error cases
|
||||
|
||||
} // end switch
|
||||
} // end if
|
||||
Example Code
|
||||
For an example, see Reading, Writing, and Locking Files.
|
||||
|
||||
Requirements
|
||||
Windows NT/2000/XP: Included in Windows NT 3.1 and later.
|
||||
Windows 95/98/Me: Included in Windows 95 and later.
|
||||
Header: Declared in Winbase.h; include Windows.h.
|
||||
Library: Use Kernel32.lib.
|
||||
|
||||
See Also
|
||||
File I/O Overview, File I/O Functions, CancelIo, CreateFile, GetCommTimeouts, GetOverlappedResult, GetQueuedCompletionStatus, OVERLAPPED, PeekNamedPipe, ReadFileEx, SetCommTimeouts, SetErrorMode, WriteFile
|
||||
|
||||
Platform SDK Release: November 2001 What did you think of this topic?
|
||||
Let us know. Order a Platform SDK CD Online
|
||||
(U.S/Canada) (International)
|
||||
|
||||
|
||||
|
||||
Requirements
|
||||
Windows NT/2000/XP: Included in Windows NT 3.1 and later.
|
||||
Windows 95/98/Me: Included in Windows 95 and later.
|
||||
Header: Declared in Winbase.h; include Windows.h.
|
||||
Library: Use Kernel32.lib.
|
||||
See Also
|
||||
File I/O Overview, File I/O Functions, CancelIo, CreateFile, GetCommTimeouts, GetOverlappedResult, GetQueuedCompletionStatus, OVERLAPPED, PeekNamedPipe, ReadFileEx, SetCommTimeouts, SetErrorMode, WriteFile
|
128
opal/event/WIN32-Prj/libevent.dsp
Обычный файл
128
opal/event/WIN32-Prj/libevent.dsp
Обычный файл
@ -0,0 +1,128 @@
|
||||
# Microsoft Developer Studio Project File - Name="libevent" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=libevent - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "libevent.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "libevent.mak" CFG="libevent - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "libevent - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "libevent - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "libevent - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /I "..\\" /I "..\WIN32-Code" /I "..\compat" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "libevent - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\\" /I "..\WIN32-Code" /I "..\compat" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "libevent - Win32 Release"
|
||||
# Name "libevent - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\err.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\event.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\WIN32-Code\misc.c"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\WIN32-Code\win32.c"
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\acconfig.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\WIN32-Code\config.h"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\compat\err.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\event.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\WIN32-Code\misc.h"
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
74
opal/event/WIN32-Prj/libevent.dsw
Обычный файл
74
opal/event/WIN32-Prj/libevent.dsw
Обычный файл
@ -0,0 +1,74 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "event_test"=".\event_test\event_test.dsp" - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name libevent
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "libevent"=".\libevent.dsp" - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "signal_test"=".\signal_test\signal_test.dsp" - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name libevent
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "time_test"=".\time_test\time_test.dsp" - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name libevent
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
2
opal/event/WIN32-Prj/signal_test/CVS/Entries
Обычный файл
2
opal/event/WIN32-Prj/signal_test/CVS/Entries
Обычный файл
@ -0,0 +1,2 @@
|
||||
/signal_test.dsp/1.1/Sat Jun 7 19:57:00 2003//
|
||||
D
|
1
opal/event/WIN32-Prj/signal_test/CVS/Repository
Обычный файл
1
opal/event/WIN32-Prj/signal_test/CVS/Repository
Обычный файл
@ -0,0 +1 @@
|
||||
libevent/WIN32-Prj/signal_test
|
1
opal/event/WIN32-Prj/signal_test/CVS/Root
Обычный файл
1
opal/event/WIN32-Prj/signal_test/CVS/Root
Обычный файл
@ -0,0 +1 @@
|
||||
nprovos@cvs.sourceforge.net:/cvsroot/levent
|
100
opal/event/WIN32-Prj/signal_test/signal_test.dsp
Обычный файл
100
opal/event/WIN32-Prj/signal_test/signal_test.dsp
Обычный файл
@ -0,0 +1,100 @@
|
||||
# Microsoft Developer Studio Project File - Name="signal_test" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=signal_test - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "signal_test.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "signal_test.mak" CFG="signal_test - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "signal_test - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "signal_test - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "signal_test - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "signal_test - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\\" /I "..\..\WIN32-Code" /I "..\..\compat" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "signal_test - Win32 Release"
|
||||
# Name "signal_test - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\..\sample\signal-test.c"
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
2
opal/event/WIN32-Prj/time_test/CVS/Entries
Обычный файл
2
opal/event/WIN32-Prj/time_test/CVS/Entries
Обычный файл
@ -0,0 +1,2 @@
|
||||
/time_test.dsp/1.1/Sat Jun 7 19:57:00 2003//
|
||||
D
|
1
opal/event/WIN32-Prj/time_test/CVS/Repository
Обычный файл
1
opal/event/WIN32-Prj/time_test/CVS/Repository
Обычный файл
@ -0,0 +1 @@
|
||||
libevent/WIN32-Prj/time_test
|
1
opal/event/WIN32-Prj/time_test/CVS/Root
Обычный файл
1
opal/event/WIN32-Prj/time_test/CVS/Root
Обычный файл
@ -0,0 +1 @@
|
||||
nprovos@cvs.sourceforge.net:/cvsroot/levent
|
100
opal/event/WIN32-Prj/time_test/time_test.dsp
Обычный файл
100
opal/event/WIN32-Prj/time_test/time_test.dsp
Обычный файл
@ -0,0 +1,100 @@
|
||||
# Microsoft Developer Studio Project File - Name="time_test" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=time_test - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "time_test.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "time_test.mak" CFG="time_test - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "time_test - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "time_test - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "time_test - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "time_test - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\\" /I "..\..\WIN32-Code" /I "..\..\compat" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "time_test - Win32 Release"
|
||||
# Name "time_test - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\..\sample\time-test.c"
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
423
opal/event/buffer.c
Обычный файл
423
opal/event/buffer.c
Обычный файл
@ -0,0 +1,423 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2003 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opal_config.h"
|
||||
|
||||
#ifdef HAVE_VASPRINTF
|
||||
/* If we have vasprintf, we need to define this before we include stdio.h. */
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "event.h"
|
||||
|
||||
struct evbuffer *
|
||||
evbuffer_new(void)
|
||||
{
|
||||
struct evbuffer *buffer;
|
||||
|
||||
buffer = calloc(1, sizeof(struct evbuffer));
|
||||
|
||||
return (buffer);
|
||||
}
|
||||
|
||||
void
|
||||
evbuffer_free(struct evbuffer *buffer)
|
||||
{
|
||||
if (buffer->orig_buffer != NULL)
|
||||
free(buffer->orig_buffer);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a destructive add. The data from one buffer moves into
|
||||
* the other buffer.
|
||||
*/
|
||||
|
||||
#define SWAP(x,y) do { \
|
||||
(x)->buffer = (y)->buffer; \
|
||||
(x)->orig_buffer = (y)->orig_buffer; \
|
||||
(x)->misalign = (y)->misalign; \
|
||||
(x)->totallen = (y)->totallen; \
|
||||
(x)->off = (y)->off; \
|
||||
} while (0)
|
||||
|
||||
int
|
||||
evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
|
||||
{
|
||||
int res;
|
||||
|
||||
/* Short cut for better performance */
|
||||
if (outbuf->off == 0) {
|
||||
struct evbuffer tmp;
|
||||
size_t oldoff = inbuf->off;
|
||||
|
||||
/* Swap them directly */
|
||||
SWAP(&tmp, outbuf);
|
||||
SWAP(outbuf, inbuf);
|
||||
SWAP(inbuf, &tmp);
|
||||
|
||||
/*
|
||||
* Optimization comes with a price; we need to notify the
|
||||
* buffer if necessary of the changes. oldoff is the amount
|
||||
* of data that we tranfered from inbuf to outbuf
|
||||
*/
|
||||
if (inbuf->off != oldoff && inbuf->cb != NULL)
|
||||
(*inbuf->cb)(inbuf, oldoff, inbuf->off, inbuf->cbarg);
|
||||
if (oldoff && outbuf->cb != NULL)
|
||||
(*outbuf->cb)(outbuf, 0, oldoff, outbuf->cbarg);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
res = evbuffer_add(outbuf, inbuf->buffer, inbuf->off);
|
||||
if (res == 0)
|
||||
evbuffer_drain(inbuf, inbuf->off);
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
int
|
||||
evbuffer_add_printf(struct evbuffer *buf, char *fmt, ...)
|
||||
{
|
||||
int res = -1;
|
||||
char *msg;
|
||||
#ifndef HAVE_VASPRINTF
|
||||
static char buffer[4096];
|
||||
#endif
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
#ifdef HAVE_VASPRINTF
|
||||
if (vasprintf(&msg, fmt, ap) == -1)
|
||||
goto end;
|
||||
#else
|
||||
# ifdef WIN32
|
||||
_vsnprintf(buffer, sizeof(buffer) - 1, fmt, ap);
|
||||
buffer[sizeof(buffer)-1] = '\0';
|
||||
# else /* ! WIN32 */
|
||||
vsnprintf(buffer, sizeof(buffer), fmt, ap);
|
||||
# endif
|
||||
msg = buffer;
|
||||
#endif
|
||||
|
||||
res = strlen(msg);
|
||||
if (evbuffer_add(buf, msg, res) == -1)
|
||||
res = -1;
|
||||
#ifdef HAVE_VASPRINTF
|
||||
free(msg);
|
||||
|
||||
end:
|
||||
#endif
|
||||
va_end(ap);
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
/* Reads data from an event buffer and drains the bytes read */
|
||||
|
||||
int
|
||||
evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen)
|
||||
{
|
||||
size_t nread = datlen;
|
||||
if (nread >= buf->off)
|
||||
nread = buf->off;
|
||||
|
||||
memcpy(data, buf->buffer, nread);
|
||||
evbuffer_drain(buf, nread);
|
||||
|
||||
return (nread);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'.
|
||||
* The returned buffer needs to be freed by the called.
|
||||
*/
|
||||
|
||||
char *
|
||||
evbuffer_readline(struct evbuffer *buffer)
|
||||
{
|
||||
char *data = (char*) OPAL_EVBUFFER_DATA(buffer);
|
||||
size_t len = OPAL_EVBUFFER_LENGTH(buffer);
|
||||
char *line;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (int) len; i++) {
|
||||
if (data[i] == '\r' || data[i] == '\n')
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == (int) len)
|
||||
return (NULL);
|
||||
|
||||
if ((line = malloc(i + 1)) == NULL) {
|
||||
fprintf(stderr, "%s: out of memory\n", __func__);
|
||||
evbuffer_drain(buffer, i);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
memcpy(line, data, i);
|
||||
line[i] = '\0';
|
||||
|
||||
/*
|
||||
* Some protocols terminate a line with '\r\n', so check for
|
||||
* that, too.
|
||||
*/
|
||||
if ( i < (int) len - 1 ) {
|
||||
char fch = data[i], sch = data[i+1];
|
||||
|
||||
/* Drain one more character if needed */
|
||||
if ( (sch == '\r' || sch == '\n') && sch != fch )
|
||||
i += 1;
|
||||
}
|
||||
|
||||
evbuffer_drain(buffer, i + 1);
|
||||
|
||||
return (line);
|
||||
}
|
||||
|
||||
/* Adds data to an event buffer */
|
||||
|
||||
static inline void
|
||||
evbuffer_align(struct evbuffer *buf)
|
||||
{
|
||||
memmove(buf->orig_buffer, buf->buffer, buf->off);
|
||||
buf->buffer = buf->orig_buffer;
|
||||
buf->misalign = 0;
|
||||
}
|
||||
|
||||
/* Expands the available space in the event buffer to at least datlen */
|
||||
|
||||
int
|
||||
evbuffer_expand(struct evbuffer *buf, size_t datlen)
|
||||
{
|
||||
size_t need = buf->misalign + buf->off + datlen;
|
||||
|
||||
/* If we can fit all the data, then we don't have to do anything */
|
||||
if (buf->totallen >= need)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* If the misalignment fulfills our data needs, we just force an
|
||||
* alignment to happen. Afterwards, we have enough space.
|
||||
*/
|
||||
if (buf->misalign >= datlen) {
|
||||
evbuffer_align(buf);
|
||||
} else {
|
||||
void *newbuf;
|
||||
size_t length = buf->totallen;
|
||||
|
||||
if (length < 256)
|
||||
length = 256;
|
||||
while (length < need)
|
||||
length <<= 1;
|
||||
|
||||
if (buf->orig_buffer != buf->buffer)
|
||||
evbuffer_align(buf);
|
||||
if ((newbuf = realloc(buf->buffer, length)) == NULL)
|
||||
return (-1);
|
||||
|
||||
buf->orig_buffer = buf->buffer = newbuf;
|
||||
buf->totallen = length;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evbuffer_add(struct evbuffer *buf, void *data, size_t datlen)
|
||||
{
|
||||
size_t need = buf->misalign + buf->off + datlen;
|
||||
size_t oldoff = buf->off;
|
||||
|
||||
if (buf->totallen < need) {
|
||||
if (evbuffer_expand(buf, datlen) == -1)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
memcpy(buf->buffer + buf->off, data, datlen);
|
||||
buf->off += datlen;
|
||||
|
||||
if (datlen && buf->cb != NULL)
|
||||
(*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
evbuffer_drain(struct evbuffer *buf, size_t len)
|
||||
{
|
||||
size_t oldoff = buf->off;
|
||||
|
||||
if (len >= buf->off) {
|
||||
buf->off = 0;
|
||||
buf->buffer = buf->orig_buffer;
|
||||
buf->misalign = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
buf->buffer += len;
|
||||
buf->misalign += len;
|
||||
|
||||
buf->off -= len;
|
||||
|
||||
done:
|
||||
/* Tell someone about changes in this buffer */
|
||||
if (buf->off != oldoff && buf->cb != NULL)
|
||||
(*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads data from a file descriptor into a buffer.
|
||||
*/
|
||||
|
||||
#define EVBUFFER_MAX_READ 4096
|
||||
|
||||
int
|
||||
evbuffer_read(struct evbuffer *buf, int fd, int howmuch)
|
||||
{
|
||||
u_char *p;
|
||||
size_t oldoff = buf->off;
|
||||
int n = EVBUFFER_MAX_READ;
|
||||
#ifdef WIN32
|
||||
DWORD dwBytesRead;
|
||||
#endif
|
||||
|
||||
#ifdef FIONREAD
|
||||
if (ioctl(fd, FIONREAD, &n) == -1 || n == 0)
|
||||
n = EVBUFFER_MAX_READ;
|
||||
#endif
|
||||
if (howmuch < 0 || howmuch > n)
|
||||
howmuch = n;
|
||||
|
||||
/* If we don't have FIONREAD, we might waste some space here */
|
||||
if (evbuffer_expand(buf, howmuch) == -1)
|
||||
return (-1);
|
||||
|
||||
/* We can append new data at this point */
|
||||
p = buf->buffer + buf->off;
|
||||
|
||||
#ifndef WIN32
|
||||
n = read(fd, p, howmuch);
|
||||
if (n == -1)
|
||||
return (-1);
|
||||
if (n == 0)
|
||||
return (0);
|
||||
#else
|
||||
n = ReadFile((HANDLE)fd, p, howmuch, &dwBytesRead, NULL);
|
||||
if (n == 0)
|
||||
return (-1);
|
||||
if (dwBytesRead == 0)
|
||||
return (0);
|
||||
n = dwBytesRead;
|
||||
#endif
|
||||
|
||||
buf->off += n;
|
||||
|
||||
/* Tell someone about changes in this buffer */
|
||||
if (buf->off != oldoff && buf->cb != NULL)
|
||||
(*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
|
||||
|
||||
return (n);
|
||||
}
|
||||
|
||||
int
|
||||
evbuffer_write(struct evbuffer *buffer, int fd)
|
||||
{
|
||||
int n;
|
||||
#ifdef WIN32
|
||||
DWORD dwBytesWritten;
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
n = write(fd, buffer->buffer, buffer->off);
|
||||
if (n == -1)
|
||||
return (-1);
|
||||
if (n == 0)
|
||||
return (0);
|
||||
#else
|
||||
n = WriteFile((HANDLE)fd, buffer->buffer, buffer->off, &dwBytesWritten, NULL);
|
||||
if (n == 0)
|
||||
return (-1);
|
||||
if (dwBytesWritten == 0)
|
||||
return (0);
|
||||
n = dwBytesWritten;
|
||||
#endif
|
||||
evbuffer_drain(buffer, n);
|
||||
|
||||
return (n);
|
||||
}
|
||||
|
||||
u_char *
|
||||
evbuffer_find(struct evbuffer *buffer, u_char *what, size_t len)
|
||||
{
|
||||
size_t remain = buffer->off;
|
||||
u_char *search = buffer->buffer;
|
||||
u_char *p;
|
||||
|
||||
while ((p = memchr(search, *what, remain)) != NULL && remain >= len) {
|
||||
if (memcmp(p, what, len) == 0)
|
||||
return (p);
|
||||
|
||||
search = p + 1;
|
||||
remain = buffer->off - (size_t)(search - buffer->buffer);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void evbuffer_setcb(struct evbuffer *buffer,
|
||||
void (*cb)(struct evbuffer *, size_t, size_t, void *),
|
||||
void *cbarg)
|
||||
{
|
||||
buffer->cb = cb;
|
||||
buffer->cbarg = cbarg;
|
||||
}
|
23
opal/event/compat/Makefile.am
Обычный файл
23
opal/event/compat/Makefile.am
Обычный файл
@ -0,0 +1,23 @@
|
||||
#
|
||||
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The University of Tennessee and The University
|
||||
# of Tennessee Research Foundation. All rights
|
||||
# reserved.
|
||||
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
# University of Stuttgart. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
|
||||
|
||||
EXTRA_DIST = err.h
|
||||
|
||||
SUBDIRS = sys
|
21
opal/event/compat/sys/Makefile.am
Обычный файл
21
opal/event/compat/sys/Makefile.am
Обычный файл
@ -0,0 +1,21 @@
|
||||
#
|
||||
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The University of Tennessee and The University
|
||||
# of Tennessee Research Foundation. All rights
|
||||
# reserved.
|
||||
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
||||
# University of Stuttgart. All rights reserved.
|
||||
# Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
|
||||
|
||||
noinst_HEADERS = queue.h _time.h _timeradd.h tree.h
|
150
opal/event/compat/sys/_time.h
Обычный файл
150
opal/event/compat/sys/_time.h
Обычный файл
@ -0,0 +1,150 @@
|
||||
/* $OpenBSD: time.h,v 1.11 2000/10/10 13:36:48 itojun Exp $ */
|
||||
/* $NetBSD: time.h,v 1.18 1996/04/23 10:29:33 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)time.h 8.2 (Berkeley) 7/10/94
|
||||
*/
|
||||
|
||||
#ifndef OMPI_TIME_H
|
||||
#ifndef _SYS_TIME_H_
|
||||
#define _SYS_TIME_H_
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Structure returned by gettimeofday(2) system call,
|
||||
* and used in other calls.
|
||||
*/
|
||||
struct timeval {
|
||||
long tv_sec; /* seconds */
|
||||
long tv_usec; /* and microseconds */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure defined by POSIX.1b to be like a timeval.
|
||||
*/
|
||||
struct timespec {
|
||||
time_t tv_sec; /* seconds */
|
||||
long tv_nsec; /* and nanoseconds */
|
||||
};
|
||||
|
||||
#define TIMEVAL_TO_TIMESPEC(tv, ts) { \
|
||||
(ts)->tv_sec = (tv)->tv_sec; \
|
||||
(ts)->tv_nsec = (tv)->tv_usec * 1000; \
|
||||
}
|
||||
#define TIMESPEC_TO_TIMEVAL(tv, ts) { \
|
||||
(tv)->tv_sec = (ts)->tv_sec; \
|
||||
(tv)->tv_usec = (ts)->tv_nsec / 1000; \
|
||||
}
|
||||
|
||||
struct timezone {
|
||||
int tz_minuteswest; /* minutes west of Greenwich */
|
||||
int tz_dsttime; /* type of dst correction */
|
||||
};
|
||||
#define DST_NONE 0 /* not on dst */
|
||||
#define DST_USA 1 /* USA style dst */
|
||||
#define DST_AUST 2 /* Australian style dst */
|
||||
#define DST_WET 3 /* Western European dst */
|
||||
#define DST_MET 4 /* Middle European dst */
|
||||
#define DST_EET 5 /* Eastern European dst */
|
||||
#define DST_CAN 6 /* Canada */
|
||||
|
||||
/* Operations on timevals. */
|
||||
#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
|
||||
#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
|
||||
#define timercmp(tvp, uvp, cmp) \
|
||||
(((tvp)->tv_sec == (uvp)->tv_sec) ? \
|
||||
((tvp)->tv_usec cmp (uvp)->tv_usec) : \
|
||||
((tvp)->tv_sec cmp (uvp)->tv_sec))
|
||||
#include <sys/_timeradd.h>
|
||||
|
||||
/* Operations on timespecs. */
|
||||
#define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0
|
||||
#define timespecisset(tsp) ((tsp)->tv_sec || (tsp)->tv_nsec)
|
||||
#define timespeccmp(tsp, usp, cmp) \
|
||||
(((tsp)->tv_sec == (usp)->tv_sec) ? \
|
||||
((tsp)->tv_nsec cmp (usp)->tv_nsec) : \
|
||||
((tsp)->tv_sec cmp (usp)->tv_sec))
|
||||
#define timespecadd(tsp, usp, vsp) \
|
||||
do { \
|
||||
(vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \
|
||||
(vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \
|
||||
if ((vsp)->tv_nsec >= 1000000000L) { \
|
||||
(vsp)->tv_sec++; \
|
||||
(vsp)->tv_nsec -= 1000000000L; \
|
||||
} \
|
||||
} while (0)
|
||||
#define timespecsub(tsp, usp, vsp) \
|
||||
do { \
|
||||
(vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \
|
||||
(vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \
|
||||
if ((vsp)->tv_nsec < 0) { \
|
||||
(vsp)->tv_sec--; \
|
||||
(vsp)->tv_nsec += 1000000000L; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Names of the interval timers, and structure
|
||||
* defining a timer setting.
|
||||
*/
|
||||
#define ITIMER_REAL 0
|
||||
#define ITIMER_VIRTUAL 1
|
||||
#define ITIMER_PROF 2
|
||||
|
||||
struct itimerval {
|
||||
struct timeval it_interval; /* timer interval */
|
||||
struct timeval it_value; /* current value */
|
||||
};
|
||||
|
||||
/*
|
||||
* Getkerninfo clock information structure
|
||||
*/
|
||||
struct clockinfo {
|
||||
int hz; /* clock frequency */
|
||||
int tick; /* micro-seconds per hz tick */
|
||||
int tickadj; /* clock skew rate for adjtime() */
|
||||
int stathz; /* statistics clock frequency */
|
||||
int profhz; /* profiling clock frequency */
|
||||
};
|
||||
|
||||
#define CLOCK_REALTIME 0
|
||||
#define CLOCK_VIRTUAL 1
|
||||
#define CLOCK_PROF 2
|
||||
|
||||
#define TIMER_RELTIME 0x0 /* relative timer */
|
||||
#define TIMER_ABSTIME 0x1 /* absolute timer */
|
||||
|
||||
/* --- stuff got cut here - niels --- */
|
||||
|
||||
#endif /* !_SYS_TIME_H_ */
|
||||
#endif /* !OMPI_TIME_H */
|
59
opal/event/compat/sys/_timeradd.h
Обычный файл
59
opal/event/compat/sys/_timeradd.h
Обычный файл
@ -0,0 +1,59 @@
|
||||
/* $OpenBSD: time.h,v 1.11 2000/10/10 13:36:48 itojun Exp $ */
|
||||
/* $NetBSD: time.h,v 1.18 1996/04/23 10:29:33 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)time.h 8.2 (Berkeley) 7/10/94
|
||||
*/
|
||||
|
||||
#ifndef OMPI_TIMERADD_H
|
||||
|
||||
#ifndef HAVE_TIMERADD
|
||||
/* Operations on timevals. */
|
||||
#define timeradd(tvp, uvp, vvp) \
|
||||
do { \
|
||||
(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
|
||||
(vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
|
||||
if ((vvp)->tv_usec >= 1000000) { \
|
||||
(vvp)->tv_sec++; \
|
||||
(vvp)->tv_usec -= 1000000; \
|
||||
} \
|
||||
} while (0)
|
||||
#define timersub(tvp, uvp, vvp) \
|
||||
do { \
|
||||
(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
|
||||
(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
|
||||
if ((vvp)->tv_usec < 0) { \
|
||||
(vvp)->tv_sec--; \
|
||||
(vvp)->tv_usec += 1000000; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif /* HAVE_TIMERADD */
|
||||
|
||||
#endif /* !OMPI_TIME_H */
|
488
opal/event/compat/sys/queue.h
Обычный файл
488
opal/event/compat/sys/queue.h
Обычный файл
@ -0,0 +1,488 @@
|
||||
/* $OpenBSD: queue.h,v 1.16 2000/09/07 19:47:59 art Exp $ */
|
||||
/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
||||
*/
|
||||
|
||||
#ifndef _SYS_QUEUE_H_
|
||||
#define _SYS_QUEUE_H_
|
||||
|
||||
/*
|
||||
* This file defines five types of data structures: singly-linked lists,
|
||||
* lists, simple queues, tail queues, and circular queues.
|
||||
*
|
||||
*
|
||||
* A singly-linked list is headed by a single forward pointer. The elements
|
||||
* are singly linked for minimum space and pointer manipulation overhead at
|
||||
* the expense of O(n) removal for arbitrary elements. New elements can be
|
||||
* added to the list after an existing element or at the head of the list.
|
||||
* Elements being removed from the head of the list should use the explicit
|
||||
* macro for this purpose for optimum efficiency. A singly-linked list may
|
||||
* only be traversed in the forward direction. Singly-linked lists are ideal
|
||||
* for applications with large datasets and few or no removals or for
|
||||
* implementing a LIFO queue.
|
||||
*
|
||||
* A list is headed by a single forward pointer (or an array of forward
|
||||
* pointers for a hash table header). The elements are doubly linked
|
||||
* so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before
|
||||
* or after an existing element or at the head of the list. A list
|
||||
* may only be traversed in the forward direction.
|
||||
*
|
||||
* A simple queue is headed by a pair of pointers, one the head of the
|
||||
* list and the other to the tail of the list. The elements are singly
|
||||
* linked to save space, so elements can only be removed from the
|
||||
* head of the list. New elements can be added to the list before or after
|
||||
* an existing element, at the head of the list, or at the end of the
|
||||
* list. A simple queue may only be traversed in the forward direction.
|
||||
*
|
||||
* A tail queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or
|
||||
* after an existing element, at the head of the list, or at the end of
|
||||
* the list. A tail queue may be traversed in either direction.
|
||||
*
|
||||
* A circle queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or after
|
||||
* an existing element, at the head of the list, or at the end of the list.
|
||||
* A circle queue may be traversed in either direction, but has a more
|
||||
* complex end of list detection.
|
||||
*
|
||||
* For details on the use of these macros, see the queue(3) manual page.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Singly-linked List definitions.
|
||||
*/
|
||||
#define SLIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *slh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define SLIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#ifndef WIN32
|
||||
#define SLIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sle_next; /* next element */ \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Singly-linked List access methods.
|
||||
*/
|
||||
#define SLIST_FIRST(head) ((head)->slh_first)
|
||||
#define SLIST_END(head) NULL
|
||||
#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
|
||||
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
||||
|
||||
#define SLIST_FOREACH(var, head, field) \
|
||||
for((var) = SLIST_FIRST(head); \
|
||||
(var) != SLIST_END(head); \
|
||||
(var) = SLIST_NEXT(var, field))
|
||||
|
||||
/*
|
||||
* Singly-linked List functions.
|
||||
*/
|
||||
#define SLIST_INIT(head) { \
|
||||
SLIST_FIRST(head) = SLIST_END(head); \
|
||||
}
|
||||
|
||||
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
|
||||
(elm)->field.sle_next = (slistelm)->field.sle_next; \
|
||||
(slistelm)->field.sle_next = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_INSERT_HEAD(head, elm, field) do { \
|
||||
(elm)->field.sle_next = (head)->slh_first; \
|
||||
(head)->slh_first = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_REMOVE_HEAD(head, field) do { \
|
||||
(head)->slh_first = (head)->slh_first->field.sle_next; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* List definitions.
|
||||
*/
|
||||
#define LIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *lh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define LIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define LIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *le_next; /* next element */ \
|
||||
struct type **le_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* List access methods
|
||||
*/
|
||||
#define LIST_FIRST(head) ((head)->lh_first)
|
||||
#define LIST_END(head) NULL
|
||||
#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
|
||||
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
|
||||
|
||||
#define LIST_FOREACH(var, head, field) \
|
||||
for((var) = LIST_FIRST(head); \
|
||||
(var)!= LIST_END(head); \
|
||||
(var) = LIST_NEXT(var, field))
|
||||
|
||||
/*
|
||||
* List functions.
|
||||
*/
|
||||
#define LIST_INIT(head) do { \
|
||||
LIST_FIRST(head) = LIST_END(head); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
|
||||
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
|
||||
(listelm)->field.le_next->field.le_prev = \
|
||||
&(elm)->field.le_next; \
|
||||
(listelm)->field.le_next = (elm); \
|
||||
(elm)->field.le_prev = &(listelm)->field.le_next; \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.le_prev = (listelm)->field.le_prev; \
|
||||
(elm)->field.le_next = (listelm); \
|
||||
*(listelm)->field.le_prev = (elm); \
|
||||
(listelm)->field.le_prev = &(elm)->field.le_next; \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
|
||||
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
|
||||
(head)->lh_first = (elm); \
|
||||
(elm)->field.le_prev = &(head)->lh_first; \
|
||||
} while (0)
|
||||
|
||||
#define LIST_REMOVE(elm, field) do { \
|
||||
if ((elm)->field.le_next != NULL) \
|
||||
(elm)->field.le_next->field.le_prev = \
|
||||
(elm)->field.le_prev; \
|
||||
*(elm)->field.le_prev = (elm)->field.le_next; \
|
||||
} while (0)
|
||||
|
||||
#define LIST_REPLACE(elm, elm2, field) do { \
|
||||
if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
|
||||
(elm2)->field.le_next->field.le_prev = \
|
||||
&(elm2)->field.le_next; \
|
||||
(elm2)->field.le_prev = (elm)->field.le_prev; \
|
||||
*(elm2)->field.le_prev = (elm2); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Simple queue definitions.
|
||||
*/
|
||||
#define SIMPLEQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *sqh_first; /* first element */ \
|
||||
struct type **sqh_last; /* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define SIMPLEQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).sqh_first }
|
||||
|
||||
#define SIMPLEQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sqe_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple queue access methods.
|
||||
*/
|
||||
#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
|
||||
#define SIMPLEQ_END(head) NULL
|
||||
#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
|
||||
#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
|
||||
|
||||
#define SIMPLEQ_FOREACH(var, head, field) \
|
||||
for((var) = SIMPLEQ_FIRST(head); \
|
||||
(var) != SIMPLEQ_END(head); \
|
||||
(var) = SIMPLEQ_NEXT(var, field))
|
||||
|
||||
/*
|
||||
* Simple queue functions.
|
||||
*/
|
||||
#define SIMPLEQ_INIT(head) do { \
|
||||
(head)->sqh_first = NULL; \
|
||||
(head)->sqh_last = &(head)->sqh_first; \
|
||||
} while (0)
|
||||
|
||||
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
(head)->sqh_first = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
|
||||
(elm)->field.sqe_next = NULL; \
|
||||
*(head)->sqh_last = (elm); \
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
} while (0)
|
||||
|
||||
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
(listelm)->field.sqe_next = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \
|
||||
if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \
|
||||
(head)->sqh_last = &(head)->sqh_first; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Tail queue definitions.
|
||||
*/
|
||||
#define TAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *tqh_first; /* first element */ \
|
||||
struct type **tqh_last; /* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define TAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).tqh_first }
|
||||
|
||||
#define TAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *tqe_next; /* next element */ \
|
||||
struct type **tqe_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* tail queue access methods
|
||||
*/
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
#define TAILQ_END(head) NULL
|
||||
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
#define TAILQ_LAST(head, headname) \
|
||||
(*(((struct headname *)((head)->tqh_last))->tqh_last))
|
||||
/* XXX */
|
||||
#define TAILQ_PREV(elm, headname, field) \
|
||||
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
|
||||
#define TAILQ_EMPTY(head) \
|
||||
(TAILQ_FIRST(head) == TAILQ_END(head))
|
||||
|
||||
#define TAILQ_FOREACH(var, head, field) \
|
||||
for((var) = TAILQ_FIRST(head); \
|
||||
(var) != TAILQ_END(head); \
|
||||
(var) = TAILQ_NEXT(var, field))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE(var, head, field, headname) \
|
||||
for((var) = TAILQ_LAST(head, headname); \
|
||||
(var) != TAILQ_END(head); \
|
||||
(var) = TAILQ_PREV(var, headname, field))
|
||||
|
||||
/*
|
||||
* Tail queue functions.
|
||||
*/
|
||||
#define TAILQ_INIT(head) do { \
|
||||
(head)->tqh_first = NULL; \
|
||||
(head)->tqh_last = &(head)->tqh_first; \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
|
||||
(head)->tqh_first->field.tqe_prev = \
|
||||
&(elm)->field.tqe_next; \
|
||||
else \
|
||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||
(head)->tqh_first = (elm); \
|
||||
(elm)->field.tqe_prev = &(head)->tqh_first; \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
(elm)->field.tqe_next = NULL; \
|
||||
(elm)->field.tqe_prev = (head)->tqh_last; \
|
||||
*(head)->tqh_last = (elm); \
|
||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
|
||||
(elm)->field.tqe_next->field.tqe_prev = \
|
||||
&(elm)->field.tqe_next; \
|
||||
else \
|
||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||
(listelm)->field.tqe_next = (elm); \
|
||||
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
||||
(elm)->field.tqe_next = (listelm); \
|
||||
*(listelm)->field.tqe_prev = (elm); \
|
||||
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_REMOVE(head, elm, field) do { \
|
||||
if (((elm)->field.tqe_next) != NULL) \
|
||||
(elm)->field.tqe_next->field.tqe_prev = \
|
||||
(elm)->field.tqe_prev; \
|
||||
else \
|
||||
(head)->tqh_last = (elm)->field.tqe_prev; \
|
||||
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_REPLACE(head, elm, elm2, field) do { \
|
||||
if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
|
||||
(elm2)->field.tqe_next->field.tqe_prev = \
|
||||
&(elm2)->field.tqe_next; \
|
||||
else \
|
||||
(head)->tqh_last = &(elm2)->field.tqe_next; \
|
||||
(elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
|
||||
*(elm2)->field.tqe_prev = (elm2); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Circular queue definitions.
|
||||
*/
|
||||
#define CIRCLEQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *cqh_first; /* first element */ \
|
||||
struct type *cqh_last; /* last element */ \
|
||||
}
|
||||
|
||||
#define CIRCLEQ_HEAD_INITIALIZER(head) \
|
||||
{ CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
|
||||
|
||||
#define CIRCLEQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *cqe_next; /* next element */ \
|
||||
struct type *cqe_prev; /* previous element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Circular queue access methods
|
||||
*/
|
||||
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
|
||||
#define CIRCLEQ_LAST(head) ((head)->cqh_last)
|
||||
#define CIRCLEQ_END(head) ((void *)(head))
|
||||
#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
|
||||
#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
|
||||
#define CIRCLEQ_EMPTY(head) \
|
||||
(CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
|
||||
|
||||
#define CIRCLEQ_FOREACH(var, head, field) \
|
||||
for((var) = CIRCLEQ_FIRST(head); \
|
||||
(var) != CIRCLEQ_END(head); \
|
||||
(var) = CIRCLEQ_NEXT(var, field))
|
||||
|
||||
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
|
||||
for((var) = CIRCLEQ_LAST(head); \
|
||||
(var) != CIRCLEQ_END(head); \
|
||||
(var) = CIRCLEQ_PREV(var, field))
|
||||
|
||||
/*
|
||||
* Circular queue functions.
|
||||
*/
|
||||
#define CIRCLEQ_INIT(head) do { \
|
||||
(head)->cqh_first = CIRCLEQ_END(head); \
|
||||
(head)->cqh_last = CIRCLEQ_END(head); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
(elm)->field.cqe_next = (listelm)->field.cqe_next; \
|
||||
(elm)->field.cqe_prev = (listelm); \
|
||||
if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \
|
||||
(head)->cqh_last = (elm); \
|
||||
else \
|
||||
(listelm)->field.cqe_next->field.cqe_prev = (elm); \
|
||||
(listelm)->field.cqe_next = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
|
||||
(elm)->field.cqe_next = (listelm); \
|
||||
(elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
|
||||
if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \
|
||||
(head)->cqh_first = (elm); \
|
||||
else \
|
||||
(listelm)->field.cqe_prev->field.cqe_next = (elm); \
|
||||
(listelm)->field.cqe_prev = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
|
||||
(elm)->field.cqe_next = (head)->cqh_first; \
|
||||
(elm)->field.cqe_prev = CIRCLEQ_END(head); \
|
||||
if ((head)->cqh_last == CIRCLEQ_END(head)) \
|
||||
(head)->cqh_last = (elm); \
|
||||
else \
|
||||
(head)->cqh_first->field.cqe_prev = (elm); \
|
||||
(head)->cqh_first = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
|
||||
(elm)->field.cqe_next = CIRCLEQ_END(head); \
|
||||
(elm)->field.cqe_prev = (head)->cqh_last; \
|
||||
if ((head)->cqh_first == CIRCLEQ_END(head)) \
|
||||
(head)->cqh_first = (elm); \
|
||||
else \
|
||||
(head)->cqh_last->field.cqe_next = (elm); \
|
||||
(head)->cqh_last = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_REMOVE(head, elm, field) do { \
|
||||
if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \
|
||||
(head)->cqh_last = (elm)->field.cqe_prev; \
|
||||
else \
|
||||
(elm)->field.cqe_next->field.cqe_prev = \
|
||||
(elm)->field.cqe_prev; \
|
||||
if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \
|
||||
(head)->cqh_first = (elm)->field.cqe_next; \
|
||||
else \
|
||||
(elm)->field.cqe_prev->field.cqe_next = \
|
||||
(elm)->field.cqe_next; \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
|
||||
if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
|
||||
CIRCLEQ_END(head)) \
|
||||
(head).cqh_last = (elm2); \
|
||||
else \
|
||||
(elm2)->field.cqe_next->field.cqe_prev = (elm2); \
|
||||
if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
|
||||
CIRCLEQ_END(head)) \
|
||||
(head).cqh_first = (elm2); \
|
||||
else \
|
||||
(elm2)->field.cqe_prev->field.cqe_next = (elm2); \
|
||||
} while (0)
|
||||
|
||||
#endif /* !_SYS_QUEUE_H_ */
|
677
opal/event/compat/sys/tree.h
Обычный файл
677
opal/event/compat/sys/tree.h
Обычный файл
@ -0,0 +1,677 @@
|
||||
/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_TREE_H_
|
||||
#define _SYS_TREE_H_
|
||||
|
||||
/*
|
||||
* This file defines data structures for different types of trees:
|
||||
* splay trees and red-black trees.
|
||||
*
|
||||
* A splay tree is a self-organizing data structure. Every operation
|
||||
* on the tree causes a splay to happen. The splay moves the requested
|
||||
* node to the root of the tree and partly rebalances it.
|
||||
*
|
||||
* This has the benefit that request locality causes faster lookups as
|
||||
* the requested nodes move to the top of the tree. On the other hand,
|
||||
* every lookup causes memory writes.
|
||||
*
|
||||
* The Balance Theorem bounds the total access time for m operations
|
||||
* and n inserts on an initially empty tree as O((m + n)lg n). The
|
||||
* amortized cost for a sequence of m accesses to a splay tree is O(lg n);
|
||||
*
|
||||
* A red-black tree is a binary search tree with the node color as an
|
||||
* extra attribute. It fulfills a set of conditions:
|
||||
* - every search path from the root to a leaf consists of the
|
||||
* same number of black nodes,
|
||||
* - each red node (except for the root) has a black parent,
|
||||
* - each leaf node is black.
|
||||
*
|
||||
* Every operation on a red-black tree is bounded as O(lg n).
|
||||
* The maximum height of a red-black tree is 2lg (n+1).
|
||||
*/
|
||||
|
||||
#define SPLAY_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *sph_root; /* root of the tree */ \
|
||||
}
|
||||
|
||||
#define SPLAY_INITIALIZER(root) \
|
||||
{ NULL }
|
||||
|
||||
#define SPLAY_INIT(root) do { \
|
||||
(root)->sph_root = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define SPLAY_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *spe_left; /* left element */ \
|
||||
struct type *spe_right; /* right element */ \
|
||||
}
|
||||
|
||||
#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
|
||||
#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
|
||||
#define SPLAY_ROOT(head) (head)->sph_root
|
||||
#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
|
||||
|
||||
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
|
||||
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (0)
|
||||
|
||||
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (0)
|
||||
|
||||
#define SPLAY_LINKLEFT(head, tmp, field) do { \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
|
||||
} while (0)
|
||||
|
||||
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
} while (0)
|
||||
|
||||
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
|
||||
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
|
||||
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
|
||||
} while (0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
|
||||
#define SPLAY_PROTOTYPE(name, type, field, cmp) \
|
||||
void name##_SPLAY(struct name *, struct type *); \
|
||||
void name##_SPLAY_MINMAX(struct name *, int); \
|
||||
struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
|
||||
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
|
||||
\
|
||||
/* Finds the node with the same key as elm */ \
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_FIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return(NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) \
|
||||
return (head->sph_root); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_NEXT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
name##_SPLAY(head, elm); \
|
||||
if (SPLAY_RIGHT(elm, field) != NULL) { \
|
||||
elm = SPLAY_RIGHT(elm, field); \
|
||||
while (SPLAY_LEFT(elm, field) != NULL) { \
|
||||
elm = SPLAY_LEFT(elm, field); \
|
||||
} \
|
||||
} else \
|
||||
elm = NULL; \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_MIN_MAX(struct name *head, int val) \
|
||||
{ \
|
||||
name##_SPLAY_MINMAX(head, val); \
|
||||
return (SPLAY_ROOT(head)); \
|
||||
}
|
||||
|
||||
/* Main splay operation.
|
||||
* Moves node close to the key of elm to top
|
||||
*/
|
||||
#define SPLAY_GENERATE(name, type, field, cmp) \
|
||||
struct type * \
|
||||
name##_SPLAY_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
|
||||
} else { \
|
||||
int __comp; \
|
||||
name##_SPLAY(head, elm); \
|
||||
__comp = (cmp)(elm, (head)->sph_root); \
|
||||
if(__comp < 0) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
|
||||
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_LEFT((head)->sph_root, field) = NULL; \
|
||||
} else if (__comp > 0) { \
|
||||
SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
SPLAY_LEFT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
|
||||
} else \
|
||||
return ((head)->sph_root); \
|
||||
} \
|
||||
(head)->sph_root = (elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *__tmp; \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return (NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) { \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
} else { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
|
||||
name##_SPLAY(head, elm); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
name##_SPLAY(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
int __comp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while ((__comp = (cmp)(elm, (head)->sph_root))) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) < 0){ \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) > 0){ \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
} \
|
||||
\
|
||||
/* Splay with either the minimum or the maximum element \
|
||||
* Used to find minimum or maximum element in tree. \
|
||||
*/ \
|
||||
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while (1) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp < 0){ \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp > 0) { \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
}
|
||||
|
||||
#define SPLAY_NEGINF -1
|
||||
#define SPLAY_INF 1
|
||||
|
||||
#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
|
||||
#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
|
||||
#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
|
||||
#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
|
||||
#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||
: name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
|
||||
#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||
: name##_SPLAY_MIN_MAX(x, SPLAY_INF))
|
||||
|
||||
#define SPLAY_FOREACH(x, name, head) \
|
||||
for ((x) = SPLAY_MIN(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = SPLAY_NEXT(name, head, x))
|
||||
|
||||
/* Macros that define a red-back tree */
|
||||
#define RB_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *rbh_root; /* root of the tree */ \
|
||||
}
|
||||
|
||||
#define RB_INITIALIZER(root) \
|
||||
{ NULL }
|
||||
|
||||
#define RB_INIT(root) do { \
|
||||
(root)->rbh_root = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define RB_BLACK 0
|
||||
#define RB_RED 1
|
||||
#define RB_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *rbe_left; /* left element */ \
|
||||
struct type *rbe_right; /* right element */ \
|
||||
struct type *rbe_parent; /* parent element */ \
|
||||
int rbe_color; /* node color */ \
|
||||
}
|
||||
|
||||
#define RB_LEFT(elm, field) (elm)->field.rbe_left
|
||||
#define RB_RIGHT(elm, field) (elm)->field.rbe_right
|
||||
#define RB_PARENT(elm, field) (elm)->field.rbe_parent
|
||||
#define RB_COLOR(elm, field) (elm)->field.rbe_color
|
||||
#define RB_ROOT(head) (head)->rbh_root
|
||||
#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
|
||||
|
||||
#define RB_SET(elm, parent, field) do { \
|
||||
RB_PARENT(elm, field) = parent; \
|
||||
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
|
||||
RB_COLOR(elm, field) = RB_RED; \
|
||||
} while (0)
|
||||
|
||||
#define RB_SET_BLACKRED(black, red, field) do { \
|
||||
RB_COLOR(black, field) = RB_BLACK; \
|
||||
RB_COLOR(red, field) = RB_RED; \
|
||||
} while (0)
|
||||
|
||||
#ifndef RB_AUGMENT
|
||||
#define RB_AUGMENT(x)
|
||||
#endif
|
||||
|
||||
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
|
||||
(tmp) = RB_RIGHT(elm, field); \
|
||||
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \
|
||||
RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
|
||||
} \
|
||||
RB_AUGMENT(elm); \
|
||||
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
|
||||
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
|
||||
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
|
||||
else \
|
||||
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
|
||||
} else \
|
||||
(head)->rbh_root = (tmp); \
|
||||
RB_LEFT(tmp, field) = (elm); \
|
||||
RB_PARENT(elm, field) = (tmp); \
|
||||
RB_AUGMENT(tmp); \
|
||||
if ((RB_PARENT(tmp, field))) \
|
||||
RB_AUGMENT(RB_PARENT(tmp, field)); \
|
||||
} while (0)
|
||||
|
||||
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
|
||||
(tmp) = RB_LEFT(elm, field); \
|
||||
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \
|
||||
RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
|
||||
} \
|
||||
RB_AUGMENT(elm); \
|
||||
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
|
||||
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
|
||||
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
|
||||
else \
|
||||
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
|
||||
} else \
|
||||
(head)->rbh_root = (tmp); \
|
||||
RB_RIGHT(tmp, field) = (elm); \
|
||||
RB_PARENT(elm, field) = (tmp); \
|
||||
RB_AUGMENT(tmp); \
|
||||
if ((RB_PARENT(tmp, field))) \
|
||||
RB_AUGMENT(RB_PARENT(tmp, field)); \
|
||||
} while (0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
#define RB_PROTOTYPE(name, type, field, cmp) \
|
||||
void name##_RB_INSERT_COLOR(struct name *, struct type *); \
|
||||
void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
|
||||
struct type *name##_RB_REMOVE(struct name *, struct type *); \
|
||||
struct type *name##_RB_INSERT(struct name *, struct type *); \
|
||||
struct type *name##_RB_FIND(struct name *, struct type *); \
|
||||
struct type *name##_RB_NEXT(struct type *); \
|
||||
struct type *name##_RB_MINMAX(struct name *, int); \
|
||||
\
|
||||
|
||||
/* Main rb operation.
|
||||
* Moves node close to the key of elm to top
|
||||
*/
|
||||
#define RB_GENERATE(name, type, field, cmp) \
|
||||
void \
|
||||
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *parent, *gparent, *tmp; \
|
||||
while ((parent = RB_PARENT(elm, field)) && \
|
||||
RB_COLOR(parent, field) == RB_RED) { \
|
||||
gparent = RB_PARENT(parent, field); \
|
||||
if (parent == RB_LEFT(gparent, field)) { \
|
||||
tmp = RB_RIGHT(gparent, field); \
|
||||
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
|
||||
RB_COLOR(tmp, field) = RB_BLACK; \
|
||||
RB_SET_BLACKRED(parent, gparent, field);\
|
||||
elm = gparent; \
|
||||
continue; \
|
||||
} \
|
||||
if (RB_RIGHT(parent, field) == elm) { \
|
||||
RB_ROTATE_LEFT(head, parent, tmp, field);\
|
||||
tmp = parent; \
|
||||
parent = elm; \
|
||||
elm = tmp; \
|
||||
} \
|
||||
RB_SET_BLACKRED(parent, gparent, field); \
|
||||
RB_ROTATE_RIGHT(head, gparent, tmp, field); \
|
||||
} else { \
|
||||
tmp = RB_LEFT(gparent, field); \
|
||||
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
|
||||
RB_COLOR(tmp, field) = RB_BLACK; \
|
||||
RB_SET_BLACKRED(parent, gparent, field);\
|
||||
elm = gparent; \
|
||||
continue; \
|
||||
} \
|
||||
if (RB_LEFT(parent, field) == elm) { \
|
||||
RB_ROTATE_RIGHT(head, parent, tmp, field);\
|
||||
tmp = parent; \
|
||||
parent = elm; \
|
||||
elm = tmp; \
|
||||
} \
|
||||
RB_SET_BLACKRED(parent, gparent, field); \
|
||||
RB_ROTATE_LEFT(head, gparent, tmp, field); \
|
||||
} \
|
||||
} \
|
||||
RB_COLOR(head->rbh_root, field) = RB_BLACK; \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp; \
|
||||
while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
|
||||
elm != RB_ROOT(head)) { \
|
||||
if (RB_LEFT(parent, field) == elm) { \
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
if (RB_COLOR(tmp, field) == RB_RED) { \
|
||||
RB_SET_BLACKRED(tmp, parent, field); \
|
||||
RB_ROTATE_LEFT(head, parent, tmp, field);\
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
} \
|
||||
if ((RB_LEFT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
|
||||
(RB_RIGHT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
|
||||
RB_COLOR(tmp, field) = RB_RED; \
|
||||
elm = parent; \
|
||||
parent = RB_PARENT(elm, field); \
|
||||
} else { \
|
||||
if (RB_RIGHT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
|
||||
struct type *oleft; \
|
||||
if ((oleft = RB_LEFT(tmp, field)))\
|
||||
RB_COLOR(oleft, field) = RB_BLACK;\
|
||||
RB_COLOR(tmp, field) = RB_RED; \
|
||||
RB_ROTATE_RIGHT(head, tmp, oleft, field);\
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
} \
|
||||
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
|
||||
RB_COLOR(parent, field) = RB_BLACK; \
|
||||
if (RB_RIGHT(tmp, field)) \
|
||||
RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
|
||||
RB_ROTATE_LEFT(head, parent, tmp, field);\
|
||||
elm = RB_ROOT(head); \
|
||||
break; \
|
||||
} \
|
||||
} else { \
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
if (RB_COLOR(tmp, field) == RB_RED) { \
|
||||
RB_SET_BLACKRED(tmp, parent, field); \
|
||||
RB_ROTATE_RIGHT(head, parent, tmp, field);\
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
} \
|
||||
if ((RB_LEFT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
|
||||
(RB_RIGHT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
|
||||
RB_COLOR(tmp, field) = RB_RED; \
|
||||
elm = parent; \
|
||||
parent = RB_PARENT(elm, field); \
|
||||
} else { \
|
||||
if (RB_LEFT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
|
||||
struct type *oright; \
|
||||
if ((oright = RB_RIGHT(tmp, field)))\
|
||||
RB_COLOR(oright, field) = RB_BLACK;\
|
||||
RB_COLOR(tmp, field) = RB_RED; \
|
||||
RB_ROTATE_LEFT(head, tmp, oright, field);\
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
} \
|
||||
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
|
||||
RB_COLOR(parent, field) = RB_BLACK; \
|
||||
if (RB_LEFT(tmp, field)) \
|
||||
RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
|
||||
RB_ROTATE_RIGHT(head, parent, tmp, field);\
|
||||
elm = RB_ROOT(head); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if (elm) \
|
||||
RB_COLOR(elm, field) = RB_BLACK; \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_RB_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *child, *parent, *old = elm; \
|
||||
int color; \
|
||||
if (RB_LEFT(elm, field) == NULL) \
|
||||
child = RB_RIGHT(elm, field); \
|
||||
else if (RB_RIGHT(elm, field) == NULL) \
|
||||
child = RB_LEFT(elm, field); \
|
||||
else { \
|
||||
struct type *left; \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
while ((left = RB_LEFT(elm, field))) \
|
||||
elm = left; \
|
||||
child = RB_RIGHT(elm, field); \
|
||||
parent = RB_PARENT(elm, field); \
|
||||
color = RB_COLOR(elm, field); \
|
||||
if (child) \
|
||||
RB_PARENT(child, field) = parent; \
|
||||
if (parent) { \
|
||||
if (RB_LEFT(parent, field) == elm) \
|
||||
RB_LEFT(parent, field) = child; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = child; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = child; \
|
||||
if (RB_PARENT(elm, field) == old) \
|
||||
parent = elm; \
|
||||
(elm)->field = (old)->field; \
|
||||
if (RB_PARENT(old, field)) { \
|
||||
if (RB_LEFT(RB_PARENT(old, field), field) == old)\
|
||||
RB_LEFT(RB_PARENT(old, field), field) = elm;\
|
||||
else \
|
||||
RB_RIGHT(RB_PARENT(old, field), field) = elm;\
|
||||
RB_AUGMENT(RB_PARENT(old, field)); \
|
||||
} else \
|
||||
RB_ROOT(head) = elm; \
|
||||
RB_PARENT(RB_LEFT(old, field), field) = elm; \
|
||||
if (RB_RIGHT(old, field)) \
|
||||
RB_PARENT(RB_RIGHT(old, field), field) = elm; \
|
||||
if (parent) { \
|
||||
left = parent; \
|
||||
do { \
|
||||
RB_AUGMENT(left); \
|
||||
} while ((left = RB_PARENT(left, field))); \
|
||||
} \
|
||||
goto color; \
|
||||
} \
|
||||
parent = RB_PARENT(elm, field); \
|
||||
color = RB_COLOR(elm, field); \
|
||||
if (child) \
|
||||
RB_PARENT(child, field) = parent; \
|
||||
if (parent) { \
|
||||
if (RB_LEFT(parent, field) == elm) \
|
||||
RB_LEFT(parent, field) = child; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = child; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = child; \
|
||||
color: \
|
||||
if (color == RB_BLACK) \
|
||||
name##_RB_REMOVE_COLOR(head, parent, child); \
|
||||
return (old); \
|
||||
} \
|
||||
\
|
||||
/* Inserts a node into the RB tree */ \
|
||||
struct type * \
|
||||
name##_RB_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp; \
|
||||
struct type *parent = NULL; \
|
||||
int comp = 0; \
|
||||
tmp = RB_ROOT(head); \
|
||||
while (tmp) { \
|
||||
parent = tmp; \
|
||||
comp = (cmp)(elm, parent); \
|
||||
if (comp < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
RB_SET(elm, parent, field); \
|
||||
if (parent != NULL) { \
|
||||
if (comp < 0) \
|
||||
RB_LEFT(parent, field) = elm; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = elm; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = elm; \
|
||||
name##_RB_INSERT_COLOR(head, elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
/* Finds the node with the same key as elm */ \
|
||||
struct type * \
|
||||
name##_RB_FIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
int comp; \
|
||||
while (tmp) { \
|
||||
comp = cmp(elm, tmp); \
|
||||
if (comp < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_RB_NEXT(struct type *elm) \
|
||||
{ \
|
||||
if (RB_RIGHT(elm, field)) { \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
while (RB_LEFT(elm, field)) \
|
||||
elm = RB_LEFT(elm, field); \
|
||||
} else { \
|
||||
if (RB_PARENT(elm, field) && \
|
||||
(elm == RB_LEFT(RB_PARENT(elm, field), field))) \
|
||||
elm = RB_PARENT(elm, field); \
|
||||
else { \
|
||||
while (RB_PARENT(elm, field) && \
|
||||
(elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
|
||||
elm = RB_PARENT(elm, field); \
|
||||
elm = RB_PARENT(elm, field); \
|
||||
} \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_RB_MINMAX(struct name *head, int val) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
struct type *parent = NULL; \
|
||||
while (tmp) { \
|
||||
parent = tmp; \
|
||||
if (val < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
} \
|
||||
return (parent); \
|
||||
}
|
||||
|
||||
#define RB_NEGINF -1
|
||||
#define RB_INF 1
|
||||
|
||||
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
|
||||
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
|
||||
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
|
||||
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
|
||||
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
|
||||
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
|
||||
|
||||
#define RB_FOREACH(x, name, head) \
|
||||
for ((x) = RB_MIN(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = name##_RB_NEXT(x))
|
||||
|
||||
#endif /* _SYS_TREE_H_ */
|
1388
opal/event/config/config.guess
поставляемый
Исполняемый файл
1388
opal/event/config/config.guess
поставляемый
Исполняемый файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
1489
opal/event/config/config.sub
поставляемый
Исполняемый файл
1489
opal/event/config/config.sub
поставляемый
Исполняемый файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
295
opal/event/config/install-sh
Исполняемый файл
295
opal/event/config/install-sh
Исполняемый файл
@ -0,0 +1,295 @@
|
||||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2003-09-24.23
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch. It can only install one file at a time, a restriction
|
||||
# shared with many OS's install programs.
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
transformbasename=
|
||||
transform_arg=
|
||||
instcmd="$mvprog"
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=
|
||||
chgrpcmd=
|
||||
stripcmd=
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
|
||||
usage="Usage: $0 [OPTION]... SRCFILE DSTFILE
|
||||
or: $0 -d DIR1 DIR2...
|
||||
|
||||
In the first form, install SRCFILE to DSTFILE, removing SRCFILE by default.
|
||||
In the second, create the directory path DIR.
|
||||
|
||||
Options:
|
||||
-b=TRANSFORMBASENAME
|
||||
-c copy source (using $cpprog) instead of moving (using $mvprog).
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrp installed files to GROUP.
|
||||
-m MODE $chmod installed files to MODE.
|
||||
-o USER $chown installed files to USER.
|
||||
-s strip installed files (using $stripprog).
|
||||
-t=TRANSFORM
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test -n "$1"; do
|
||||
case $1 in
|
||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-c) instcmd=$cpprog
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
--help) echo "$usage"; exit 0;;
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd=$stripprog
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit 0;;
|
||||
|
||||
*) if test -z "$src"; then
|
||||
src=$1
|
||||
else
|
||||
# this colon is to work around a 386BSD /bin/sh bug
|
||||
:
|
||||
dst=$1
|
||||
fi
|
||||
shift
|
||||
continue;;
|
||||
esac
|
||||
done
|
||||
|
||||
if test -z "$src"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Protect names starting with `-'.
|
||||
case $src in
|
||||
-*) src=./$src ;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
src=
|
||||
|
||||
if test -d "$dst"; then
|
||||
instcmd=:
|
||||
chmodcmd=
|
||||
else
|
||||
instcmd=$mkdirprog
|
||||
fi
|
||||
else
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dst"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Protect names starting with `-'.
|
||||
case $dst in
|
||||
-*) dst=./$dst ;;
|
||||
esac
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
dst=$dst/`basename "$src"`
|
||||
fi
|
||||
fi
|
||||
|
||||
# This sed command emulates the dirname command.
|
||||
dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if test ! -d "$dstdir"; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-$defaultIFS}"
|
||||
|
||||
oIFS=$IFS
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS=$oIFS
|
||||
|
||||
pathcomp=
|
||||
|
||||
while test $# -ne 0 ; do
|
||||
pathcomp=$pathcomp$1
|
||||
shift
|
||||
test -d "$pathcomp" || $mkdirprog "$pathcomp"
|
||||
pathcomp=$pathcomp/
|
||||
done
|
||||
fi
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
$doit $instcmd "$dst" \
|
||||
&& { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
|
||||
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
|
||||
&& { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
|
||||
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
|
||||
|
||||
else
|
||||
# If we're going to rename the final executable, determine the name now.
|
||||
if test -z "$transformarg"; then
|
||||
dstfile=`basename "$dst"`
|
||||
else
|
||||
dstfile=`basename "$dst" $transformbasename \
|
||||
| sed $transformarg`$transformbasename
|
||||
fi
|
||||
|
||||
# don't allow the sed command to completely eliminate the filename.
|
||||
test -z "$dstfile" && dstfile=`basename "$dst"`
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
|
||||
trap '(exit $?); exit' 1 2 13 15
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
$doit $instcmd "$src" "$dsttmp" &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
|
||||
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
|
||||
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
|
||||
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
|
||||
|
||||
# Now remove or move aside any old file at destination location. We
|
||||
# try this two ways since rm can't unlink itself on some systems and
|
||||
# the destination file might be busy for other reasons. In this case,
|
||||
# the final cleanup might fail but the new file should still install
|
||||
# successfully.
|
||||
{
|
||||
if test -f "$dstdir/$dstfile"; then
|
||||
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
|
||||
|| $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
|
||||
|| {
|
||||
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
|
||||
(exit 1); exit
|
||||
}
|
||||
else
|
||||
:
|
||||
fi
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
|
||||
fi &&
|
||||
|
||||
# The final little trick to "correctly" pass the exit status to the exit trap.
|
||||
{
|
||||
(exit 0); exit
|
||||
}
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
6290
opal/event/config/ltmain.sh
Обычный файл
6290
opal/event/config/ltmain.sh
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
360
opal/event/config/missing
Исполняемый файл
360
opal/event/config/missing
Исполняемый файл
@ -0,0 +1,360 @@
|
||||
#! /bin/sh
|
||||
# Common stub for a few missing GNU programs while installing.
|
||||
|
||||
scriptversion=2003-09-02.23
|
||||
|
||||
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003
|
||||
# Free Software Foundation, Inc.
|
||||
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program 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 General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run=:
|
||||
|
||||
# In the cases where this matters, `missing' is being run in the
|
||||
# srcdir already.
|
||||
if test -f configure.ac; then
|
||||
configure_ac=configure.ac
|
||||
else
|
||||
configure_ac=configure.in
|
||||
fi
|
||||
|
||||
msg="missing on your system"
|
||||
|
||||
case "$1" in
|
||||
--run)
|
||||
# Try to run requested program, and just exit if it succeeds.
|
||||
run=
|
||||
shift
|
||||
"$@" && exit 0
|
||||
# Exit code 63 means version mismatch. This often happens
|
||||
# when the user try to use an ancient version of a tool on
|
||||
# a file that requires a minimum version. In this case we
|
||||
# we should proceed has if the program had been absent, or
|
||||
# if --run hadn't been passed.
|
||||
if test $? = 63; then
|
||||
run=:
|
||||
msg="probably too old"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# If it does not exist, or fails to run (possibly an outdated version),
|
||||
# try to emulate it.
|
||||
case "$1" in
|
||||
|
||||
-h|--h|--he|--hel|--help)
|
||||
echo "\
|
||||
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||
|
||||
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
|
||||
error status if there is no known handling for PROGRAM.
|
||||
|
||||
Options:
|
||||
-h, --help display this help and exit
|
||||
-v, --version output version information and exit
|
||||
--run try to run the given command, and emulate it if it fails
|
||||
|
||||
Supported PROGRAM values:
|
||||
aclocal touch file \`aclocal.m4'
|
||||
autoconf touch file \`configure'
|
||||
autoheader touch file \`config.h.in'
|
||||
automake touch all \`Makefile.in' files
|
||||
bison create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
flex create \`lex.yy.c', if possible, from existing .c
|
||||
help2man touch the output file
|
||||
lex create \`lex.yy.c', if possible, from existing .c
|
||||
makeinfo touch the output file
|
||||
tar try tar, gnutar, gtar, then tar without non-portable flags
|
||||
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
|
||||
Send bug reports to <bug-automake@gnu.org>."
|
||||
;;
|
||||
|
||||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "missing $scriptversion (GNU Automake)"
|
||||
;;
|
||||
|
||||
-*)
|
||||
echo 1>&2 "$0: Unknown \`$1' option"
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
aclocal*)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
|
||||
to install the \`Automake' and \`Perl' packages. Grab them from
|
||||
any GNU archive site."
|
||||
touch aclocal.m4
|
||||
;;
|
||||
|
||||
autoconf)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`${configure_ac}'. You might want to install the
|
||||
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
|
||||
archive site."
|
||||
touch configure
|
||||
;;
|
||||
|
||||
autoheader)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acconfig.h' or \`${configure_ac}'. You might want
|
||||
to install the \`Autoconf' and \`GNU m4' packages. Grab them
|
||||
from any GNU archive site."
|
||||
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
|
||||
test -z "$files" && files="config.h"
|
||||
touch_files=
|
||||
for f in $files; do
|
||||
case "$f" in
|
||||
*:*) touch_files="$touch_files "`echo "$f" |
|
||||
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
|
||||
*) touch_files="$touch_files $f.in";;
|
||||
esac
|
||||
done
|
||||
touch $touch_files
|
||||
;;
|
||||
|
||||
automake*)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
|
||||
You might want to install the \`Automake' and \`Perl' packages.
|
||||
Grab them from any GNU archive site."
|
||||
find . -type f -name Makefile.am -print |
|
||||
sed 's/\.am$/.in/' |
|
||||
while read f; do touch "$f"; done
|
||||
;;
|
||||
|
||||
autom4te)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, but is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them.
|
||||
You can get \`$1' as part of \`Autoconf' from any GNU
|
||||
archive site."
|
||||
|
||||
file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
|
||||
test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
|
||||
if test -f "$file"; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo "#! /bin/sh"
|
||||
echo "# Created by GNU Automake missing as a replacement of"
|
||||
echo "# $ $@"
|
||||
echo "exit 0"
|
||||
chmod +x $file
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
bison|yacc)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' $msg. You should only need it if
|
||||
you modified a \`.y' file. You may need the \`Bison' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Bison' from any GNU archive site."
|
||||
rm -f y.tab.c y.tab.h
|
||||
if [ $# -ne 1 ]; then
|
||||
eval LASTARG="\${$#}"
|
||||
case "$LASTARG" in
|
||||
*.y)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
|
||||
if [ -f "$SRCFILE" ]; then
|
||||
cp "$SRCFILE" y.tab.c
|
||||
fi
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
|
||||
if [ -f "$SRCFILE" ]; then
|
||||
cp "$SRCFILE" y.tab.h
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if [ ! -f y.tab.h ]; then
|
||||
echo >y.tab.h
|
||||
fi
|
||||
if [ ! -f y.tab.c ]; then
|
||||
echo 'main() { return 0; }' >y.tab.c
|
||||
fi
|
||||
;;
|
||||
|
||||
lex|flex)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.l' file. You may need the \`Flex' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Flex' from any GNU archive site."
|
||||
rm -f lex.yy.c
|
||||
if [ $# -ne 1 ]; then
|
||||
eval LASTARG="\${$#}"
|
||||
case "$LASTARG" in
|
||||
*.l)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
|
||||
if [ -f "$SRCFILE" ]; then
|
||||
cp "$SRCFILE" lex.yy.c
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if [ ! -f lex.yy.c ]; then
|
||||
echo 'main() { return 0; }' >lex.yy.c
|
||||
fi
|
||||
;;
|
||||
|
||||
help2man)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a dependency of a manual page. You may need the
|
||||
\`Help2man' package in order for those modifications to take
|
||||
effect. You can get \`Help2man' from any GNU archive site."
|
||||
|
||||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
|
||||
if test -z "$file"; then
|
||||
file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
|
||||
fi
|
||||
if [ -f "$file" ]; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo ".ab help2man is required to generate this page"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
makeinfo)
|
||||
if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then
|
||||
# We have makeinfo, but it failed.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.texi' or \`.texinfo' file, or any other file
|
||||
indirectly affecting the aspect of the manual. The spurious
|
||||
call might also be the consequence of using a buggy \`make' (AIX,
|
||||
DU, IRIX). You might want to install the \`Texinfo' package or
|
||||
the \`GNU make' package. Grab either from any GNU archive site."
|
||||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
|
||||
if test -z "$file"; then
|
||||
file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
|
||||
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
|
||||
fi
|
||||
touch $file
|
||||
;;
|
||||
|
||||
tar)
|
||||
shift
|
||||
if test -n "$run"; then
|
||||
echo 1>&2 "ERROR: \`tar' requires --run"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# We have already tried tar in the generic part.
|
||||
# Look for gnutar/gtar before invocation to avoid ugly error
|
||||
# messages.
|
||||
if (gnutar --version > /dev/null 2>&1); then
|
||||
gnutar "$@" && exit 0
|
||||
fi
|
||||
if (gtar --version > /dev/null 2>&1); then
|
||||
gtar "$@" && exit 0
|
||||
fi
|
||||
firstarg="$1"
|
||||
if shift; then
|
||||
case "$firstarg" in
|
||||
*o*)
|
||||
firstarg=`echo "$firstarg" | sed s/o//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
case "$firstarg" in
|
||||
*h*)
|
||||
firstarg=`echo "$firstarg" | sed s/h//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: I can't seem to be able to run \`tar' with the given arguments.
|
||||
You may want to install GNU tar or Free paxutils, or check the
|
||||
command line arguments."
|
||||
exit 1
|
||||
;;
|
||||
|
||||
*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, and is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them. Check the \`README' file,
|
||||
it often tells you about the needed prerequisites for installing
|
||||
this package. You may also peek at any GNU archive site, in case
|
||||
some other package would contain this missing \`$1' program."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
413
opal/event/devpoll.c
Обычный файл
413
opal/event/devpoll.c
Обычный файл
@ -0,0 +1,413 @@
|
||||
/*
|
||||
* Copyright 2000-2004 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "opal_config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/resource.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <sys/_time.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#include <sys/devpoll.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "event.h"
|
||||
#include "evsignal.h"
|
||||
#include "log.h"
|
||||
|
||||
#include "opal/threads/mutex.h"
|
||||
|
||||
extern opal_mutex_t opal_event_lock;
|
||||
|
||||
extern volatile sig_atomic_t opal_evsignal_caught;
|
||||
|
||||
/* due to limitations in the devpoll interface, we need to keep track of
|
||||
* all file descriptors outself.
|
||||
*/
|
||||
struct evdevpoll {
|
||||
struct opal_event *evread;
|
||||
struct opal_event *evwrite;
|
||||
};
|
||||
|
||||
struct devpollop {
|
||||
struct evdevpoll *fds;
|
||||
int nfds;
|
||||
struct pollfd *events;
|
||||
int nevents;
|
||||
int dpfd;
|
||||
sigset_t evsigmask;
|
||||
struct pollfd *changes;
|
||||
int nchanges;
|
||||
};
|
||||
|
||||
static void *devpoll_init (void);
|
||||
static int devpoll_add (void *, struct opal_event *);
|
||||
static int devpoll_del (void *, struct opal_event *);
|
||||
static int devpoll_recalc (struct event_base *, void *, int);
|
||||
static int devpoll_dispatch (struct event_base *, void *, struct timeval *);
|
||||
|
||||
struct opal_eventop devpollops = {
|
||||
"devpoll",
|
||||
devpoll_init,
|
||||
devpoll_add,
|
||||
devpoll_del,
|
||||
devpoll_recalc,
|
||||
devpoll_dispatch
|
||||
};
|
||||
|
||||
#define NEVENT 32000
|
||||
|
||||
static int
|
||||
devpoll_commit(struct devpollop *devpollop)
|
||||
{
|
||||
/*
|
||||
* Due to a bug in Solaris, we have to use pwrite with an offset of 0.
|
||||
* Write is limited to 2GB of data, until it will fail.
|
||||
*/
|
||||
if (pwrite(devpollop->dpfd, devpollop->changes,
|
||||
sizeof(struct pollfd) * devpollop->nchanges, 0) == -1)
|
||||
return(-1);
|
||||
|
||||
devpollop->nchanges = 0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
devpoll_queue(struct devpollop *devpollop, int fd, int events) {
|
||||
struct pollfd *pfd;
|
||||
|
||||
if (devpollop->nchanges >= devpollop->nevents) {
|
||||
/*
|
||||
* Change buffer is full, must commit it to /dev/poll before
|
||||
* adding more
|
||||
*/
|
||||
if (devpoll_commit(devpollop) != 0)
|
||||
return(-1);
|
||||
}
|
||||
|
||||
pfd = &devpollop->changes[devpollop->nchanges++];
|
||||
pfd->fd = fd;
|
||||
pfd->events = events;
|
||||
pfd->revents = 0;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void *
|
||||
devpoll_init(void)
|
||||
{
|
||||
int dpfd, nfiles = NEVENT;
|
||||
struct rlimit rl;
|
||||
struct devpollop *devpollop;
|
||||
|
||||
/* Disable devpoll when this environment variable is set */
|
||||
if (getenv("EVENT_NODEVPOLL"))
|
||||
return (NULL);
|
||||
|
||||
if (!(devpollop = calloc(1, sizeof(struct devpollop))))
|
||||
return (NULL);
|
||||
|
||||
if (getrlimit(RLIMIT_NOFILE, &rl) == 0 &&
|
||||
rl.rlim_cur != RLIM_INFINITY)
|
||||
nfiles = rl.rlim_cur;
|
||||
|
||||
/* Initialize the kernel queue */
|
||||
if ((dpfd = open("/dev/poll", O_RDWR)) == -1) {
|
||||
event_warn("open: /dev/poll");
|
||||
free(devpollop);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
devpollop->dpfd = dpfd;
|
||||
|
||||
/* Initialize fields */
|
||||
devpollop->events = calloc(nfiles, sizeof(struct pollfd));
|
||||
if (devpollop->events == NULL) {
|
||||
free(devpollop);
|
||||
close(dpfd);
|
||||
return (NULL);
|
||||
}
|
||||
devpollop->nevents = nfiles;
|
||||
|
||||
devpollop->fds = calloc(nfiles, sizeof(struct evdevpoll));
|
||||
if (devpollop->fds == NULL) {
|
||||
free(devpollop->events);
|
||||
free(devpollop);
|
||||
close(dpfd);
|
||||
return (NULL);
|
||||
}
|
||||
devpollop->nfds = nfiles;
|
||||
|
||||
devpollop->changes = calloc(nfiles, sizeof(struct pollfd));
|
||||
if (devpollop->changes == NULL) {
|
||||
free(devpollop->fds);
|
||||
free(devpollop->events);
|
||||
free(devpollop);
|
||||
close(dpfd);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
opal_evsignal_init(&devpollop->evsigmask);
|
||||
|
||||
return (devpollop);
|
||||
}
|
||||
|
||||
int
|
||||
devpoll_recalc(struct event_base *base, void *arg, int max)
|
||||
{
|
||||
struct devpollop *devpollop = arg;
|
||||
|
||||
if (max > devpollop->nfds) {
|
||||
struct evdevpoll *fds;
|
||||
int nfds;
|
||||
|
||||
nfds = devpollop->nfds;
|
||||
while (nfds < max)
|
||||
nfds <<= 1;
|
||||
|
||||
fds = realloc(devpollop->fds, nfds * sizeof(struct evdevpoll));
|
||||
if (fds == NULL) {
|
||||
event_warn("realloc");
|
||||
return (-1);
|
||||
}
|
||||
devpollop->fds = fds;
|
||||
memset(fds + devpollop->nfds, 0,
|
||||
(nfds - devpollop->nfds) * sizeof(struct evdevpoll));
|
||||
devpollop->nfds = nfds;
|
||||
}
|
||||
|
||||
return (opal_evsignal_recalc(&devpollop->evsigmask));
|
||||
}
|
||||
|
||||
int
|
||||
devpoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
{
|
||||
struct devpollop *devpollop = arg;
|
||||
struct pollfd *events = devpollop->events;
|
||||
struct dvpoll dvp;
|
||||
struct evdevpoll *evdp;
|
||||
int i, res, timeout;
|
||||
|
||||
if (opal_evsignal_deliver(&devpollop->evsigmask) == -1)
|
||||
return (-1);
|
||||
|
||||
if (devpollop->nchanges)
|
||||
devpoll_commit(devpollop);
|
||||
|
||||
timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
|
||||
|
||||
dvp.dp_fds = devpollop->events;
|
||||
dvp.dp_nfds = devpollop->nevents;
|
||||
dvp.dp_timeout = timeout;
|
||||
|
||||
|
||||
/* we should release the lock if we're going to enter the
|
||||
kernel in a multi-threaded application. However, if we're
|
||||
single threaded, there's really no advantage to releasing
|
||||
the lock and it just takes up time we could spend doing
|
||||
something else. */
|
||||
OPAL_THREAD_UNLOCK(&opal_event_lock);
|
||||
res = ioctl(devpollop->dpfd, DP_POLL, &dvp);
|
||||
OPAL_THREAD_LOCK(&opal_event_lock);
|
||||
|
||||
if (opal_evsignal_recalc(&devpollop->evsigmask) == -1)
|
||||
return (-1);
|
||||
|
||||
if (res == -1) {
|
||||
if (errno != EINTR) {
|
||||
event_warn("ioctl: DP_POLL");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
opal_evsignal_process();
|
||||
return (0);
|
||||
} else if (opal_evsignal_caught)
|
||||
opal_evsignal_process();
|
||||
|
||||
event_debug(("%s: devpoll_wait reports %d", __func__, res));
|
||||
|
||||
for (i = 0; i < res; i++) {
|
||||
int which = 0;
|
||||
int what = events[i].revents;
|
||||
struct opal_event *evread = NULL, *evwrite = NULL;
|
||||
|
||||
assert(events[i].fd < devpollop->nfds);
|
||||
evdp = &devpollop->fds[events[i].fd];
|
||||
|
||||
if (what & POLLHUP)
|
||||
what |= POLLIN | POLLOUT;
|
||||
else if (what & POLLERR)
|
||||
what |= POLLIN | POLLOUT;
|
||||
|
||||
if (what & POLLIN) {
|
||||
evread = evdp->evread;
|
||||
which |= OPAL_EV_READ;
|
||||
}
|
||||
|
||||
if (what & POLLOUT) {
|
||||
evwrite = evdp->evwrite;
|
||||
which |= OPAL_EV_WRITE;
|
||||
}
|
||||
|
||||
if (!which)
|
||||
continue;
|
||||
|
||||
if (evread != NULL && !(evread->ev_events & OPAL_EV_PERSIST))
|
||||
opal_event_del(evread);
|
||||
if (evwrite != NULL && evwrite != evread &&
|
||||
!(evwrite->ev_events & OPAL_EV_PERSIST))
|
||||
opal_event_del(evwrite);
|
||||
|
||||
if (evread != NULL)
|
||||
opal_event_active(evread, OPAL_EV_READ, 1);
|
||||
if (evwrite != NULL)
|
||||
opal_event_active(evwrite, OPAL_EV_WRITE, 1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
devpoll_add(void *arg, struct opal_event *ev)
|
||||
{
|
||||
struct devpollop *devpollop = arg;
|
||||
struct evdevpoll *evdp;
|
||||
int fd, events;
|
||||
|
||||
if (ev->ev_events & OPAL_EV_SIGNAL)
|
||||
return (opal_evsignal_add(&devpollop->evsigmask, ev));
|
||||
|
||||
fd = ev->ev_fd;
|
||||
if (fd >= devpollop->nfds) {
|
||||
/* Extend the file descriptor array as necessary */
|
||||
if (devpoll_recalc(ev->ev_base, devpollop, fd) == -1)
|
||||
return (-1);
|
||||
}
|
||||
evdp = &devpollop->fds[fd];
|
||||
|
||||
/*
|
||||
* It's not necessary to OR the existing read/write events that we
|
||||
* are currently interested in with the new event we are adding.
|
||||
* The /dev/poll driver ORs any new events with the existing events
|
||||
* that it has cached for the fd.
|
||||
*/
|
||||
|
||||
events = 0;
|
||||
if (ev->ev_events & OPAL_EV_READ) {
|
||||
if (evdp->evread && evdp->evread != ev) {
|
||||
/* There is already a different read event registered */
|
||||
return(-1);
|
||||
}
|
||||
events |= POLLIN;
|
||||
}
|
||||
|
||||
if (ev->ev_events & OPAL_EV_WRITE) {
|
||||
if (evdp->evwrite && evdp->evwrite != ev) {
|
||||
/* There is already a different write event registered */
|
||||
return(-1);
|
||||
}
|
||||
events |= POLLOUT;
|
||||
}
|
||||
|
||||
if (devpoll_queue(devpollop, fd, events) != 0)
|
||||
return(-1);
|
||||
|
||||
/* Update events responsible */
|
||||
if (ev->ev_events & OPAL_EV_READ)
|
||||
evdp->evread = ev;
|
||||
if (ev->ev_events & OPAL_EV_WRITE)
|
||||
evdp->evwrite = ev;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
devpoll_del(void *arg, struct opal_event *ev)
|
||||
{
|
||||
struct devpollop *devpollop = arg;
|
||||
struct evdevpoll *evdp;
|
||||
int fd, events;
|
||||
int needwritedelete = 1, needreaddelete = 1;
|
||||
|
||||
if (ev->ev_events & OPAL_EV_SIGNAL)
|
||||
return (opal_evsignal_del(&devpollop->evsigmask, ev));
|
||||
|
||||
fd = ev->ev_fd;
|
||||
if (fd >= devpollop->nfds)
|
||||
return (0);
|
||||
evdp = &devpollop->fds[fd];
|
||||
|
||||
events = 0;
|
||||
if (ev->ev_events & OPAL_EV_READ)
|
||||
events |= POLLIN;
|
||||
if (ev->ev_events & OPAL_EV_WRITE)
|
||||
events |= POLLOUT;
|
||||
|
||||
/*
|
||||
* The only way to remove an fd from the /dev/poll monitored set is
|
||||
* to use POLLREMOVE by itself. This removes ALL events for the fd
|
||||
* provided so if we care about two events and are only removing one
|
||||
* we must re-add the other event after POLLREMOVE.
|
||||
*/
|
||||
|
||||
if (devpoll_queue(devpollop, fd, POLLREMOVE) != 0)
|
||||
return(-1);
|
||||
|
||||
if ((events & (POLLIN|POLLOUT)) != (POLLIN|POLLOUT)) {
|
||||
/*
|
||||
* We're not deleting all events, so we must resubmit the
|
||||
* event that we are still interested in if one exists.
|
||||
*/
|
||||
|
||||
if ((events & POLLIN) && evdp->evwrite != NULL) {
|
||||
/* Deleting read, still care about write */
|
||||
devpoll_queue(devpollop, fd, POLLOUT);
|
||||
needwritedelete = 0;
|
||||
} else if ((events & POLLOUT) && evdp->evread != NULL) {
|
||||
/* Deleting write, still care about read */
|
||||
devpoll_queue(devpollop, fd, POLLIN);
|
||||
needreaddelete = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (needreaddelete)
|
||||
evdp->evread = NULL;
|
||||
if (needwritedelete)
|
||||
evdp->evwrite = NULL;
|
||||
|
||||
return (0);
|
||||
}
|
360
opal/event/epoll.c
Обычный файл
360
opal/event/epoll.c
Обычный файл
@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Copyright 2000-2003 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "opal_config.h"
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <sys/_time.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "event.h"
|
||||
#include "evsignal.h"
|
||||
#include "log.h"
|
||||
|
||||
#include "opal/threads/mutex.h"
|
||||
|
||||
extern volatile sig_atomic_t opal_evsignal_caught;
|
||||
extern opal_mutex_t opal_event_lock;
|
||||
|
||||
/* due to limitations in the epoll interface, we need to keep track of
|
||||
* all file descriptors outself.
|
||||
*/
|
||||
struct evepoll {
|
||||
struct opal_event *evread;
|
||||
struct opal_event *evwrite;
|
||||
};
|
||||
|
||||
struct epollop {
|
||||
struct evepoll *fds;
|
||||
int nfds;
|
||||
struct epoll_event *events;
|
||||
int nevents;
|
||||
int epfd;
|
||||
sigset_t evsigmask;
|
||||
};
|
||||
|
||||
static void *epoll_init (void);
|
||||
static int epoll_add (void *, struct opal_event *);
|
||||
static int epoll_del (void *, struct opal_event *);
|
||||
static int epoll_recalc (struct event_base *, void *, int);
|
||||
static int epoll_dispatch (struct event_base *, void *, struct timeval *);
|
||||
|
||||
struct opal_eventop opal_epollops = {
|
||||
"epoll",
|
||||
epoll_init,
|
||||
epoll_add,
|
||||
epoll_del,
|
||||
epoll_recalc,
|
||||
epoll_dispatch
|
||||
};
|
||||
|
||||
#ifdef HAVE_SETFD
|
||||
#define FD_CLOSEONEXEC(x) do { \
|
||||
if (fcntl(x, F_SETFD, 1) == -1) \
|
||||
event_warn("fcntl(%d, F_SETFD)", x); \
|
||||
} while (0)
|
||||
#else
|
||||
#define FD_CLOSEONEXEC(x)
|
||||
#endif
|
||||
|
||||
#define NEVENT 32000
|
||||
|
||||
static void *
|
||||
epoll_init(void)
|
||||
{
|
||||
int epfd, nfiles = NEVENT;
|
||||
struct rlimit rl;
|
||||
struct epollop *epollop;
|
||||
|
||||
/* Disable epollueue when this environment variable is set */
|
||||
if (getenv("EVENT_NOEPOLL"))
|
||||
return (NULL);
|
||||
|
||||
if (getrlimit(RLIMIT_NOFILE, &rl) == 0 &&
|
||||
rl.rlim_cur != RLIM_INFINITY)
|
||||
nfiles = rl.rlim_cur;
|
||||
|
||||
/* Initalize the kernel queue */
|
||||
|
||||
if ((epfd = epoll_create(nfiles)) == -1) {
|
||||
event_warn("epoll_create");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
FD_CLOSEONEXEC(epfd);
|
||||
|
||||
if (!(epollop = calloc(1, sizeof(struct epollop))))
|
||||
return (NULL);
|
||||
|
||||
epollop->epfd = epfd;
|
||||
|
||||
/* Initalize fields */
|
||||
epollop->events = malloc(nfiles * sizeof(struct epoll_event));
|
||||
if (epollop->events == NULL) {
|
||||
free(epollop);
|
||||
return (NULL);
|
||||
}
|
||||
epollop->nevents = nfiles;
|
||||
|
||||
epollop->fds = calloc(nfiles, sizeof(struct evepoll));
|
||||
if (epollop->fds == NULL) {
|
||||
free(epollop->events);
|
||||
free(epollop);
|
||||
return (NULL);
|
||||
}
|
||||
epollop->nfds = nfiles;
|
||||
|
||||
opal_evsignal_init(&epollop->evsigmask);
|
||||
|
||||
return (epollop);
|
||||
}
|
||||
|
||||
static int
|
||||
epoll_recalc(struct event_base *base, void *arg, int max)
|
||||
{
|
||||
struct epollop *epollop = arg;
|
||||
if (max > epollop->nfds) {
|
||||
struct evepoll *fds;
|
||||
int nfds;
|
||||
|
||||
nfds = epollop->nfds;
|
||||
while (nfds < max)
|
||||
nfds <<= 1;
|
||||
|
||||
fds = realloc(epollop->fds, nfds * sizeof(struct evepoll));
|
||||
if (fds == NULL) {
|
||||
event_warn("realloc");
|
||||
return (-1);
|
||||
}
|
||||
epollop->fds = fds;
|
||||
memset(fds + epollop->nfds, 0,
|
||||
(nfds - epollop->nfds) * sizeof(struct evepoll));
|
||||
epollop->nfds = nfds;
|
||||
}
|
||||
|
||||
return (opal_evsignal_recalc(&epollop->evsigmask));
|
||||
}
|
||||
|
||||
int
|
||||
epoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
{
|
||||
struct epollop *epollop = arg;
|
||||
struct epoll_event *events = epollop->events;
|
||||
struct evepoll *evep;
|
||||
int i, res, timeout;
|
||||
|
||||
if (opal_evsignal_deliver(&epollop->evsigmask) == -1)
|
||||
return (-1);
|
||||
|
||||
timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
|
||||
/* we should release the lock if we're going to enter the
|
||||
kernel in a multi-threaded application. However, if we're
|
||||
single threaded, there's really no advantage to releasing
|
||||
the lock and it just takes up time we could spend doing
|
||||
something else. */
|
||||
OPAL_THREAD_UNLOCK(&opal_event_lock);
|
||||
res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout);
|
||||
OPAL_THREAD_LOCK(&opal_event_lock);
|
||||
|
||||
if (opal_evsignal_recalc(&epollop->evsigmask) == -1)
|
||||
return (-1);
|
||||
|
||||
if (res == -1) {
|
||||
if (errno != EINTR) {
|
||||
event_warn("epoll_wait");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
opal_evsignal_process();
|
||||
return (0);
|
||||
} else if (opal_evsignal_caught)
|
||||
opal_evsignal_process();
|
||||
|
||||
event_debug(("%s: epoll_wait reports %d", __func__, res));
|
||||
|
||||
for (i = 0; i < res; i++) {
|
||||
int which = 0;
|
||||
int what = events[i].events;
|
||||
struct opal_event *evread = NULL, *evwrite = NULL;
|
||||
|
||||
evep = (struct evepoll *)events[i].data.ptr;
|
||||
|
||||
if (what & EPOLLHUP)
|
||||
what |= EPOLLIN | EPOLLOUT;
|
||||
else if (what & EPOLLERR)
|
||||
what |= EPOLLIN | EPOLLOUT;
|
||||
|
||||
if (what & EPOLLIN) {
|
||||
evread = evep->evread;
|
||||
which |= OPAL_EV_READ;
|
||||
}
|
||||
|
||||
if (what & EPOLLOUT) {
|
||||
evwrite = evep->evwrite;
|
||||
which |= OPAL_EV_WRITE;
|
||||
}
|
||||
|
||||
if (!which)
|
||||
continue;
|
||||
|
||||
if (evread != NULL && !(evread->ev_events & OPAL_EV_PERSIST))
|
||||
opal_event_del_i(evread);
|
||||
if (evwrite != NULL && evwrite != evread &&
|
||||
!(evwrite->ev_events & OPAL_EV_PERSIST))
|
||||
opal_event_del_i(evwrite);
|
||||
|
||||
if (evread != NULL)
|
||||
opal_event_active_i(evread, OPAL_EV_READ, 1);
|
||||
if (evwrite != NULL)
|
||||
opal_event_active_i(evwrite, OPAL_EV_WRITE, 1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
epoll_add(void *arg, struct opal_event *ev)
|
||||
{
|
||||
struct epollop *epollop = arg;
|
||||
struct epoll_event epev = {0, {0}};
|
||||
struct evepoll *evep;
|
||||
int fd, op, events;
|
||||
|
||||
if (ev->ev_events & OPAL_EV_SIGNAL)
|
||||
return (opal_evsignal_add(&epollop->evsigmask, ev));
|
||||
|
||||
fd = ev->ev_fd;
|
||||
if (fd >= epollop->nfds) {
|
||||
/* Extent the file descriptor array as necessary */
|
||||
if (epoll_recalc(ev->ev_base, epollop, fd) == -1)
|
||||
return (-1);
|
||||
}
|
||||
evep = &epollop->fds[fd];
|
||||
op = EPOLL_CTL_ADD;
|
||||
events = 0;
|
||||
if (evep->evread != NULL) {
|
||||
events |= EPOLLIN;
|
||||
op = EPOLL_CTL_MOD;
|
||||
}
|
||||
if (evep->evwrite != NULL) {
|
||||
events |= EPOLLOUT;
|
||||
op = EPOLL_CTL_MOD;
|
||||
}
|
||||
|
||||
if (ev->ev_events & OPAL_EV_READ)
|
||||
events |= EPOLLIN;
|
||||
if (ev->ev_events & OPAL_EV_WRITE)
|
||||
events |= EPOLLOUT;
|
||||
|
||||
epev.data.ptr = evep;
|
||||
epev.events = events;
|
||||
if (epoll_ctl(epollop->epfd, op, ev->ev_fd, &epev) == -1)
|
||||
return (-1);
|
||||
|
||||
/* Update events responsible */
|
||||
if (ev->ev_events & OPAL_EV_READ)
|
||||
evep->evread = ev;
|
||||
if (ev->ev_events & OPAL_EV_WRITE)
|
||||
evep->evwrite = ev;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
epoll_del(void *arg, struct opal_event *ev)
|
||||
{
|
||||
struct epollop *epollop = arg;
|
||||
struct epoll_event epev = {0, {0}};
|
||||
struct evepoll *evep;
|
||||
int fd, events, op;
|
||||
int needwritedelete = 1, needreaddelete = 1;
|
||||
|
||||
if (ev->ev_events & OPAL_EV_SIGNAL)
|
||||
return (opal_evsignal_del(&epollop->evsigmask, ev));
|
||||
|
||||
fd = ev->ev_fd;
|
||||
if (fd >= epollop->nfds)
|
||||
return (0);
|
||||
evep = &epollop->fds[fd];
|
||||
|
||||
op = EPOLL_CTL_DEL;
|
||||
events = 0;
|
||||
|
||||
if (ev->ev_events & OPAL_EV_READ)
|
||||
events |= EPOLLIN;
|
||||
if (ev->ev_events & OPAL_EV_WRITE)
|
||||
events |= EPOLLOUT;
|
||||
|
||||
if ((events & (EPOLLIN|EPOLLOUT)) != (EPOLLIN|EPOLLOUT)) {
|
||||
if ((events & EPOLLIN) && evep->evwrite != NULL) {
|
||||
needwritedelete = 0;
|
||||
events = EPOLLOUT;
|
||||
op = EPOLL_CTL_MOD;
|
||||
} else if ((events & EPOLLOUT) && evep->evread != NULL) {
|
||||
needreaddelete = 0;
|
||||
events = EPOLLIN;
|
||||
op = EPOLL_CTL_MOD;
|
||||
}
|
||||
}
|
||||
|
||||
epev.events = events;
|
||||
epev.data.ptr = evep;
|
||||
|
||||
if (needreaddelete)
|
||||
evep->evread = NULL;
|
||||
if (needwritedelete)
|
||||
evep->evwrite = NULL;
|
||||
|
||||
if (epoll_ctl(epollop->epfd, op, fd, &epev) == -1)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
61
opal/event/epoll_sub.c
Обычный файл
61
opal/event/epoll_sub.c
Обычный файл
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2003 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "opal_config.h"
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/epoll.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
int
|
||||
epoll_create(int size)
|
||||
{
|
||||
return (syscall(__NR_epoll_create, size));
|
||||
}
|
||||
|
||||
int
|
||||
epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
|
||||
{
|
||||
|
||||
return (syscall(__NR_epoll_ctl, epfd, op, fd, event));
|
||||
}
|
||||
|
||||
int
|
||||
epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
|
||||
{
|
||||
return (syscall(__NR_epoll_wait, epfd, events, maxevents, timeout));
|
||||
}
|
372
opal/event/evbuffer.c
Обычный файл
372
opal/event/evbuffer.c
Обычный файл
@ -0,0 +1,372 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2004 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opal_config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
#include "event.h"
|
||||
|
||||
/* prototypes */
|
||||
|
||||
void bufferevent_setwatermark(struct bufferevent *, short, size_t, size_t);
|
||||
static void bufferevent_read_pressure_cb(struct evbuffer *, size_t, size_t, void *);
|
||||
|
||||
static int
|
||||
bufferevent_add(struct opal_event *ev, int timeout)
|
||||
{
|
||||
struct timeval tv, *ptv = NULL;
|
||||
|
||||
if (timeout) {
|
||||
timerclear(&tv);
|
||||
tv.tv_sec = timeout;
|
||||
ptv = &tv;
|
||||
}
|
||||
|
||||
return (opal_event_add(ev, ptv));
|
||||
}
|
||||
|
||||
/*
|
||||
* This callback is executed when the size of the input buffer changes.
|
||||
* We use it to apply back pressure on the reading side.
|
||||
*/
|
||||
|
||||
static void
|
||||
bufferevent_read_pressure_cb(struct evbuffer *buf, size_t old, size_t now,
|
||||
void *arg) {
|
||||
struct bufferevent *bufev = arg;
|
||||
/*
|
||||
* If we are below the watermak then reschedule reading if it's
|
||||
* still enabled.
|
||||
*/
|
||||
if (bufev->wm_read.high == 0 || now < bufev->wm_read.high) {
|
||||
evbuffer_setcb(buf, NULL, NULL);
|
||||
|
||||
if (bufev->enabled & OPAL_EV_READ)
|
||||
bufferevent_add(&bufev->ev_read, bufev->timeout_read);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bufferevent_readcb(int fd, short event, void *arg)
|
||||
{
|
||||
struct bufferevent *bufev = arg;
|
||||
int res = 0;
|
||||
short what = OPAL_EVBUFFER_READ;
|
||||
size_t len;
|
||||
|
||||
if (event == OPAL_EV_TIMEOUT) {
|
||||
what |= OPAL_EVBUFFER_TIMEOUT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
res = evbuffer_read(bufev->input, fd, -1);
|
||||
if (res == -1) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
goto reschedule;
|
||||
/* error case */
|
||||
what |= OPAL_EVBUFFER_ERROR;
|
||||
} else if (res == 0) {
|
||||
/* eof case */
|
||||
what |= OPAL_EVBUFFER_EOF;
|
||||
}
|
||||
|
||||
if (res <= 0)
|
||||
goto error;
|
||||
|
||||
bufferevent_add(&bufev->ev_read, bufev->timeout_read);
|
||||
|
||||
/* See if this callbacks meets the water marks */
|
||||
len = OPAL_EVBUFFER_LENGTH(bufev->input);
|
||||
if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
|
||||
return;
|
||||
if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) {
|
||||
struct evbuffer *buf = bufev->input;
|
||||
opal_event_del(&bufev->ev_read);
|
||||
|
||||
/* Now schedule a callback for us */
|
||||
evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Invoke the user callback - must always be called last */
|
||||
(*bufev->readcb)(bufev, bufev->cbarg);
|
||||
return;
|
||||
|
||||
reschedule:
|
||||
bufferevent_add(&bufev->ev_read, bufev->timeout_read);
|
||||
return;
|
||||
|
||||
error:
|
||||
(*bufev->errorcb)(bufev, what, bufev->cbarg);
|
||||
}
|
||||
|
||||
static void
|
||||
bufferevent_writecb(int fd, short event, void *arg)
|
||||
{
|
||||
struct bufferevent *bufev = arg;
|
||||
int res = 0;
|
||||
short what = OPAL_EVBUFFER_WRITE;
|
||||
|
||||
if (event == OPAL_EV_TIMEOUT) {
|
||||
what |= OPAL_EVBUFFER_TIMEOUT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (OPAL_EVBUFFER_LENGTH(bufev->output)) {
|
||||
res = evbuffer_write(bufev->output, fd);
|
||||
if (res == -1) {
|
||||
if (errno == EAGAIN ||
|
||||
errno == EINTR ||
|
||||
errno == EINPROGRESS)
|
||||
goto reschedule;
|
||||
/* error case */
|
||||
what |= OPAL_EVBUFFER_ERROR;
|
||||
} else if (res == 0) {
|
||||
/* eof case */
|
||||
what |= OPAL_EVBUFFER_EOF;
|
||||
}
|
||||
if (res <= 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (OPAL_EVBUFFER_LENGTH(bufev->output) != 0)
|
||||
bufferevent_add(&bufev->ev_write, bufev->timeout_write);
|
||||
|
||||
/*
|
||||
* Invoke the user callback if our buffer is drained or below the
|
||||
* low watermark.
|
||||
*/
|
||||
if (OPAL_EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
|
||||
(*bufev->writecb)(bufev, bufev->cbarg);
|
||||
|
||||
return;
|
||||
|
||||
reschedule:
|
||||
if (OPAL_EVBUFFER_LENGTH(bufev->output) != 0)
|
||||
bufferevent_add(&bufev->ev_write, bufev->timeout_write);
|
||||
return;
|
||||
|
||||
error:
|
||||
(*bufev->errorcb)(bufev, what, bufev->cbarg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new buffered event object.
|
||||
*
|
||||
* The read callback is invoked whenever we read new data.
|
||||
* The write callback is invoked whenever the output buffer is drained.
|
||||
* The error callback is invoked on a write/read error or on EOF.
|
||||
*/
|
||||
|
||||
struct bufferevent *
|
||||
bufferevent_new(int fd, evbuffercb readcb, evbuffercb writecb,
|
||||
everrorcb errorcb, void *cbarg)
|
||||
{
|
||||
struct bufferevent *bufev;
|
||||
|
||||
if ((bufev = calloc(1, sizeof(struct bufferevent))) == NULL)
|
||||
return (NULL);
|
||||
|
||||
if ((bufev->input = evbuffer_new()) == NULL) {
|
||||
free(bufev);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ((bufev->output = evbuffer_new()) == NULL) {
|
||||
evbuffer_free(bufev->input);
|
||||
free(bufev);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
opal_event_set(&bufev->ev_read, fd, OPAL_EV_READ, bufferevent_readcb, bufev);
|
||||
opal_event_set(&bufev->ev_write, fd, OPAL_EV_WRITE, bufferevent_writecb, bufev);
|
||||
|
||||
bufev->readcb = readcb;
|
||||
bufev->writecb = writecb;
|
||||
bufev->errorcb = errorcb;
|
||||
|
||||
bufev->cbarg = cbarg;
|
||||
|
||||
bufev->enabled = OPAL_EV_READ | OPAL_EV_WRITE;
|
||||
|
||||
return (bufev);
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_priority_set(struct bufferevent *bufev, int priority)
|
||||
{
|
||||
if (opal_event_priority_set(&bufev->ev_read, priority) == -1)
|
||||
return (-1);
|
||||
if (opal_event_priority_set(&bufev->ev_write, priority) == -1)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Closing the file descriptor is the responsibility of the caller */
|
||||
|
||||
void
|
||||
bufferevent_free(struct bufferevent *bufev)
|
||||
{
|
||||
opal_event_del(&bufev->ev_read);
|
||||
opal_event_del(&bufev->ev_write);
|
||||
|
||||
evbuffer_free(bufev->input);
|
||||
evbuffer_free(bufev->output);
|
||||
|
||||
free(bufev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 0 on success;
|
||||
* -1 on failure.
|
||||
*/
|
||||
|
||||
int
|
||||
bufferevent_write(struct bufferevent *bufev, void *data, size_t size)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = evbuffer_add(bufev->output, data, size);
|
||||
|
||||
if (res == -1)
|
||||
return (res);
|
||||
|
||||
/* If everything is okay, we need to schedule a write */
|
||||
if (size > 0 && (bufev->enabled & OPAL_EV_WRITE))
|
||||
bufferevent_add(&bufev->ev_write, bufev->timeout_write);
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = bufferevent_write(bufev, buf->buffer, buf->off);
|
||||
if (res != -1)
|
||||
evbuffer_drain(buf, buf->off);
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
size_t
|
||||
bufferevent_read(struct bufferevent *bufev, void *data, size_t size)
|
||||
{
|
||||
struct evbuffer *buf = bufev->input;
|
||||
|
||||
if (buf->off < size)
|
||||
size = buf->off;
|
||||
|
||||
/* Copy the available data to the user buffer */
|
||||
memcpy(data, buf->buffer, size);
|
||||
|
||||
if (size)
|
||||
evbuffer_drain(buf, size);
|
||||
|
||||
return (size);
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_enable(struct bufferevent *bufev, short event)
|
||||
{
|
||||
if (event & OPAL_EV_READ) {
|
||||
if (bufferevent_add(&bufev->ev_read, bufev->timeout_read) == -1)
|
||||
return (-1);
|
||||
}
|
||||
if (event & OPAL_EV_WRITE) {
|
||||
if (bufferevent_add(&bufev->ev_write, bufev->timeout_write) == -1)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
bufev->enabled |= event;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_disable(struct bufferevent *bufev, short event)
|
||||
{
|
||||
if (event & OPAL_EV_READ) {
|
||||
if (opal_event_del(&bufev->ev_read) == -1)
|
||||
return (-1);
|
||||
}
|
||||
if (event & OPAL_EV_WRITE) {
|
||||
if (opal_event_del(&bufev->ev_write) == -1)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
bufev->enabled &= ~event;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the read and write timeout for a buffered event.
|
||||
*/
|
||||
|
||||
void
|
||||
bufferevent_settimeout(struct bufferevent *bufev,
|
||||
int timeout_read, int timeout_write) {
|
||||
bufev->timeout_read = timeout_read;
|
||||
bufev->timeout_write = timeout_write;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the water marks
|
||||
*/
|
||||
|
||||
void
|
||||
bufferevent_setwatermark(struct bufferevent *bufev, short events,
|
||||
size_t lowmark, size_t highmark)
|
||||
{
|
||||
if (events & OPAL_EV_READ) {
|
||||
bufev->wm_read.low = lowmark;
|
||||
bufev->wm_read.high = highmark;
|
||||
}
|
||||
|
||||
if (events & OPAL_EV_WRITE) {
|
||||
bufev->wm_write.low = lowmark;
|
||||
bufev->wm_write.high = highmark;
|
||||
}
|
||||
|
||||
/* If the watermarks changed then see if we should call read again */
|
||||
bufferevent_read_pressure_cb(bufev->input,
|
||||
0, OPAL_EVBUFFER_LENGTH(bufev->input), bufev);
|
||||
}
|
56
opal/event/event-internal.h
Обычный файл
56
opal/event/event-internal.h
Обычный файл
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _EVENT_INTERNAL_H_
|
||||
#define _EVENT_INTERNAL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct event_base {
|
||||
const struct opal_eventop *evsel;
|
||||
void *evbase;
|
||||
int event_count; /* counts number of total events */
|
||||
int event_count_active; /* counts number of active events */
|
||||
|
||||
int event_gotterm; /* Set to terminate loop */
|
||||
|
||||
/* active event management */
|
||||
struct opal_event_list **activequeues;
|
||||
int nactivequeues;
|
||||
|
||||
struct opal_event_list eventqueue;
|
||||
struct timeval event_tv;
|
||||
|
||||
RB_HEAD(opal_event_tree, opal_event) timetree;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _EVENT_INTERNAL_H_ */
|
517
opal/event/event.3
Обычный файл
517
opal/event/event.3
Обычный файл
@ -0,0 +1,517 @@
|
||||
.\" $OpenBSD: event.3,v 1.4 2002/07/12 18:50:48 provos Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Artur Grabowski <art@openbsd.org>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\"
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd August 8, 2000
|
||||
.Dt EVENT 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm event_init ,
|
||||
.Nm event_dispatch ,
|
||||
.Nm event_loop ,
|
||||
.Nm event_loopexit ,
|
||||
.Nm event_base_loop ,
|
||||
.Nm event_base_loopexit ,
|
||||
.Nm event_set ,
|
||||
.Nm event_add ,
|
||||
.Nm event_del ,
|
||||
.Nm event_once ,
|
||||
.Nm event_pending ,
|
||||
.Nm event_initialized ,
|
||||
.Nm event_priority_init ,
|
||||
.Nm event_priority_set ,
|
||||
.Nm evtimer_set ,
|
||||
.Nm evtimer_add ,
|
||||
.Nm evtimer_del
|
||||
.Nm evtimer_pending ,
|
||||
.Nm evtimer_initialized ,
|
||||
.Nm signal_set ,
|
||||
.Nm signal_add ,
|
||||
.Nm signal_del
|
||||
.Nm signal_pending ,
|
||||
.Nm signal_initialized ,
|
||||
.Nm bufferevent_new ,
|
||||
.Nm bufferevent_free ,
|
||||
.Nm bufferevent_write ,
|
||||
.Nm bufferevent_write_buffer ,
|
||||
.Nm bufferevent_read ,
|
||||
.Nm bufferevent_enable ,
|
||||
.Nm bufferevent_disable ,
|
||||
.Nm bufferevent_settimeout ,
|
||||
.Nm evbuffer_new ,
|
||||
.Nm evbuffer_free ,
|
||||
.Nm evbuffer_add ,
|
||||
.Nm evbuffer_add_buffer ,
|
||||
.Nm evbuffer_add_printf ,
|
||||
.Nm evbuffer_drain ,
|
||||
.Nm evbuffer_write ,
|
||||
.Nm evbuffer_read ,
|
||||
.Nm evbuffer_find ,
|
||||
.Nm evbuffer_readline
|
||||
.Nd execute a function when a specific event occurs
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <sys/time.h>
|
||||
.Fd #include <event.h>
|
||||
.Ft "struct event_base *"
|
||||
.Fn "event_init"
|
||||
.Ft int
|
||||
.Fn "event_dispatch"
|
||||
.Ft int
|
||||
.Fn "event_loop" "int flags"
|
||||
.Ft int
|
||||
.Fn "event_loopexit" "struct timeval *tv"
|
||||
.Ft int
|
||||
.Fn "event_base_loop" "struct event_base *" "int flags"
|
||||
.Ft int
|
||||
.Fn "event_base_loopexit" "struct event_base *" "struct timeval *tv"
|
||||
.Ft void
|
||||
.Fn "event_set" "struct event *ev" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg"
|
||||
.Ft int
|
||||
.Fn "event_add" "struct event *ev" "struct timeval *tv"
|
||||
.Ft int
|
||||
.Fn "event_del" "struct event *ev"
|
||||
.Ft int
|
||||
.Fn "event_once" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv"
|
||||
.Ft int
|
||||
.Fn "event_pending" "struct event *ev" "short event" "struct timeval *tv"
|
||||
.Ft int
|
||||
.Fn "event_initialized" "struct event *ev"
|
||||
.Ft int
|
||||
.Fn "event_priority_init" "int npriorities"
|
||||
.Ft int
|
||||
.Fn "event_priority_set" "struct event *ev" "int priority"
|
||||
.Ft void
|
||||
.Fn "evtimer_set" "struct event *ev" "void (*fn)(int, short, void *)" "void *arg"
|
||||
.Ft void
|
||||
.Fn "evtimer_add" "struct event *ev" "struct timeval *"
|
||||
.Ft void
|
||||
.Fn "evtimer_del" "struct event *ev"
|
||||
.Ft int
|
||||
.Fn "evtimer_pending" "struct event *ev" "struct timeval *tv"
|
||||
.Ft int
|
||||
.Fn "evtimer_initialized" "struct event *ev"
|
||||
.Ft void
|
||||
.Fn "signal_set" "struct event *ev" "int signal" "void (*fn)(int, short, void *)" "void *arg"
|
||||
.Ft void
|
||||
.Fn "signal_add" "struct event *ev" "struct timeval *"
|
||||
.Ft void
|
||||
.Fn "signal_del" "struct event *ev"
|
||||
.Ft int
|
||||
.Fn "signal_pending" "struct event *ev" "struct timeval *tv"
|
||||
.Ft int
|
||||
.Fn "signal_initialized" "struct event *ev"
|
||||
.Ft "struct bufferevent *"
|
||||
.Fn "bufferevent_new" "int fd" "evbuffercb readcb" "evbuffercb writecb" "everrorcb" "void *cbarg"
|
||||
.Ft void
|
||||
.Fn "bufferevent_free" "struct bufferevent *bufev"
|
||||
.Ft int
|
||||
.Fn "bufferevent_write" "struct bufferevent *bufev" "void *data" "size_t size"
|
||||
.Ft int
|
||||
.Fn "bufferevent_write_buffer" "struct bufferevent *bufev" "struct evbuffer *buf"
|
||||
.Ft size_t
|
||||
.Fn "bufferevent_read" "struct bufferevent *bufev" "void *data" "size_t size"
|
||||
.Ft int
|
||||
.Fn "bufferevent_enable" "struct bufferevent *bufev" "short event"
|
||||
.Ft int
|
||||
.Fn "bufferevent_disable" "struct bufferevent *bufev" "short event"
|
||||
.Ft void
|
||||
.Fn "bufferevent_settimeout" "struct bufferevent *bufev" "int timeout_read" "int timeout_write"
|
||||
.Ft "struct evbuffer *"
|
||||
.Fn "evbuffer_new" "void"
|
||||
.Ft void
|
||||
.Fn "evbuffer_free" "struct evbuffer *buf"
|
||||
.Ft int
|
||||
.Fn "evbuffer_add" "struct evbuffer *buf" "u_char *data" "size_t size"
|
||||
.Ft int
|
||||
.Fn "evbuffer_add_buffer" "struct evbuffer *dst" "struct evbuffer *src"
|
||||
.Ft int
|
||||
.Fn "evbuffer_add_printf" "struct evbuffer *buf" "char *fmt" "..."
|
||||
.Ft void
|
||||
.Fn "evbuffer_drain" "struct evbuffer *buf" "size_t size"
|
||||
.Ft int
|
||||
.Fn "evbuffer_write" "struct evbuffer *buf" "int fd"
|
||||
.Ft int
|
||||
.Fn "evbuffer_read" "struct evbuffer *buf" "int fd" "int size"
|
||||
.Ft "u_char *"
|
||||
.Fn "evbuffer_find" "struct evbuffer *buf" "u_char *data" "size_t size"
|
||||
.Ft "char *"
|
||||
.Fn "evbuffer_readline" "struct evbuffer *buf"
|
||||
.Ft int
|
||||
.Fa (*event_sigcb)(void) ;
|
||||
.Ft int
|
||||
.Fa event_gotsig ;
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm event
|
||||
API provides a mechanism to execute a function when a specific event
|
||||
on a file descriptor occurs or after a given time has passed.
|
||||
.Pp
|
||||
The
|
||||
.Nm event
|
||||
API needs to be initialized with
|
||||
.Fn event_init
|
||||
before it can be used.
|
||||
.Pp
|
||||
In order to process events, an application needs to call
|
||||
.Fn event_dispatch .
|
||||
This function only returns on error, and should replace the event core
|
||||
of the application program.
|
||||
.Pp
|
||||
In order to avoid races in signal handlers, the
|
||||
.Nm event
|
||||
API provides two variables:
|
||||
.Va event_sigcb
|
||||
and
|
||||
.Va event_gotsig .
|
||||
A signal handler
|
||||
sets
|
||||
.Va event_gotsig
|
||||
to indicate that a signal has been received.
|
||||
The application sets
|
||||
.Va event_sigcb
|
||||
to a callback function. After the signal handler sets
|
||||
.Va event_gotsig ,
|
||||
.Nm event_dispatch
|
||||
will execute the callback function to process received signals. The
|
||||
callback returns 1 when no events are registered any more. It can
|
||||
return -1 to indicate an error to the
|
||||
.Nm event
|
||||
library, causing
|
||||
.Fn event_dispatch
|
||||
to terminate with
|
||||
.Va errno
|
||||
set to
|
||||
.Er EINTR.
|
||||
.Pp
|
||||
The
|
||||
.Nm event_loop
|
||||
function provides an interface for single pass execution of pending
|
||||
events. The flags
|
||||
.Va EVLOOP_ONCE
|
||||
and
|
||||
.Va EVLOOP_NONBLOCK
|
||||
are recognized.
|
||||
The
|
||||
.Nm event_loopexit
|
||||
function allows the loop to be terminated after some amount of time
|
||||
has passed.
|
||||
The parameter indicates the time after which the loop should terminate.
|
||||
.Pp
|
||||
It is the responsibility of the caller to provide these functions with
|
||||
pre-allocated event structures.
|
||||
.Pp
|
||||
The function
|
||||
.Fn event_set
|
||||
prepares the event structure
|
||||
.Fa ev
|
||||
to be used in future calls to
|
||||
.Fn event_add
|
||||
and
|
||||
.Fn event_del .
|
||||
The event will be prepared to call the function specified by the
|
||||
.Fa fn
|
||||
argument with an
|
||||
.Fa int
|
||||
argument indicating the file descriptor, a
|
||||
.Fa short
|
||||
argument indicating the type of event, and a
|
||||
.Fa void *
|
||||
argument given in the
|
||||
.Fa arg
|
||||
argument.
|
||||
The
|
||||
.Fa fd
|
||||
indicates the file descriptor that should be monitored for events.
|
||||
The events can be either
|
||||
.Va EV_READ ,
|
||||
.Va EV_WRITE ,
|
||||
or both.
|
||||
Indicating that an application can read or write from the file descriptor
|
||||
respectively without blocking.
|
||||
.Pp
|
||||
The function
|
||||
.Fa fn
|
||||
will be called with the file descriptor that triggered the event and
|
||||
the type of event which will be either
|
||||
.Va EV_TIMEOUT ,
|
||||
.Va EV_SIGNAL ,
|
||||
.Va EV_READ ,
|
||||
or
|
||||
.Va EV_WRITE .
|
||||
The additional flag
|
||||
.Va EV_PERSIST
|
||||
makes an
|
||||
.Fn event_add
|
||||
persistent until
|
||||
.Fn event_del
|
||||
has been called.
|
||||
.Pp
|
||||
Once initialized, the
|
||||
.Fa ev
|
||||
structure can be used repeatedly with
|
||||
.Fn event_add
|
||||
and
|
||||
.Fn event_del
|
||||
and does not need to be reinitialized unless the function called and/or
|
||||
the argument to it are to be changed.
|
||||
However, when an
|
||||
.Fa ev
|
||||
structure has been added to libevent using
|
||||
.Fn event_add
|
||||
the structure must persist until the event occurs (assuming
|
||||
.Fa EV_PERSIST
|
||||
is not set) or is removed
|
||||
using
|
||||
.Fn event_del .
|
||||
You may not reuse the same
|
||||
.Fa ev
|
||||
structure for multiple monitored descriptors; each descriptor
|
||||
needs its own
|
||||
.Fa ev .
|
||||
.Pp
|
||||
The function
|
||||
.Fn event_add
|
||||
schedules the execution of the
|
||||
.Fa ev
|
||||
event when the event specified in
|
||||
.Fn event_set
|
||||
occurs or in at least the time specified in the
|
||||
.Fa tv .
|
||||
If
|
||||
.Fa tv
|
||||
is NULL, no timeout occurs and the function will only be called
|
||||
if a matching event occurs on the file descriptor.
|
||||
The event in the
|
||||
.Fa ev
|
||||
argument must be already initialized by
|
||||
.Fn event_set
|
||||
and may not be used in calls to
|
||||
.Fn event_set
|
||||
until it has timed out or been removed with
|
||||
.Fn event_del .
|
||||
If the event in the
|
||||
.Fa ev
|
||||
argument already has a scheduled timeout, the old timeout will be
|
||||
replaced by the new one.
|
||||
.Pp
|
||||
The function
|
||||
.Fn event_del
|
||||
will cancel the event in the argument
|
||||
.Fa ev .
|
||||
If the event has already executed or has never been added
|
||||
the call will have no effect.
|
||||
.Pp
|
||||
The function
|
||||
.Fn event_once
|
||||
is similar to
|
||||
.Fn event_set .
|
||||
However, it schedules a callback to be called exactly once and does not
|
||||
require the caller to prepare an
|
||||
.Fa event
|
||||
structure.
|
||||
This function supports
|
||||
.Fa EV_TIMEOUT ,
|
||||
.Fa EV_READ
|
||||
and
|
||||
.Fa EV_WRITE .
|
||||
.Pp
|
||||
The
|
||||
.Fn event_pending
|
||||
function can be used to check if the event specified by
|
||||
.Fa event
|
||||
is pending to run.
|
||||
If
|
||||
.Va EV_TIMEOUT
|
||||
was specified and
|
||||
.Fa tv
|
||||
is not
|
||||
.Va NULL ,
|
||||
the expiration time of the event will be returned in
|
||||
.Fa tv .
|
||||
.Pp
|
||||
The
|
||||
.Fn event_initialized
|
||||
macro can be used to check if an event has been initialized.
|
||||
.Pp
|
||||
The functions
|
||||
.Fn evtimer_set ,
|
||||
.Fn evtimer_add ,
|
||||
.Fn evtimer_del ,
|
||||
.Fn evtimer_initialized ,
|
||||
and
|
||||
.Fn evtimer_pending
|
||||
are abbreviations for common situations where only a timeout is required.
|
||||
The file descriptor passed will be -1, and the event type will be
|
||||
.Va EV_TIMEOUT .
|
||||
.Pp
|
||||
.Pp
|
||||
The functions
|
||||
.Fn signal_set ,
|
||||
.Fn signal_add ,
|
||||
.Fn signal_del ,
|
||||
.Fn signal_initialized ,
|
||||
and
|
||||
.Fn signal_pending
|
||||
are abbreviations.
|
||||
The event type will be a persistent
|
||||
.Va EV_SIGNAL .
|
||||
That means
|
||||
.Fn signal_set
|
||||
adds
|
||||
.Va EV_PERSIST .
|
||||
.Pp
|
||||
It is possible to disable support for
|
||||
.Va epoll , kqueue , devpoll, poll
|
||||
or
|
||||
.Va select
|
||||
by setting the environment variable
|
||||
.Va EVENT_NOEPOLL , EVENT_NOKQUEUE , EVENT_NODEVPOLL, EVENT_NOPOLL
|
||||
or
|
||||
.Va EVENT_NOSELECT .
|
||||
By setting the environment variable
|
||||
.Va EVENT_SHOW_METHOD ,
|
||||
.Nm libevent
|
||||
displays the kernel notification method that it uses.
|
||||
.Pp
|
||||
.Sh EVENT PRIORITIES
|
||||
By default
|
||||
.Nm libevent
|
||||
schedules all active events with the same priority.
|
||||
However, sometime it is desirable to process some events with a higher
|
||||
priority than others.
|
||||
For that reason,
|
||||
.Nm libevent
|
||||
supports strict priority queues.
|
||||
Active events with a lower priority are always processed before events
|
||||
with a higher priority.
|
||||
.Pp
|
||||
The number of different priorities can be set initially with the
|
||||
.Fn event_priority_init
|
||||
function.
|
||||
This function should be called before the first call to
|
||||
.Fn event_dispatch .
|
||||
The
|
||||
.Fn event_priority_set
|
||||
function can be used to assign a priority to an event.
|
||||
By default,
|
||||
.Nm libevent
|
||||
assigns the middle priority to all events unless their priority
|
||||
is explicitly set.
|
||||
.Pp
|
||||
.Sh THREAD SAFE EVENTS
|
||||
.Nm Libevent
|
||||
has experimental support for thread-safe events.
|
||||
When initializing the library via
|
||||
.Fn event_init ,
|
||||
an event base is returned.
|
||||
This event base can be used in conjunction with calls to
|
||||
.Fn event_base_set
|
||||
.Fn event_base_dispatch ,
|
||||
.Fn event_base_loop ,
|
||||
and
|
||||
.Fn event_base_loopexit .
|
||||
.Fn event_base_set
|
||||
should be called after preparing an event with
|
||||
.Fn event_set ,
|
||||
as
|
||||
.Fn event_set
|
||||
assigns the provided event to the most recently created event base.
|
||||
.Pp
|
||||
.Sh BUFFERED EVENTS
|
||||
.Nm libevent
|
||||
provides an abstraction on top of the regular event callbacks.
|
||||
This abstraction is called a
|
||||
.Va "buffered event" .
|
||||
A buffered event provides input and output buffer that get filled
|
||||
and drained automatically.
|
||||
The user of a buffered event no longer deals directly with the IO,
|
||||
but instead is reading from input and writing to output buffers.
|
||||
.Pp
|
||||
A new bufferevent is created by
|
||||
.Fn bufferevent_new .
|
||||
The parameter
|
||||
.Fa "fd"
|
||||
specifies the file descriptor from which data is read and written to.
|
||||
This file descriptor is not allowed to be a
|
||||
.Xr pipe 2 .
|
||||
The next three parameters are callbacks.
|
||||
The read and write callback have the following form
|
||||
.Ft void
|
||||
.Fn "(*cb)" "struct bufferevent *bufev" "void *arg"
|
||||
The argument is specified by the fourth parameter
|
||||
.Fa "cbarg" .
|
||||
.Pp
|
||||
By default the buffered event is read enabled and will try to read
|
||||
from the file descriptor.
|
||||
The write callback is executed whenever the output buffer is drained
|
||||
below the write low watermark which is
|
||||
.Va 0
|
||||
by default.
|
||||
.Pp
|
||||
The
|
||||
.Fn bufferevent_write
|
||||
function can be used to write data to the file descriptor.
|
||||
The data is appended to the output buffer and written to the descriptor
|
||||
automatically as it becomes available for writing.
|
||||
The
|
||||
.Fn bufferevent_read
|
||||
function is used to read data from the input buffer.
|
||||
Both functions return the amount of data written or read.
|
||||
.Pp
|
||||
.Sh RETURN VALUES
|
||||
Upon successful completion
|
||||
.Fn event_add
|
||||
and
|
||||
.Fn event_del
|
||||
return 0.
|
||||
Otherwise, -1 is returned and the global variable errno is
|
||||
set to indicate the error.
|
||||
.Sh SEE ALSO
|
||||
.Xr timeout 9 ,
|
||||
.Xr select 2 ,
|
||||
.Xr kqueue 2
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm event
|
||||
API manpage is based on the
|
||||
.Xr timeout 9
|
||||
manpage by Artur Grabowski.
|
||||
The port of
|
||||
.Nm libevent
|
||||
to Windows is due to Michael A. Davis.
|
||||
Support for real-time signals is due to Taral.
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm event
|
||||
library was written by Niels Provos.
|
||||
.Pp
|
||||
.Sh BUGS
|
||||
This documentation is neither complete nor authoritative.
|
||||
If you are in doubt about the usage of this API then
|
||||
check the source code to find out how it works, write
|
||||
up the missing piece of documentation and send it to
|
||||
me for inclusion in this man page.
|
1094
opal/event/event.c
Обычный файл
1094
opal/event/event.c
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
401
opal/event/event.h
Обычный файл
401
opal/event/event.h
Обычный файл
@ -0,0 +1,401 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _EVENT_H_
|
||||
#define _EVENT_H_
|
||||
|
||||
#if defined(c_plusplus) || defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "opal_config.h"
|
||||
|
||||
#include "opal/threads/mutex.h"
|
||||
#include "opal/event/event_rename.h"
|
||||
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
typedef unsigned char u_char;
|
||||
#endif
|
||||
|
||||
#define OPAL_EVLIST_TIMEOUT 0x01
|
||||
#define OPAL_EVLIST_INSERTED 0x02
|
||||
#define OPAL_EVLIST_SIGNAL 0x04
|
||||
#define OPAL_EVLIST_ACTIVE 0x08
|
||||
#define OPAL_EVLIST_INTERNAL 0x10
|
||||
#define OPAL_EVLIST_INIT 0x80
|
||||
|
||||
/* EVLIST_X_ Private space: 0x1000-0xf000 */
|
||||
#define OPAL_EVLIST_ALL (0xf000 | 0x9f)
|
||||
|
||||
#define OPAL_EV_TIMEOUT 0x01
|
||||
#define OPAL_EV_READ 0x02
|
||||
#define OPAL_EV_WRITE 0x04
|
||||
#define OPAL_EV_SIGNAL 0x08
|
||||
#define OPAL_EV_PERSIST 0x10 /* Persistant event */
|
||||
|
||||
#ifdef OPAL_EVENT_USE_SIGNALS
|
||||
#undef OPAL_EVENT_USE_SIGNALS
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
/* We do not have the required framework for EVENT_SIGNALS to work on windows.
|
||||
We currently use the select module on windows without the EVENT_SIGNALS.
|
||||
This might have adverse effect in 2 cases:
|
||||
1. People using event library for keeping track of file descriptors (NOT
|
||||
socket descriptors) will have to come up with something else since
|
||||
select() under windows works only on sockets.
|
||||
2. Since the EVENT_SIGNALS are disabled, instances of code which rely on
|
||||
this mechanism will NOT work under windows
|
||||
*/
|
||||
#define OPAL_EVENT_USE_SIGNALS 0
|
||||
#else
|
||||
#define OPAL_EVENT_USE_SIGNALS 1
|
||||
#endif
|
||||
|
||||
/* Fix so that ppl dont have to run with <sys/queue.h> */
|
||||
#ifndef TAILQ_ENTRY
|
||||
#define _EVENT_DEFINED_TQENTRY
|
||||
#define TAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *tqe_next; /* next element */ \
|
||||
struct type **tqe_prev; /* address of previous next element */ \
|
||||
}
|
||||
#endif /* !TAILQ_ENTRY */
|
||||
#ifndef RB_ENTRY
|
||||
#define _EVENT_DEFINED_RBENTRY
|
||||
#define RB_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *rbe_left; /* left element */ \
|
||||
struct type *rbe_right; /* right element */ \
|
||||
struct type *rbe_parent; /* parent element */ \
|
||||
int rbe_color; /* node color */ \
|
||||
}
|
||||
#endif /* !RB_ENTRY */
|
||||
|
||||
struct event_base;
|
||||
struct opal_event {
|
||||
TAILQ_ENTRY (opal_event) ev_next;
|
||||
TAILQ_ENTRY (opal_event) ev_active_next;
|
||||
TAILQ_ENTRY (opal_event) ev_signal_next;
|
||||
RB_ENTRY (opal_event) ev_timeout_node;
|
||||
|
||||
struct event_base *ev_base;
|
||||
int ev_fd;
|
||||
short ev_events;
|
||||
short ev_ncalls;
|
||||
short *ev_pncalls; /* Allows deletes in callback */
|
||||
|
||||
struct timeval ev_timeout;
|
||||
|
||||
int ev_pri; /* smaller numbers are higher priority */
|
||||
|
||||
void (*ev_callback)(int, short, void *arg);
|
||||
void *ev_arg;
|
||||
|
||||
int ev_res; /* result passed to event callback */
|
||||
int ev_flags;
|
||||
};
|
||||
typedef struct opal_event opal_event_t;
|
||||
|
||||
#define OPAL_EVENT_SIGNAL(ev) (int)ev->ev_fd
|
||||
#define OPAL_EVENT_FD(ev) (int)ev->ev_fd
|
||||
|
||||
#ifdef _EVENT_DEFINED_TQENTRY
|
||||
#undef TAILQ_ENTRY
|
||||
#undef _EVENT_DEFINED_TQENTRY
|
||||
#else
|
||||
TAILQ_HEAD (opal_event_list, opal_event);
|
||||
#endif /* _EVENT_DEFINED_TQENTRY */
|
||||
#ifdef _EVENT_DEFINED_RBENTRY
|
||||
#undef RB_ENTRY
|
||||
#undef _EVENT_DEFINED_RBENTRY
|
||||
#endif /* _EVENT_DEFINED_RBENTRY */
|
||||
|
||||
struct opal_eventop {
|
||||
char *name;
|
||||
void *(*init)(void);
|
||||
int (*add)(void *, struct opal_event *);
|
||||
int (*del)(void *, struct opal_event *);
|
||||
int (*recalc)(struct event_base *, void *, int);
|
||||
int (*dispatch)(struct event_base *, void *, struct timeval *);
|
||||
};
|
||||
|
||||
#define OPAL_TIMEOUT_DEFAULT {1, 0}
|
||||
|
||||
OMPI_DECLSPEC int opal_event_init(void);
|
||||
OMPI_DECLSPEC int opal_event_dispatch(void);
|
||||
OMPI_DECLSPEC int opal_event_base_dispatch(struct event_base *);
|
||||
|
||||
OMPI_DECLSPEC int opal_event_fini(void);
|
||||
OMPI_DECLSPEC int opal_event_enable(void);
|
||||
OMPI_DECLSPEC int opal_event_disable(void);
|
||||
OMPI_DECLSPEC bool opal_event_progress_thread(void);
|
||||
OMPI_DECLSPEC int opal_event_restart(void);
|
||||
|
||||
#define _EVENT_LOG_DEBUG 0
|
||||
#define _EVENT_LOG_MSG 1
|
||||
#define _EVENT_LOG_WARN 2
|
||||
#define _EVENT_LOG_ERR 3
|
||||
typedef void (*event_log_cb)(int severity, const char *msg);
|
||||
void event_set_log_callback(event_log_cb cb);
|
||||
|
||||
/* Associate a different event base with an event */
|
||||
int opal_event_base_set(struct event_base *, struct opal_event *);
|
||||
|
||||
#define OPAL_EVLOOP_ONCE 0x01
|
||||
#define OPAL_EVLOOP_NONBLOCK 0x02
|
||||
OMPI_DECLSPEC int opal_event_loop(int);
|
||||
int opal_event_base_loop(struct event_base *, int);
|
||||
int opal_event_loopexit(struct timeval *); /* Causes the loop to exit */
|
||||
int event_base_loopexit(struct event_base *, struct timeval *);
|
||||
|
||||
#define opal_evtimer_add(ev, tv) opal_event_add(ev, tv)
|
||||
#define opal_evtimer_set(ev, cb, arg) opal_event_set(ev, -1, 0, cb, arg)
|
||||
#define opal_evtimer_del(ev) opal_event_del(ev)
|
||||
#define opal_evtimer_pending(ev, tv) opal_event_pending(ev, OPAL_EV_TIMEOUT, tv)
|
||||
#define opal_evtimer_initialized(ev) (ev)->ev_flags & OPAL_EVLIST_INIT)
|
||||
|
||||
#define opal_timeout_add(ev, tv) opal_event_add(ev, tv)
|
||||
#define opal_timeout_set(ev, cb, arg) opal_event_set(ev, -1, 0, cb, arg)
|
||||
#define opal_timeout_del(ev) opal_event_del(ev)
|
||||
#define opal_timeout_pending(ev, tv) opal_event_pending(ev, OPAL_EV_TIMEOUT, tv)
|
||||
#define opal_timeout_initialized(ev) ((ev)->ev_flags & OPAL_EVLIST_INIT)
|
||||
|
||||
#define opal_signal_add(ev, tv) opal_event_add(ev, tv)
|
||||
#define opal_signal_set(ev, x, cb, arg) \
|
||||
opal_event_set(ev, x, OPAL_EV_SIGNAL|OPAL_EV_PERSIST, cb, arg)
|
||||
#define opal_signal_del(ev) opal_event_del(ev)
|
||||
#define opal_signal_pending(ev, tv) opal_event_pending(ev, OPAL_EV_SIGNAL, tv)
|
||||
#define opal_signal_initialized(ev) ((ev)->ev_flags & OPAL_EVLIST_INIT)
|
||||
|
||||
/* for internal use only */
|
||||
OMPI_DECLSPEC int opal_event_add_i(struct opal_event *, struct timeval *);
|
||||
OMPI_DECLSPEC int opal_event_del_i(struct opal_event *);
|
||||
OMPI_DECLSPEC void opal_event_active_i(struct opal_event*, int, short);
|
||||
OMPI_DECLSPEC extern opal_mutex_t opal_event_lock;
|
||||
OMPI_DECLSPEC extern int opal_evsignal_restart(void);
|
||||
|
||||
extern struct event_base *current_base;
|
||||
|
||||
/* public functions */
|
||||
|
||||
void
|
||||
opal_event_set(struct opal_event *ev, int fd, short events,
|
||||
void (*callback)(int, short, void *), void *arg);
|
||||
|
||||
int opal_event_once(int, short, void (*)(int, short, void *), void *, struct timeval *);
|
||||
|
||||
static inline int
|
||||
opal_event_add(struct opal_event *ev, struct timeval *tv)
|
||||
{
|
||||
extern opal_mutex_t opal_event_lock;
|
||||
int rc;
|
||||
if(opal_using_threads()) {
|
||||
opal_mutex_lock(&opal_event_lock);
|
||||
rc = opal_event_add_i(ev, tv);
|
||||
opal_mutex_unlock(&opal_event_lock);
|
||||
} else {
|
||||
rc = opal_event_add_i(ev, tv);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int
|
||||
opal_event_del(struct opal_event *ev)
|
||||
{
|
||||
extern opal_mutex_t opal_event_lock;
|
||||
int rc;
|
||||
if(opal_using_threads()) {
|
||||
opal_mutex_lock(&opal_event_lock);
|
||||
rc = opal_event_del_i(ev);
|
||||
opal_mutex_unlock(&opal_event_lock);
|
||||
} else {
|
||||
rc = opal_event_del_i(ev);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline void
|
||||
opal_event_active(struct opal_event* ev, int res, short ncalls)
|
||||
{
|
||||
if(opal_using_threads()) {
|
||||
opal_mutex_lock(&opal_event_lock);
|
||||
opal_event_active_i(ev, res, ncalls);
|
||||
opal_mutex_unlock(&opal_event_lock);
|
||||
} else {
|
||||
opal_event_active_i(ev, res, ncalls);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
opal_event_pending(struct opal_event *ev, short event, struct timeval *tv)
|
||||
{
|
||||
int flags = 0;
|
||||
|
||||
if (ev->ev_flags & OPAL_EVLIST_INSERTED)
|
||||
flags |= (ev->ev_events & (OPAL_EV_READ|OPAL_EV_WRITE));
|
||||
if (ev->ev_flags & OPAL_EVLIST_ACTIVE)
|
||||
flags |= ev->ev_res;
|
||||
if (ev->ev_flags & OPAL_EVLIST_TIMEOUT)
|
||||
flags |= OPAL_EV_TIMEOUT;
|
||||
if (ev->ev_flags & OPAL_EVLIST_SIGNAL)
|
||||
flags |= OPAL_EV_SIGNAL;
|
||||
|
||||
event &= (OPAL_EV_TIMEOUT|OPAL_EV_READ|OPAL_EV_WRITE|OPAL_EV_SIGNAL);
|
||||
|
||||
/* See if there is a timeout that we should report */
|
||||
if (tv != NULL && (flags & event & OPAL_EV_TIMEOUT))
|
||||
*tv = ev->ev_timeout;
|
||||
|
||||
return (flags & event);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
#define opal_event_initialized(ev) ((ev)->ev_flags & OPAL_EVLIST_INIT && (ev)->ev_fd != INVALID_HANDLE_VALUE)
|
||||
#else
|
||||
#define opal_event_initialized(ev) ((ev)->ev_flags & OPAL_EVLIST_INIT)
|
||||
#endif
|
||||
|
||||
/* Some simple debugging functions */
|
||||
const char *event_get_version(void);
|
||||
const char *event_get_method(void);
|
||||
|
||||
/* These functions deal with event priorities */
|
||||
|
||||
int opal_event_priority_init(int);
|
||||
int opal_event_base_priority_init(struct event_base *, int);
|
||||
int opal_event_priority_set(struct opal_event *, int);
|
||||
|
||||
/* These functions deal with buffering input and output */
|
||||
|
||||
struct evbuffer {
|
||||
u_char *buffer;
|
||||
u_char *orig_buffer;
|
||||
|
||||
size_t misalign;
|
||||
size_t totallen;
|
||||
size_t off;
|
||||
|
||||
void (*cb)(struct evbuffer *, size_t, size_t, void *);
|
||||
void *cbarg;
|
||||
};
|
||||
|
||||
/* Just for error reporting - use other constants otherwise */
|
||||
#define OPAL_EVBUFFER_READ 0x01
|
||||
#define OPAL_EVBUFFER_WRITE 0x02
|
||||
#define OPAL_EVBUFFER_EOF 0x10
|
||||
#define OPAL_EVBUFFER_ERROR 0x20
|
||||
#define OPAL_EVBUFFER_TIMEOUT 0x40
|
||||
|
||||
struct bufferevent;
|
||||
typedef void (*evbuffercb)(struct bufferevent *, void *);
|
||||
typedef void (*everrorcb)(struct bufferevent *, short what, void *);
|
||||
|
||||
struct event_watermark {
|
||||
size_t low;
|
||||
size_t high;
|
||||
};
|
||||
|
||||
struct bufferevent {
|
||||
struct opal_event ev_read;
|
||||
struct opal_event ev_write;
|
||||
|
||||
struct evbuffer *input;
|
||||
struct evbuffer *output;
|
||||
|
||||
struct event_watermark wm_read;
|
||||
struct event_watermark wm_write;
|
||||
|
||||
evbuffercb readcb;
|
||||
evbuffercb writecb;
|
||||
everrorcb errorcb;
|
||||
void *cbarg;
|
||||
|
||||
int timeout_read; /* in seconds */
|
||||
int timeout_write; /* in seconds */
|
||||
|
||||
short enabled; /* events that are currently enabled */
|
||||
};
|
||||
|
||||
struct bufferevent *bufferevent_new(int fd,
|
||||
evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg);
|
||||
int bufferevent_priority_set(struct bufferevent *bufev, int pri);
|
||||
void bufferevent_free(struct bufferevent *bufev);
|
||||
int bufferevent_write(struct bufferevent *bufev, void *data, size_t size);
|
||||
int bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf);
|
||||
size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size);
|
||||
int bufferevent_enable(struct bufferevent *bufev, short event);
|
||||
int bufferevent_disable(struct bufferevent *bufev, short event);
|
||||
void bufferevent_settimeout(struct bufferevent *bufev,
|
||||
int timeout_read, int timeout_write);
|
||||
|
||||
#define OPAL_EVBUFFER_LENGTH(x) (x)->off
|
||||
#define OPAL_EVBUFFER_DATA(x) (x)->buffer
|
||||
#define OPAL_EVBUFFER_INPUT(x) (x)->input
|
||||
#define OPAL_EVBUFFER_OUTPUT(x) (x)->output
|
||||
|
||||
struct evbuffer *evbuffer_new(void);
|
||||
void evbuffer_free(struct evbuffer *);
|
||||
int evbuffer_expand(struct evbuffer *, size_t);
|
||||
int evbuffer_add(struct evbuffer *, void *, size_t);
|
||||
int evbuffer_remove(struct evbuffer *, void *, size_t);
|
||||
char *evbuffer_readline(struct evbuffer *);
|
||||
int evbuffer_add_buffer(struct evbuffer *, struct evbuffer *);
|
||||
int evbuffer_add_printf(struct evbuffer *, char *fmt, ...);
|
||||
void evbuffer_drain(struct evbuffer *, size_t);
|
||||
int evbuffer_write(struct evbuffer *, int);
|
||||
int evbuffer_read(struct evbuffer *, int, int);
|
||||
u_char *evbuffer_find(struct evbuffer *, u_char *, size_t);
|
||||
void evbuffer_setcb(struct evbuffer *, void (*)(struct evbuffer *, size_t, size_t, void *), void *);
|
||||
|
||||
#if defined(c_plusplus) || defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* #defines to allow callers to know if opal_event_loop is going to do anything */
|
||||
|
||||
#if defined(HAVE_SELECT) && HAVE_SELECT
|
||||
#define OPAL_HAVE_WORKING_EVENTOPS 1
|
||||
#elif defined(HAVE_POLL) && HAVE_POLL && HAVE_WORKING_POLL
|
||||
#define OPAL_HAVE_WORKING_EVENTOPS 1
|
||||
#elif defined(HAVE_RTSIG) && HAVE_RTSIG
|
||||
#define OPAL_HAVE_WORKING_EVENTOPS 1
|
||||
#elif defined(HAVE_EPOLL) && HAVE_EPOLL
|
||||
#define OPAL_HAVE_WORKING_EVENTOPS 1
|
||||
#elif defined(HAVE_WORKING_KQUEUE) && HAVE_WORKING_KQUEUE
|
||||
#define OPAL_HAVE_WORKING_EVENTOPS 1
|
||||
#else
|
||||
#define OPAL_HAVE_WORKING_EVENTOPS 0
|
||||
#endif
|
||||
|
||||
#endif /* _EVENT_H_ */
|
69
opal/event/event_rename.h
Обычный файл
69
opal/event/event_rename.h
Обычный файл
@ -0,0 +1,69 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2004-2006 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*
|
||||
*/
|
||||
|
||||
/* buffer.c */
|
||||
#define evbuffer_add opal_evbuffer_add
|
||||
#define evbuffer_add_buffer opal_evbuffer_add_buffer
|
||||
#define evbuffer_add_printf opal_evbuffer_add_printf
|
||||
#define evbuffer_drain opal_evbuffer_drain
|
||||
#define evbuffer_expand opal_evbuffer_expand
|
||||
#define evbuffer_find opal_evbuffer_find
|
||||
#define evbuffer_free opal_evbuffer_free
|
||||
#define evbuffer_new opal_evbuffer_new
|
||||
#define evbuffer_read opal_evbuffer_read
|
||||
#define evbuffer_readline opal_evbuffer_readline
|
||||
#define evbuffer_remove opal_evbuffer_remove
|
||||
#define evbuffer_setcb opal_evbuffer_setcb
|
||||
#define evbuffer_write opal_evbuffer_write
|
||||
|
||||
/* devpoll.c */
|
||||
#define devpollops opal_devpollops
|
||||
|
||||
/* epoll_sub.c */
|
||||
/* these symbols should *NOT* be renamed */
|
||||
|
||||
/* evbuffer.c */
|
||||
#define bufferevent_disable opal_bufferevent_disable
|
||||
#define bufferevent_enable opal_bufferevent_enable
|
||||
#define bufferevent_free opal_bufferevent_free
|
||||
#define bufferevent_new opal_bufferevent_new
|
||||
#define bufferevent_priority_set opal_bufferevent_priority_set
|
||||
#define bufferevent_read opal_bufferevent_read
|
||||
#define bufferevent_settimeout opal_bufferevent_settimeout
|
||||
#define bufferevent_setwatermark opal_bufferevent_setwatermark
|
||||
#define bufferevent_write opal_bufferevent_write
|
||||
#define bufferevent_write_buffer opal_bufferevent_write_buffer
|
||||
|
||||
/* event.c */
|
||||
#define current_base opal_current_base
|
||||
#define event_base_loopexit opal_event_base_loopexit
|
||||
#define event_get_method opal_event_get_method
|
||||
#define event_get_version opal_event_get_version
|
||||
#define event_gotsig opal_event_gotsig
|
||||
#define event_sigcb opal_event_sigcb
|
||||
|
||||
/* log.c */
|
||||
#define _event_debugx opal__event_debugx
|
||||
#define event_err opal_event_err
|
||||
#define event_errx opal_event_errx
|
||||
#define event_msgx opal_event_msgx
|
||||
#define event_set_log_callback opal_event_set_log_callback
|
||||
#define event_warn opal_event_warn
|
||||
#define event_warnx opal_event_warnx
|
||||
|
||||
/* poll.c */
|
||||
#define poll_add opal_poll_add
|
||||
#define poll_del opal_poll_del
|
||||
#define poll_dispatch opal_poll_dispatch
|
||||
#define poll_init opal_poll_init
|
||||
#define poll_recalc opal_poll_recalc
|
||||
|
37
opal/event/evsignal.h
Обычный файл
37
opal/event/evsignal.h
Обычный файл
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _EVSIGNAL_H_
|
||||
#define _EVSIGNAL_H_
|
||||
|
||||
void opal_evsignal_init(sigset_t *);
|
||||
void opal_evsignal_process(void);
|
||||
int opal_evsignal_recalc(sigset_t *);
|
||||
int opal_evsignal_deliver(sigset_t *);
|
||||
int opal_evsignal_add(sigset_t *, struct opal_event *);
|
||||
int opal_evsignal_del(sigset_t *, struct opal_event *);
|
||||
|
||||
#endif /* _EVSIGNAL_H_ */
|
412
opal/event/kqueue.c
Обычный файл
412
opal/event/kqueue.c
Обычный файл
@ -0,0 +1,412 @@
|
||||
/* $OpenBSD: kqueue.c,v 1.5 2002/07/10 14:41:31 art Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "opal_config.h"
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <sys/_time.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#include <sys/event.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INTTYPES_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__)
|
||||
#define INTPTR(x) (intptr_t)x
|
||||
#else
|
||||
#define INTPTR(x) x
|
||||
#endif
|
||||
|
||||
#include "event.h"
|
||||
#include "log.h"
|
||||
|
||||
#include "opal/threads/mutex.h"
|
||||
|
||||
extern opal_mutex_t opal_event_lock;
|
||||
|
||||
#define EVLIST_X_KQINKERNEL 0x1000
|
||||
|
||||
#define NEVENT 64
|
||||
|
||||
struct kqop {
|
||||
struct kevent *changes;
|
||||
int nchanges;
|
||||
struct kevent *events;
|
||||
int nevents;
|
||||
int kq;
|
||||
};
|
||||
|
||||
static void *kq_init (void);
|
||||
static int kq_add (void *, struct opal_event *);
|
||||
static int kq_del (void *, struct opal_event *);
|
||||
static int kq_recalc (struct event_base *, void *, int);
|
||||
static int kq_dispatch (struct event_base *, void *, struct timeval *);
|
||||
static int kq_insert (struct kqop *, struct kevent *);
|
||||
|
||||
const struct opal_eventop opal_kqops = {
|
||||
"kqueue",
|
||||
kq_init,
|
||||
kq_add,
|
||||
kq_del,
|
||||
kq_recalc,
|
||||
kq_dispatch
|
||||
};
|
||||
|
||||
static void *
|
||||
kq_init(void)
|
||||
{
|
||||
int kq;
|
||||
struct kqop *kqueueop;
|
||||
|
||||
/* Disable kqueue when this environment variable is set */
|
||||
if (getenv("EVENT_NOKQUEUE"))
|
||||
return (NULL);
|
||||
|
||||
if (!(kqueueop = calloc(1, sizeof(struct kqop))))
|
||||
return (NULL);
|
||||
|
||||
/* Initalize the kernel queue */
|
||||
|
||||
if ((kq = kqueue()) == -1) {
|
||||
event_warn("kqueue");
|
||||
free (kqueueop);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
kqueueop->kq = kq;
|
||||
|
||||
/* Initalize fields */
|
||||
kqueueop->changes = malloc(NEVENT * sizeof(struct kevent));
|
||||
if (kqueueop->changes == NULL) {
|
||||
free (kqueueop);
|
||||
return (NULL);
|
||||
}
|
||||
kqueueop->events = malloc(NEVENT * sizeof(struct kevent));
|
||||
if (kqueueop->events == NULL) {
|
||||
free (kqueueop->changes);
|
||||
free (kqueueop);
|
||||
return (NULL);
|
||||
}
|
||||
kqueueop->nevents = NEVENT;
|
||||
|
||||
/* Check for Mac OS X kqueue bug. */
|
||||
kqueueop->changes[0].ident = -1;
|
||||
kqueueop->changes[0].filter = EVFILT_READ;
|
||||
kqueueop->changes[0].flags = EV_ADD;
|
||||
/*
|
||||
* If kqueue works, then kevent will succeed, and it will
|
||||
* stick an error in events[0]. If kqueue is broken, then
|
||||
* kevent will fail.
|
||||
*/
|
||||
if (kevent(kq,
|
||||
kqueueop->changes, 1, kqueueop->events, NEVENT, NULL) != 1 ||
|
||||
kqueueop->events[0].ident != -1 ||
|
||||
kqueueop->events[0].flags != EV_ERROR) {
|
||||
event_warn("%s: detected broken kqueue; not using.", __func__);
|
||||
free(kqueueop->changes);
|
||||
free(kqueueop->events);
|
||||
free(kqueueop);
|
||||
close(kq);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (kqueueop);
|
||||
}
|
||||
|
||||
static int
|
||||
kq_recalc(struct event_base *base, void *arg, int max)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
kq_insert(struct kqop *kqop, struct kevent *kev)
|
||||
{
|
||||
int nevents = kqop->nevents;
|
||||
|
||||
if (kqop->nchanges == nevents) {
|
||||
struct kevent *newchange;
|
||||
struct kevent *newresult;
|
||||
|
||||
nevents *= 2;
|
||||
|
||||
newchange = realloc(kqop->changes,
|
||||
nevents * sizeof(struct kevent));
|
||||
if (newchange == NULL) {
|
||||
event_warn("%s: malloc", __func__);
|
||||
return (-1);
|
||||
}
|
||||
kqop->changes = newchange;
|
||||
|
||||
newresult = realloc(kqop->events,
|
||||
nevents * sizeof(struct kevent));
|
||||
|
||||
/*
|
||||
* If we fail, we don't have to worry about freeing,
|
||||
* the next realloc will pick it up.
|
||||
*/
|
||||
if (newresult == NULL) {
|
||||
event_warn("%s: malloc", __func__);
|
||||
return (-1);
|
||||
}
|
||||
kqop->events = newresult;
|
||||
|
||||
kqop->nevents = nevents;
|
||||
}
|
||||
|
||||
memcpy(&kqop->changes[kqop->nchanges++], kev, sizeof(struct kevent));
|
||||
|
||||
event_debug(("%s: fd %d %s%s",
|
||||
__func__, kev->ident,
|
||||
kev->filter == EVFILT_READ ? "EVFILT_READ" : "EVFILT_WRITE",
|
||||
kev->flags == EV_DELETE ? " (del)" : ""));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
kq_sighandler(int sig)
|
||||
{
|
||||
/* Do nothing here */
|
||||
}
|
||||
|
||||
static int
|
||||
kq_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
{
|
||||
struct kqop *kqop = arg;
|
||||
struct kevent *changes = kqop->changes;
|
||||
struct kevent *events = kqop->events;
|
||||
struct opal_event *ev;
|
||||
struct timespec ts;
|
||||
int i, res;
|
||||
|
||||
TIMEVAL_TO_TIMESPEC(tv, &ts);
|
||||
|
||||
/* we should release the lock if we're going to enter the
|
||||
kernel in a multi-threaded application. However, if we're
|
||||
single threaded, there's really no advantage to releasing
|
||||
the lock and it just takes up time we could spend doing
|
||||
something else. */
|
||||
OPAL_THREAD_UNLOCK(&opal_event_lock);
|
||||
res = kevent(kqop->kq, changes, kqop->nchanges,
|
||||
events, kqop->nevents, &ts);
|
||||
OPAL_THREAD_LOCK(&opal_event_lock);
|
||||
|
||||
kqop->nchanges = 0;
|
||||
if (res == -1) {
|
||||
if (errno != EINTR) {
|
||||
event_warn("kevent");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
event_debug(("%s: kevent reports %d", __func__, res));
|
||||
|
||||
for (i = 0; i < res; i++) {
|
||||
int which = 0;
|
||||
|
||||
if (events[i].flags & EV_ERROR) {
|
||||
/*
|
||||
* Error messages that can happen, when a delete fails.
|
||||
* EBADF happens when the file discriptor has been
|
||||
* closed,
|
||||
* ENOENT when the file discriptor was closed and
|
||||
* then reopened.
|
||||
* EINVAL for some reasons not understood; EINVAL
|
||||
* should not be returned ever; but FreeBSD does :-\
|
||||
* An error is also indicated when a callback deletes
|
||||
* an event we are still processing. In that case
|
||||
* the data field is set to ENOENT.
|
||||
*/
|
||||
if (events[i].data == EBADF ||
|
||||
events[i].data == EINVAL ||
|
||||
events[i].data == ENOENT)
|
||||
continue;
|
||||
errno = events[i].data;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
ev = (struct opal_event *)events[i].udata;
|
||||
|
||||
if (events[i].filter == EVFILT_READ) {
|
||||
which |= OPAL_EV_READ;
|
||||
} else if (events[i].filter == EVFILT_WRITE) {
|
||||
which |= OPAL_EV_WRITE;
|
||||
} else if (events[i].filter == EVFILT_SIGNAL) {
|
||||
which |= OPAL_EV_SIGNAL;
|
||||
}
|
||||
|
||||
if (!which)
|
||||
continue;
|
||||
|
||||
if (!(ev->ev_events & OPAL_EV_PERSIST)) {
|
||||
ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
|
||||
opal_event_del_i(ev);
|
||||
}
|
||||
|
||||
opal_event_active_i(ev, which,
|
||||
ev->ev_events & OPAL_EV_SIGNAL ? events[i].data : 1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
kq_add(void *arg, struct opal_event *ev)
|
||||
{
|
||||
struct kqop *kqop = arg;
|
||||
struct kevent kev;
|
||||
|
||||
if (ev->ev_events & OPAL_EV_SIGNAL) {
|
||||
int nsignal = OPAL_EVENT_SIGNAL(ev);
|
||||
|
||||
memset(&kev, 0, sizeof(kev));
|
||||
kev.ident = nsignal;
|
||||
kev.filter = EVFILT_SIGNAL;
|
||||
kev.flags = EV_ADD;
|
||||
if (!(ev->ev_events & OPAL_EV_PERSIST))
|
||||
kev.flags |= EV_ONESHOT;
|
||||
kev.udata = (void *) INTPTR(ev);
|
||||
|
||||
if (kq_insert(kqop, &kev) == -1)
|
||||
return (-1);
|
||||
|
||||
if (signal(nsignal, kq_sighandler) == SIG_ERR)
|
||||
return (-1);
|
||||
|
||||
ev->ev_flags |= EVLIST_X_KQINKERNEL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (ev->ev_events & OPAL_EV_READ) {
|
||||
memset(&kev, 0, sizeof(kev));
|
||||
kev.ident = ev->ev_fd;
|
||||
kev.filter = EVFILT_READ;
|
||||
#ifdef NOTE_EOF
|
||||
/* Make it behave like select() and poll() */
|
||||
kev.fflags = NOTE_EOF;
|
||||
#endif
|
||||
kev.flags = EV_ADD;
|
||||
if (!(ev->ev_events & OPAL_EV_PERSIST))
|
||||
kev.flags |= EV_ONESHOT;
|
||||
kev.udata = (void *) INTPTR(ev);
|
||||
|
||||
if (kq_insert(kqop, &kev) == -1)
|
||||
return (-1);
|
||||
|
||||
ev->ev_flags |= EVLIST_X_KQINKERNEL;
|
||||
}
|
||||
|
||||
if (ev->ev_events & OPAL_EV_WRITE) {
|
||||
memset(&kev, 0, sizeof(kev));
|
||||
kev.ident = ev->ev_fd;
|
||||
kev.filter = EVFILT_WRITE;
|
||||
kev.flags = EV_ADD;
|
||||
if (!(ev->ev_events & OPAL_EV_PERSIST))
|
||||
kev.flags |= EV_ONESHOT;
|
||||
kev.udata = (void *) INTPTR(ev);
|
||||
|
||||
if (kq_insert(kqop, &kev) == -1)
|
||||
return (-1);
|
||||
|
||||
ev->ev_flags |= EVLIST_X_KQINKERNEL;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
kq_del(void *arg, struct opal_event *ev)
|
||||
{
|
||||
struct kqop *kqop = arg;
|
||||
struct kevent kev;
|
||||
|
||||
if (!(ev->ev_flags & EVLIST_X_KQINKERNEL))
|
||||
return (0);
|
||||
|
||||
if (ev->ev_events & OPAL_EV_SIGNAL) {
|
||||
int nsignal = OPAL_EVENT_SIGNAL(ev);
|
||||
|
||||
memset(&kev, 0, sizeof(kev));
|
||||
kev.ident = (int)signal;
|
||||
kev.filter = EVFILT_SIGNAL;
|
||||
kev.flags = EV_DELETE;
|
||||
|
||||
if (kq_insert(kqop, &kev) == -1)
|
||||
return (-1);
|
||||
|
||||
if (signal(nsignal, SIG_DFL) == SIG_ERR)
|
||||
return (-1);
|
||||
|
||||
ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (ev->ev_events & OPAL_EV_READ) {
|
||||
memset(&kev, 0, sizeof(kev));
|
||||
kev.ident = ev->ev_fd;
|
||||
kev.filter = EVFILT_READ;
|
||||
kev.flags = EV_DELETE;
|
||||
|
||||
if (kq_insert(kqop, &kev) == -1)
|
||||
return (-1);
|
||||
|
||||
ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
|
||||
}
|
||||
|
||||
if (ev->ev_events & OPAL_EV_WRITE) {
|
||||
memset(&kev, 0, sizeof(kev));
|
||||
kev.ident = ev->ev_fd;
|
||||
kev.filter = EVFILT_WRITE;
|
||||
kev.flags = EV_DELETE;
|
||||
|
||||
if (kq_insert(kqop, &kev) == -1)
|
||||
return (-1);
|
||||
|
||||
ev->ev_flags &= ~EVLIST_X_KQINKERNEL;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
217
opal/event/log.c
Обычный файл
217
opal/event/log.c
Обычный файл
@ -0,0 +1,217 @@
|
||||
/* $OpenBSD: err.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
|
||||
|
||||
/*
|
||||
* log.c
|
||||
*
|
||||
* Based on err.c, which was adapted from OpenBSD libc *err* *warn* code.
|
||||
*
|
||||
* Copyright (c) 2005 Nick Mathewson <nickm@freehaven.net>
|
||||
*
|
||||
* Copyright (c) 2000 Dug Song <dugsong@monkey.org>
|
||||
*
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opal_config.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#include "misc.h"
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/tree.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <sys/_time.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "event.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
static void _warn_helper(int severity, int log_errno, const char *fmt,
|
||||
va_list ap);
|
||||
static void event_log(int severity, const char *msg);
|
||||
|
||||
static int
|
||||
event_vsnprintf(char *str, size_t size, const char *format, va_list args)
|
||||
{
|
||||
int r;
|
||||
if (size == 0)
|
||||
return -1;
|
||||
#ifdef WIN32
|
||||
r = _vsnprintf(str, size, format, args);
|
||||
#else
|
||||
r = vsnprintf(str, size, format, args);
|
||||
#endif
|
||||
str[size-1] = '\0';
|
||||
if (r < 0 || ((size_t)r) >= size) {
|
||||
/* different platforms behave differently on overflow;
|
||||
* handle both kinds. */
|
||||
return -1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
event_snprintf(char *str, size_t size, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int r;
|
||||
va_start(ap, format);
|
||||
r = event_vsnprintf(str, size, format, ap);
|
||||
va_end(ap);
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
event_err(int eval, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
_warn_helper(_EVENT_LOG_ERR, errno, fmt, ap);
|
||||
va_end(ap);
|
||||
exit(eval);
|
||||
}
|
||||
|
||||
void
|
||||
event_warn(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
_warn_helper(_EVENT_LOG_WARN, errno, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
event_errx(int eval, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
_warn_helper(_EVENT_LOG_ERR, -1, fmt, ap);
|
||||
va_end(ap);
|
||||
exit(eval);
|
||||
}
|
||||
|
||||
void
|
||||
event_warnx(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
_warn_helper(_EVENT_LOG_WARN, -1, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
event_msgx(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
_warn_helper(_EVENT_LOG_MSG, -1, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
_event_debugx(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
_warn_helper(_EVENT_LOG_DEBUG, -1, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void
|
||||
_warn_helper(int severity, int log_errno, const char *fmt, va_list ap)
|
||||
{
|
||||
char buf[1024];
|
||||
size_t len;
|
||||
|
||||
if (fmt != NULL)
|
||||
event_vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
else
|
||||
buf[0] = '\0';
|
||||
|
||||
if (log_errno >= 0) {
|
||||
len = strlen(buf);
|
||||
if (len < sizeof(buf) - 3) {
|
||||
event_snprintf(buf + len, sizeof(buf) - len, ": %s",
|
||||
strerror(log_errno));
|
||||
}
|
||||
}
|
||||
|
||||
event_log(severity, buf);
|
||||
}
|
||||
|
||||
static event_log_cb log_fn = NULL;
|
||||
|
||||
void
|
||||
event_set_log_callback(event_log_cb cb)
|
||||
{
|
||||
log_fn = cb;
|
||||
}
|
||||
|
||||
static void
|
||||
event_log(int severity, const char *msg)
|
||||
{
|
||||
if (log_fn)
|
||||
log_fn(severity, msg);
|
||||
else {
|
||||
const char *severity_str;
|
||||
switch (severity) {
|
||||
case _EVENT_LOG_DEBUG:
|
||||
severity_str = "debug";
|
||||
break;
|
||||
case _EVENT_LOG_MSG:
|
||||
severity_str = "msg";
|
||||
break;
|
||||
case _EVENT_LOG_WARN:
|
||||
severity_str = "warn";
|
||||
break;
|
||||
case _EVENT_LOG_ERR:
|
||||
severity_str = "err";
|
||||
break;
|
||||
default:
|
||||
severity_str = "???";
|
||||
break;
|
||||
}
|
||||
(void)fprintf(stderr, "[%s] %s\n", severity_str, msg);
|
||||
}
|
||||
}
|
43
opal/event/log.h
Обычный файл
43
opal/event/log.h
Обычный файл
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _LOG_H_
|
||||
#define _LOG_H_
|
||||
|
||||
void event_err(int eval, const char *fmt, ...);
|
||||
void event_warn(const char *fmt, ...);
|
||||
void event_errx(int eval, const char *fmt, ...);
|
||||
void event_warnx(const char *fmt, ...);
|
||||
void event_msgx(const char *fmt, ...);
|
||||
void _event_debugx(const char *fmt, ...);
|
||||
#undef USE_DEBUG
|
||||
#ifdef USE_DEBUG
|
||||
#define event_debug(x) _event_debugx x
|
||||
#else
|
||||
#define event_debug(x)
|
||||
#endif
|
||||
|
||||
#endif
|
396
opal/event/poll.c
Обычный файл
396
opal/event/poll.c
Обычный файл
@ -0,0 +1,396 @@
|
||||
/* $OpenBSD: poll.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2000-2003 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "opal_config.h"
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <sys/_time.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#include <sys/tree.h>
|
||||
#ifdef HAVE_POLL_H
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#ifdef CHECK_INVARIANTS
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include "event.h"
|
||||
#include "event-internal.h"
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
#include "evsignal.h"
|
||||
#endif
|
||||
#include "log.h"
|
||||
|
||||
#include "opal/util/output.h"
|
||||
#include "opal/threads/mutex.h"
|
||||
|
||||
extern volatile sig_atomic_t opal_evsignal_caught;
|
||||
extern opal_mutex_t opal_event_lock;
|
||||
|
||||
extern volatile sig_atomic_t evsignal_caught;
|
||||
|
||||
struct pollop {
|
||||
int event_count; /* Highest number alloc */
|
||||
int nfds; /* Size of event_* */
|
||||
int fd_count; /* Size of idxplus1_by_fd */
|
||||
struct pollfd *event_set;
|
||||
struct opal_event **event_r_back;
|
||||
struct opal_event **event_w_back;
|
||||
int *idxplus1_by_fd; /* Index into event_set by fd; we add 1 so
|
||||
* that 0 (which is easy to memset) can mean
|
||||
* "no entry." */
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
sigset_t evsigmask;
|
||||
#endif
|
||||
};
|
||||
|
||||
void *poll_init (void);
|
||||
int poll_add (void *, struct opal_event *);
|
||||
int poll_del (void *, struct opal_event *);
|
||||
int poll_recalc (struct event_base *, void *, int);
|
||||
int poll_dispatch (struct event_base *, void *, struct timeval *);
|
||||
|
||||
struct opal_eventop opal_pollops = {
|
||||
"poll",
|
||||
poll_init,
|
||||
poll_add,
|
||||
poll_del,
|
||||
poll_recalc,
|
||||
poll_dispatch
|
||||
};
|
||||
|
||||
void *
|
||||
poll_init(void)
|
||||
{
|
||||
struct pollop *pollop;
|
||||
|
||||
/* Disable kqueue when this environment variable is set */
|
||||
if (getenv("EVENT_NOPOLL"))
|
||||
return (NULL);
|
||||
|
||||
if (!(pollop = calloc(1, sizeof(struct pollop))))
|
||||
return (NULL);
|
||||
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
opal_evsignal_init(&pollop->evsigmask);
|
||||
#endif
|
||||
|
||||
return (pollop);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called with the highest fd that we know about. If it is 0, completely
|
||||
* recalculate everything.
|
||||
*/
|
||||
|
||||
int
|
||||
poll_recalc(struct event_base *base, void *arg, int max)
|
||||
{
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
struct pollop *pop = arg;
|
||||
|
||||
return (opal_evsignal_recalc(&pop->evsigmask));
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CHECK_INVARIANTS
|
||||
static void
|
||||
poll_check_ok(struct pollop *pop)
|
||||
{
|
||||
int i, idx;
|
||||
struct opal_event *ev;
|
||||
|
||||
for (i = 0; i < pop->fd_count; ++i) {
|
||||
idx = pop->idxplus1_by_fd[i]-1;
|
||||
if (idx < 0)
|
||||
continue;
|
||||
assert(pop->event_set[idx].fd == i);
|
||||
if (pop->event_set[idx].events & POLLIN) {
|
||||
ev = pop->event_r_back[idx];
|
||||
assert(ev);
|
||||
assert(ev->ev_events & OPAL_EV_READ);
|
||||
assert(ev->ev_fd == i);
|
||||
}
|
||||
if (pop->event_set[idx].events & POLLOUT) {
|
||||
ev = pop->event_w_back[idx];
|
||||
assert(ev);
|
||||
assert(ev->ev_events & OPAL_EV_WRITE);
|
||||
assert(ev->ev_fd == i);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < pop->nfds; ++i) {
|
||||
struct pollfd *pfd = &pop->event_set[i];
|
||||
assert(pop->idxplus1_by_fd[pfd->fd] == i+1);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define poll_check_ok(pop)
|
||||
#endif
|
||||
|
||||
int
|
||||
poll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
{
|
||||
int res, i, sec, nfds;
|
||||
struct pollop *pop = arg;
|
||||
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
if (opal_evsignal_deliver(&pop->evsigmask) == -1)
|
||||
return (-1);
|
||||
#endif
|
||||
|
||||
poll_check_ok(pop);
|
||||
sec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
|
||||
nfds = pop->nfds;
|
||||
/* we should release the lock if we're going to enter the
|
||||
kernel in a multi-threaded application. However, if we're
|
||||
single threaded, there's really no advantage to releasing
|
||||
the lock and it just takes up time we could spend doing
|
||||
something else. */
|
||||
OPAL_THREAD_UNLOCK(&opal_event_lock);
|
||||
res = poll(pop->event_set, nfds, sec);
|
||||
OPAL_THREAD_LOCK(&opal_event_lock);
|
||||
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
if (opal_evsignal_recalc(&pop->evsigmask) == -1)
|
||||
return (-1);
|
||||
#endif
|
||||
|
||||
if (res == -1) {
|
||||
if (errno != EINTR) {
|
||||
event_warn("poll");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
opal_evsignal_process();
|
||||
#endif
|
||||
return (0);
|
||||
} else if (opal_evsignal_caught)
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
opal_evsignal_process();
|
||||
#endif
|
||||
|
||||
event_debug(("%s: poll reports %d", __func__, res));
|
||||
|
||||
if (res == 0)
|
||||
return (0);
|
||||
|
||||
for (i = 0; i < nfds; i++) {
|
||||
int what = pop->event_set[i].revents;
|
||||
struct opal_event *r_ev = NULL, *w_ev = NULL;
|
||||
if (!what)
|
||||
continue;
|
||||
|
||||
res = 0;
|
||||
|
||||
/* If the file gets closed notify */
|
||||
if (what & (POLLHUP|POLLERR))
|
||||
what |= POLLIN|POLLOUT;
|
||||
if (what & POLLIN) {
|
||||
res |= OPAL_EV_READ;
|
||||
r_ev = pop->event_r_back[i];
|
||||
}
|
||||
if (what & POLLOUT) {
|
||||
res |= OPAL_EV_WRITE;
|
||||
w_ev = pop->event_w_back[i];
|
||||
}
|
||||
if (res == 0)
|
||||
continue;
|
||||
|
||||
if (r_ev && (res & r_ev->ev_events)) {
|
||||
if (!(r_ev->ev_events & OPAL_EV_PERSIST))
|
||||
opal_event_del(r_ev);
|
||||
opal_event_active(r_ev, res & r_ev->ev_events, 1);
|
||||
}
|
||||
if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) {
|
||||
if (!(w_ev->ev_events & OPAL_EV_PERSIST))
|
||||
opal_event_del(w_ev);
|
||||
opal_event_active(w_ev, res & w_ev->ev_events, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
poll_add(void *arg, struct opal_event *ev)
|
||||
{
|
||||
struct pollop *pop = arg;
|
||||
struct pollfd *pfd = NULL;
|
||||
int i;
|
||||
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
if (ev->ev_events & OPAL_EV_SIGNAL)
|
||||
return (opal_evsignal_add(&pop->evsigmask, ev));
|
||||
#endif
|
||||
if (!(ev->ev_events & (OPAL_EV_READ|OPAL_EV_WRITE)))
|
||||
return (0);
|
||||
|
||||
poll_check_ok(pop);
|
||||
if (pop->nfds + 1 >= pop->event_count) {
|
||||
if (pop->event_count < 32)
|
||||
pop->event_count = 32;
|
||||
else
|
||||
pop->event_count *= 2;
|
||||
|
||||
/* We need more file descriptors */
|
||||
pop->event_set = realloc(pop->event_set,
|
||||
pop->event_count * sizeof(struct pollfd));
|
||||
if (pop->event_set == NULL) {
|
||||
event_warn("realloc");
|
||||
return (-1);
|
||||
}
|
||||
pop->event_r_back = realloc(pop->event_r_back,
|
||||
pop->event_count * sizeof(struct opal_event *));
|
||||
pop->event_w_back = realloc(pop->event_w_back,
|
||||
pop->event_count * sizeof(struct opal_event *));
|
||||
if (pop->event_r_back == NULL ||
|
||||
pop->event_w_back == NULL) {
|
||||
event_warn("realloc");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
if (ev->ev_fd >= pop->fd_count) {
|
||||
int new_count;
|
||||
if (pop->fd_count < 32)
|
||||
new_count = 32;
|
||||
else
|
||||
new_count = pop->fd_count * 2;
|
||||
while (new_count <= ev->ev_fd)
|
||||
new_count *= 2;
|
||||
pop->idxplus1_by_fd =
|
||||
realloc(pop->idxplus1_by_fd, new_count*sizeof(int));
|
||||
if (pop->idxplus1_by_fd == NULL) {
|
||||
event_warn("realloc");
|
||||
return (-1);
|
||||
}
|
||||
memset(pop->idxplus1_by_fd + pop->fd_count,
|
||||
0, sizeof(int)*(new_count - pop->fd_count));
|
||||
pop->fd_count = new_count;
|
||||
}
|
||||
|
||||
i = pop->idxplus1_by_fd[ev->ev_fd] - 1;
|
||||
if (i >= 0) {
|
||||
pfd = &pop->event_set[i];
|
||||
} else {
|
||||
i = pop->nfds++;
|
||||
pfd = &pop->event_set[i];
|
||||
pfd->events = 0;
|
||||
pfd->fd = ev->ev_fd;
|
||||
pop->event_w_back[i] = pop->event_r_back[i] = NULL;
|
||||
pop->idxplus1_by_fd[ev->ev_fd] = i + 1;
|
||||
}
|
||||
|
||||
pfd->revents = 0;
|
||||
if (ev->ev_events & OPAL_EV_WRITE) {
|
||||
pfd->events |= POLLOUT;
|
||||
pop->event_w_back[i] = ev;
|
||||
}
|
||||
if (ev->ev_events & OPAL_EV_READ) {
|
||||
pfd->events |= POLLIN;
|
||||
pop->event_r_back[i] = ev;
|
||||
}
|
||||
poll_check_ok(pop);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Nothing to be done here.
|
||||
*/
|
||||
|
||||
int
|
||||
poll_del(void *arg, struct opal_event *ev)
|
||||
{
|
||||
struct pollop *pop = arg;
|
||||
struct pollfd *pfd = NULL;
|
||||
int i;
|
||||
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
if (ev->ev_events & OPAL_EV_SIGNAL)
|
||||
return (opal_evsignal_del(&pop->evsigmask, ev));
|
||||
#endif
|
||||
|
||||
if (!(ev->ev_events & (OPAL_EV_READ|OPAL_EV_WRITE)))
|
||||
return (0);
|
||||
|
||||
poll_check_ok(pop);
|
||||
i = pop->idxplus1_by_fd[ev->ev_fd] - 1;
|
||||
if (i < 0)
|
||||
return (-1);
|
||||
|
||||
/* Do we still want to read or write? */
|
||||
pfd = &pop->event_set[i];
|
||||
if (ev->ev_events & OPAL_EV_READ) {
|
||||
pfd->events &= ~POLLIN;
|
||||
pop->event_r_back[i] = NULL;
|
||||
}
|
||||
if (ev->ev_events & OPAL_EV_WRITE) {
|
||||
pfd->events &= ~POLLOUT;
|
||||
pop->event_w_back[i] = NULL;
|
||||
}
|
||||
poll_check_ok(pop);
|
||||
if (pfd->events)
|
||||
/* Another event cares about that fd. */
|
||||
return (0);
|
||||
|
||||
/* Okay, so we aren't interested in that fd anymore. */
|
||||
pop->idxplus1_by_fd[ev->ev_fd] = 0;
|
||||
|
||||
--pop->nfds;
|
||||
if (i != pop->nfds) {
|
||||
/*
|
||||
* Shift the last pollfd down into the now-unoccupied
|
||||
* position.
|
||||
*/
|
||||
memcpy(&pop->event_set[i], &pop->event_set[pop->nfds],
|
||||
sizeof(struct pollfd));
|
||||
pop->event_r_back[i] = pop->event_r_back[pop->nfds];
|
||||
pop->event_w_back[i] = pop->event_w_back[pop->nfds];
|
||||
pop->idxplus1_by_fd[pop->event_set[i].fd] = i + 1;
|
||||
}
|
||||
|
||||
poll_check_ok(pop);
|
||||
return (0);
|
||||
}
|
437
opal/event/rtsig.c
Обычный файл
437
opal/event/rtsig.c
Обычный файл
@ -0,0 +1,437 @@
|
||||
#include "opal_config.h"
|
||||
|
||||
/* Enable F_SETSIG and F_SETOWN */
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <sys/_time.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/queue.h>
|
||||
#ifndef HAVE_WORKING_RTSIG
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define EVLIST_X_NORT 0x1000 /* Skip RT signals (internal) */
|
||||
|
||||
#include "event.h"
|
||||
#include "log.h"
|
||||
extern struct event_list signalqueue;
|
||||
|
||||
struct rtsigop {
|
||||
sigset_t sigs;
|
||||
struct pollfd *poll;
|
||||
struct event **toev;
|
||||
int cur, max, total;
|
||||
#ifndef HAVE_WORKING_RTSIG
|
||||
int pollmode;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define INIT_MAX 16
|
||||
|
||||
static int
|
||||
poll_add(struct rtsigop *op, struct event *ev)
|
||||
{
|
||||
struct pollfd *pfd;
|
||||
|
||||
if (op->poll == NULL) return 0;
|
||||
|
||||
if (op->cur == op->max) {
|
||||
void *p;
|
||||
|
||||
p = realloc(op->poll, sizeof(*op->poll) * (op->max << 1));
|
||||
if (!p) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
op->poll = p;
|
||||
p = realloc(op->toev, sizeof(*op->toev) * (op->max << 1));
|
||||
if (!p) {
|
||||
op->poll = realloc(op->poll, sizeof(*op->poll) * op->max);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
op->toev = p;
|
||||
op->max <<= 1;
|
||||
}
|
||||
|
||||
pfd = &op->poll[op->cur];
|
||||
pfd->fd = ev->ev_fd;
|
||||
pfd->events = 0;
|
||||
if (ev->ev_events & EV_READ) pfd->events |= POLLIN;
|
||||
if (ev->ev_events & EV_WRITE) pfd->events |= POLLOUT;
|
||||
pfd->revents = 0;
|
||||
|
||||
op->toev[op->cur] = ev;
|
||||
op->cur++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
poll_free(struct rtsigop *op, int n)
|
||||
{
|
||||
if (op->poll == NULL) return;
|
||||
|
||||
op->cur--;
|
||||
if (n < op->cur) {
|
||||
memcpy(&op->poll[n], &op->poll[op->cur], sizeof(*op->poll));
|
||||
op->toev[n] = op->toev[op->cur];
|
||||
}
|
||||
if (op->max > INIT_MAX && op->cur < op->max >> 1) {
|
||||
op->max >>= 1;
|
||||
op->poll = realloc(op->poll, sizeof(*op->poll) * op->max);
|
||||
op->toev = realloc(op->toev, sizeof(*op->toev) * op->max);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
poll_remove(struct rtsigop *op, struct event *ev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < op->cur; i++) {
|
||||
if (op->toev[i] == ev) {
|
||||
poll_free(op, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
activate(struct event *ev, int flags)
|
||||
{
|
||||
if (!(ev->ev_events & EV_PERSIST)) event_del(ev);
|
||||
event_active(ev, flags, 1);
|
||||
}
|
||||
|
||||
static void *rtsig_init(void);
|
||||
static int rtsig_add(void *, struct event *);
|
||||
static int rtsig_del(void *, struct event *);
|
||||
static int rtsig_recalc(struct event_base *, void *, int);
|
||||
static int rtsig_dispatch(struct event_base *, void *, struct timeval *);
|
||||
|
||||
struct opal_eventop rtsigops = {
|
||||
"rtsig",
|
||||
rtsig_init,
|
||||
rtsig_add,
|
||||
rtsig_del,
|
||||
rtsig_recalc,
|
||||
rtsig_dispatch
|
||||
};
|
||||
|
||||
static void *
|
||||
rtsig_init(void)
|
||||
{
|
||||
struct rtsigop *op;
|
||||
|
||||
if (getenv("EVENT_NORTSIG"))
|
||||
return (NULL);
|
||||
|
||||
op = malloc(sizeof(*op));
|
||||
if (op == NULL) return (NULL);
|
||||
|
||||
memset(op, 0, sizeof(*op));
|
||||
|
||||
op->max = INIT_MAX;
|
||||
op->poll = malloc(sizeof(*op->poll) * op->max);
|
||||
if (op->poll == NULL) {
|
||||
free(op);
|
||||
return (NULL);
|
||||
}
|
||||
op->toev = malloc(sizeof(*op->toev) * op->max);
|
||||
if (op->toev == NULL) {
|
||||
free(op->poll);
|
||||
free(op);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
sigemptyset(&op->sigs);
|
||||
sigaddset(&op->sigs, SIGIO);
|
||||
sigaddset(&op->sigs, SIGRTMIN);
|
||||
sigprocmask(SIG_BLOCK, &op->sigs, NULL);
|
||||
|
||||
return (op);
|
||||
}
|
||||
|
||||
static int
|
||||
rtsig_add(void *arg, struct event *ev)
|
||||
{
|
||||
struct rtsigop *op = (struct rtsigop *) arg;
|
||||
int flags, i;
|
||||
#ifndef HAVE_WORKING_RTSIG
|
||||
struct stat st;
|
||||
#endif
|
||||
|
||||
if (ev->ev_events & EV_SIGNAL) {
|
||||
sigaddset(&op->sigs, EVENT_SIGNAL(ev));
|
||||
return sigprocmask(SIG_BLOCK, &op->sigs, NULL);
|
||||
}
|
||||
|
||||
if (!(ev->ev_events & (EV_READ | EV_WRITE))) return 0;
|
||||
|
||||
#ifndef HAVE_WORKING_RTSIG
|
||||
if (fstat(ev->ev_fd, &st) == -1) return -1;
|
||||
if (S_ISFIFO(st.st_mode)) {
|
||||
ev->ev_flags |= EVLIST_X_NORT;
|
||||
op->pollmode++;
|
||||
}
|
||||
#endif
|
||||
|
||||
flags = fcntl(ev->ev_fd, F_GETFL);
|
||||
if (flags == -1)
|
||||
return (-1);
|
||||
|
||||
if (!(flags & O_ASYNC)) {
|
||||
if (fcntl(ev->ev_fd, F_SETSIG, SIGRTMIN) == -1
|
||||
|| fcntl(ev->ev_fd, F_SETOWN, (int) getpid()) == -1)
|
||||
return (-1);
|
||||
|
||||
if (fcntl(ev->ev_fd, F_SETFL, flags | O_ASYNC))
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#ifdef O_ONESIGFD
|
||||
fcntl(ev->ev_fd, F_SETAUXFL, O_ONESIGFD);
|
||||
#endif
|
||||
|
||||
op->total++;
|
||||
if (poll_add(op, ev) == -1)
|
||||
goto err;
|
||||
|
||||
return (0);
|
||||
|
||||
err:
|
||||
i = errno;
|
||||
fcntl(ev->ev_fd, F_SETFL, flags);
|
||||
errno = i;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
rtsig_del(void *arg, struct event *ev)
|
||||
{
|
||||
struct rtsigop *op = (struct rtsigop *) arg;
|
||||
|
||||
if (ev->ev_events & EV_SIGNAL) {
|
||||
sigset_t sigs;
|
||||
|
||||
sigdelset(&op->sigs, EVENT_SIGNAL(ev));
|
||||
|
||||
sigemptyset(&sigs);
|
||||
sigaddset(&sigs, EVENT_SIGNAL(ev));
|
||||
return (sigprocmask(SIG_UNBLOCK, &sigs, NULL));
|
||||
}
|
||||
|
||||
if (!(ev->ev_events & (EV_READ | EV_WRITE)))
|
||||
return (0);
|
||||
|
||||
#ifndef HAVE_WORKING_RTSIG
|
||||
if (ev->ev_flags & EVLIST_X_NORT)
|
||||
op->pollmode--;
|
||||
#endif
|
||||
poll_remove(op, ev);
|
||||
op->total--;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
rtsig_recalc(struct event_base *base, void *arg, int max)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
rtsig_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
{
|
||||
struct rtsigop *op = (struct rtsigop *) arg;
|
||||
struct timespec ts;
|
||||
int res, i;
|
||||
|
||||
if (op->poll == NULL)
|
||||
goto retry_poll;
|
||||
#ifndef HAVE_WORKING_RTSIG
|
||||
if (op->pollmode)
|
||||
goto poll_all;
|
||||
#endif
|
||||
|
||||
if (op->cur) {
|
||||
ts.tv_sec = ts.tv_nsec = 0;
|
||||
} else {
|
||||
ts.tv_sec = tv->tv_sec;
|
||||
ts.tv_nsec = tv->tv_usec * 1000;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
siginfo_t info;
|
||||
struct event *ev;
|
||||
int signum;
|
||||
|
||||
signum = sigtimedwait(&op->sigs, &info, &ts);
|
||||
|
||||
if (signum == -1) {
|
||||
if (errno == EAGAIN)
|
||||
break;
|
||||
return (errno == EINTR ? 0 : -1);
|
||||
}
|
||||
|
||||
ts.tv_sec = ts.tv_nsec = 0;
|
||||
|
||||
if (signum == SIGIO) {
|
||||
#ifndef HAVE_WORKING_RTSIG
|
||||
poll_all:
|
||||
#endif
|
||||
free(op->poll);
|
||||
free(op->toev);
|
||||
retry_poll:
|
||||
op->cur = 0;
|
||||
op->max = op->total;
|
||||
op->poll = malloc(sizeof(*op->poll) * op->total);
|
||||
if (op->poll == NULL)
|
||||
return (-1);
|
||||
op->toev = malloc(sizeof(*op->toev) * op->total);
|
||||
if (op->toev == NULL) {
|
||||
free(op->poll);
|
||||
op->poll = NULL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(ev, &base->eventqueue, ev_next)
|
||||
if (!(ev->ev_flags & EVLIST_X_NORT))
|
||||
poll_add(op, ev);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (signum == SIGRTMIN) {
|
||||
int flags, i, sigok = 0;
|
||||
|
||||
if (info.si_band <= 0) { /* SI_SIGIO */
|
||||
flags = EV_READ | EV_WRITE;
|
||||
} else {
|
||||
flags = 0;
|
||||
if (info.si_band & POLLIN) flags |= EV_READ;
|
||||
if (info.si_band & POLLOUT) flags |= EV_WRITE;
|
||||
if (!flags) continue;
|
||||
}
|
||||
|
||||
for (i = 0; flags && i < op->cur; i++) {
|
||||
ev = op->toev[i];
|
||||
|
||||
if (ev->ev_fd == info.si_fd) {
|
||||
flags &= ~ev->ev_events;
|
||||
sigok = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (ev = TAILQ_FIRST(&base->eventqueue);
|
||||
flags && ev != TAILQ_END(&base->eventqueue);
|
||||
ev = TAILQ_NEXT(ev, ev_next)) {
|
||||
if (ev->ev_fd == info.si_fd) {
|
||||
if (flags & ev->ev_events) {
|
||||
i = poll_add(op, ev);
|
||||
if (i == -1) return -1;
|
||||
flags &= ~ev->ev_events;
|
||||
}
|
||||
sigok = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sigok) {
|
||||
flags = fcntl(info.si_fd, F_GETFL);
|
||||
if (flags == -1) return -1;
|
||||
fcntl(info.si_fd, F_SETFL, flags & ~O_ASYNC);
|
||||
}
|
||||
} else {
|
||||
TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
|
||||
if (EVENT_SIGNAL(ev) == signum)
|
||||
activate(ev, EV_SIGNAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!op->cur)
|
||||
return (0);
|
||||
|
||||
res = poll(op->poll, op->cur, tv->tv_sec * 1000 +
|
||||
(tv->tv_usec + 999) / 1000);
|
||||
if (res < 0)
|
||||
return (-1);
|
||||
|
||||
i = 0;
|
||||
#ifdef HAVE_WORKING_RTSIG
|
||||
while (i < res) {
|
||||
#else
|
||||
while (i < op->cur) {
|
||||
#endif
|
||||
if (op->poll[i].revents) {
|
||||
int flags = 0;
|
||||
struct event *ev = op->toev[i];
|
||||
|
||||
if (op->poll[i].revents & POLLIN)
|
||||
flags |= EV_READ;
|
||||
if (op->poll[i].revents & POLLOUT)
|
||||
flags |= EV_WRITE;
|
||||
|
||||
if (!(ev->ev_events & EV_PERSIST)) {
|
||||
event_del(ev);
|
||||
res--;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
event_active(ev, flags, 1);
|
||||
} else {
|
||||
#ifndef HAVE_WORKING_RTSIG
|
||||
if (op->toev[i]->ev_flags & EVLIST_X_NORT) {
|
||||
i++;
|
||||
res++;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
for (;;) {
|
||||
op->cur--;
|
||||
if (i == op->cur)
|
||||
break;
|
||||
if (op->poll[op->cur].revents) {
|
||||
memcpy(&op->poll[i], &op->poll[op->cur], sizeof(*op->poll));
|
||||
op->toev[i] = op->toev[op->cur];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_WORKING_RTSIG
|
||||
op->cur = res;
|
||||
#endif
|
||||
|
||||
if (!op->cur) {
|
||||
op->max = INIT_MAX;
|
||||
free(op->poll);
|
||||
free(op->toev);
|
||||
/* We just freed it, we shouldn't have a problem getting it back. */
|
||||
op->poll = malloc(sizeof(*op->poll) * op->max);
|
||||
op->toev = malloc(sizeof(*op->toev) * op->max);
|
||||
|
||||
if (op->poll == NULL || op->toev == NULL)
|
||||
event_err(1, "%s: malloc");
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
15
opal/event/sample/Makefile.am
Обычный файл
15
opal/event/sample/Makefile.am
Обычный файл
@ -0,0 +1,15 @@
|
||||
AUTOMAKE_OPTIONS = foreign no-dependencies
|
||||
|
||||
LDADD = ../libevent.la
|
||||
CPPFPLAGS = -I..
|
||||
CFLAGS = -I../compat
|
||||
|
||||
noinst_PROGRAMS = event-test time-test signal-test
|
||||
|
||||
event_test_sources = event-test.c
|
||||
time_test_sources = time-test.c
|
||||
signal_test_sources = signal-test.c
|
||||
|
||||
verify:
|
||||
|
||||
DISTCLEANFILES = *~
|
431
opal/event/sample/Makefile.in
Обычный файл
431
opal/event/sample/Makefile.in
Обычный файл
@ -0,0 +1,431 @@
|
||||
# Makefile.in generated by automake 1.9 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
SOURCES = event-test.c signal-test.c time-test.c
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
top_builddir = ..
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
INSTALL = @INSTALL@
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
host_triplet = @host@
|
||||
noinst_PROGRAMS = event-test$(EXEEXT) time-test$(EXEEXT) \
|
||||
signal-test$(EXEEXT)
|
||||
subdir = sample
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.in
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
PROGRAMS = $(noinst_PROGRAMS)
|
||||
event_test_SOURCES = event-test.c
|
||||
event_test_OBJECTS = event-test.$(OBJEXT)
|
||||
event_test_LDADD = $(LDADD)
|
||||
event_test_DEPENDENCIES = ../libevent.la
|
||||
signal_test_SOURCES = signal-test.c
|
||||
signal_test_OBJECTS = signal-test.$(OBJEXT)
|
||||
signal_test_LDADD = $(LDADD)
|
||||
signal_test_DEPENDENCIES = ../libevent.la
|
||||
time_test_SOURCES = time-test.c
|
||||
time_test_OBJECTS = time-test.$(OBJEXT)
|
||||
time_test_LDADD = $(LDADD)
|
||||
time_test_DEPENDENCIES = ../libevent.la
|
||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
||||
depcomp =
|
||||
am__depfiles_maybe =
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(CC) $(DEFS) \
|
||||
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||
$(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) --mode=link --tag=CC $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
SOURCES = event-test.c signal-test.c time-test.c
|
||||
DIST_SOURCES = event-test.c signal-test.c time-test.c
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMDEP_FALSE = @AMDEP_FALSE@
|
||||
AMDEP_TRUE = @AMDEP_TRUE@
|
||||
AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = -I../compat
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO = @ECHO@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
F77 = @F77@
|
||||
FFLAGS = @FFLAGS@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIBTOOL_DEPS = @LIBTOOL_DEPS@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAINT = @MAINT@
|
||||
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
|
||||
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_F77 = @ac_ct_F77@
|
||||
ac_ct_RANLIB = @ac_ct_RANLIB@
|
||||
ac_ct_STRIP = @ac_ct_STRIP@
|
||||
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
|
||||
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
|
||||
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
|
||||
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
datadir = @datadir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
AUTOMAKE_OPTIONS = foreign no-dependencies
|
||||
LDADD = ../libevent.la
|
||||
CPPFPLAGS = -I..
|
||||
event_test_sources = event-test.c
|
||||
time_test_sources = time-test.c
|
||||
signal_test_sources = signal-test.c
|
||||
DISTCLEANFILES = *~
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .lo .o .obj
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sample/Makefile'; \
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign sample/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
clean-noinstPROGRAMS:
|
||||
@list='$(noinst_PROGRAMS)'; for p in $$list; do \
|
||||
f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
|
||||
echo " rm -f $$p $$f"; \
|
||||
rm -f $$p $$f ; \
|
||||
done
|
||||
event-test$(EXEEXT): $(event_test_OBJECTS) $(event_test_DEPENDENCIES)
|
||||
@rm -f event-test$(EXEEXT)
|
||||
$(LINK) $(event_test_LDFLAGS) $(event_test_OBJECTS) $(event_test_LDADD) $(LIBS)
|
||||
signal-test$(EXEEXT): $(signal_test_OBJECTS) $(signal_test_DEPENDENCIES)
|
||||
@rm -f signal-test$(EXEEXT)
|
||||
$(LINK) $(signal_test_LDFLAGS) $(signal_test_OBJECTS) $(signal_test_LDADD) $(LIBS)
|
||||
time-test$(EXEEXT): $(time_test_OBJECTS) $(time_test_DEPENDENCIES)
|
||||
@rm -f time-test$(EXEEXT)
|
||||
$(LINK) $(time_test_LDFLAGS) $(time_test_OBJECTS) $(time_test_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
.c.obj:
|
||||
$(COMPILE) -c `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
$(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
distclean-libtool:
|
||||
-rm -f libtool
|
||||
uninstall-info-am:
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$tags $$unique; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& cd $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) $$here
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(DISTFILES)'; for file in $$list; do \
|
||||
case $$file in \
|
||||
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
|
||||
esac; \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
||||
dir="/$$dir"; \
|
||||
$(mkdir_p) "$(distdir)$$dir"; \
|
||||
else \
|
||||
dir=''; \
|
||||
fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(PROGRAMS)
|
||||
installdirs:
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
|
||||
mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-libtool distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-man:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-info-am
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
|
||||
clean-libtool clean-noinstPROGRAMS ctags distclean \
|
||||
distclean-compile distclean-generic distclean-libtool \
|
||||
distclean-tags distdir dvi dvi-am html html-am info info-am \
|
||||
install install-am install-data install-data-am install-exec \
|
||||
install-exec-am install-info install-info-am install-man \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
maintainer-clean maintainer-clean-generic mostlyclean \
|
||||
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
|
||||
pdf pdf-am ps ps-am tags uninstall uninstall-am \
|
||||
uninstall-info-am
|
||||
|
||||
|
||||
verify:
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
143
opal/event/sample/event-test.c
Обычный файл
143
opal/event/sample/event-test.c
Обычный файл
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Compile with:
|
||||
* cc -I/usr/local/include -o event-test event-test.c -L/usr/local/lib -levent
|
||||
*/
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#ifndef WIN32
|
||||
#ifdef HAVE_SYS_QUEUE_H
|
||||
#include <sys/queue.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <event.h>
|
||||
|
||||
void
|
||||
fifo_read(int fd, short event, void *arg)
|
||||
{
|
||||
char buf[255];
|
||||
int len;
|
||||
struct opal_event *ev = arg;
|
||||
#ifdef WIN32
|
||||
DWORD dwBytesRead;
|
||||
#endif
|
||||
|
||||
/* Reschedule this event */
|
||||
opal_event_add(ev, NULL);
|
||||
|
||||
fprintf(stderr, "fifo_read called with fd: %d, event: %d, arg: %p\n",
|
||||
fd, event, arg);
|
||||
#ifdef WIN32
|
||||
len = ReadFile((HANDLE)fd, buf, sizeof(buf) - 1, &dwBytesRead, NULL);
|
||||
|
||||
// Check for end of file.
|
||||
if(len && dwBytesRead == 0) {
|
||||
fprintf(stderr, "End Of File");
|
||||
opal_event_del(ev);
|
||||
return;
|
||||
}
|
||||
|
||||
buf[dwBytesRead] = '\0';
|
||||
#else
|
||||
len = read(fd, buf, sizeof(buf) - 1);
|
||||
|
||||
if (len == -1) {
|
||||
perror("read");
|
||||
return;
|
||||
} else if (len == 0) {
|
||||
fprintf(stderr, "Connection closed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
buf[len] = '\0';
|
||||
#endif
|
||||
fprintf(stdout, "Read: %s\n", buf);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
struct opal_event evfifo;
|
||||
#ifdef WIN32
|
||||
HANDLE socket;
|
||||
// Open a file.
|
||||
socket = CreateFile("test.txt", // open File
|
||||
GENERIC_READ, // open for reading
|
||||
0, // do not share
|
||||
NULL, // no security
|
||||
OPEN_EXISTING, // existing file only
|
||||
FILE_ATTRIBUTE_NORMAL, // normal file
|
||||
NULL); // no attr. template
|
||||
|
||||
if(socket == INVALID_HANDLE_VALUE)
|
||||
return 1;
|
||||
|
||||
#else
|
||||
struct stat st;
|
||||
char *fifo = "event.fifo";
|
||||
int socket;
|
||||
|
||||
if (lstat (fifo, &st) == 0) {
|
||||
if ((st.st_mode & S_IFMT) == S_IFREG) {
|
||||
errno = EEXIST;
|
||||
perror("lstat");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
unlink (fifo);
|
||||
if (mkfifo (fifo, 0600) == -1) {
|
||||
perror("mkfifo");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Linux pipes are broken, we need O_RDWR instead of O_RDONLY */
|
||||
#ifdef __linux
|
||||
socket = open (fifo, O_RDWR | O_NONBLOCK, 0);
|
||||
#else
|
||||
socket = open (fifo, O_RDONLY | O_NONBLOCK, 0);
|
||||
#endif
|
||||
|
||||
if (socket == -1) {
|
||||
perror("open");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Write data to %s\n", fifo);
|
||||
#endif
|
||||
/* Initalize the event library */
|
||||
opal_event_init();
|
||||
|
||||
/* Initalize one event */
|
||||
#ifdef WIN32
|
||||
opal_event_set(&evfifo, (int)socket, OPAL_EV_READ, fifo_read, &evfifo);
|
||||
#else
|
||||
opal_event_set(&evfifo, socket, OPAL_EV_READ, fifo_read, &evfifo);
|
||||
#endif
|
||||
|
||||
/* Add it to the active events, without a timeout */
|
||||
opal_event_add(&evfifo, NULL);
|
||||
|
||||
opal_event_dispatch();
|
||||
#ifdef WIN32
|
||||
CloseHandle(socket);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
66
opal/event/sample/signal-test.c
Обычный файл
66
opal/event/sample/signal-test.c
Обычный файл
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Compile with:
|
||||
* cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent
|
||||
*/
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#ifndef WIN32
|
||||
#ifdef HAVE_SYS_QUEUE_H
|
||||
#include <sys/queue.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <event.h>
|
||||
|
||||
int called = 0;
|
||||
|
||||
void
|
||||
signal_cb(int fd, short event, void *arg)
|
||||
{
|
||||
struct opal_event *signal = arg;
|
||||
|
||||
printf("%s: got signal %d\n", __func__, OPAL_EVENT_SIGNAL(signal));
|
||||
|
||||
if (called >= 2)
|
||||
opal_event_del(signal);
|
||||
|
||||
called++;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
struct opal_event signal_int;
|
||||
|
||||
/* Initalize the event library */
|
||||
opal_event_init();
|
||||
|
||||
/* Initalize one event */
|
||||
opal_event_set(&signal_int, SIGINT, OPAL_EV_SIGNAL|OPAL_EV_PERSIST, signal_cb,
|
||||
&signal_int);
|
||||
|
||||
opal_event_add(&signal_int, NULL);
|
||||
|
||||
opal_event_dispatch();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
72
opal/event/sample/time-test.c
Обычный файл
72
opal/event/sample/time-test.c
Обычный файл
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Compile with:
|
||||
* cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent
|
||||
*/
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#ifndef WIN32
|
||||
#ifdef HAVE_SYS_QUEUE_H
|
||||
#include <sys/queue.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <event.h>
|
||||
|
||||
int lasttime;
|
||||
|
||||
void
|
||||
timeout_cb(int fd, short event, void *arg)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct opal_event *timeout = arg;
|
||||
int newtime = time(NULL);
|
||||
|
||||
printf("%s: called at %d: %d\n", __func__, newtime,
|
||||
newtime - lasttime);
|
||||
lasttime = newtime;
|
||||
|
||||
timerclear(&tv);
|
||||
tv.tv_sec = 2;
|
||||
opal_event_add(timeout, &tv);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
struct opal_event timeout;
|
||||
struct timeval tv;
|
||||
|
||||
/* Initalize the event library */
|
||||
opal_event_init();
|
||||
|
||||
/* Initalize one event */
|
||||
opal_evtimer_set(&timeout, timeout_cb, &timeout);
|
||||
|
||||
timerclear(&tv);
|
||||
tv.tv_sec = 2;
|
||||
opal_event_add(&timeout, &tv);
|
||||
|
||||
lasttime = time(NULL);
|
||||
|
||||
opal_event_dispatch();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
418
opal/event/select.c
Обычный файл
418
opal/event/select.c
Обычный файл
@ -0,0 +1,418 @@
|
||||
/* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "opal_config.h"
|
||||
#include "opal/util/output.h"
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <sys/_time.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#include <sys/tree.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#ifdef CHECK_INVARIANTS
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include "event.h"
|
||||
#include "event-internal.h"
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
#include "evsignal.h"
|
||||
#endif
|
||||
#include "log.h"
|
||||
|
||||
#include "opal/threads/mutex.h"
|
||||
|
||||
extern opal_mutex_t opal_event_lock;
|
||||
|
||||
#ifndef howmany
|
||||
#define howmany(x, y) (((x)+((y)-1))/(y))
|
||||
#endif
|
||||
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
extern volatile sig_atomic_t opal_evsignal_caught;
|
||||
#endif
|
||||
|
||||
struct selectop {
|
||||
int event_fds; /* Highest fd in fd set */
|
||||
int event_fdsz;
|
||||
fd_set *event_readset_in;
|
||||
fd_set *event_writeset_in;
|
||||
fd_set *event_readset_out;
|
||||
fd_set *event_writeset_out;
|
||||
struct opal_event **event_r_by_fd;
|
||||
struct opal_event **event_w_by_fd;
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
sigset_t evsigmask;
|
||||
#endif
|
||||
};
|
||||
|
||||
static void *select_init (void);
|
||||
static int select_add (void *, struct opal_event *);
|
||||
static int select_del (void *, struct opal_event *);
|
||||
static int select_recalc (struct event_base *, void *, int);
|
||||
static int select_dispatch (struct event_base *, void *, struct timeval *);
|
||||
|
||||
const struct opal_eventop opal_selectops = {
|
||||
"select",
|
||||
select_init,
|
||||
select_add,
|
||||
select_del,
|
||||
#ifdef WIN32
|
||||
NULL,
|
||||
#else
|
||||
select_recalc,
|
||||
#endif
|
||||
select_dispatch
|
||||
};
|
||||
|
||||
static int select_resize(struct selectop *sop, int fdsz);
|
||||
|
||||
static void *
|
||||
select_init(void)
|
||||
{
|
||||
struct selectop *sop;
|
||||
|
||||
/* Disable kqueue when this environment variable is set */
|
||||
if (getenv("EVENT_NOSELECT"))
|
||||
return (NULL);
|
||||
if (!(sop = calloc(1, sizeof(struct selectop))))
|
||||
return (NULL);
|
||||
|
||||
select_resize(sop, howmany(32 + 1, NFDBITS)*sizeof(fd_mask));
|
||||
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
opal_evsignal_init(&sop->evsigmask);
|
||||
#endif
|
||||
|
||||
return (sop);
|
||||
}
|
||||
|
||||
#ifdef CHECK_INVARIANTS
|
||||
static void
|
||||
check_selectop(struct selectop *sop)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<=sop->event_fds;++i) {
|
||||
if (FD_ISSET(i, sop->event_readset_in)) {
|
||||
assert(sop->event_r_by_fd[i]);
|
||||
assert(sop->event_r_by_fd[i]->ev_events & EV_READ);
|
||||
assert(sop->event_r_by_fd[i]->ev_fd == i);
|
||||
} else {
|
||||
assert(! sop->event_r_by_fd[i]);
|
||||
}
|
||||
if (FD_ISSET(i, sop->event_writeset_in)) {
|
||||
assert(sop->event_w_by_fd[i]);
|
||||
assert(sop->event_w_by_fd[i]->ev_events & EV_WRITE);
|
||||
assert(sop->event_w_by_fd[i]->ev_fd == i);
|
||||
} else {
|
||||
assert(! sop->event_w_by_fd[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#else
|
||||
#define check_selectop(sop)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Called with the highest fd that we know about. If it is 0, completely
|
||||
* recalculate everything.
|
||||
*/
|
||||
|
||||
static int
|
||||
select_recalc(struct event_base *base, void *arg, int max)
|
||||
{
|
||||
struct selectop *sop = arg;
|
||||
|
||||
check_selectop(sop);
|
||||
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
return (opal_evsignal_recalc(&sop->evsigmask));
|
||||
#else
|
||||
return (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
select_dispatch(struct event_base *base, void *arg, struct timeval *tv)
|
||||
{
|
||||
int res, i;
|
||||
struct selectop *sop = arg;
|
||||
|
||||
check_selectop(sop);
|
||||
|
||||
memcpy(sop->event_readset_out, sop->event_readset_in,
|
||||
sop->event_fdsz);
|
||||
memcpy(sop->event_writeset_out, sop->event_writeset_in,
|
||||
sop->event_fdsz);
|
||||
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
if (opal_evsignal_deliver(&sop->evsigmask) == -1)
|
||||
return (-1);
|
||||
#endif
|
||||
|
||||
/* we should release the lock if we're going to enter the
|
||||
kernel in a multi-threaded application. However, if we're
|
||||
single threaded, there's really no advantage to releasing
|
||||
the lock and it just takes up time we could spend doing
|
||||
something else. */
|
||||
OPAL_THREAD_UNLOCK(&opal_event_lock);
|
||||
res = select(sop->event_fds + 1, sop->event_readset_out,
|
||||
sop->event_writeset_out, NULL, tv);
|
||||
OPAL_THREAD_LOCK(&opal_event_lock);
|
||||
|
||||
check_selectop(sop);
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
if (opal_evsignal_recalc(&sop->evsigmask) == -1)
|
||||
return (-1);
|
||||
#endif
|
||||
|
||||
if (res == -1) {
|
||||
#if 0
|
||||
if (errno == EBADF) {
|
||||
/* poll each of the file descriptors individually to determine
|
||||
* which is bad
|
||||
*/
|
||||
for (ev = TAILQ_FIRST(&base->eventqueue); ev != NULL; ev = next) {
|
||||
next = TAILQ_NEXT(ev, ev_next);
|
||||
|
||||
tv->tv_sec = 0;
|
||||
tv->tv_usec = 0;
|
||||
memset(sop->event_readset, 0, sop->event_fdsz);
|
||||
memset(sop->event_writeset, 0, sop->event_fdsz);
|
||||
if (ev->ev_events & OPAL_EV_WRITE)
|
||||
FD_SET(ev->ev_fd, sop->event_writeset);
|
||||
if (ev->ev_events & OPAL_EV_READ)
|
||||
FD_SET(ev->ev_fd, sop->event_readset);
|
||||
res = select(sop->event_fds + 1, sop->event_readset,
|
||||
sop->event_writeset, NULL, tv);
|
||||
if(res < 0) {
|
||||
opal_output(0, "bad file descriptor: %d\n", ev->ev_fd);
|
||||
opal_event_del_i(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (errno != EINTR) {
|
||||
opal_output(0, "select failed with errno=%d\n", errno);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
opal_evsignal_process();
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
else if (opal_evsignal_caught)
|
||||
opal_evsignal_process();
|
||||
#endif
|
||||
|
||||
event_debug(("%s: select reports %d", __func__, res));
|
||||
|
||||
check_selectop(sop);
|
||||
for (i = 0; i <= sop->event_fds; ++i) {
|
||||
struct opal_event *r_ev = NULL, *w_ev = NULL;
|
||||
res = 0;
|
||||
if (FD_ISSET(i, sop->event_readset_out)) {
|
||||
r_ev = sop->event_r_by_fd[i];
|
||||
res |= OPAL_EV_READ;
|
||||
}
|
||||
if (FD_ISSET(i, sop->event_writeset_out)) {
|
||||
w_ev = sop->event_w_by_fd[i];
|
||||
res |= OPAL_EV_WRITE;
|
||||
}
|
||||
if (r_ev && (res & r_ev->ev_events)) {
|
||||
if (!(r_ev->ev_events & OPAL_EV_PERSIST))
|
||||
opal_event_del(r_ev);
|
||||
opal_event_active(r_ev, res & r_ev->ev_events, 1);
|
||||
}
|
||||
if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) {
|
||||
if (!(w_ev->ev_events & OPAL_EV_PERSIST))
|
||||
opal_event_del(w_ev);
|
||||
opal_event_active(w_ev, res & w_ev->ev_events, 1);
|
||||
}
|
||||
}
|
||||
check_selectop(sop);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
select_resize(struct selectop *sop, int fdsz)
|
||||
{
|
||||
int n_events, n_events_old;
|
||||
|
||||
fd_set *readset_in = NULL;
|
||||
fd_set *writeset_in = NULL;
|
||||
fd_set *readset_out = NULL;
|
||||
fd_set *writeset_out = NULL;
|
||||
struct opal_event **r_by_fd = NULL;
|
||||
struct opal_event **w_by_fd = NULL;
|
||||
|
||||
n_events = (fdsz/sizeof(fd_mask)) * NFDBITS;
|
||||
n_events_old = (sop->event_fdsz/sizeof(fd_mask)) * NFDBITS;
|
||||
|
||||
if (sop->event_readset_in)
|
||||
check_selectop(sop);
|
||||
|
||||
if ((readset_in = realloc(sop->event_readset_in, fdsz)) == NULL)
|
||||
goto error;
|
||||
sop->event_readset_in = readset_in;
|
||||
if ((readset_out = realloc(sop->event_readset_out, fdsz)) == NULL)
|
||||
goto error;
|
||||
sop->event_readset_out = readset_out;
|
||||
if ((writeset_in = realloc(sop->event_writeset_in, fdsz)) == NULL)
|
||||
goto error;
|
||||
sop->event_writeset_in = writeset_in;
|
||||
if ((writeset_out = realloc(sop->event_writeset_out, fdsz)) == NULL)
|
||||
goto error;
|
||||
sop->event_writeset_out = writeset_out;
|
||||
if ((r_by_fd = realloc(sop->event_r_by_fd,
|
||||
n_events*sizeof(struct event*))) == NULL)
|
||||
goto error;
|
||||
sop->event_r_by_fd = r_by_fd;
|
||||
if ((w_by_fd = realloc(sop->event_w_by_fd,
|
||||
n_events * sizeof(struct event*))) == NULL)
|
||||
goto error;
|
||||
sop->event_w_by_fd = w_by_fd;
|
||||
|
||||
memset((char *)sop->event_readset_in + sop->event_fdsz, 0,
|
||||
fdsz - sop->event_fdsz);
|
||||
memset((char *)sop->event_writeset_in + sop->event_fdsz, 0,
|
||||
fdsz - sop->event_fdsz);
|
||||
memset(sop->event_r_by_fd + n_events_old, 0,
|
||||
(n_events-n_events_old) * sizeof(struct event*));
|
||||
memset(sop->event_w_by_fd + n_events_old, 0,
|
||||
(n_events-n_events_old) * sizeof(struct event*));
|
||||
|
||||
sop->event_fdsz = fdsz;
|
||||
check_selectop(sop);
|
||||
|
||||
return (0);
|
||||
|
||||
error:
|
||||
event_warn("malloc");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
select_add(void *arg, struct opal_event *ev)
|
||||
{
|
||||
struct selectop *sop = arg;
|
||||
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
if (ev->ev_events & OPAL_EV_SIGNAL)
|
||||
return (opal_evsignal_add(&sop->evsigmask, ev));
|
||||
#endif
|
||||
|
||||
check_selectop(sop);
|
||||
/*
|
||||
* Keep track of the highest fd, so that we can calculate the size
|
||||
* of the fd_sets for select(2)
|
||||
*/
|
||||
if (sop->event_fds < ev->ev_fd) {
|
||||
int fdsz = sop->event_fdsz;
|
||||
|
||||
if (fdsz < (int) sizeof(fd_mask))
|
||||
fdsz = sizeof(fd_mask);
|
||||
|
||||
while (fdsz <
|
||||
(int) (howmany(ev->ev_fd + 1, NFDBITS) * sizeof(fd_mask)))
|
||||
fdsz *= 2;
|
||||
|
||||
if (fdsz != sop->event_fdsz) {
|
||||
if (select_resize(sop, fdsz)) {
|
||||
check_selectop(sop);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
sop->event_fds = ev->ev_fd;
|
||||
}
|
||||
|
||||
if (ev->ev_events & OPAL_EV_READ) {
|
||||
FD_SET(ev->ev_fd, sop->event_readset_in);
|
||||
sop->event_r_by_fd[ev->ev_fd] = ev;
|
||||
}
|
||||
if (ev->ev_events & OPAL_EV_WRITE) {
|
||||
FD_SET(ev->ev_fd, sop->event_writeset_in);
|
||||
sop->event_w_by_fd[ev->ev_fd] = ev;
|
||||
}
|
||||
check_selectop(sop);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Nothing to be done here.
|
||||
*/
|
||||
|
||||
static int
|
||||
select_del(void *arg, struct opal_event *ev)
|
||||
{
|
||||
struct selectop *sop = arg;
|
||||
|
||||
check_selectop(sop);
|
||||
#if OPAL_EVENT_USE_SIGNALS
|
||||
if (ev->ev_events & OPAL_EV_SIGNAL)
|
||||
return (opal_evsignal_del(&sop->evsigmask, ev));
|
||||
#endif
|
||||
|
||||
if (sop->event_fds < ev->ev_fd) {
|
||||
check_selectop(sop);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (ev->ev_events & OPAL_EV_READ) {
|
||||
FD_CLR(ev->ev_fd, sop->event_readset_in);
|
||||
sop->event_r_by_fd[ev->ev_fd] = NULL;
|
||||
}
|
||||
|
||||
if (ev->ev_events & OPAL_EV_WRITE) {
|
||||
FD_CLR(ev->ev_fd, sop->event_writeset_in);
|
||||
sop->event_w_by_fd[ev->ev_fd] = NULL;
|
||||
}
|
||||
|
||||
check_selectop(sop);
|
||||
return (0);
|
||||
}
|
||||
|
266
opal/event/signal.c
Обычный файл
266
opal/event/signal.c
Обычный файл
@ -0,0 +1,266 @@
|
||||
/* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "opal_config.h"
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <sys/_time.h>
|
||||
#endif
|
||||
#include <sys/queue.h>
|
||||
#include <sys/tree.h>
|
||||
#include <sys/socket.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "event.h"
|
||||
#include "event-internal.h"
|
||||
#include "evsignal.h"
|
||||
#include "log.h"
|
||||
|
||||
#include "opal/util/output.h"
|
||||
|
||||
extern struct opal_event_list opal_signalqueue;
|
||||
|
||||
static short opal_evsigcaught[NSIG];
|
||||
static int opal_needrecalc;
|
||||
volatile sig_atomic_t opal_evsignal_caught = 0;
|
||||
|
||||
void opal_evsignal_handler(int sig);
|
||||
|
||||
static struct opal_event ev_signal;
|
||||
static int ev_signal_pair[2];
|
||||
static int ev_signal_added;
|
||||
|
||||
/* Callback for when the signal handler write a byte to our signaling socket */
|
||||
static void evsignal_cb(int fd, short what, void *arg)
|
||||
{
|
||||
static char signals[100];
|
||||
struct opal_event *ev = arg;
|
||||
int n;
|
||||
|
||||
n = read(fd, signals, sizeof(signals));
|
||||
if (n == -1)
|
||||
event_err(1, "%s: read", __func__);
|
||||
opal_event_add(ev, NULL);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SETFD
|
||||
#define FD_CLOSEONEXEC(x) do { \
|
||||
if (fcntl(x, F_SETFD, 1) == -1) \
|
||||
event_warn("fcntl(%d, F_SETFD)", x); \
|
||||
} while (0)
|
||||
#else
|
||||
#define FD_CLOSEONEXEC(x)
|
||||
#endif
|
||||
|
||||
void
|
||||
opal_evsignal_init(sigset_t *evsigmask)
|
||||
{
|
||||
#ifndef WIN32
|
||||
sigemptyset(evsigmask);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Our signal handler is going to write to one end of the socket
|
||||
* pair to wake up our event loop. The event loop then scans for
|
||||
* signals that got delivered.
|
||||
*/
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, ev_signal_pair) == -1)
|
||||
event_err(1, "%s: socketpair", __func__);
|
||||
|
||||
FD_CLOSEONEXEC(ev_signal_pair[0]);
|
||||
FD_CLOSEONEXEC(ev_signal_pair[1]);
|
||||
|
||||
opal_event_set(&ev_signal, ev_signal_pair[1], OPAL_EV_READ,
|
||||
evsignal_cb, &ev_signal);
|
||||
ev_signal.ev_flags |= OPAL_EVLIST_INTERNAL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
opal_evsignal_add(sigset_t *evsigmask, struct opal_event *ev)
|
||||
{
|
||||
int evsignal;
|
||||
|
||||
if (ev->ev_events & (OPAL_EV_READ|OPAL_EV_WRITE))
|
||||
event_errx(1, "%s: OPAL_EV_SIGNAL incompatible use", __func__);
|
||||
evsignal = OPAL_EVENT_SIGNAL(ev);
|
||||
|
||||
/* force a recalc of the events we are waiting for, otherwise
|
||||
events aren't recalculated until the next time event_loop
|
||||
is called. Since that might not be for some time, that
|
||||
gives a window where a signal handler *should* be installed
|
||||
but actually is not. */
|
||||
if (ev->ev_base->evsel->recalc && ev->ev_base->evsel->recalc(ev->ev_base, ev->ev_base->evbase, 0) == -1) {
|
||||
opal_output(0, "opal_evsignal_add: opal_evsel->recalc() failed.");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
sigaddset(evsigmask, evsignal);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
opal_evsignal_restart(void)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Nothing to be done here.
|
||||
*/
|
||||
|
||||
int
|
||||
opal_evsignal_del(sigset_t *evsigmask, struct opal_event *ev)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return 0;
|
||||
#else
|
||||
int evsignal, ret;
|
||||
struct sigaction sa;
|
||||
sigset_t set;
|
||||
|
||||
evsignal = OPAL_EVENT_SIGNAL(ev);
|
||||
|
||||
/* remove from the "in use" signal list */
|
||||
sigdelset(evsigmask, evsignal);
|
||||
opal_needrecalc = 1;
|
||||
|
||||
/* set back to default handler */
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = SIG_DFL;
|
||||
|
||||
ret = sigaction(evsignal, &sa, NULL);
|
||||
|
||||
/* unblock signal, in case we were blocking the "in use" signals
|
||||
when this function was called */
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, evsignal);
|
||||
sigprocmask(SIG_UNBLOCK, &set, NULL);
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
opal_evsignal_handler(int sig)
|
||||
{
|
||||
opal_evsigcaught[sig]++;
|
||||
opal_evsignal_caught = 1;
|
||||
|
||||
/* Wake up our notification mechanism */
|
||||
write(ev_signal_pair[0], "a", 1);
|
||||
}
|
||||
|
||||
int
|
||||
opal_evsignal_recalc(sigset_t *evsigmask)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return 0;
|
||||
#else
|
||||
struct sigaction sa;
|
||||
struct opal_event *ev;
|
||||
|
||||
if (!ev_signal_added) {
|
||||
ev_signal_added = 1;
|
||||
opal_event_add(&ev_signal, NULL);
|
||||
}
|
||||
|
||||
if (TAILQ_FIRST(&opal_signalqueue) == NULL && !opal_needrecalc)
|
||||
return (0);
|
||||
opal_needrecalc = 0;
|
||||
|
||||
if (sigprocmask(SIG_BLOCK, evsigmask, NULL) == -1)
|
||||
return (-1);
|
||||
|
||||
/* Reinstall our signal handler. */
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = opal_evsignal_handler;
|
||||
sa.sa_mask = *evsigmask;
|
||||
#if OMPI_HAVE_SA_RESTART
|
||||
sa.sa_flags |= SA_RESTART;
|
||||
#endif
|
||||
|
||||
TAILQ_FOREACH(ev, &opal_signalqueue, ev_signal_next) {
|
||||
if (sigaction(OPAL_EVENT_SIGNAL(ev), &sa, NULL) == -1)
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
opal_evsignal_deliver(sigset_t *evsigmask)
|
||||
{
|
||||
if (TAILQ_FIRST(&opal_signalqueue) == NULL)
|
||||
return (0);
|
||||
|
||||
#ifdef WIN32
|
||||
return 0;
|
||||
#else
|
||||
return (sigprocmask(SIG_UNBLOCK, evsigmask, NULL));
|
||||
/* XXX - pending signals handled here */
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
opal_evsignal_process(void)
|
||||
{
|
||||
struct opal_event *ev;
|
||||
short ncalls;
|
||||
|
||||
TAILQ_FOREACH(ev, &opal_signalqueue, ev_signal_next) {
|
||||
ncalls = opal_evsigcaught[OPAL_EVENT_SIGNAL(ev)];
|
||||
if (ncalls) {
|
||||
if (!(ev->ev_events & OPAL_EV_PERSIST))
|
||||
opal_event_del_i(ev);
|
||||
opal_event_active_i(ev, OPAL_EV_SIGNAL, ncalls);
|
||||
}
|
||||
}
|
||||
|
||||
memset(opal_evsigcaught, 0, sizeof(opal_evsigcaught));
|
||||
opal_evsignal_caught = 0;
|
||||
}
|
||||
|
23
opal/event/test/Makefile.am
Обычный файл
23
opal/event/test/Makefile.am
Обычный файл
@ -0,0 +1,23 @@
|
||||
AUTOMAKE_OPTIONS = foreign no-dependencies
|
||||
|
||||
LDADD = ../libevent.la
|
||||
CPPFPLAGS = -I..
|
||||
CFLAGS = -I../compat @CFLAGS@
|
||||
|
||||
noinst_PROGRAMS = test-init test-eof test-weof test-time regress bench
|
||||
|
||||
test_init_sources = test-init.c
|
||||
test_eof_sources = test-eof.c
|
||||
test_weof_sources = test-weof.c
|
||||
test_time_sources = test-time.c
|
||||
regress_sources = regress.c
|
||||
bench_sources = bench.c
|
||||
|
||||
DISTCLEANFILES = *~
|
||||
|
||||
test: test-init test-eof test-weof test-time regress
|
||||
|
||||
verify: test
|
||||
@./test.sh
|
||||
|
||||
bench test-init test-eof test-weof test-time regress: ../libevent.la
|
463
opal/event/test/Makefile.in
Обычный файл
463
opal/event/test/Makefile.in
Обычный файл
@ -0,0 +1,463 @@
|
||||
# Makefile.in generated by automake 1.9 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
SOURCES = bench.c regress.c test-eof.c test-init.c test-time.c test-weof.c
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
top_builddir = ..
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
INSTALL = @INSTALL@
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
host_triplet = @host@
|
||||
noinst_PROGRAMS = test-init$(EXEEXT) test-eof$(EXEEXT) \
|
||||
test-weof$(EXEEXT) test-time$(EXEEXT) regress$(EXEEXT) \
|
||||
bench$(EXEEXT)
|
||||
subdir = test
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.in
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
PROGRAMS = $(noinst_PROGRAMS)
|
||||
bench_SOURCES = bench.c
|
||||
bench_OBJECTS = bench.$(OBJEXT)
|
||||
bench_LDADD = $(LDADD)
|
||||
bench_DEPENDENCIES = ../libevent.la
|
||||
regress_SOURCES = regress.c
|
||||
regress_OBJECTS = regress.$(OBJEXT)
|
||||
regress_LDADD = $(LDADD)
|
||||
regress_DEPENDENCIES = ../libevent.la
|
||||
test_eof_SOURCES = test-eof.c
|
||||
test_eof_OBJECTS = test-eof.$(OBJEXT)
|
||||
test_eof_LDADD = $(LDADD)
|
||||
test_eof_DEPENDENCIES = ../libevent.la
|
||||
test_init_SOURCES = test-init.c
|
||||
test_init_OBJECTS = test-init.$(OBJEXT)
|
||||
test_init_LDADD = $(LDADD)
|
||||
test_init_DEPENDENCIES = ../libevent.la
|
||||
test_time_SOURCES = test-time.c
|
||||
test_time_OBJECTS = test-time.$(OBJEXT)
|
||||
test_time_LDADD = $(LDADD)
|
||||
test_time_DEPENDENCIES = ../libevent.la
|
||||
test_weof_SOURCES = test-weof.c
|
||||
test_weof_OBJECTS = test-weof.$(OBJEXT)
|
||||
test_weof_LDADD = $(LDADD)
|
||||
test_weof_DEPENDENCIES = ../libevent.la
|
||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
||||
depcomp =
|
||||
am__depfiles_maybe =
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(CC) $(DEFS) \
|
||||
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||
$(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) --mode=link --tag=CC $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
SOURCES = bench.c regress.c test-eof.c test-init.c test-time.c \
|
||||
test-weof.c
|
||||
DIST_SOURCES = bench.c regress.c test-eof.c test-init.c test-time.c \
|
||||
test-weof.c
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMDEP_FALSE = @AMDEP_FALSE@
|
||||
AMDEP_TRUE = @AMDEP_TRUE@
|
||||
AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = -I../compat @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO = @ECHO@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
F77 = @F77@
|
||||
FFLAGS = @FFLAGS@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIBTOOL_DEPS = @LIBTOOL_DEPS@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAINT = @MAINT@
|
||||
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
|
||||
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_F77 = @ac_ct_F77@
|
||||
ac_ct_RANLIB = @ac_ct_RANLIB@
|
||||
ac_ct_STRIP = @ac_ct_STRIP@
|
||||
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
|
||||
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
|
||||
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
|
||||
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
datadir = @datadir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
AUTOMAKE_OPTIONS = foreign no-dependencies
|
||||
LDADD = ../libevent.la
|
||||
CPPFPLAGS = -I..
|
||||
test_init_sources = test-init.c
|
||||
test_eof_sources = test-eof.c
|
||||
test_weof_sources = test-weof.c
|
||||
test_time_sources = test-time.c
|
||||
regress_sources = regress.c
|
||||
bench_sources = bench.c
|
||||
DISTCLEANFILES = *~
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .lo .o .obj
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/Makefile'; \
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign test/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
clean-noinstPROGRAMS:
|
||||
@list='$(noinst_PROGRAMS)'; for p in $$list; do \
|
||||
f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
|
||||
echo " rm -f $$p $$f"; \
|
||||
rm -f $$p $$f ; \
|
||||
done
|
||||
bench$(EXEEXT): $(bench_OBJECTS) $(bench_DEPENDENCIES)
|
||||
@rm -f bench$(EXEEXT)
|
||||
$(LINK) $(bench_LDFLAGS) $(bench_OBJECTS) $(bench_LDADD) $(LIBS)
|
||||
regress$(EXEEXT): $(regress_OBJECTS) $(regress_DEPENDENCIES)
|
||||
@rm -f regress$(EXEEXT)
|
||||
$(LINK) $(regress_LDFLAGS) $(regress_OBJECTS) $(regress_LDADD) $(LIBS)
|
||||
test-eof$(EXEEXT): $(test_eof_OBJECTS) $(test_eof_DEPENDENCIES)
|
||||
@rm -f test-eof$(EXEEXT)
|
||||
$(LINK) $(test_eof_LDFLAGS) $(test_eof_OBJECTS) $(test_eof_LDADD) $(LIBS)
|
||||
test-init$(EXEEXT): $(test_init_OBJECTS) $(test_init_DEPENDENCIES)
|
||||
@rm -f test-init$(EXEEXT)
|
||||
$(LINK) $(test_init_LDFLAGS) $(test_init_OBJECTS) $(test_init_LDADD) $(LIBS)
|
||||
test-time$(EXEEXT): $(test_time_OBJECTS) $(test_time_DEPENDENCIES)
|
||||
@rm -f test-time$(EXEEXT)
|
||||
$(LINK) $(test_time_LDFLAGS) $(test_time_OBJECTS) $(test_time_LDADD) $(LIBS)
|
||||
test-weof$(EXEEXT): $(test_weof_OBJECTS) $(test_weof_DEPENDENCIES)
|
||||
@rm -f test-weof$(EXEEXT)
|
||||
$(LINK) $(test_weof_LDFLAGS) $(test_weof_OBJECTS) $(test_weof_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
.c.obj:
|
||||
$(COMPILE) -c `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
$(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
distclean-libtool:
|
||||
-rm -f libtool
|
||||
uninstall-info-am:
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$tags $$unique; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& cd $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) $$here
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(DISTFILES)'; for file in $$list; do \
|
||||
case $$file in \
|
||||
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
|
||||
esac; \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
||||
dir="/$$dir"; \
|
||||
$(mkdir_p) "$(distdir)$$dir"; \
|
||||
else \
|
||||
dir=''; \
|
||||
fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(PROGRAMS)
|
||||
installdirs:
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
|
||||
mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-libtool distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-man:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-info-am
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
|
||||
clean-libtool clean-noinstPROGRAMS ctags distclean \
|
||||
distclean-compile distclean-generic distclean-libtool \
|
||||
distclean-tags distdir dvi dvi-am html html-am info info-am \
|
||||
install install-am install-data install-data-am install-exec \
|
||||
install-exec-am install-info install-info-am install-man \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
maintainer-clean maintainer-clean-generic mostlyclean \
|
||||
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
|
||||
pdf pdf-am ps ps-am tags uninstall uninstall-am \
|
||||
uninstall-info-am
|
||||
|
||||
|
||||
test: test-init test-eof test-weof test-time regress
|
||||
|
||||
verify: test
|
||||
@./test.sh
|
||||
|
||||
bench test-init test-eof test-weof test-time regress: ../libevent.la
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
191
opal/event/test/bench.c
Обычный файл
191
opal/event/test/bench.c
Обычный файл
@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright 2003 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO OPAL_EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWLAM_EVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, OPAL_EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* Mon 03/10/2003 - Modified by Davide Libenzi <davidel@xmailserver.org>
|
||||
*
|
||||
* Added chain event propagation to improve the sensitivity of
|
||||
* the measure respect to the event loop efficency.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <sys/signal.h>
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#include <event.h>
|
||||
|
||||
|
||||
static int count, writes, fired;
|
||||
static int *pipes;
|
||||
static int num_pipes, num_active, num_writes;
|
||||
static struct opal_event *events;
|
||||
|
||||
|
||||
|
||||
void
|
||||
read_cb(int fd, short which, void *arg)
|
||||
{
|
||||
int idx = (int) arg, widx = idx + 1;
|
||||
u_char ch;
|
||||
|
||||
count += read(fd, &ch, sizeof(ch));
|
||||
if (writes) {
|
||||
if (widx >= num_pipes)
|
||||
widx -= num_pipes;
|
||||
write(pipes[2 * widx + 1], "e", 1);
|
||||
writes--;
|
||||
fired++;
|
||||
}
|
||||
}
|
||||
|
||||
struct timeval *
|
||||
run_once(void)
|
||||
{
|
||||
int *cp, i, space;
|
||||
static struct timeval ts, te;
|
||||
|
||||
for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) {
|
||||
opal_event_del(&events[i]);
|
||||
opal_event_set(&events[i], cp[0], OPAL_EV_READ | OPAL_EV_PERSIST, read_cb, (void *) i);
|
||||
opal_event_add(&events[i], NULL);
|
||||
}
|
||||
|
||||
opal_event_loop(OPAL_EVLOOP_ONCE | OPAL_EVLOOP_NONBLOCK);
|
||||
|
||||
fired = 0;
|
||||
space = num_pipes / num_active;
|
||||
space = space * 2;
|
||||
for (i = 0; i < num_active; i++, fired++)
|
||||
write(pipes[i * space + 1], "e", 1);
|
||||
|
||||
count = 0;
|
||||
writes = num_writes;
|
||||
{ int xcount = 0;
|
||||
gettimeofday(&ts, NULL);
|
||||
do {
|
||||
opal_event_loop(OPAL_EVLOOP_ONCE | OPAL_EVLOOP_NONBLOCK);
|
||||
xcount++;
|
||||
} while (count != fired);
|
||||
gettimeofday(&te, NULL);
|
||||
|
||||
if (xcount != count) fprintf(stderr, "Xcount: %d, Rcount: %d\n", xcount, count);
|
||||
}
|
||||
|
||||
timersub(&te, &ts, &te);
|
||||
|
||||
return (&te);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
struct rlimit rl;
|
||||
int i, c;
|
||||
struct timeval *tv;
|
||||
int *cp;
|
||||
extern char *optarg;
|
||||
|
||||
num_pipes = 100;
|
||||
num_active = 1;
|
||||
num_writes = num_pipes;
|
||||
while ((c = getopt(argc, argv, "n:a:w:")) != -1) {
|
||||
switch (c) {
|
||||
case 'n':
|
||||
num_pipes = atoi(optarg);
|
||||
break;
|
||||
case 'a':
|
||||
num_active = atoi(optarg);
|
||||
break;
|
||||
case 'w':
|
||||
num_writes = atoi(optarg);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Illegal argument \"%c\"\n", c);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
rl.rlim_cur = rl.rlim_max = num_pipes * 2 + 50;
|
||||
if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
|
||||
perror("setrlimit");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
events = calloc(num_pipes, sizeof(struct opal_event));
|
||||
pipes = calloc(num_pipes * 2, sizeof(int));
|
||||
if (events == NULL || pipes == NULL) {
|
||||
perror("malloc");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
opal_event_init();
|
||||
|
||||
for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) {
|
||||
#ifdef USE_PIPES
|
||||
if (pipe(cp) == -1) {
|
||||
#else
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, cp) == -1) {
|
||||
#endif
|
||||
perror("pipe");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 25; i++) {
|
||||
tv = run_once();
|
||||
if (tv == NULL)
|
||||
exit(1);
|
||||
fprintf(stdout, "%ld\n",
|
||||
tv->tv_sec * 1000000L + tv->tv_usec);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
685
opal/event/test/regress.c
Обычный файл
685
opal/event/test/regress.c
Обычный файл
@ -0,0 +1,685 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2004 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifndef WIN32
|
||||
#include <sys/socket.h>
|
||||
#include <sys/signal.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <event.h>
|
||||
|
||||
static int pair[2];
|
||||
static int test_ok;
|
||||
static int called;
|
||||
static char wbuf[4096];
|
||||
static char rbuf[4096];
|
||||
static int woff;
|
||||
static int roff;
|
||||
static int usepersist;
|
||||
static struct timeval tset;
|
||||
static struct timeval tcalled;
|
||||
static struct event_base *event_base;
|
||||
|
||||
#define TEST1 "this is a test"
|
||||
#define SECONDS 1
|
||||
|
||||
void
|
||||
simple_read_cb(int fd, short event, void *arg)
|
||||
{
|
||||
char buf[256];
|
||||
int len;
|
||||
|
||||
len = read(fd, buf, sizeof(buf));
|
||||
|
||||
if (len) {
|
||||
if (!called) {
|
||||
if (event_add(arg, NULL) == -1)
|
||||
exit(1);
|
||||
}
|
||||
} else if (called == 1)
|
||||
test_ok = 1;
|
||||
|
||||
called++;
|
||||
}
|
||||
|
||||
void
|
||||
simple_write_cb(int fd, short event, void *arg)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = write(fd, TEST1, strlen(TEST1) + 1);
|
||||
if (len == -1)
|
||||
test_ok = 0;
|
||||
else
|
||||
test_ok = 1;
|
||||
}
|
||||
|
||||
void
|
||||
multiple_write_cb(int fd, short event, void *arg)
|
||||
{
|
||||
struct event *ev = arg;
|
||||
int len;
|
||||
|
||||
len = 128;
|
||||
if (woff + len >= sizeof(wbuf))
|
||||
len = sizeof(wbuf) - woff;
|
||||
|
||||
len = write(fd, wbuf + woff, len);
|
||||
if (len == -1) {
|
||||
fprintf(stderr, "%s: write\n", __func__);
|
||||
if (usepersist)
|
||||
event_del(ev);
|
||||
return;
|
||||
}
|
||||
|
||||
woff += len;
|
||||
|
||||
if (woff >= sizeof(wbuf)) {
|
||||
shutdown(fd, SHUT_WR);
|
||||
if (usepersist)
|
||||
event_del(ev);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!usepersist) {
|
||||
if (event_add(ev, NULL) == -1)
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
multiple_read_cb(int fd, short event, void *arg)
|
||||
{
|
||||
struct event *ev = arg;
|
||||
int len;
|
||||
|
||||
len = read(fd, rbuf + roff, sizeof(rbuf) - roff);
|
||||
if (len == -1)
|
||||
fprintf(stderr, "%s: read\n", __func__);
|
||||
if (len <= 0) {
|
||||
if (usepersist)
|
||||
event_del(ev);
|
||||
return;
|
||||
}
|
||||
|
||||
roff += len;
|
||||
if (!usepersist) {
|
||||
if (event_add(ev, NULL) == -1)
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
timeout_cb(int fd, short event, void *arg)
|
||||
{
|
||||
struct timeval tv;
|
||||
int diff;
|
||||
|
||||
gettimeofday(&tcalled, NULL);
|
||||
if (timercmp(&tcalled, &tset, >))
|
||||
timersub(&tcalled, &tset, &tv);
|
||||
else
|
||||
timersub(&tset, &tcalled, &tv);
|
||||
|
||||
diff = tv.tv_sec*1000 + tv.tv_usec/1000 - SECONDS * 1000;
|
||||
if (diff < 0)
|
||||
diff = -diff;
|
||||
|
||||
if (diff < 100)
|
||||
test_ok = 1;
|
||||
}
|
||||
|
||||
void
|
||||
signal_cb(int fd, short event, void *arg)
|
||||
{
|
||||
struct event *ev = arg;
|
||||
|
||||
signal_del(ev);
|
||||
test_ok = 1;
|
||||
}
|
||||
|
||||
struct both {
|
||||
struct event ev;
|
||||
int nread;
|
||||
};
|
||||
|
||||
void
|
||||
combined_read_cb(int fd, short event, void *arg)
|
||||
{
|
||||
struct both *both = arg;
|
||||
char buf[128];
|
||||
int len;
|
||||
|
||||
len = read(fd, buf, sizeof(buf));
|
||||
if (len == -1)
|
||||
fprintf(stderr, "%s: read\n", __func__);
|
||||
if (len <= 0)
|
||||
return;
|
||||
|
||||
both->nread += len;
|
||||
if (event_add(&both->ev, NULL) == -1)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
combined_write_cb(int fd, short event, void *arg)
|
||||
{
|
||||
struct both *both = arg;
|
||||
char buf[128];
|
||||
int len;
|
||||
|
||||
len = sizeof(buf);
|
||||
if (len > both->nread)
|
||||
len = both->nread;
|
||||
|
||||
len = write(fd, buf, len);
|
||||
if (len == -1)
|
||||
fprintf(stderr, "%s: write\n", __func__);
|
||||
if (len <= 0) {
|
||||
shutdown(fd, SHUT_WR);
|
||||
return;
|
||||
}
|
||||
|
||||
both->nread -= len;
|
||||
if (event_add(&both->ev, NULL) == -1)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Test infrastructure */
|
||||
|
||||
int
|
||||
setup_test(char *name)
|
||||
{
|
||||
|
||||
fprintf(stdout, "%s", name);
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
|
||||
fprintf(stderr, "%s: socketpair\n", __func__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef HAVE_FCNTL
|
||||
if (fcntl(pair[0], F_SETFL, O_NONBLOCK) == -1)
|
||||
fprintf(stderr, "fcntl(O_NONBLOCK)");
|
||||
|
||||
if (fcntl(pair[1], F_SETFL, O_NONBLOCK) == -1)
|
||||
fprintf(stderr, "fcntl(O_NONBLOCK)");
|
||||
#endif
|
||||
|
||||
test_ok = 0;
|
||||
called = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
cleanup_test(void)
|
||||
{
|
||||
#ifndef WIN32
|
||||
close(pair[0]);
|
||||
close(pair[1]);
|
||||
#else
|
||||
CloseHandle((HANDLE)pair[0]);
|
||||
CloseHandle((HANDLE)pair[1]);
|
||||
#endif
|
||||
if (test_ok)
|
||||
fprintf(stdout, "OK\n");
|
||||
else {
|
||||
fprintf(stdout, "FAILED\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
test1(void)
|
||||
{
|
||||
struct event ev;
|
||||
|
||||
/* Very simple read test */
|
||||
setup_test("Simple read: ");
|
||||
|
||||
write(pair[0], TEST1, strlen(TEST1)+1);
|
||||
shutdown(pair[0], SHUT_WR);
|
||||
|
||||
event_set(&ev, pair[1], EV_READ, simple_read_cb, &ev);
|
||||
if (event_add(&ev, NULL) == -1)
|
||||
exit(1);
|
||||
event_dispatch();
|
||||
|
||||
cleanup_test();
|
||||
}
|
||||
|
||||
void
|
||||
test2(void)
|
||||
{
|
||||
struct event ev;
|
||||
|
||||
/* Very simple write test */
|
||||
setup_test("Simple write: ");
|
||||
|
||||
event_set(&ev, pair[0], EV_WRITE, simple_write_cb, &ev);
|
||||
if (event_add(&ev, NULL) == -1)
|
||||
exit(1);
|
||||
event_dispatch();
|
||||
|
||||
cleanup_test();
|
||||
}
|
||||
|
||||
void
|
||||
test3(void)
|
||||
{
|
||||
struct event ev, ev2;
|
||||
int i;
|
||||
|
||||
/* Multiple read and write test */
|
||||
setup_test("Multiple read/write: ");
|
||||
memset(rbuf, 0, sizeof(rbuf));
|
||||
for (i = 0; i < sizeof(wbuf); i++)
|
||||
wbuf[i] = i;
|
||||
|
||||
roff = woff = 0;
|
||||
usepersist = 0;
|
||||
|
||||
event_set(&ev, pair[0], EV_WRITE, multiple_write_cb, &ev);
|
||||
if (event_add(&ev, NULL) == -1)
|
||||
exit(1);
|
||||
event_set(&ev2, pair[1], EV_READ, multiple_read_cb, &ev2);
|
||||
if (event_add(&ev2, NULL) == -1)
|
||||
exit(1);
|
||||
event_dispatch();
|
||||
|
||||
if (roff == woff)
|
||||
test_ok = memcmp(rbuf, wbuf, sizeof(wbuf)) == 0;
|
||||
|
||||
cleanup_test();
|
||||
}
|
||||
|
||||
void
|
||||
test4(void)
|
||||
{
|
||||
struct event ev, ev2;
|
||||
int i;
|
||||
|
||||
/* Multiple read and write test with persist */
|
||||
setup_test("Persist read/write: ");
|
||||
memset(rbuf, 0, sizeof(rbuf));
|
||||
for (i = 0; i < sizeof(wbuf); i++)
|
||||
wbuf[i] = i;
|
||||
|
||||
roff = woff = 0;
|
||||
usepersist = 1;
|
||||
|
||||
event_set(&ev, pair[0], EV_WRITE|EV_PERSIST, multiple_write_cb, &ev);
|
||||
if (event_add(&ev, NULL) == -1)
|
||||
exit(1);
|
||||
event_set(&ev2, pair[1], EV_READ|EV_PERSIST, multiple_read_cb, &ev2);
|
||||
if (event_add(&ev2, NULL) == -1)
|
||||
exit(1);
|
||||
event_dispatch();
|
||||
|
||||
if (roff == woff)
|
||||
test_ok = memcmp(rbuf, wbuf, sizeof(wbuf)) == 0;
|
||||
|
||||
cleanup_test();
|
||||
}
|
||||
|
||||
void
|
||||
test5(void)
|
||||
{
|
||||
struct both r1, r2, w1, w2;
|
||||
|
||||
setup_test("Combined read/write: ");
|
||||
memset(&r1, 0, sizeof(r1));
|
||||
memset(&r2, 0, sizeof(r2));
|
||||
memset(&w1, 0, sizeof(w1));
|
||||
memset(&w2, 0, sizeof(w2));
|
||||
|
||||
w1.nread = 4096;
|
||||
w2.nread = 8192;
|
||||
|
||||
event_set(&r1.ev, pair[0], EV_READ, combined_read_cb, &r1);
|
||||
event_set(&w1.ev, pair[0], EV_WRITE, combined_write_cb, &w1);
|
||||
event_set(&r2.ev, pair[1], EV_READ, combined_read_cb, &r2);
|
||||
event_set(&w2.ev, pair[1], EV_WRITE, combined_write_cb, &w2);
|
||||
if (event_add(&r1.ev, NULL) == -1)
|
||||
exit(1);
|
||||
if (event_add(&w1.ev, NULL))
|
||||
exit(1);
|
||||
if (event_add(&r2.ev, NULL))
|
||||
exit(1);
|
||||
if (event_add(&w2.ev, NULL))
|
||||
exit(1);
|
||||
|
||||
event_dispatch();
|
||||
|
||||
if (r1.nread == 8192 && r2.nread == 4096)
|
||||
test_ok = 1;
|
||||
|
||||
cleanup_test();
|
||||
}
|
||||
|
||||
void
|
||||
test6(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct event ev;
|
||||
|
||||
setup_test("Simple timeout: ");
|
||||
|
||||
tv.tv_usec = 0;
|
||||
tv.tv_sec = SECONDS;
|
||||
evtimer_set(&ev, timeout_cb, NULL);
|
||||
evtimer_add(&ev, &tv);
|
||||
|
||||
gettimeofday(&tset, NULL);
|
||||
event_dispatch();
|
||||
|
||||
cleanup_test();
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
void
|
||||
test7(void)
|
||||
{
|
||||
struct event ev;
|
||||
struct itimerval itv;
|
||||
|
||||
setup_test("Simple signal: ");
|
||||
signal_set(&ev, SIGALRM, signal_cb, &ev);
|
||||
signal_add(&ev, NULL);
|
||||
|
||||
memset(&itv, 0, sizeof(itv));
|
||||
itv.it_value.tv_sec = 1;
|
||||
if (setitimer(ITIMER_REAL, &itv, NULL) == -1)
|
||||
goto skip_simplesignal;
|
||||
|
||||
event_dispatch();
|
||||
skip_simplesignal:
|
||||
signal_del(&ev);
|
||||
|
||||
cleanup_test();
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
test8(void)
|
||||
{
|
||||
struct timeval tv, tv_start, tv_end;
|
||||
struct event ev;
|
||||
|
||||
setup_test("Loop exit: ");
|
||||
|
||||
tv.tv_usec = 0;
|
||||
tv.tv_sec = 60*60*24;
|
||||
evtimer_set(&ev, timeout_cb, NULL);
|
||||
evtimer_add(&ev, &tv);
|
||||
|
||||
tv.tv_usec = 0;
|
||||
tv.tv_sec = 1;
|
||||
event_loopexit(&tv);
|
||||
|
||||
gettimeofday(&tv_start, NULL);
|
||||
event_dispatch();
|
||||
gettimeofday(&tv_end, NULL);
|
||||
timersub(&tv_end, &tv_start, &tv_end);
|
||||
|
||||
evtimer_del(&ev);
|
||||
|
||||
if (tv.tv_sec < 2)
|
||||
test_ok = 1;
|
||||
|
||||
cleanup_test();
|
||||
}
|
||||
|
||||
void
|
||||
readcb(struct bufferevent *bev, void *arg)
|
||||
{
|
||||
if (EVBUFFER_LENGTH(bev->input) == 8333) {
|
||||
bufferevent_disable(bev, EV_READ);
|
||||
test_ok++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
writecb(struct bufferevent *bev, void *arg)
|
||||
{
|
||||
if (EVBUFFER_LENGTH(bev->output) == 0)
|
||||
test_ok++;
|
||||
}
|
||||
|
||||
void
|
||||
errorcb(struct bufferevent *bev, short what, void *arg)
|
||||
{
|
||||
test_ok = -2;
|
||||
}
|
||||
|
||||
void
|
||||
test9(void)
|
||||
{
|
||||
struct bufferevent *bev1, *bev2;
|
||||
char buffer[8333];
|
||||
int i;
|
||||
|
||||
setup_test("Bufferevent: ");
|
||||
|
||||
bev1 = bufferevent_new(pair[0], readcb, writecb, errorcb, NULL);
|
||||
bev2 = bufferevent_new(pair[1], readcb, writecb, errorcb, NULL);
|
||||
|
||||
bufferevent_disable(bev1, EV_READ);
|
||||
bufferevent_enable(bev2, EV_READ);
|
||||
|
||||
for (i = 0; i < sizeof(buffer); i++)
|
||||
buffer[0] = i;
|
||||
|
||||
bufferevent_write(bev1, buffer, sizeof(buffer));
|
||||
|
||||
event_dispatch();
|
||||
|
||||
bufferevent_free(bev1);
|
||||
bufferevent_free(bev2);
|
||||
|
||||
if (test_ok != 2)
|
||||
test_ok = 0;
|
||||
|
||||
cleanup_test();
|
||||
}
|
||||
|
||||
struct test_pri_event {
|
||||
struct event ev;
|
||||
int count;
|
||||
};
|
||||
|
||||
void
|
||||
test_priorities_cb(int fd, short what, void *arg)
|
||||
{
|
||||
struct test_pri_event *pri = arg;
|
||||
struct timeval tv;
|
||||
|
||||
if (pri->count == 3) {
|
||||
event_loopexit(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
pri->count++;
|
||||
|
||||
timerclear(&tv);
|
||||
event_add(&pri->ev, &tv);
|
||||
}
|
||||
|
||||
void
|
||||
test_priorities(int npriorities)
|
||||
{
|
||||
char buf[32];
|
||||
struct test_pri_event one, two;
|
||||
struct timeval tv;
|
||||
|
||||
snprintf(buf, sizeof(buf), "Priorities %d: ", npriorities);
|
||||
setup_test(buf);
|
||||
|
||||
event_base_priority_init(event_base, npriorities);
|
||||
|
||||
memset(&one, 0, sizeof(one));
|
||||
memset(&two, 0, sizeof(two));
|
||||
|
||||
timeout_set(&one.ev, test_priorities_cb, &one);
|
||||
if (event_priority_set(&one.ev, 0) == -1) {
|
||||
fprintf(stderr, "%s: failed to set priority", __func__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
timeout_set(&two.ev, test_priorities_cb, &two);
|
||||
if (event_priority_set(&two.ev, npriorities - 1) == -1) {
|
||||
fprintf(stderr, "%s: failed to set priority", __func__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
timerclear(&tv);
|
||||
|
||||
if (event_add(&one.ev, &tv) == -1)
|
||||
exit(1);
|
||||
if (event_add(&two.ev, &tv) == -1)
|
||||
exit(1);
|
||||
|
||||
event_dispatch();
|
||||
|
||||
event_del(&one.ev);
|
||||
event_del(&two.ev);
|
||||
|
||||
if (npriorities == 1) {
|
||||
if (one.count == 3 && two.count == 3)
|
||||
test_ok = 1;
|
||||
} else if (npriorities == 2) {
|
||||
/* Two is called once because event_loopexit is priority 1 */
|
||||
if (one.count == 3 && two.count == 1)
|
||||
test_ok = 1;
|
||||
} else {
|
||||
if (one.count == 3 && two.count == 0)
|
||||
test_ok = 1;
|
||||
}
|
||||
|
||||
cleanup_test();
|
||||
}
|
||||
|
||||
static void
|
||||
test_multiple_cb(int fd, short event, void *arg)
|
||||
{
|
||||
if (event & EV_READ)
|
||||
test_ok |= 1;
|
||||
else if (event & EV_WRITE)
|
||||
test_ok |= 2;
|
||||
}
|
||||
|
||||
void
|
||||
test_multiple_events_for_same_fd(void)
|
||||
{
|
||||
struct event e1, e2;
|
||||
|
||||
setup_test("Multiple events for same fd: ");
|
||||
|
||||
event_set(&e1, pair[0], EV_READ, test_multiple_cb, NULL);
|
||||
event_add(&e1, NULL);
|
||||
event_set(&e2, pair[0], EV_WRITE, test_multiple_cb, NULL);
|
||||
event_add(&e2, NULL);
|
||||
event_loop(EVLOOP_ONCE);
|
||||
event_del(&e2);
|
||||
write(pair[1], TEST1, strlen(TEST1)+1);
|
||||
event_loop(EVLOOP_ONCE);
|
||||
event_del(&e1);
|
||||
|
||||
if (test_ok != 3)
|
||||
test_ok = 0;
|
||||
|
||||
cleanup_test();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
#ifdef WIN32
|
||||
WORD wVersionRequested;
|
||||
WSADATA wsaData;
|
||||
int err;
|
||||
|
||||
wVersionRequested = MAKEWORD( 2, 2 );
|
||||
|
||||
err = WSAStartup( wVersionRequested, &wsaData );
|
||||
#endif
|
||||
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
|
||||
/* Initalize the event library */
|
||||
event_base = event_init();
|
||||
|
||||
test1();
|
||||
|
||||
test2();
|
||||
|
||||
test3();
|
||||
|
||||
test4();
|
||||
|
||||
test5();
|
||||
|
||||
test6();
|
||||
#ifndef WIN32
|
||||
test7();
|
||||
#endif
|
||||
test8();
|
||||
|
||||
test9();
|
||||
|
||||
test_priorities(1);
|
||||
test_priorities(2);
|
||||
test_priorities(3);
|
||||
|
||||
test_multiple_events_for_same_fd();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
76
opal/event/test/test-eof.c
Обычный файл
76
opal/event/test/test-eof.c
Обычный файл
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Compile with:
|
||||
* cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent
|
||||
*/
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#include <event.h>
|
||||
|
||||
int test_okay = 1;
|
||||
int called = 0;
|
||||
|
||||
void
|
||||
read_cb(int fd, short event, void *arg)
|
||||
{
|
||||
char buf[256];
|
||||
int len;
|
||||
|
||||
len = read(fd, buf, sizeof(buf));
|
||||
|
||||
printf("%s: read %d%s\n", __func__,
|
||||
len, len ? "" : " - means EOF");
|
||||
|
||||
if (len) {
|
||||
if (!called)
|
||||
opal_event_add(arg, NULL);
|
||||
} else if (called == 1)
|
||||
test_okay = 0;
|
||||
|
||||
called++;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
struct opal_event ev;
|
||||
char *test = "test string";
|
||||
int pair[2];
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
|
||||
return (1);
|
||||
|
||||
|
||||
write(pair[0], test, strlen(test)+1);
|
||||
shutdown(pair[0], SHUT_WR);
|
||||
|
||||
/* Initalize the event library */
|
||||
opal_event_init();
|
||||
|
||||
/* Initalize one event */
|
||||
opal_event_set(&ev, pair[1], OPAL_EV_READ, read_cb, &ev);
|
||||
|
||||
opal_event_add(&ev, NULL);
|
||||
|
||||
opal_event_dispatch();
|
||||
|
||||
return (test_okay);
|
||||
}
|
||||
|
35
opal/event/test/test-init.c
Обычный файл
35
opal/event/test/test-init.c
Обычный файл
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Compile with:
|
||||
* cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent
|
||||
*/
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#include <event.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
/* Initalize the event library */
|
||||
opal_event_init();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
74
opal/event/test/test-time.c
Обычный файл
74
opal/event/test/test-time.c
Обычный файл
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Compile with:
|
||||
* cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent
|
||||
*/
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#include <event.h>
|
||||
|
||||
int called = 0;
|
||||
|
||||
#define NEVENT 20000
|
||||
|
||||
struct opal_event *ev[NEVENT];
|
||||
|
||||
void
|
||||
time_cb(int fd, short event, void *arg)
|
||||
{
|
||||
struct timeval tv;
|
||||
int i, j;
|
||||
|
||||
called++;
|
||||
|
||||
if (called < 10*NEVENT) {
|
||||
for (i = 0; i < 10; i++) {
|
||||
j = random() % NEVENT;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = random() % 50000L;
|
||||
if (tv.tv_usec % 2)
|
||||
opal_evtimer_add(ev[j], &tv);
|
||||
else
|
||||
opal_evtimer_del(ev[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
struct timeval tv;
|
||||
int i;
|
||||
|
||||
/* Initalize the event library */
|
||||
opal_event_init();
|
||||
|
||||
for (i = 0; i < NEVENT; i++) {
|
||||
ev[i] = malloc(sizeof(struct opal_event));
|
||||
|
||||
/* Initalize one event */
|
||||
opal_evtimer_set(ev[i], time_cb, ev[i]);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = random() % 50000L;
|
||||
opal_evtimer_add(ev[i], &tv);
|
||||
}
|
||||
|
||||
opal_event_dispatch();
|
||||
|
||||
return (called < NEVENT);
|
||||
}
|
||||
|
74
opal/event/test/test-weof.c
Обычный файл
74
opal/event/test/test-weof.c
Обычный файл
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Compile with:
|
||||
* cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent
|
||||
*/
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#include <event.h>
|
||||
|
||||
int pair[2];
|
||||
int test_okay = 1;
|
||||
int called = 0;
|
||||
|
||||
void
|
||||
write_cb(int fd, short event, void *arg)
|
||||
{
|
||||
char *test = "test string";
|
||||
int len;
|
||||
|
||||
len = write(fd, test, strlen(test) + 1);
|
||||
|
||||
printf("%s: write %d%s\n", __func__,
|
||||
len, len ? "" : " - means EOF");
|
||||
|
||||
if (len > 0) {
|
||||
if (!called)
|
||||
opal_event_add(arg, NULL);
|
||||
close(pair[0]);
|
||||
} else if (called == 1)
|
||||
test_okay = 0;
|
||||
|
||||
called++;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
struct opal_event ev;
|
||||
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_IGN)
|
||||
return (1);
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
|
||||
return (1);
|
||||
|
||||
/* Initalize the event library */
|
||||
opal_event_init();
|
||||
|
||||
/* Initalize one event */
|
||||
opal_event_set(&ev, pair[1], OPAL_EV_WRITE, write_cb, &ev);
|
||||
opal_event_add(&ev, NULL);
|
||||
opal_event_dispatch();
|
||||
|
||||
return (test_okay);
|
||||
}
|
||||
|
83
opal/event/test/test.sh
Исполняемый файл
83
opal/event/test/test.sh
Исполняемый файл
@ -0,0 +1,83 @@
|
||||
#!/bin/sh
|
||||
|
||||
setup () {
|
||||
export EVENT_NOKQUEUE=yes
|
||||
export EVENT_NODEVPOLL=yes
|
||||
export EVENT_NOPOLL=yes
|
||||
export EVENT_NOSELECT=yes
|
||||
export EVENT_NOEPOLL=yes
|
||||
export EVENT_NORTSIG=yes
|
||||
}
|
||||
|
||||
test () {
|
||||
if ! ./test-init 2>/dev/null ;
|
||||
then
|
||||
echo Skipping test
|
||||
return
|
||||
fi
|
||||
|
||||
echo -n " test-eof: "
|
||||
if ./test-eof >/dev/null ;
|
||||
then
|
||||
echo OKAY ;
|
||||
else
|
||||
echo FAILED ;
|
||||
fi
|
||||
echo -n " test-weof: "
|
||||
if ./test-weof >/dev/null ;
|
||||
then
|
||||
echo OKAY ;
|
||||
else
|
||||
echo FAILED ;
|
||||
fi
|
||||
echo -n " test-time: "
|
||||
if ./test-time >/dev/null ;
|
||||
then
|
||||
echo OKAY ;
|
||||
else
|
||||
echo FAILED ;
|
||||
fi
|
||||
echo -n " regress: "
|
||||
if ./regress >/dev/null ;
|
||||
then
|
||||
echo OKAY ;
|
||||
else
|
||||
echo FAILED ;
|
||||
fi
|
||||
}
|
||||
|
||||
echo "Running tests:"
|
||||
|
||||
# Need to do this by hand?
|
||||
setup
|
||||
unset EVENT_NOKQUEUE
|
||||
echo "KQUEUE"
|
||||
test
|
||||
|
||||
setup
|
||||
unset EVENT_NODEVPOLL
|
||||
echo "DEVPOLL"
|
||||
test
|
||||
|
||||
setup
|
||||
unset EVENT_NOPOLL
|
||||
echo "POLL"
|
||||
test
|
||||
|
||||
setup
|
||||
unset EVENT_NOSELECT
|
||||
echo "SELECT"
|
||||
test
|
||||
|
||||
setup
|
||||
unset EVENT_NORTSIG
|
||||
echo "RTSIG"
|
||||
test
|
||||
|
||||
setup
|
||||
unset EVENT_NOEPOLL
|
||||
echo "EPOLL"
|
||||
test
|
||||
|
||||
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user