mirror of /home/gitosis/repositories/libev.git
*** empty log message ***
This commit is contained in:
parent
ebd88ad8a1
commit
598407e832
6
Changes
6
Changes
|
@ -5,9 +5,13 @@ TODO: maybe use timerfd to detect time jumps on linux
|
|||
TODO: document EV_TSTAMP_T
|
||||
|
||||
4.31
|
||||
TODO: use TFD_TIMER_CANCEL_ON_SET to call periodics_reschedule, maybe? (must)
|
||||
- handle backends with minimum wait time a bit better by not
|
||||
waiting in the presence of already-expired timers
|
||||
(behaviour reported by Felipe Gsper).
|
||||
(behaviour reported by Felipe Gasper).
|
||||
- new feature: use timerfd to detect timejumps quickly,
|
||||
can be disabled with the new EVFLAG_NOTIMERFD loop flag.
|
||||
- document EV_USE_SIGNALFD feature macro.
|
||||
|
||||
4.30 (EV only)
|
||||
- change non-autoconf test for __kernel_rwf_t by testing
|
||||
|
|
32
ev.3
32
ev.3
|
@ -133,7 +133,7 @@
|
|||
.\" ========================================================================
|
||||
.\"
|
||||
.IX Title "LIBEV 3"
|
||||
.TH LIBEV 3 "2019-07-07" "libev-4.27" "libev - high performance full featured event loop"
|
||||
.TH LIBEV 3 "2019-12-20" "libev-4.27" "libev - high performance full featured event loop"
|
||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
||||
.\" way too many mistakes in technical documents.
|
||||
.if n .ad l
|
||||
|
@ -595,6 +595,13 @@ threads that are not interested in handling them.
|
|||
Signalfd will not be used by default as this changes your signal mask, and
|
||||
there are a lot of shoddy libraries and programs (glib's threadpool for
|
||||
example) that can't properly initialise their signal masks.
|
||||
.ie n .IP """EVFLAG_NOTIMERFD""" 4
|
||||
.el .IP "\f(CWEVFLAG_NOTIMERFD\fR" 4
|
||||
.IX Item "EVFLAG_NOTIMERFD"
|
||||
When this flag is specified, the libev will avoid using a \f(CW\*(C`timerfd\*(C'\fR to
|
||||
detect time jumps. It will still be able to detect time jumps, but takes
|
||||
longer and has a lower accuracy in doing so, but saves a file descriptor
|
||||
per loop.
|
||||
.ie n .IP """EVFLAG_NOSIGMASK""" 4
|
||||
.el .IP "\f(CWEVFLAG_NOSIGMASK\fR" 4
|
||||
.IX Item "EVFLAG_NOSIGMASK"
|
||||
|
@ -1656,7 +1663,7 @@ Many event loops support \fIwatcher priorities\fR, which are usually small
|
|||
integers that influence the ordering of event callback invocation
|
||||
between watchers in some way, all else being equal.
|
||||
.PP
|
||||
In libev, Watcher priorities can be set using \f(CW\*(C`ev_set_priority\*(C'\fR. See its
|
||||
In libev, watcher priorities can be set using \f(CW\*(C`ev_set_priority\*(C'\fR. See its
|
||||
description for the more technical details such as the actual priority
|
||||
range.
|
||||
.PP
|
||||
|
@ -4756,6 +4763,27 @@ available and will probe for kernel support at runtime. This will improve
|
|||
\&\f(CW\*(C`ev_signal\*(C'\fR and \f(CW\*(C`ev_async\*(C'\fR performance and reduce resource consumption.
|
||||
If undefined, it will be enabled if the headers indicate GNU/Linux + Glibc
|
||||
2.7 or newer, otherwise disabled.
|
||||
.IP "\s-1EV_USE_SIGNALFD\s0" 4
|
||||
.IX Item "EV_USE_SIGNALFD"
|
||||
If defined to be \f(CW1\fR, then libev will assume that \f(CW\*(C`signalfd ()\*(C'\fR is
|
||||
available and will probe for kernel support at runtime. This enables
|
||||
the use of \s-1EVFLAG_SIGNALFD\s0 for faster and simpler signal handling. If
|
||||
undefined, it will be enabled if the headers indicate GNU/Linux + Glibc
|
||||
2.7 or newer, otherwise disabled.
|
||||
.IP "\s-1EV_USE_TIMERFD\s0" 4
|
||||
.IX Item "EV_USE_TIMERFD"
|
||||
If defined to be \f(CW1\fR, then libev will assume that \f(CW\*(C`timerfd ()\*(C'\fR is
|
||||
available and will probe for kernel support at runtime. This allows
|
||||
libev to detect time jumps accurately. If undefined, it will be enabled
|
||||
if the headers indicate GNU/Linux + Glibc 2.8 or newer and define
|
||||
\&\f(CW\*(C`TFD_TIMER_CANCEL_ON_SET\*(C'\fR, otherwise disabled.
|
||||
.IP "\s-1EV_USE_EVENTFD\s0" 4
|
||||
.IX Item "EV_USE_EVENTFD"
|
||||
If defined to be \f(CW1\fR, then libev will assume that \f(CW\*(C`eventfd ()\*(C'\fR is
|
||||
available and will probe for kernel support at runtime. This will improve
|
||||
\&\f(CW\*(C`ev_signal\*(C'\fR and \f(CW\*(C`ev_async\*(C'\fR performance and reduce resource consumption.
|
||||
If undefined, it will be enabled if the headers indicate GNU/Linux + Glibc
|
||||
2.7 or newer, otherwise disabled.
|
||||
.IP "\s-1EV_USE_SELECT\s0" 4
|
||||
.IX Item "EV_USE_SELECT"
|
||||
If undefined or defined to be \f(CW1\fR, libev will compile in support for the
|
||||
|
|
146
ev.c
146
ev.c
|
@ -180,6 +180,15 @@
|
|||
# define EV_USE_EVENTFD 0
|
||||
# endif
|
||||
|
||||
# if HAVE_SYS_TIMERFD_H
|
||||
# ifndef EV_USE_TIMERFD
|
||||
# define EV_USE_TIMERFD EV_FEATURE_OS
|
||||
# endif
|
||||
# else
|
||||
# undef EV_USE_TIMERFD
|
||||
# define EV_USE_TIMERFD 0
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
/* OS X, in its infinite idiocy, actually HARDCODES
|
||||
|
@ -383,6 +392,14 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef EV_USE_TIMERFD
|
||||
# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8))
|
||||
# define EV_USE_TIMERFD EV_FEATURE_OS
|
||||
# else
|
||||
# define EV_USE_TIMERFD 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if 0 /* debugging */
|
||||
# define EV_VERIFY 3
|
||||
# define EV_USE_4HEAP 1
|
||||
|
@ -500,7 +517,7 @@
|
|||
#endif
|
||||
|
||||
#if EV_USE_EVENTFD
|
||||
/* our minimum requirement is glibc 2.7 which has the stub, but not the header */
|
||||
/* our minimum requirement is glibc 2.7 which has the stub, but not the full header */
|
||||
# include <stdint.h>
|
||||
# ifndef EFD_NONBLOCK
|
||||
# define EFD_NONBLOCK O_NONBLOCK
|
||||
|
@ -516,7 +533,7 @@ EV_CPP(extern "C") int (eventfd) (unsigned int initval, int flags);
|
|||
#endif
|
||||
|
||||
#if EV_USE_SIGNALFD
|
||||
/* our minimum requirement is glibc 2.7 which has the stub, but not the header */
|
||||
/* our minimum requirement is glibc 2.7 which has the stub, but not the full header */
|
||||
# include <stdint.h>
|
||||
# ifndef SFD_NONBLOCK
|
||||
# define SFD_NONBLOCK O_NONBLOCK
|
||||
|
@ -528,7 +545,7 @@ EV_CPP(extern "C") int (eventfd) (unsigned int initval, int flags);
|
|||
# define SFD_CLOEXEC 02000000
|
||||
# endif
|
||||
# endif
|
||||
EV_CPP (extern "C") int signalfd (int fd, const sigset_t *mask, int flags);
|
||||
EV_CPP (extern "C") int (signalfd) (int fd, const sigset_t *mask, int flags);
|
||||
|
||||
struct signalfd_siginfo
|
||||
{
|
||||
|
@ -537,6 +554,16 @@ struct signalfd_siginfo
|
|||
};
|
||||
#endif
|
||||
|
||||
/* for timerfd, libev core requires TFD_TIMER_CANCEL_ON_SET &c */
|
||||
#if EV_USE_TIMERFD
|
||||
# include <sys/timerfd.h>
|
||||
/* timerfd is only used for periodics */
|
||||
# if !(defined (TFD_TIMER_CANCEL_ON_SET) && defined (TFD_CLOEXEC) && defined (TFD_NONBLOCK)) || !EV_PERIODIC_ENABLE
|
||||
# undef EV_USE_TIMERFD
|
||||
# define EV_USE_TIMERFD 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if EV_VERIFY >= 3
|
||||
|
@ -2850,6 +2877,58 @@ childcb (EV_P_ ev_signal *sw, int revents)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if EV_USE_TIMERFD
|
||||
|
||||
static void periodics_reschedule (EV_P);
|
||||
|
||||
static void
|
||||
timerfdcb (EV_P_ ev_io *iow, int revents)
|
||||
{
|
||||
struct itimerspec its = { 0 };
|
||||
|
||||
/* since we can't easily come zup with a (portable) maximum value of time_t,
|
||||
* we wake up once per month, which hopefully is rare enough to not
|
||||
* be a problem. */
|
||||
its.it_value.tv_sec = ev_rt_now + 86400 * 30;
|
||||
timerfd_settime (timerfd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &its, 0);
|
||||
|
||||
ev_rt_now = ev_time ();
|
||||
/* periodics_reschedule only needs ev_rt_now */
|
||||
/* but maybe in the future we want the full treatment. */
|
||||
/*
|
||||
now_floor = EV_TS_CONST (0.);
|
||||
time_update (EV_A_ EV_TSTAMP_HUGE);
|
||||
*/
|
||||
periodics_reschedule (EV_A);
|
||||
}
|
||||
|
||||
ecb_noinline ecb_cold
|
||||
static void
|
||||
evtimerfd_init (EV_P)
|
||||
{
|
||||
if (!ev_is_active (&timerfd_w))
|
||||
{
|
||||
timerfd = timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC);
|
||||
|
||||
if (timerfd >= 0)
|
||||
{
|
||||
fd_intern (timerfd); /* just to be sure */
|
||||
|
||||
ev_io_init (&timerfd_w, timerfdcb, timerfd, EV_READ);
|
||||
ev_set_priority (&sigfd_w, EV_MINPRI);
|
||||
ev_io_start (EV_A_ &timerfd_w);
|
||||
ev_unref (EV_A); /* watcher should not keep loop alive */
|
||||
|
||||
/* (re-) arm timer */
|
||||
timerfdcb (EV_A_ 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if EV_USE_IOCP
|
||||
# include "ev_iocp.c"
|
||||
#endif
|
||||
|
@ -3091,6 +3170,9 @@ loop_init (EV_P_ unsigned int flags) EV_NOEXCEPT
|
|||
#if EV_USE_SIGNALFD
|
||||
sigfd = flags & EVFLAG_SIGNALFD ? -2 : -1;
|
||||
#endif
|
||||
#if EV_USE_TIMERFD
|
||||
timerfd = flags & EVFLAG_NOTIMERFD ? -1 : -2;
|
||||
#endif
|
||||
|
||||
if (!(flags & EVBACKEND_MASK))
|
||||
flags |= ev_recommended_backends ();
|
||||
|
@ -3173,6 +3255,11 @@ ev_loop_destroy (EV_P)
|
|||
close (sigfd);
|
||||
#endif
|
||||
|
||||
#if EV_USE_TIMERFD
|
||||
if (ev_is_active (&timerfd_w))
|
||||
close (timerfd);
|
||||
#endif
|
||||
|
||||
#if EV_USE_INOTIFY
|
||||
if (fs_fd >= 0)
|
||||
close (fs_fd);
|
||||
|
@ -3273,22 +3360,44 @@ loop_fork (EV_P)
|
|||
infy_fork (EV_A);
|
||||
#endif
|
||||
|
||||
#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
|
||||
if (ev_is_active (&pipe_w) && postfork != 2)
|
||||
if (postfork != 2)
|
||||
{
|
||||
/* pipe_write_wanted must be false now, so modifying fd vars should be safe */
|
||||
#if EV_USE_SIGNALFD
|
||||
/* surprisingly, nothing needs to be done for signalfd, accoridng to docs, it does the right thing on fork */
|
||||
#endif
|
||||
|
||||
#if EV_USE_TIMERFD
|
||||
if (ev_is_active (&timerfd_w))
|
||||
{
|
||||
ev_ref (EV_A);
|
||||
ev_io_stop (EV_A_ &timerfd_w);
|
||||
|
||||
ev_ref (EV_A);
|
||||
ev_io_stop (EV_A_ &pipe_w);
|
||||
|
||||
if (evpipe [0] >= 0)
|
||||
EV_WIN32_CLOSE_FD (evpipe [0]);
|
||||
|
||||
evpipe_init (EV_A);
|
||||
/* iterate over everything, in case we missed something before */
|
||||
ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);
|
||||
close (timerfd);
|
||||
timerfd = -2;
|
||||
|
||||
evtimerfd_init (EV_A);
|
||||
/* reschedule periodics, in case we missed something */
|
||||
ev_feed_event (EV_A_ &timerfd_w, EV_CUSTOM);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
|
||||
if (ev_is_active (&pipe_w))
|
||||
{
|
||||
/* pipe_write_wanted must be false now, so modifying fd vars should be safe */
|
||||
|
||||
ev_ref (EV_A);
|
||||
ev_io_stop (EV_A_ &pipe_w);
|
||||
|
||||
if (evpipe [0] >= 0)
|
||||
EV_WIN32_CLOSE_FD (evpipe [0]);
|
||||
|
||||
evpipe_init (EV_A);
|
||||
/* iterate over everything, in case we missed something before */
|
||||
ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
postfork = 0;
|
||||
}
|
||||
|
@ -4214,6 +4323,11 @@ ev_periodic_start (EV_P_ ev_periodic *w) EV_NOEXCEPT
|
|||
if (ecb_expect_false (ev_is_active (w)))
|
||||
return;
|
||||
|
||||
#if EV_USE_TIMERFD
|
||||
if (timerfd == -2)
|
||||
evtimerfd_init (EV_A);
|
||||
#endif
|
||||
|
||||
if (w->reschedule_cb)
|
||||
ev_at (w) = w->reschedule_cb (w, ev_rt_now);
|
||||
else if (w->interval)
|
||||
|
|
15
ev.h
15
ev.h
|
@ -504,17 +504,18 @@ union ev_any_watcher
|
|||
/* flag bits for ev_default_loop and ev_loop_new */
|
||||
enum {
|
||||
/* the default */
|
||||
EVFLAG_AUTO = 0x00000000U, /* not quite a mask */
|
||||
EVFLAG_AUTO = 0x00000000U, /* not quite a mask */
|
||||
/* flag bits */
|
||||
EVFLAG_NOENV = 0x01000000U, /* do NOT consult environment */
|
||||
EVFLAG_FORKCHECK = 0x02000000U, /* check for a fork in each iteration */
|
||||
EVFLAG_NOENV = 0x01000000U, /* do NOT consult environment */
|
||||
EVFLAG_FORKCHECK = 0x02000000U, /* check for a fork in each iteration */
|
||||
/* debugging/feature disable */
|
||||
EVFLAG_NOINOTIFY = 0x00100000U, /* do not attempt to use inotify */
|
||||
EVFLAG_NOINOTIFY = 0x00100000U, /* do not attempt to use inotify */
|
||||
#if EV_COMPAT3
|
||||
EVFLAG_NOSIGFD = 0, /* compatibility to pre-3.9 */
|
||||
EVFLAG_NOSIGFD = 0, /* compatibility to pre-3.9 */
|
||||
#endif
|
||||
EVFLAG_SIGNALFD = 0x00200000U, /* attempt to use signalfd */
|
||||
EVFLAG_NOSIGMASK = 0x00400000U /* avoid modifying the signal mask */
|
||||
EVFLAG_SIGNALFD = 0x00200000U, /* attempt to use signalfd */
|
||||
EVFLAG_NOSIGMASK = 0x00400000U, /* avoid modifying the signal mask */
|
||||
EVFLAG_NOTIMERFD = 0x00800000U /* avoid creating a timerfd */
|
||||
};
|
||||
|
||||
/* method bits to be ored together */
|
||||
|
|
35
ev.pod
35
ev.pod
|
@ -482,7 +482,16 @@ unblocking the signals.
|
|||
It's also required by POSIX in a threaded program, as libev calls
|
||||
C<sigprocmask>, whose behaviour is officially unspecified.
|
||||
|
||||
This flag's behaviour will become the default in future versions of libev.
|
||||
=item C<EVFLAG_NOTIMERFD>
|
||||
|
||||
When this flag is specified, the libev will avoid using a C<timerfd> to
|
||||
detect time jumps. It will still be able to detect time jumps, but takes
|
||||
longer and has a lower accuracy in doing so, but saves a file descriptor
|
||||
per loop.
|
||||
|
||||
The current implementation only tries to use a C<timerfd> when the first
|
||||
C<ev_periodic> watcher is started and falls back on other methods if it
|
||||
cannot be created, but this behaviour might change in the future.
|
||||
|
||||
=item C<EVBACKEND_SELECT> (value 1, portable select backend)
|
||||
|
||||
|
@ -4617,6 +4626,30 @@ C<ev_signal> and C<ev_async> performance and reduce resource consumption.
|
|||
If undefined, it will be enabled if the headers indicate GNU/Linux + Glibc
|
||||
2.7 or newer, otherwise disabled.
|
||||
|
||||
=item EV_USE_SIGNALFD
|
||||
|
||||
If defined to be C<1>, then libev will assume that C<signalfd ()> is
|
||||
available and will probe for kernel support at runtime. This enables
|
||||
the use of EVFLAG_SIGNALFD for faster and simpler signal handling. If
|
||||
undefined, it will be enabled if the headers indicate GNU/Linux + Glibc
|
||||
2.7 or newer, otherwise disabled.
|
||||
|
||||
=item EV_USE_TIMERFD
|
||||
|
||||
If defined to be C<1>, then libev will assume that C<timerfd ()> is
|
||||
available and will probe for kernel support at runtime. This allows
|
||||
libev to detect time jumps accurately. If undefined, it will be enabled
|
||||
if the headers indicate GNU/Linux + Glibc 2.8 or newer and define
|
||||
C<TFD_TIMER_CANCEL_ON_SET>, otherwise disabled.
|
||||
|
||||
=item EV_USE_EVENTFD
|
||||
|
||||
If defined to be C<1>, then libev will assume that C<eventfd ()> is
|
||||
available and will probe for kernel support at runtime. This will improve
|
||||
C<ev_signal> and C<ev_async> performance and reduce resource consumption.
|
||||
If undefined, it will be enabled if the headers indicate GNU/Linux + Glibc
|
||||
2.7 or newer, otherwise disabled.
|
||||
|
||||
=item EV_USE_SELECT
|
||||
|
||||
If undefined or defined to be C<1>, libev will compile in support for the
|
||||
|
|
|
@ -228,6 +228,11 @@ VARx(ev_io, sigfd_w)
|
|||
VARx(sigset_t, sigfd_set)
|
||||
#endif
|
||||
|
||||
#if EV_USE_TIMERFD || EV_GENWRAP
|
||||
VARx(int, timerfd) /* timerfd for time jump detection */
|
||||
VARx(ev_io, timerfd_w)
|
||||
#endif
|
||||
|
||||
VARx(unsigned int, origflags) /* original loop flags */
|
||||
|
||||
#if EV_FEATURE_API || EV_GENWRAP
|
||||
|
|
|
@ -124,6 +124,8 @@
|
|||
#define sigfd_w ((loop)->sigfd_w)
|
||||
#define timeout_blocktime ((loop)->timeout_blocktime)
|
||||
#define timercnt ((loop)->timercnt)
|
||||
#define timerfd ((loop)->timerfd)
|
||||
#define timerfd_w ((loop)->timerfd_w)
|
||||
#define timermax ((loop)->timermax)
|
||||
#define timers ((loop)->timers)
|
||||
#define userdata ((loop)->userdata)
|
||||
|
@ -258,6 +260,8 @@
|
|||
#undef sigfd_w
|
||||
#undef timeout_blocktime
|
||||
#undef timercnt
|
||||
#undef timerfd
|
||||
#undef timerfd_w
|
||||
#undef timermax
|
||||
#undef timers
|
||||
#undef userdata
|
||||
|
|
Loading…
Reference in New Issue