Drop in libuv rev 2b5707d834a6b85b8e589ac04cb61a6db2dab94b

This commit is contained in:
Rob Arnold 2011-06-14 08:25:44 -07:00 committed by Brian Anderson
parent b6be83885f
commit 904f443fa9
81 changed files with 64837 additions and 0 deletions

28
src/rt/libuv/.gitignore vendored Normal file
View file

@ -0,0 +1,28 @@
*.swp
*.o
*.lo
*.la
*.a
*.opensdf
*.orig
*.sdf
*.suo
*.vcxproj.filters
*.vcxproj.user
ev/.deps/
ev/.libs/
ev/Makefile
ev/config.h
ev/config.log
ev/config.status
ev/libtool
ev/stamp-h1
ev/autom4te.cache
/msvs/ipch/
/build/
test/run-tests
test/run-benchmarks
test/run-tests.exe
test/run-benchmarks.exe
test/run-benchmarks.dSYM/
test/run-tests.dSYM/

6
src/rt/libuv/AUTHORS Normal file
View file

@ -0,0 +1,6 @@
# Authors ordered by first contribution.
Ryan Dahl <ryan@joyent.com>
Bert Belder <bertbelder@gmail.com>
Josh Roesslein <jroesslein@gmail.com>
Alan Gutierrez <alan@prettyrobots.com>
Vanilla Hsu <vanilla@fatpipi.com>

37
src/rt/libuv/LICENSE Normal file
View file

@ -0,0 +1,37 @@
libuv is part of the Node project: http://nodejs.org/
libuv may be distributed alone under Node's license:
====
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
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
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
====
This license applies to all parts of libuv that are not externally
maintained libraries.
The externally maintained libraries used by libuv are:
- tree.h (from FreeBSD), copyright Niels Provos. Two clause BSD license.
- ngx_queue.h (from Nginx), copyright Igor Sysoev. Two clause BSD license.
- libev, located at ev/ is copyright Marc Alexander Lehmann, and
dual-licensed under the MIT license and GPL2.

16
src/rt/libuv/README Normal file
View file

@ -0,0 +1,16 @@
This is the new networking layer for Node. Its purpose is to abstract
IOCP on windows and libev on Unix systems. We intend to eventually contain
all platform differences in this library.
http://nodejs.org/
(This was previously called liboio)
Supported Platforms:
Microsoft Windows operating systems since Windows XP sp2. It can be built
with either Visual Studio or MinGW.
Linux 2.6 and MacOS using the GCC toolchain.
Solaris 121 and later using GCC toolchain.

View file

@ -0,0 +1,45 @@
# Copyright Joyent, Inc. and other Node contributors. All rights reserved.
#
# 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
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# Use make -f Makefile.gcc PREFIX=i686-w64-mingw32-
# for cross compilation
CC = $(PREFIX)gcc
AR = $(PREFIX)ar
E=.exe
CFLAGS=-g --std=gnu89 -Wno-variadic-macros
LINKFLAGS=-lm
RUNNER_CFLAGS=$(CFLAGS) -D_GNU_SOURCE # Need _GNU_SOURCE for strdup?
RUNNER_LINKFLAGS=$(LINKFLAGS)
RUNNER_LIBS=-lws2_32
RUNNER_SRC=test/runner-win.c
uv.a: uv-win.o uv-common.o
$(AR) rcs uv.a uv-win.o uv-common.o
uv-win.o: uv-win.c uv.h uv-win.h
$(CC) $(CFLAGS) -c uv-win.c -o uv-win.o
uv-common.o: uv-common.c uv.h uv-win.h
$(CC) $(CFLAGS) -c uv-common.c -o uv-common.o
distclean-platform:
clean-platform:

View file

@ -0,0 +1,57 @@
# Copyright Joyent, Inc. and other Node contributors. All rights reserved.
#
# 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
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
CC = $(PREFIX)gcc
AR = $(PREFIX)ar
E=
CFLAGS=--std=gnu89 -Wno-variadic-macros -g
LINKFLAGS=-lm
ifeq (SunOS,$(uname_S))
LINKFLAGS+=-lsocket -lnsl
endif
# Need _GNU_SOURCE for strdup?
RUNNER_CFLAGS=$(CFLAGS) -D_GNU_SOURCE
RUNNER_LINKFLAGS=$(LINKFLAGS) -pthread
RUNNER_LIBS=
RUNNER_SRC=test/runner-unix.c
uv.a: uv-unix.o uv-common.o ev/ev.o
$(AR) rcs uv.a uv-unix.o uv-common.o ev/ev.o
uv-unix.o: uv-unix.c uv.h uv-unix.h
$(CC) $(CFLAGS) -c uv-unix.c -o uv-unix.o
uv-common.o: uv-common.c uv.h uv-unix.h
$(CC) $(CFLAGS) -c uv-common.c -o uv-common.o
ev/ev.o: ev/config.h ev/ev.c
$(MAKE) -C ev
ev/config.h:
cd ev && ./configure
clean-platform:
$(MAKE) -C ev clean
distclean-platform:
$(MAKE) -C ev distclean

159
src/rt/libuv/desired-api.md Normal file
View file

@ -0,0 +1,159 @@
Warning: this is not actual API but desired API.
# `uv_handle_t`
This is the abstract base class of all types of handles. All handles have in
common:
* When handles are initialized, the reference count to the event loop is
increased by one.
* The user owns the `uv_handle_t` memory and is in charge of freeing it.
* In order to free resources associated with a handle, one must `uv_close()`
and wait for the `uv_close_cb` callback. After the close callback has been
made, the user is allowed to the `uv_handle_t` object.
* The `uv_close_cb` is always made directly off the event loop. That is, it
is not called from `uv_close()`.
# `uv_tcp_server_t`
A TCP server class that is a subclass of `uv_handle_t`. This can be bound to
an address and begin accepting new TCP sockets.
int uv_bind4(uv_tcp_server_t* tcp_server, struct sockaddr_in* address);
int uv_bind6(uv_tcp_server_t* tcp_server, struct sockaddr_in6* address);
Binds the TCP server to an address. The `address` can be created with
`uv_ip4_addr()`. Call this before `uv_listen()`
Returns zero on success, -1 on failure. Errors in order of least-seriousness:
* `UV_EADDRINUSE` There is already another socket bound to the specified
address.
* `UV_EADDRNOTAVAIL` The `address` parameter is an IP address that is not
* `UV_EINVAL` The server is already bound to an address.
* `UV_EFAULT` Memory of `address` parameter is unintelligible.
int uv_listen(uv_tcp_server_t*, int backlog, uv_connection_cb cb);
Begins listening for connections. The accept callback is level-triggered.
int uv_accept(uv_tcp_server_t* server,
uv_tcp_t* client);
Accepts a connection. This should be called after the accept callback is
made. The `client` parameter should be uninitialized memory; `uv_accept` is
used instead of `uv_tcp_init` for server-side `uv_tcp_t` initialization.
Return value 0 indicates success, -1 failure. Possible errors:
* `UV_EAGAIN` There are no connections. Wait for the `uv_connection_cb` callback
to be called again.
* `UV_EFAULT` The memory of either `server` is unintelligible.
# `uv_stream_t`
An abstract subclass of `uv_handle_t`. Streams represent something that
reads and/or writes data. Streams can be half or full-duplex. TCP sockets
are streams, files are streams with offsets.
int uv_read_start(uv_stream_t* stream,
uv_alloc_cb alloc_cb,
uv_read_cb read_cb);
Starts the stream reading continuously. The `alloc_cb` is used to allow the
user to implement various means of supplying the stream with buffers to
fill. The `read_cb` returns buffers to the user filled with data.
Sometimes the buffers returned to the user do not contain data. This does
not indicate EOF as in other systems. EOF is made via the `uv_eof_cb` which
can be set like this `uv_set_eof_cb(stream, eof_cb);`
int uv_read_stop(uv_stream_t* stream);
Stops reading from the stream.
int uv_write_req_init(uv_write_req_t*,
uv_stream_t*,
uv_buf_t bufs[],
int butcnf);
Initiates a write request on a stream.
int uv_shutdown_req_init(uv_shutdown_req_t*, uv_stream_t*)
Initiates a shutdown of outgoing data once the write queue drains.
# `uv_tcp_t`
The TCP handle class represents one endpoint of a duplex TCP stream.
`uv_tcp_t` is a subclass of `uv_stream_t`. A TCP handle can represent a
client side connection (one that has been used with uv_connect_req_init`)
or a server-side connection (one that was initialized with `uv_accept`)
int uv_connect_req_init(uv_connect_req_t* req,
uv_tcp_t* socket,
struct sockaddr* addr);
Initiates a request to open a connection.
# `uv_req_t`
Abstract class represents an asynchronous request. This is a subclass of `uv_handle_t`.
# `uv_connect_req_t`
Subclass of `uv_req_t`. Represents a request for a TCP connection. Operates
on `uv_tcp_t` handles. Like other types of requests the `close_cb` indicates
completion of the request.
int uv_connect_req_init(uv_connect_req_t* req,
uv_tcp_t* socket,
struct sockaddr* addr);
Initializes the connection request. Returning 0 indicates success, -1 if
there was an error. The following values can be retrieved from
`uv_last_error` in the case of an error:
* ???
# `uv_shutdown_req_t`
Subclass of `uv_req_t`. Represents an ongoing shutdown request. Once the
write queue of the parent `uv_stream_t` is drained, the outbound data
channel is shutdown. Once a shutdown request is initiated on a stream, the
stream will allow no more writes.
int uv_shutdown_req_init(uv_shutdown_req_t*,
uv_stream_t* parent);
Initializes the shutdown request.
# `uv_write_req_t`
int uv_write_req_init(uv_write_req_t*,
uv_stream_t*,
uv_buf_t bufs[],
int butcnf);
Initiates a write request on a stream.

388
src/rt/libuv/ev/Changes Normal file
View file

@ -0,0 +1,388 @@
Revision history for libev, a high-performance and full-featured event loop.
4.04 Wed Feb 16 09:01:51 CET 2011
- fix two problems in the native win32 backend, where reuse of fd's
with different underlying handles caused handles not to be removed
or added to the select set (analyzed and tested by Bert Belder).
- do no rely on ceil() in ev_e?poll.c.
- backport libev to HP-UX versions before 11 v3.
- configure did not detect nanosleep and clock_gettime properly when
they are available in the libc (as opposed to -lrt).
4.03 Tue Jan 11 14:37:25 CET 2011
- officially support polling files with all backends.
- support files, /dev/zero etc. the same way as select in the epoll
backend, by generating events on our own.
- ports backend: work around solaris bug 6874410 and many related ones
(EINTR, maybe more), with no performance loss (note that the solaris
bug report is actually wrong, reality is far more bizarre and broken
than that).
- define EV_READ/EV_WRITE as macros in event.h, as some programs use
#ifdef to test for them.
- new (experimental) function: ev_feed_signal.
- new (to become default) EVFLAG_NOSIGMASK flag.
- new EVBACKEND_MASK symbol.
- updated COMMON IDIOMS SECTION.
4.01 Fri Nov 5 21:51:29 CET 2010
- automake fucked it up, apparently, --add-missing -f is not quite enough
to make it update its files, so 4.00 didn't install ev++.h and
event.h on make install. grrr.
- ev_loop(count|depth) didn't return anything (Robin Haberkorn).
- change EV_UNDEF to 0xffffffff to silence some overzealous compilers.
- use "(libev) " prefix for all libev error messages now.
4.00 Mon Oct 25 12:32:12 CEST 2010
- "PORTING FROM LIBEV 3.X TO 4.X" (in ev.pod) is recommended reading.
- ev_embed_stop did not correctly stop the watcher (very good
testcase by Vladimir Timofeev).
- ev_run will now always update the current loop time - it erroneously
didn't when idle watchers were active, causing timers not to fire.
- fix a bug where a timeout of zero caused the timer not to fire
in the libevent emulation (testcase by Péter Szabó).
- applied win32 fixes by Michael Lenaghan (also James Mansion).
- replace EV_MINIMAL by EV_FEATURES.
- prefer EPOLL_CTL_ADD over EPOLL_CTL_MOD in some more cases, as it
seems the former is *much* faster than the latter.
- linux kernel version detection (for inotify bug workarounds)
did not work properly.
- reduce the number of spurious wake-ups with the ports backend.
- remove dependency on sys/queue.h on freebsd (patch by Vanilla Hsu).
- do async init within ev_async_start, not ev_async_set, which avoids
an API quirk where the set function must be called in the C++ API
even when there is nothing to set.
- add (undocumented) EV_ENABLE when adding events with kqueue,
this might help with OS X, which seems to need it despite documenting
not to need it (helpfully pointed out by Tilghman Lesher).
- do not use poll by default on freebsd, it's broken (what isn't
on freebsd...).
- allow to embed epoll on kernels >= 2.6.32.
- configure now prepends -O3, not appends it, so one can still
override it.
- ev.pod: greatly expanded the portability section, added a porting
section, a description of watcher states and made lots of minor fixes.
- disable poll backend on AIX, the poll header spams the namespace
and it's not worth working around dead platforms (reported
and analyzed by Aivars Kalvans).
- improve header file compatibility of the standalone eventfd code
in an obscure case.
- implement EV_AVOID_STDIO option.
- do not use sscanf to parse linux version number (smaller, faster,
no sscanf dependency).
- new EV_CHILD_ENABLE and EV_SIGNAL_ENABLE configurable settings.
- update libev.m4 HAVE_CLOCK_SYSCALL test for newer glibcs.
- add section on accept() problems to the manpage.
- rename EV_TIMEOUT to EV_TIMER.
- rename ev_loop_count/depth/verify/loop/unloop.
- remove ev_default_destroy and ev_default_fork.
- switch to two-digit minor version.
- work around an apparent gentoo compiler bug.
- define _DARWIN_UNLIMITED_SELECT. just so.
- use enum instead of #define for most constants.
- improve compatibility to older C++ compilers.
- (experimental) ev_run/ev_default_loop/ev_break/ev_loop_new have now
default arguments when compiled as C++.
- enable automake dependency tracking.
- ev_loop_new no longer leaks memory when loop creation failed.
- new ev_cleanup watcher type.
3.9 Thu Dec 31 07:59:59 CET 2009
- signalfd is no longer used by default and has to be requested
explicitly - this means that easy to catch bugs become hard to
catch race conditions, but the users have spoken.
- point out the unspecified signal mask in the documentation, and
that this is a race condition regardless of EV_SIGNALFD.
- backport inotify code to C89.
- inotify file descriptors could leak into child processes.
- ev_stat watchers could keep an errornous extra ref on the loop,
preventing exit when unregistering all watchers (testcases
provided by ry@tinyclouds.org).
- implement EV_WIN32_HANDLE_TO_FD and EV_WIN32_CLOSE_FD configuration
symbols to make it easier for apps to do their own fd management.
- support EV_IDLE_ENABLE being disabled in ev++.h
(patch by Didier Spezia).
- take advantage of inotify_init1, if available, to set cloexec/nonblock
on fd creation, to avoid races.
- the signal handling pipe wasn't always initialised under windows
(analysed by lekma).
- changed minimum glibc requirement from glibc 2.9 to 2.7, for
signalfd.
- add missing string.h include (Denis F. Latypoff).
- only replace ev_stat.prev when we detect an actual difference,
so prev is (almost) always different to attr. this might
have caused the problems with 04_stat.t.
- add ev::timer->remaining () method to C++ API.
3.8 Sun Aug 9 14:30:45 CEST 2009
- incompatible change: do not necessarily reset signal handler
to SIG_DFL when a sighandler is stopped.
- ev_default_destroy did not properly free or zero some members,
potentially causing crashes and memory corruption on repeated
ev_default_destroy/ev_default_loop calls.
- take advantage of signalfd on GNU/Linux systems.
- document that the signal mask might be in an unspecified
state when using libev's signal handling.
- take advantage of some GNU/Linux calls to set cloexec/nonblock
on fd creation, to avoid race conditions.
3.7 Fri Jul 17 16:36:32 CEST 2009
- ev_unloop and ev_loop wrongly used a global variable to exit loops,
instead of using a per-loop variable (bug caught by accident...).
- the ev_set_io_collect_interval interpretation has changed.
- add new functionality: ev_set_userdata, ev_userdata,
ev_set_invoke_pending_cb, ev_set_loop_release_cb,
ev_invoke_pending, ev_pending_count, together with a long example
about thread locking.
- add ev_timer_remaining (as requested by Denis F. Latypoff).
- add ev_loop_depth.
- calling ev_unloop in fork/prepare watchers will no longer poll
for new events.
- Denis F. Latypoff corrected many typos in example code snippets.
- honor autoconf detection of EV_USE_CLOCK_SYSCALL, also double-
check that the syscall number is available before trying to
use it (reported by ry@tinyclouds).
- use GetSystemTimeAsFileTime instead of _timeb on windows, for
slightly higher accuracy.
- properly declare ev_loop_verify and ev_now_update even when
!EV_MULTIPLICITY.
- do not compile in any priority code when EV_MAXPRI == EV_MINPRI.
- support EV_MINIMAL==2 for a reduced API.
- actually 0-initialise struct sigaction when installing signals.
- add section on hibernate and stopped processes to ev_timer docs.
3.6 Tue Apr 28 02:49:30 CEST 2009
- multiple timers becoming ready within an event loop iteration
will be invoked in the "correct" order now.
- do not leave the event loop early just because we have no active
watchers, fixing a problem when embedding a kqueue loop
that has active kernel events but no registered watchers
(reported by blacksand blacksand).
- correctly zero the idx values for arrays, so destroying and
reinitialising the default loop actually works (patch by
Malek Hadj-Ali).
- implement ev_suspend and ev_resume.
- new EV_CUSTOM revents flag for use by applications.
- add documentation section about priorites.
- add a glossary to the dcoumentation.
- extend the ev_fork description slightly.
- optimize a jump out of call_pending.
3.53 Sun Feb 15 02:38:20 CET 2009
- fix a bug in event pipe creation on win32 that would cause a
failed assertion on event loop creation (patch by Malek Hadj-Ali).
- probe for CLOCK_REALTIME support at runtime as well and fall
back to gettimeofday if there is an error, to support older
operating systems with newer header files/libraries.
- prefer gettimeofday over clock_gettime with USE_CLOCK_SYSCALL
(default most everywhere), otherwise not.
3.52 Wed Jan 7 21:43:02 CET 2009
- fix compilation of select backend in fd_set mode when NFDBITS is
missing (to get it to compile on QNX, reported by Rodrigo Campos).
- better select-nfds handling when select backend is in fd_set mode.
- diagnose fd_set overruns when select backend is in fd_set mode.
- due to a thinko, instead of disabling everything but
select on the borked OS X platform, everything but select was
allowed (reported by Emanuele Giaquinta).
- actually verify that local and remote port are matching in
libev's socketpair emulation, which makes denial-of-service
attacks harder (but not impossible - it's windows). Make sure
it even works under vista, which thinks that getpeer/sockname
should return fantasy port numbers.
- include "libev" in all assertion messages for potentially
clearer diagnostics.
- event_get_version (libevent compatibility) returned
a useless string instead of the expected version string
(patch by W.C.A. Wijngaards).
3.51 Wed Dec 24 23:00:11 CET 2008
- fix a bug where an inotify watcher was added twice, causing
freezes on hash collisions (reported and analysed by Graham Leggett).
- new config symbol, EV_USE_CLOCK_SYSCALL, to make libev use
a direct syscall - slower, but no dependency on librt et al.
- assume negative return values != -1 signals success of port_getn
(http://cvs.epicsol.org/cgi/viewcvs.cgi/epic5/source/newio.c?rev=1.52)
(no known failure reports, but it doesn't hurt).
- fork detection in ev_embed now stops and restarts the watcher
automatically.
- EXPERIMENTAL: default the method to operator () in ev++.h,
to make it nicer to use functors (requested by Benedek László).
- fixed const object callbacks in ev++.h.
- replaced loop_ref argument of watcher.set (loop) by a direct
ev_loop * in ev++.h, to avoid clashes with functor patch.
- do not try to watch the empty string via inotify.
- inotify watchers could be leaked under certain circumstances.
- OS X 10.5 is actually even more broken than earlier versions,
so fall back to select on that piece of garbage.
- fixed some weirdness in the ev_embed documentation.
3.49 Wed Nov 19 11:26:53 CET 2008
- ev_stat watchers will now use inotify as a mere hint on
kernels <2.6.25, or if the filesystem is not in the
"known to be good" list.
- better mingw32 compatibility (it's not as borked as native win32)
(analysed by Roger Pack).
- include stdio.h in the example program, as too many people are
confused by the weird C language otherwise. I guess the next thing
I get told is that the "..." ellipses in the examples don't compile
with their C compiler.
3.48 Thu Oct 30 09:02:37 CET 2008
- further optimise away the EPOLL_CTL_ADD/MOD combo in the epoll
backend by assuming the kernel event mask hasn't changed if
ADD fails with EEXIST.
- work around spurious event notification bugs in epoll by using
a 32-bit generation counter. recreate kernel state if we receive
spurious notifications or unwanted events. this is very costly,
but I didn't come up with this horrible design.
- use memset to initialise most arrays now and do away with the
init functions.
- expand time-out strategies into a "Be smart about timeouts" section.
- drop the "struct" from all ev_watcher declarations in the
documentation and did other clarifications (yeah, it was a mistake
to have a struct AND a function called ev_loop).
- fix a bug where ev_default would not initialise the default
loop again after it was destroyed with ev_default_destroy.
- rename syserr to ev_syserr to avoid name clashes when embedding,
do similar changes for event.c.
3.45 Tue Oct 21 21:59:26 CEST 2008
- disable inotify usage on linux <2.6.25, as it is broken
(reported by Yoann Vandoorselaere).
- ev_stat erroneously would try to add inotify watchers
even when inotify wasn't available (this should only
have a performance impact).
- ev_once now passes both timeout and io to the callback if both
occur concurrently, instead of giving timeouts precedence.
- disable EV_USE_INOTIFY when sys/inotify.h is too old.
3.44 Mon Sep 29 05:18:39 CEST 2008
- embed watchers now automatically invoke ev_loop_fork on the
embedded loop when the parent loop forks.
- new function: ev_now_update (loop).
- verify_watcher was not marked static.
- improve the "associating..." manpage section.
- documentation tweaks here and there.
3.43 Sun Jul 6 05:34:41 CEST 2008
- include more include files on windows to get struct _stati64
(reported by Chris Hulbert, but doesn't quite fix his issue).
- add missing #include <io.h> in ev.c on windows (reported by
Matt Tolton).
3.42 Tue Jun 17 12:12:07 CEST 2008
- work around yet another windows bug: FD_SET actually adds fd's
multiple times to the fd_*SET*, despite official MSN docs claiming
otherwise. Reported and well-analysed by Matt Tolton.
- define NFDBITS to 0 when EV_SELECT_IS_WINSOCKET to make it compile
(reported any analysed by Chris Hulbert).
- fix a bug in ev_ebadf (this function is only used to catch
programming errors in the libev user). reported by Matt Tolton.
- fix a bug in fd_intern on win32 (could lead to compile errors
under some circumstances, but would work correctly if it compiles).
reported by Matt Tolton.
- (try to) work around missing lstat on windows.
- pass in the write fd set as except fd set under windows. windows
is so uncontrollably lame that it requires this. this means that
switching off oobinline is not supported (but tcp/ip doesn't
have oob, so that would be stupid anyways.
- use posix module symbol to auto-detect monotonic clock presence
and some other default values.
3.41 Fri May 23 18:42:54 CEST 2008
- work around an obscure bug in winsocket select: if you
provide only empty fd sets then select returns WSAEINVAL. how sucky.
- improve timer scheduling stability and reduce use of time_epsilon.
- use 1-based 2-heap for EV_MINIMAL, simplifies code, reduces
codesize and makes for better cache-efficiency.
- use 3-based 4-heap for !EV_MINIMAL. this makes better use
of cpu cache lines and gives better growth behaviour than
2-based heaps.
- cache timestamp within heap for !EV_MINIMAL, to avoid random
memory accesses.
- document/add EV_USE_4HEAP and EV_HEAP_CACHE_AT.
- fix a potential aliasing issue in ev_timer_again.
- add/document ev_periodic_at, retract direct access to ->at.
- improve ev_stat docs.
- add portability requirements section.
- fix manpage headers etc.
- normalise WSA error codes to lower range on windows.
- add consistency check code that can be called automatically
or on demand to check for internal structures (ev_loop_verify).
3.31 Wed Apr 16 20:45:04 CEST 2008
- added last minute fix for ev_poll.c by Brandon Black.
3.3 Wed Apr 16 19:04:10 CEST 2008
- event_base_loopexit should return 0 on success
(W.C.A. Wijngaards).
- added linux eventfd support.
- try to autodetect epoll and inotify support
by libc header version if not using autoconf.
- new symbols: EV_DEFAULT_UC and EV_DEFAULT_UC_.
- declare functions defined in ev.h as inline if
C99 or gcc are available.
- enable inlining with gcc versions 2 and 3.
- work around broken poll implementations potentially
not clearing revents field in ev_poll (Brandon Black)
(no such systems are known at this time).
- work around a bug in realloc on openbsd and darwin,
also makes the erroneous valgrind complaints
go away (noted by various people).
- fix ev_async_pending, add c++ wrapper for ev_async
(based on patch sent by Johannes Deisenhofer).
- add sensible set method to ev::embed.
- made integer constants type int in ev.h.
3.2 Wed Apr 2 17:11:19 CEST 2008
- fix a 64 bit overflow issue in the select backend,
by using fd_mask instead of int for the mask.
- rename internal sighandler to avoid clash with very old perls.
- entering ev_loop will not clear the ONESHOT or NONBLOCKING
flags of any outer loops anymore.
- add ev_async_pending.
3.1 Thu Mar 13 13:45:22 CET 2008
- implement ev_async watchers.
- only initialise signal pipe on demand.
- make use of sig_atomic_t configurable.
- improved documentation.
3.0 Mon Jan 28 13:14:47 CET 2008
- API/ABI bump to version 3.0.
- ev++.h includes "ev.h" by default now, not <ev.h>.
- slightly improved documentation.
- speed up signal detection after a fork.
- only optionally return trace status changed in ev_child
watchers.
- experimental (and undocumented) loop wrappers for ev++.h.
2.01 Tue Dec 25 08:04:41 CET 2007
- separate Changes file.
- fix ev_path_set => ev_stat_set typo.
- remove event_compat.h from the libev tarball.
- change how include files are found.
- doc updates.
- update licenses, explicitly allow for GPL relicensing.
2.0 Sat Dec 22 17:47:03 CET 2007
- new ev_sleep, ev_set_(io|timeout)_collect_interval.
- removed epoll from embeddable fd set.
- fix embed watchers.
- renamed ev_embed.loop to other.
- added exported Symbol tables.
- undefine member wrapper macros at the end of ev.c.
- respect EV_H in ev++.h.
1.86 Tue Dec 18 02:36:57 CET 2007
- fix memleak on loop destroy (not relevant for perl).
1.85 Fri Dec 14 20:32:40 CET 2007
- fix some aliasing issues w.r.t. timers and periodics
(not relevant for perl).
(for historic versions refer to EV/Changes, found in the Perl interface)
0.1 Wed Oct 31 21:31:48 CET 2007
- original version; hacked together in <24h.

36
src/rt/libuv/ev/LICENSE Normal file
View file

@ -0,0 +1,36 @@
All files in libev are Copyright (C)2007,2008,2009 Marc Alexander Lehmann.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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 COPYRIGHT HOLDERS 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 COPYRIGHT
OWNER 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.
Alternatively, the contents of this package may be used under the terms
of the GNU General Public License ("GPL") version 2 or any later version,
in which case the provisions of the GPL are applicable instead of the
above. If you wish to allow the use of your version of this package only
under the terms of the GPL and not to allow others to use your version of
this file under the BSD license, indicate your decision by deleting the
provisions above and replace them with the notice and other provisions
required by the GPL in this and the other files of this package. If you do
not delete the provisions above, a recipient may use your version of this
file under either the BSD or the GPL.

View file

@ -0,0 +1,18 @@
AUTOMAKE_OPTIONS = foreign
VERSION_INFO = 4:0:0
EXTRA_DIST = LICENSE Changes libev.m4 autogen.sh \
ev_vars.h ev_wrap.h \
ev_epoll.c ev_select.c ev_poll.c ev_kqueue.c ev_port.c ev_win32.c \
ev.3 ev.pod
man_MANS = ev.3
include_HEADERS = ev.h ev++.h event.h
lib_LTLIBRARIES = libev.la
libev_la_SOURCES = ev.c event.c
libev_la_LDFLAGS = -version-info $(VERSION_INFO)

771
src/rt/libuv/ev/Makefile.in Normal file
View file

@ -0,0 +1,771 @@
# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
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 = :
build_triplet = @build@
host_triplet = @host@
subdir = .
DIST_COMMON = README $(am__configure_deps) $(include_HEADERS) \
$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(srcdir)/config.h.in $(top_srcdir)/configure config.guess \
config.sub depcomp install-sh ltmain.sh missing mkinstalldirs
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/libev.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno config.status.lineno
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(man3dir)" \
"$(DESTDIR)$(includedir)"
LTLIBRARIES = $(lib_LTLIBRARIES)
libev_la_LIBADD =
am_libev_la_OBJECTS = ev.lo event.lo
libev_la_OBJECTS = $(am_libev_la_OBJECTS)
libev_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(libev_la_LDFLAGS) \
$(LDFLAGS) -o $@
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libev_la_SOURCES)
DIST_SOURCES = $(libev_la_SOURCES)
man3dir = $(mandir)/man3
NROFF = nroff
MANS = $(man_MANS)
HEADERS = $(include_HEADERS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
am__remove_distdir = \
{ test ! -d "$(distdir)" \
|| { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
&& rm -fr "$(distdir)"; }; }
DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best
distuninstallcheck_listfiles = find . -type f -print
distcleancheck_listfiles = find . -type f -print
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
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@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = foreign
VERSION_INFO = 4:0:0
EXTRA_DIST = LICENSE Changes libev.m4 autogen.sh \
ev_vars.h ev_wrap.h \
ev_epoll.c ev_select.c ev_poll.c ev_kqueue.c ev_port.c ev_win32.c \
ev.3 ev.pod
man_MANS = ev.3
include_HEADERS = ev.h ev++.h event.h
lib_LTLIBRARIES = libev.la
libev_la_SOURCES = ev.c event.c
libev_la_LDFLAGS = -version-info $(VERSION_INFO)
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
am--refresh:
@:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
$(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
echo ' $(SHELL) ./config.status'; \
$(SHELL) ./config.status;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
$(am__cd) $(srcdir) && $(AUTOCONF)
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
$(am__aclocal_m4_deps):
config.h: stamp-h1
@if test ! -f $@; then \
rm -f stamp-h1; \
$(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
else :; fi
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
@rm -f stamp-h1
cd $(top_builddir) && $(SHELL) ./config.status config.h
$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
rm -f stamp-h1
touch $@
distclean-hdr:
-rm -f config.h stamp-h1
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
list2=; for p in $$list; do \
if test -f $$p; then \
list2="$$list2 $$p"; \
else :; fi; \
done; \
test -z "$$list2" || { \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
}
uninstall-libLTLIBRARIES:
@$(NORMAL_UNINSTALL)
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
for p in $$list; do \
$(am__strip_dir) \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
done
clean-libLTLIBRARIES:
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
test "$$dir" != "$$p" || dir=.; \
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
libev.la: $(libev_la_OBJECTS) $(libev_la_DEPENDENCIES)
$(libev_la_LINK) -rpath $(libdir) $(libev_la_OBJECTS) $(libev_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ev.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool config.lt
install-man3: $(man_MANS)
@$(NORMAL_INSTALL)
test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)"
@list=''; test -n "$(man3dir)" || exit 0; \
{ for i in $$list; do echo "$$i"; done; \
l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
sed -n '/\.3[a-z]*$$/p'; \
} | while read p; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; echo "$$p"; \
done | \
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
sed 'N;N;s,\n, ,g' | { \
list=; while read file base inst; do \
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \
fi; \
done; \
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
while read files; do \
test -z "$$files" || { \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \
done; }
uninstall-man3:
@$(NORMAL_UNINSTALL)
@list=''; test -n "$(man3dir)" || exit 0; \
files=`{ for i in $$list; do echo "$$i"; done; \
l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
sed -n '/\.3[a-z]*$$/p'; \
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
test -z "$$files" || { \
echo " ( cd '$(DESTDIR)$(man3dir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(man3dir)" && rm -f $$files; }
install-includeHEADERS: $(include_HEADERS)
@$(NORMAL_INSTALL)
test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
$(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
done
uninstall-includeHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(includedir)" && rm -f $$files
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; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) config.h.in $(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; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) config.h.in $(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; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@list='$(MANS)'; if test -n "$$list"; then \
list=`for p in $$list; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
if test -n "$$list" && \
grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \
grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
echo " typically \`make maintainer-clean' will remove them" >&2; \
exit 1; \
else :; fi; \
else :; fi
$(am__remove_distdir)
test -d "$(distdir)" || mkdir "$(distdir)"
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
-test -n "$(am__skip_mode_fix)" \
|| find "$(distdir)" -type d ! -perm -755 \
-exec chmod u+rwx,go+rx {} \; -o \
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|| chmod -R a+r "$(distdir)"
dist-gzip: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
$(am__remove_distdir)
dist-bzip2: distdir
tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
$(am__remove_distdir)
dist-lzma: distdir
tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
$(am__remove_distdir)
dist-xz: distdir
tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz
$(am__remove_distdir)
dist-tarZ: distdir
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
$(am__remove_distdir)
dist-shar: distdir
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
$(am__remove_distdir)
dist-zip: distdir
-rm -f $(distdir).zip
zip -rq $(distdir).zip $(distdir)
$(am__remove_distdir)
dist dist-all: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
$(am__remove_distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
case '$(DIST_ARCHIVES)' in \
*.tar.gz*) \
GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
*.tar.bz2*) \
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
*.tar.lzma*) \
lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\
*.tar.xz*) \
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
*.tar.Z*) \
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
*.shar.gz*) \
GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
esac
chmod -R a-w $(distdir); chmod a+w $(distdir)
mkdir $(distdir)/_build
mkdir $(distdir)/_inst
chmod a-w $(distdir)
test -d $(distdir)/_build || exit 0; \
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
&& am__cwd=`pwd` \
&& $(am__cd) $(distdir)/_build \
&& ../configure --srcdir=.. --prefix="$$dc_install_base" \
$(DISTCHECK_CONFIGURE_FLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
distuninstallcheck \
&& chmod -R a-w "$$dc_install_base" \
&& ({ \
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
} || { rm -rf "$$dc_destdir"; exit 1; }) \
&& rm -rf "$$dc_destdir" \
&& $(MAKE) $(AM_MAKEFLAGS) dist \
&& rm -rf $(DIST_ARCHIVES) \
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
&& cd "$$am__cwd" \
|| exit 1
$(am__remove_distdir)
@(echo "$(distdir) archives ready for distribution: "; \
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
distuninstallcheck:
@$(am__cd) '$(distuninstallcheck_dir)' \
&& test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
|| { echo "ERROR: files left after uninstall:" ; \
if test -n "$(DESTDIR)"; then \
echo " (check DESTDIR support)"; \
fi ; \
$(distuninstallcheck_listfiles) ; \
exit 1; } >&2
distcleancheck: distclean
@if test '$(srcdir)' = . ; then \
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
exit 1 ; \
fi
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|| { echo "ERROR: files left in build directory after distclean:" ; \
$(distcleancheck_listfiles) ; \
exit 1; } >&2
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES) $(MANS) $(HEADERS) config.h
installdirs:
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(includedir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
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 . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
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-libLTLIBRARIES clean-libtool \
mostlyclean-am
distclean: distclean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-hdr distclean-libtool distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am: install-includeHEADERS install-man
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am: install-libLTLIBRARIES
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man: install-man3
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
-rm -rf ./$(DEPDIR)
-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-includeHEADERS uninstall-libLTLIBRARIES \
uninstall-man
uninstall-man: uninstall-man3
.MAKE: all install-am install-strip
.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \
clean-generic clean-libLTLIBRARIES clean-libtool ctags dist \
dist-all dist-bzip2 dist-gzip dist-lzma dist-shar dist-tarZ \
dist-xz dist-zip distcheck distclean distclean-compile \
distclean-generic distclean-hdr distclean-libtool \
distclean-tags distcleancheck distdir distuninstallcheck dvi \
dvi-am html html-am info info-am install install-am \
install-data install-data-am install-dvi install-dvi-am \
install-exec install-exec-am install-html install-html-am \
install-includeHEADERS install-info install-info-am \
install-libLTLIBRARIES install-man install-man3 install-pdf \
install-pdf-am install-ps install-ps-am 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-includeHEADERS \
uninstall-libLTLIBRARIES uninstall-man uninstall-man3
# 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:

58
src/rt/libuv/ev/README Normal file
View file

@ -0,0 +1,58 @@
libev is a high-performance event loop/event model with lots of features.
(see benchmark at http://libev.schmorp.de/bench.html)
ABOUT
Homepage: http://software.schmorp.de/pkg/libev
Mailinglist: libev@lists.schmorp.de
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Library Documentation: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod
Libev is modelled (very losely) after libevent and the Event perl
module, but is faster, scales better and is more correct, and also more
featureful. And also smaller. Yay.
Some of the specialties of libev not commonly found elsewhere are:
- extensive and detailed, readable documentation (not doxygen garbage).
- fully supports fork, can detect fork in various ways and automatically
re-arms kernel mechanisms that do not support fork.
- highly optimised select, poll, epoll, kqueue and event ports backends.
- filesystem object (path) watching (with optional linux inotify support).
- wallclock-based times (using absolute time, cron-like).
- relative timers/timeouts (handle time jumps).
- fast intra-thread communication between multiple
event loops (with optional fast linux eventfd backend).
- extremely easy to embed.
- very small codebase, no bloated library.
- fully extensible by being able to plug into the event loop,
integrate other event loops, integrate other event loop users.
- very little memory use (small watchers, small event loop data).
- optional C++ interface allowing method and function callbacks
at no extra memory or runtime overhead.
- optional Perl interface with similar characteristics (capable
of running Glib/Gtk2 on libev, interfaces with Net::SNMP and
libadns).
- support for other languages (multiple C++ interfaces, D, Ruby,
Python) available from third-parties.
Examples of programs that embed libev: the EV perl module,
rxvt-unicode, gvpe (GNU Virtual Private Ethernet), the Deliantra MMORPG
server (http://www.deliantra.net/), Rubinius (a next-generation Ruby
VM), the Ebb web server, the Rev event toolkit.
CONTRIBUTORS
libev was written and designed by Marc Lehmann and Emanuele Giaquinta.
The following people sent in patches or made other noteworthy
contributions to the design (for minor patches, see the Changes
file. If I forgot to include you, please shout at me, it was an
accident):
W.C.A. Wijngaards
Christopher Layne
Chris Brody

8957
src/rt/libuv/ev/aclocal.m4 vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,6 @@
#!/bin/sh
libtoolize --force
automake --add-missing --force-missing
autoreconf

1526
src/rt/libuv/ev/config.guess vendored Executable file

File diff suppressed because it is too large Load diff

125
src/rt/libuv/ev/config.h.in Normal file
View file

@ -0,0 +1,125 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the `clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME
/* "use syscall interface for clock_gettime" */
#undef HAVE_CLOCK_SYSCALL
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the `epoll_ctl' function. */
#undef HAVE_EPOLL_CTL
/* Define to 1 if you have the `eventfd' function. */
#undef HAVE_EVENTFD
/* Define to 1 if you have the `inotify_init' function. */
#undef HAVE_INOTIFY_INIT
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `kqueue' function. */
#undef HAVE_KQUEUE
/* Define to 1 if you have the `m' library (-lm). */
#undef HAVE_LIBM
/* Define to 1 if you have the `rt' library (-lrt). */
#undef HAVE_LIBRT
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `nanosleep' function. */
#undef HAVE_NANOSLEEP
/* Define to 1 if you have the `poll' function. */
#undef HAVE_POLL
/* Define to 1 if you have the <poll.h> header file. */
#undef HAVE_POLL_H
/* Define to 1 if you have the `port_create' function. */
#undef HAVE_PORT_CREATE
/* Define to 1 if you have the <port.h> header file. */
#undef HAVE_PORT_H
/* Define to 1 if you have the `select' function. */
#undef HAVE_SELECT
/* Define to 1 if you have the `signalfd' function. */
#undef HAVE_SIGNALFD
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/epoll.h> header file. */
#undef HAVE_SYS_EPOLL_H
/* Define to 1 if you have the <sys/eventfd.h> header file. */
#undef HAVE_SYS_EVENTFD_H
/* Define to 1 if you have the <sys/event.h> header file. */
#undef HAVE_SYS_EVENT_H
/* Define to 1 if you have the <sys/inotify.h> header file. */
#undef HAVE_SYS_INOTIFY_H
/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define to 1 if you have the <sys/signalfd.h> header file. */
#undef HAVE_SYS_SIGNALFD_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION

1658
src/rt/libuv/ev/config.sub vendored Executable file

File diff suppressed because it is too large Load diff

13037
src/rt/libuv/ev/configure vendored Executable file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,18 @@
AC_INIT
AC_CONFIG_SRCDIR([ev_epoll.c])
AM_INIT_AUTOMAKE(libev,4.04) dnl also update ev.h!
AC_CONFIG_HEADERS([config.h])
AM_MAINTAINER_MODE
AC_PROG_INSTALL
AC_PROG_LIBTOOL
if test "x$GCC" = xyes ; then
CFLAGS="-O3 $CFLAGS"
fi
m4_include([libev.m4])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

630
src/rt/libuv/ev/depcomp Executable file
View file

@ -0,0 +1,630 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2009-04-28.21; # UTC
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free
# Software Foundation, Inc.
# 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, see <http://www.gnu.org/licenses/>.
# 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.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
case $1 in
'')
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by `PROGRAMS ARGS'.
object Object file output by `PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputing dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u="sed s,\\\\\\\\,/,g"
depmode=msvisualcpp
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say).
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
## The second -e expression handles DOS-style file names with drive letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the `deleted header file' problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
tr ' ' '
' < "$tmpdepfile" |
## Some versions of gcc put a space before the `:'. On the theory
## that the space means something, we add a space to the output as
## well.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like `#:fec' to the end of the
# dependency line.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
tr '
' ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts `$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
# Each line is of the form `foo.o: dependent.h'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
# That's a tab and a space in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
icc)
# Intel's C compiler understands `-MD -MF file'. However on
# icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
# ICC 7.0 will fill foo.d with something like
# foo.o: sub/foo.c
# foo.o: sub/foo.h
# which is wrong. We want:
# sub/foo.o: sub/foo.c
# sub/foo.o: sub/foo.h
# sub/foo.c:
# sub/foo.h:
# ICC 7.1 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using \ :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
# Add `dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in `foo.d' instead, so we check for that too.
# Subdirectories are respected.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
# With Tru64 cc, shared objects can also be used to make a
# static library. This mechanism is used in libtool 1.4 series to
# handle both shared and static libraries in a single compilation.
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
#
# With libtool 1.5 this exception was removed, and libtool now
# generates 2 separate objects for the 2 libraries. These two
# compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
tmpdepfile2=$dir$base.o.d # libtool 1.5
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.o.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
tmpdepfile4=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
# That's a tab and a space in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for `:'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
"$@" $dashmflag |
sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
tr ' ' '
' < "$tmpdepfile" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-arch)
eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
sed '1,2d' "$tmpdepfile" | tr ' ' '
' | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E |
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
echo " " >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

816
src/rt/libuv/ev/ev++.h Normal file
View file

@ -0,0 +1,816 @@
/*
* libev simple C++ wrapper classes
*
* Copyright (c) 2007,2008,2010 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, 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 MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, 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 OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#ifndef EVPP_H__
#define EVPP_H__
#ifdef EV_H
# include EV_H
#else
# include "ev.h"
#endif
#ifndef EV_USE_STDEXCEPT
# define EV_USE_STDEXCEPT 1
#endif
#if EV_USE_STDEXCEPT
# include <stdexcept>
#endif
namespace ev {
typedef ev_tstamp tstamp;
enum {
UNDEF = EV_UNDEF,
NONE = EV_NONE,
READ = EV_READ,
WRITE = EV_WRITE,
#if EV_COMPAT3
TIMEOUT = EV_TIMEOUT,
#endif
TIMER = EV_TIMER,
PERIODIC = EV_PERIODIC,
SIGNAL = EV_SIGNAL,
CHILD = EV_CHILD,
STAT = EV_STAT,
IDLE = EV_IDLE,
CHECK = EV_CHECK,
PREPARE = EV_PREPARE,
FORK = EV_FORK,
ASYNC = EV_ASYNC,
EMBED = EV_EMBED,
# undef ERROR // some systems stupidly #define ERROR
ERROR = EV_ERROR
};
enum
{
AUTO = EVFLAG_AUTO,
NOENV = EVFLAG_NOENV,
FORKCHECK = EVFLAG_FORKCHECK,
SELECT = EVBACKEND_SELECT,
POLL = EVBACKEND_POLL,
EPOLL = EVBACKEND_EPOLL,
KQUEUE = EVBACKEND_KQUEUE,
DEVPOLL = EVBACKEND_DEVPOLL,
PORT = EVBACKEND_PORT
};
enum
{
#if EV_COMPAT3
NONBLOCK = EVLOOP_NONBLOCK,
ONESHOT = EVLOOP_ONESHOT,
#endif
NOWAIT = EVRUN_NOWAIT,
ONCE = EVRUN_ONCE
};
enum how_t
{
ONE = EVBREAK_ONE,
ALL = EVBREAK_ALL
};
struct bad_loop
#if EV_USE_STDEXCEPT
: std::runtime_error
#endif
{
#if EV_USE_STDEXCEPT
bad_loop ()
: std::runtime_error ("libev event loop cannot be initialized, bad value of LIBEV_FLAGS?")
{
}
#endif
};
#ifdef EV_AX
# undef EV_AX
#endif
#ifdef EV_AX_
# undef EV_AX_
#endif
#if EV_MULTIPLICITY
# define EV_AX raw_loop
# define EV_AX_ raw_loop,
#else
# define EV_AX
# define EV_AX_
#endif
struct loop_ref
{
loop_ref (EV_P) throw ()
#if EV_MULTIPLICITY
: EV_AX (EV_A)
#endif
{
}
bool operator == (const loop_ref &other) const throw ()
{
#if EV_MULTIPLICITY
return EV_AX == other.EV_AX;
#else
return true;
#endif
}
bool operator != (const loop_ref &other) const throw ()
{
#if EV_MULTIPLICITY
return ! (*this == other);
#else
return false;
#endif
}
#if EV_MULTIPLICITY
bool operator == (const EV_P) const throw ()
{
return this->EV_AX == EV_A;
}
bool operator != (const EV_P) const throw ()
{
return (*this == EV_A);
}
operator struct ev_loop * () const throw ()
{
return EV_AX;
}
operator const struct ev_loop * () const throw ()
{
return EV_AX;
}
bool is_default () const throw ()
{
return EV_AX == ev_default_loop (0);
}
#endif
#if EV_COMPAT3
void loop (int flags = 0)
{
ev_run (EV_AX_ flags);
}
void unloop (how_t how = ONE) throw ()
{
ev_break (EV_AX_ how);
}
#endif
void run (int flags = 0)
{
ev_run (EV_AX_ flags);
}
void break_loop (how_t how = ONE) throw ()
{
ev_break (EV_AX_ how);
}
void post_fork () throw ()
{
ev_loop_fork (EV_AX);
}
unsigned int backend () const throw ()
{
return ev_backend (EV_AX);
}
tstamp now () const throw ()
{
return ev_now (EV_AX);
}
void ref () throw ()
{
ev_ref (EV_AX);
}
void unref () throw ()
{
ev_unref (EV_AX);
}
#if EV_FEATURE_API
unsigned int iteration () const throw ()
{
return ev_iteration (EV_AX);
}
unsigned int depth () const throw ()
{
return ev_depth (EV_AX);
}
void set_io_collect_interval (tstamp interval) throw ()
{
ev_set_io_collect_interval (EV_AX_ interval);
}
void set_timeout_collect_interval (tstamp interval) throw ()
{
ev_set_timeout_collect_interval (EV_AX_ interval);
}
#endif
// function callback
void once (int fd, int events, tstamp timeout, void (*cb)(int, void *), void *arg = 0) throw ()
{
ev_once (EV_AX_ fd, events, timeout, cb, arg);
}
// method callback
template<class K, void (K::*method)(int)>
void once (int fd, int events, tstamp timeout, K *object) throw ()
{
once (fd, events, timeout, method_thunk<K, method>, object);
}
// default method == operator ()
template<class K>
void once (int fd, int events, tstamp timeout, K *object) throw ()
{
once (fd, events, timeout, method_thunk<K, &K::operator ()>, object);
}
template<class K, void (K::*method)(int)>
static void method_thunk (int revents, void *arg)
{
static_cast<K *>(arg)->*method
(revents);
}
// no-argument method callback
template<class K, void (K::*method)()>
void once (int fd, int events, tstamp timeout, K *object) throw ()
{
once (fd, events, timeout, method_noargs_thunk<K, method>, object);
}
template<class K, void (K::*method)()>
static void method_noargs_thunk (int revents, void *arg)
{
static_cast<K *>(arg)->*method
();
}
// simpler function callback
template<void (*cb)(int)>
void once (int fd, int events, tstamp timeout) throw ()
{
once (fd, events, timeout, simpler_func_thunk<cb>);
}
template<void (*cb)(int)>
static void simpler_func_thunk (int revents, void *arg)
{
(*cb)
(revents);
}
// simplest function callback
template<void (*cb)()>
void once (int fd, int events, tstamp timeout) throw ()
{
once (fd, events, timeout, simplest_func_thunk<cb>);
}
template<void (*cb)()>
static void simplest_func_thunk (int revents, void *arg)
{
(*cb)
();
}
void feed_fd_event (int fd, int revents) throw ()
{
ev_feed_fd_event (EV_AX_ fd, revents);
}
void feed_signal_event (int signum) throw ()
{
ev_feed_signal_event (EV_AX_ signum);
}
#if EV_MULTIPLICITY
struct ev_loop* EV_AX;
#endif
};
#if EV_MULTIPLICITY
struct dynamic_loop : loop_ref
{
dynamic_loop (unsigned int flags = AUTO) throw (bad_loop)
: loop_ref (ev_loop_new (flags))
{
if (!EV_AX)
throw bad_loop ();
}
~dynamic_loop () throw ()
{
ev_loop_destroy (EV_AX);
EV_AX = 0;
}
private:
dynamic_loop (const dynamic_loop &);
dynamic_loop & operator= (const dynamic_loop &);
};
#endif
struct default_loop : loop_ref
{
default_loop (unsigned int flags = AUTO) throw (bad_loop)
#if EV_MULTIPLICITY
: loop_ref (ev_default_loop (flags))
#endif
{
if (
#if EV_MULTIPLICITY
!EV_AX
#else
!ev_default_loop (flags)
#endif
)
throw bad_loop ();
}
private:
default_loop (const default_loop &);
default_loop &operator = (const default_loop &);
};
inline loop_ref get_default_loop () throw ()
{
#if EV_MULTIPLICITY
return ev_default_loop (0);
#else
return loop_ref ();
#endif
}
#undef EV_AX
#undef EV_AX_
#undef EV_PX
#undef EV_PX_
#if EV_MULTIPLICITY
# define EV_PX loop_ref EV_A
# define EV_PX_ loop_ref EV_A_
#else
# define EV_PX
# define EV_PX_
#endif
template<class ev_watcher, class watcher>
struct base : ev_watcher
{
#if EV_MULTIPLICITY
EV_PX;
// loop set
void set (EV_P) throw ()
{
this->EV_A = EV_A;
}
#endif
base (EV_PX) throw ()
#if EV_MULTIPLICITY
: EV_A (EV_A)
#endif
{
ev_init (this, 0);
}
void set_ (const void *data, void (*cb)(EV_P_ ev_watcher *w, int revents)) throw ()
{
this->data = (void *)data;
ev_set_cb (static_cast<ev_watcher *>(this), cb);
}
// function callback
template<void (*function)(watcher &w, int)>
void set (void *data = 0) throw ()
{
set_ (data, function_thunk<function>);
}
template<void (*function)(watcher &w, int)>
static void function_thunk (EV_P_ ev_watcher *w, int revents)
{
function
(*static_cast<watcher *>(w), revents);
}
// method callback
template<class K, void (K::*method)(watcher &w, int)>
void set (K *object) throw ()
{
set_ (object, method_thunk<K, method>);
}
// default method == operator ()
template<class K>
void set (K *object) throw ()
{
set_ (object, method_thunk<K, &K::operator ()>);
}
template<class K, void (K::*method)(watcher &w, int)>
static void method_thunk (EV_P_ ev_watcher *w, int revents)
{
(static_cast<K *>(w->data)->*method)
(*static_cast<watcher *>(w), revents);
}
// no-argument callback
template<class K, void (K::*method)()>
void set (K *object) throw ()
{
set_ (object, method_noargs_thunk<K, method>);
}
template<class K, void (K::*method)()>
static void method_noargs_thunk (EV_P_ ev_watcher *w, int revents)
{
(static_cast<K *>(w->data)->*method)
();
}
void operator ()(int events = EV_UNDEF)
{
return
ev_cb (static_cast<ev_watcher *>(this))
(static_cast<ev_watcher *>(this), events);
}
bool is_active () const throw ()
{
return ev_is_active (static_cast<const ev_watcher *>(this));
}
bool is_pending () const throw ()
{
return ev_is_pending (static_cast<const ev_watcher *>(this));
}
void feed_event (int revents) throw ()
{
ev_feed_event (EV_A_ static_cast<const ev_watcher *>(this), revents);
}
};
inline tstamp now () throw ()
{
return ev_time ();
}
inline void delay (tstamp interval) throw ()
{
ev_sleep (interval);
}
inline int version_major () throw ()
{
return ev_version_major ();
}
inline int version_minor () throw ()
{
return ev_version_minor ();
}
inline unsigned int supported_backends () throw ()
{
return ev_supported_backends ();
}
inline unsigned int recommended_backends () throw ()
{
return ev_recommended_backends ();
}
inline unsigned int embeddable_backends () throw ()
{
return ev_embeddable_backends ();
}
inline void set_allocator (void *(*cb)(void *ptr, long size)) throw ()
{
ev_set_allocator (cb);
}
inline void set_syserr_cb (void (*cb)(const char *msg)) throw ()
{
ev_set_syserr_cb (cb);
}
#if EV_MULTIPLICITY
#define EV_CONSTRUCT(cppstem,cstem) \
(EV_PX = get_default_loop ()) throw () \
: base<ev_ ## cstem, cppstem> (EV_A) \
{ \
}
#else
#define EV_CONSTRUCT(cppstem,cstem) \
() throw () \
{ \
}
#endif
/* using a template here would require quite a bit more lines,
* so a macro solution was chosen */
#define EV_BEGIN_WATCHER(cppstem,cstem) \
\
struct cppstem : base<ev_ ## cstem, cppstem> \
{ \
void start () throw () \
{ \
ev_ ## cstem ## _start (EV_A_ static_cast<ev_ ## cstem *>(this)); \
} \
\
void stop () throw () \
{ \
ev_ ## cstem ## _stop (EV_A_ static_cast<ev_ ## cstem *>(this)); \
} \
\
cppstem EV_CONSTRUCT(cppstem,cstem) \
\
~cppstem () throw () \
{ \
stop (); \
} \
\
using base<ev_ ## cstem, cppstem>::set; \
\
private: \
\
cppstem (const cppstem &o); \
\
cppstem &operator =(const cppstem &o); \
\
public:
#define EV_END_WATCHER(cppstem,cstem) \
};
EV_BEGIN_WATCHER (io, io)
void set (int fd, int events) throw ()
{
int active = is_active ();
if (active) stop ();
ev_io_set (static_cast<ev_io *>(this), fd, events);
if (active) start ();
}
void set (int events) throw ()
{
int active = is_active ();
if (active) stop ();
ev_io_set (static_cast<ev_io *>(this), fd, events);
if (active) start ();
}
void start (int fd, int events) throw ()
{
set (fd, events);
start ();
}
EV_END_WATCHER (io, io)
EV_BEGIN_WATCHER (timer, timer)
void set (ev_tstamp after, ev_tstamp repeat = 0.) throw ()
{
int active = is_active ();
if (active) stop ();
ev_timer_set (static_cast<ev_timer *>(this), after, repeat);
if (active) start ();
}
void start (ev_tstamp after, ev_tstamp repeat = 0.) throw ()
{
set (after, repeat);
start ();
}
void again () throw ()
{
ev_timer_again (EV_A_ static_cast<ev_timer *>(this));
}
ev_tstamp remaining ()
{
return ev_timer_remaining (EV_A_ static_cast<ev_timer *>(this));
}
EV_END_WATCHER (timer, timer)
#if EV_PERIODIC_ENABLE
EV_BEGIN_WATCHER (periodic, periodic)
void set (ev_tstamp at, ev_tstamp interval = 0.) throw ()
{
int active = is_active ();
if (active) stop ();
ev_periodic_set (static_cast<ev_periodic *>(this), at, interval, 0);
if (active) start ();
}
void start (ev_tstamp at, ev_tstamp interval = 0.) throw ()
{
set (at, interval);
start ();
}
void again () throw ()
{
ev_periodic_again (EV_A_ static_cast<ev_periodic *>(this));
}
EV_END_WATCHER (periodic, periodic)
#endif
#if EV_SIGNAL_ENABLE
EV_BEGIN_WATCHER (sig, signal)
void set (int signum) throw ()
{
int active = is_active ();
if (active) stop ();
ev_signal_set (static_cast<ev_signal *>(this), signum);
if (active) start ();
}
void start (int signum) throw ()
{
set (signum);
start ();
}
EV_END_WATCHER (sig, signal)
#endif
#if EV_CHILD_ENABLE
EV_BEGIN_WATCHER (child, child)
void set (int pid, int trace = 0) throw ()
{
int active = is_active ();
if (active) stop ();
ev_child_set (static_cast<ev_child *>(this), pid, trace);
if (active) start ();
}
void start (int pid, int trace = 0) throw ()
{
set (pid, trace);
start ();
}
EV_END_WATCHER (child, child)
#endif
#if EV_STAT_ENABLE
EV_BEGIN_WATCHER (stat, stat)
void set (const char *path, ev_tstamp interval = 0.) throw ()
{
int active = is_active ();
if (active) stop ();
ev_stat_set (static_cast<ev_stat *>(this), path, interval);
if (active) start ();
}
void start (const char *path, ev_tstamp interval = 0.) throw ()
{
stop ();
set (path, interval);
start ();
}
void update () throw ()
{
ev_stat_stat (EV_A_ static_cast<ev_stat *>(this));
}
EV_END_WATCHER (stat, stat)
#endif
#if EV_IDLE_ENABLE
EV_BEGIN_WATCHER (idle, idle)
void set () throw () { }
EV_END_WATCHER (idle, idle)
#endif
#if EV_PREPARE_ENABLE
EV_BEGIN_WATCHER (prepare, prepare)
void set () throw () { }
EV_END_WATCHER (prepare, prepare)
#endif
#if EV_CHECK_ENABLE
EV_BEGIN_WATCHER (check, check)
void set () throw () { }
EV_END_WATCHER (check, check)
#endif
#if EV_EMBED_ENABLE
EV_BEGIN_WATCHER (embed, embed)
void set (struct ev_loop *embedded_loop) throw ()
{
int active = is_active ();
if (active) stop ();
ev_embed_set (static_cast<ev_embed *>(this), embedded_loop);
if (active) start ();
}
void start (struct ev_loop *embedded_loop) throw ()
{
set (embedded_loop);
start ();
}
void sweep ()
{
ev_embed_sweep (EV_A_ static_cast<ev_embed *>(this));
}
EV_END_WATCHER (embed, embed)
#endif
#if EV_FORK_ENABLE
EV_BEGIN_WATCHER (fork, fork)
void set () throw () { }
EV_END_WATCHER (fork, fork)
#endif
#if EV_ASYNC_ENABLE
EV_BEGIN_WATCHER (async, async)
void send () throw ()
{
ev_async_send (EV_A_ static_cast<ev_async *>(this));
}
bool async_pending () throw ()
{
return ev_async_pending (static_cast<ev_async *>(this));
}
EV_END_WATCHER (async, async)
#endif
#undef EV_PX
#undef EV_PX_
#undef EV_CONSTRUCT
#undef EV_BEGIN_WATCHER
#undef EV_END_WATCHER
}
#endif

5311
src/rt/libuv/ev/ev.3 Normal file

File diff suppressed because it is too large Load diff

3913
src/rt/libuv/ev/ev.c Normal file

File diff suppressed because it is too large Load diff

829
src/rt/libuv/ev/ev.h Normal file
View file

@ -0,0 +1,829 @@
/*
* libev native API header
*
* Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, 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 MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, 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 OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#ifndef EV_H_
#define EV_H_
#ifdef __cplusplus
# define EV_CPP(x) x
#else
# define EV_CPP(x)
#endif
EV_CPP(extern "C" {)
/*****************************************************************************/
/* pre-4.0 compatibility */
#ifndef EV_COMPAT3
# define EV_COMPAT3 1
#endif
#ifndef EV_FEATURES
# define EV_FEATURES 0x7f
#endif
#define EV_FEATURE_CODE ((EV_FEATURES) & 1)
#define EV_FEATURE_DATA ((EV_FEATURES) & 2)
#define EV_FEATURE_CONFIG ((EV_FEATURES) & 4)
#define EV_FEATURE_API ((EV_FEATURES) & 8)
#define EV_FEATURE_WATCHERS ((EV_FEATURES) & 16)
#define EV_FEATURE_BACKENDS ((EV_FEATURES) & 32)
#define EV_FEATURE_OS ((EV_FEATURES) & 64)
/* these priorities are inclusive, higher priorities will be invoked earlier */
#ifndef EV_MINPRI
# define EV_MINPRI (EV_FEATURE_CONFIG ? -2 : 0)
#endif
#ifndef EV_MAXPRI
# define EV_MAXPRI (EV_FEATURE_CONFIG ? +2 : 0)
#endif
#ifndef EV_MULTIPLICITY
# define EV_MULTIPLICITY EV_FEATURE_CONFIG
#endif
#ifndef EV_PERIODIC_ENABLE
# define EV_PERIODIC_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_STAT_ENABLE
# define EV_STAT_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_PREPARE_ENABLE
# define EV_PREPARE_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_CHECK_ENABLE
# define EV_CHECK_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_IDLE_ENABLE
# define EV_IDLE_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_FORK_ENABLE
# define EV_FORK_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_CLEANUP_ENABLE
# define EV_CLEANUP_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_SIGNAL_ENABLE
# define EV_SIGNAL_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_CHILD_ENABLE
# ifdef _WIN32
# define EV_CHILD_ENABLE 0
# else
# define EV_CHILD_ENABLE EV_FEATURE_WATCHERS
#endif
#endif
#ifndef EV_ASYNC_ENABLE
# define EV_ASYNC_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_EMBED_ENABLE
# define EV_EMBED_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_WALK_ENABLE
# define EV_WALK_ENABLE 0 /* not yet */
#endif
/*****************************************************************************/
#if EV_CHILD_ENABLE && !EV_SIGNAL_ENABLE
# undef EV_SIGNAL_ENABLE
# define EV_SIGNAL_ENABLE 1
#endif
/*****************************************************************************/
typedef double ev_tstamp;
#ifndef EV_ATOMIC_T
# include <signal.h>
# define EV_ATOMIC_T sig_atomic_t volatile
#endif
#if EV_STAT_ENABLE
# ifdef _WIN32
# include <time.h>
# include <sys/types.h>
# endif
# include <sys/stat.h>
#endif
/* support multiple event loops? */
#if EV_MULTIPLICITY
struct ev_loop;
# define EV_P struct ev_loop *loop /* a loop as sole parameter in a declaration */
# define EV_P_ EV_P, /* a loop as first of multiple parameters */
# define EV_A loop /* a loop as sole argument to a function call */
# define EV_A_ EV_A, /* a loop as first of multiple arguments */
# define EV_DEFAULT_UC ev_default_loop_uc_ () /* the default loop, if initialised, as sole arg */
# define EV_DEFAULT_UC_ EV_DEFAULT_UC, /* the default loop as first of multiple arguments */
# define EV_DEFAULT ev_default_loop (0) /* the default loop as sole arg */
# define EV_DEFAULT_ EV_DEFAULT, /* the default loop as first of multiple arguments */
#else
# define EV_P void
# define EV_P_
# define EV_A
# define EV_A_
# define EV_DEFAULT
# define EV_DEFAULT_
# define EV_DEFAULT_UC
# define EV_DEFAULT_UC_
# undef EV_EMBED_ENABLE
#endif
/* EV_INLINE is used for functions in header files */
#if __STDC_VERSION__ >= 199901L && __GNUC__ >= 3
# define EV_INLINE static inline
#else
# define EV_INLINE static
#endif
/* EV_PROTOTYPES can be used to switch of prototype declarations */
#ifndef EV_PROTOTYPES
# define EV_PROTOTYPES 1
#endif
/*****************************************************************************/
#define EV_VERSION_MAJOR 4
#define EV_VERSION_MINOR 4
/* eventmask, revents, events... */
enum {
EV_UNDEF = 0xFFFFFFFF, /* guaranteed to be invalid */
EV_NONE = 0x00, /* no events */
EV_READ = 0x01, /* ev_io detected read will not block */
EV_WRITE = 0x02, /* ev_io detected write will not block */
EV__IOFDSET = 0x80, /* internal use only */
EV_IO = EV_READ, /* alias for type-detection */
EV_TIMER = 0x00000100, /* timer timed out */
#if EV_COMPAT3
EV_TIMEOUT = EV_TIMER, /* pre 4.0 API compatibility */
#endif
EV_PERIODIC = 0x00000200, /* periodic timer timed out */
EV_SIGNAL = 0x00000400, /* signal was received */
EV_CHILD = 0x00000800, /* child/pid had status change */
EV_STAT = 0x00001000, /* stat data changed */
EV_IDLE = 0x00002000, /* event loop is idling */
EV_PREPARE = 0x00004000, /* event loop about to poll */
EV_CHECK = 0x00008000, /* event loop finished poll */
EV_EMBED = 0x00010000, /* embedded event loop needs sweep */
EV_FORK = 0x00020000, /* event loop resumed in child */
EV_CLEANUP = 0x00040000, /* event loop resumed in child */
EV_ASYNC = 0x00080000, /* async intra-loop signal */
EV_CUSTOM = 0x01000000, /* for use by user code */
EV_ERROR = 0x80000000 /* sent when an error occurs */
};
/* can be used to add custom fields to all watchers, while losing binary compatibility */
#ifndef EV_COMMON
# define EV_COMMON void *data;
#endif
#ifndef EV_CB_DECLARE
# define EV_CB_DECLARE(type) void (*cb)(EV_P_ struct type *w, int revents);
#endif
#ifndef EV_CB_INVOKE
# define EV_CB_INVOKE(watcher,revents) (watcher)->cb (EV_A_ (watcher), (revents))
#endif
/* not official, do not use */
#define EV_CB(type,name) void name (EV_P_ struct ev_ ## type *w, int revents)
/*
* struct member types:
* private: you may look at them, but not change them,
* and they might not mean anything to you.
* ro: can be read anytime, but only changed when the watcher isn't active.
* rw: can be read and modified anytime, even when the watcher is active.
*
* some internal details that might be helpful for debugging:
*
* active is either 0, which means the watcher is not active,
* or the array index of the watcher (periodics, timers)
* or the array index + 1 (most other watchers)
* or simply 1 for watchers that aren't in some array.
* pending is either 0, in which case the watcher isn't,
* or the array index + 1 in the pendings array.
*/
#if EV_MINPRI == EV_MAXPRI
# define EV_DECL_PRIORITY
#elif !defined (EV_DECL_PRIORITY)
# define EV_DECL_PRIORITY int priority;
#endif
/* shared by all watchers */
#define EV_WATCHER(type) \
int active; /* private */ \
int pending; /* private */ \
EV_DECL_PRIORITY /* private */ \
EV_COMMON /* rw */ \
EV_CB_DECLARE (type) /* private */
#define EV_WATCHER_LIST(type) \
EV_WATCHER (type) \
struct ev_watcher_list *next; /* private */
#define EV_WATCHER_TIME(type) \
EV_WATCHER (type) \
ev_tstamp at; /* private */
/* base class, nothing to see here unless you subclass */
typedef struct ev_watcher
{
EV_WATCHER (ev_watcher)
} ev_watcher;
/* base class, nothing to see here unless you subclass */
typedef struct ev_watcher_list
{
EV_WATCHER_LIST (ev_watcher_list)
} ev_watcher_list;
/* base class, nothing to see here unless you subclass */
typedef struct ev_watcher_time
{
EV_WATCHER_TIME (ev_watcher_time)
} ev_watcher_time;
/* invoked when fd is either EV_READable or EV_WRITEable */
/* revent EV_READ, EV_WRITE */
typedef struct ev_io
{
EV_WATCHER_LIST (ev_io)
int fd; /* ro */
int events; /* ro */
} ev_io;
/* invoked after a specific time, repeatable (based on monotonic clock) */
/* revent EV_TIMEOUT */
typedef struct ev_timer
{
EV_WATCHER_TIME (ev_timer)
ev_tstamp repeat; /* rw */
} ev_timer;
/* invoked at some specific time, possibly repeating at regular intervals (based on UTC) */
/* revent EV_PERIODIC */
typedef struct ev_periodic
{
EV_WATCHER_TIME (ev_periodic)
ev_tstamp offset; /* rw */
ev_tstamp interval; /* rw */
ev_tstamp (*reschedule_cb)(struct ev_periodic *w, ev_tstamp now); /* rw */
} ev_periodic;
/* invoked when the given signal has been received */
/* revent EV_SIGNAL */
typedef struct ev_signal
{
EV_WATCHER_LIST (ev_signal)
int signum; /* ro */
} ev_signal;
/* invoked when sigchld is received and waitpid indicates the given pid */
/* revent EV_CHILD */
/* does not support priorities */
typedef struct ev_child
{
EV_WATCHER_LIST (ev_child)
int flags; /* private */
int pid; /* ro */
int rpid; /* rw, holds the received pid */
int rstatus; /* rw, holds the exit status, use the macros from sys/wait.h */
} ev_child;
#if EV_STAT_ENABLE
/* st_nlink = 0 means missing file or other error */
# ifdef _WIN32
typedef struct _stati64 ev_statdata;
# else
typedef struct stat ev_statdata;
# endif
/* invoked each time the stat data changes for a given path */
/* revent EV_STAT */
typedef struct ev_stat
{
EV_WATCHER_LIST (ev_stat)
ev_timer timer; /* private */
ev_tstamp interval; /* ro */
const char *path; /* ro */
ev_statdata prev; /* ro */
ev_statdata attr; /* ro */
int wd; /* wd for inotify, fd for kqueue */
} ev_stat;
#endif
#if EV_IDLE_ENABLE
/* invoked when the nothing else needs to be done, keeps the process from blocking */
/* revent EV_IDLE */
typedef struct ev_idle
{
EV_WATCHER (ev_idle)
} ev_idle;
#endif
/* invoked for each run of the mainloop, just before the blocking call */
/* you can still change events in any way you like */
/* revent EV_PREPARE */
typedef struct ev_prepare
{
EV_WATCHER (ev_prepare)
} ev_prepare;
/* invoked for each run of the mainloop, just after the blocking call */
/* revent EV_CHECK */
typedef struct ev_check
{
EV_WATCHER (ev_check)
} ev_check;
#if EV_FORK_ENABLE
/* the callback gets invoked before check in the child process when a fork was detected */
/* revent EV_FORK */
typedef struct ev_fork
{
EV_WATCHER (ev_fork)
} ev_fork;
#endif
#if EV_CLEANUP_ENABLE
/* is invoked just before the loop gets destroyed */
/* revent EV_CLEANUP */
typedef struct ev_cleanup
{
EV_WATCHER (ev_cleanup)
} ev_cleanup;
#endif
#if EV_EMBED_ENABLE
/* used to embed an event loop inside another */
/* the callback gets invoked when the event loop has handled events, and can be 0 */
typedef struct ev_embed
{
EV_WATCHER (ev_embed)
struct ev_loop *other; /* ro */
ev_io io; /* private */
ev_prepare prepare; /* private */
ev_check check; /* unused */
ev_timer timer; /* unused */
ev_periodic periodic; /* unused */
ev_idle idle; /* unused */
ev_fork fork; /* private */
#if EV_CLEANUP_ENABLE
ev_cleanup cleanup; /* unused */
#endif
} ev_embed;
#endif
#if EV_ASYNC_ENABLE
/* invoked when somebody calls ev_async_send on the watcher */
/* revent EV_ASYNC */
typedef struct ev_async
{
EV_WATCHER (ev_async)
EV_ATOMIC_T sent; /* private */
} ev_async;
# define ev_async_pending(w) (+(w)->sent)
#endif
/* the presence of this union forces similar struct layout */
union ev_any_watcher
{
struct ev_watcher w;
struct ev_watcher_list wl;
struct ev_io io;
struct ev_timer timer;
struct ev_periodic periodic;
struct ev_signal signal;
struct ev_child child;
#if EV_STAT_ENABLE
struct ev_stat stat;
#endif
#if EV_IDLE_ENABLE
struct ev_idle idle;
#endif
struct ev_prepare prepare;
struct ev_check check;
#if EV_FORK_ENABLE
struct ev_fork fork;
#endif
#if EV_CLEANUP_ENABLE
struct ev_cleanup cleanup;
#endif
#if EV_EMBED_ENABLE
struct ev_embed embed;
#endif
#if EV_ASYNC_ENABLE
struct ev_async async;
#endif
};
/* flag bits for ev_default_loop and ev_loop_new */
enum {
/* the default */
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 */
/* debugging/feature disable */
EVFLAG_NOINOTIFY = 0x00100000U, /* do not attempt to use inotify */
#if EV_COMPAT3
EVFLAG_NOSIGFD = 0, /* compatibility to pre-3.9 */
#endif
EVFLAG_SIGNALFD = 0x00200000U, /* attempt to use signalfd */
EVFLAG_NOSIGMASK = 0x00400000U /* avoid modifying the signal mask */
};
/* method bits to be ored together */
enum {
EVBACKEND_SELECT = 0x00000001U, /* about anywhere */
EVBACKEND_POLL = 0x00000002U, /* !win */
EVBACKEND_EPOLL = 0x00000004U, /* linux */
EVBACKEND_KQUEUE = 0x00000008U, /* bsd */
EVBACKEND_DEVPOLL = 0x00000010U, /* solaris 8 */ /* NYI */
EVBACKEND_PORT = 0x00000020U, /* solaris 10 */
EVBACKEND_ALL = 0x0000003FU, /* all known backends */
EVBACKEND_MASK = 0x0000FFFFU /* all future backends */
};
#if EV_PROTOTYPES
int ev_version_major (void);
int ev_version_minor (void);
unsigned int ev_supported_backends (void);
unsigned int ev_recommended_backends (void);
unsigned int ev_embeddable_backends (void);
ev_tstamp ev_time (void);
void ev_sleep (ev_tstamp delay); /* sleep for a while */
/* Sets the allocation function to use, works like realloc.
* It is used to allocate and free memory.
* If it returns zero when memory needs to be allocated, the library might abort
* or take some potentially destructive action.
* The default is your system realloc function.
*/
void ev_set_allocator (void *(*cb)(void *ptr, long size));
/* set the callback function to call on a
* retryable syscall error
* (such as failed select, poll, epoll_wait)
*/
void ev_set_syserr_cb (void (*cb)(const char *msg));
#if EV_MULTIPLICITY
/* the default loop is the only one that handles signals and child watchers */
/* you can call this as often as you like */
struct ev_loop *ev_default_loop (unsigned int flags EV_CPP (= 0));
EV_INLINE struct ev_loop *
ev_default_loop_uc_ (void)
{
extern struct ev_loop *ev_default_loop_ptr;
return ev_default_loop_ptr;
}
EV_INLINE int
ev_is_default_loop (EV_P)
{
return EV_A == EV_DEFAULT_UC;
}
/* create and destroy alternative loops that don't handle signals */
struct ev_loop *ev_loop_new (unsigned int flags EV_CPP (= 0));
ev_tstamp ev_now (EV_P); /* time w.r.t. timers and the eventloop, updated after each poll */
#else
int ev_default_loop (unsigned int flags EV_CPP (= 0)); /* returns true when successful */
EV_INLINE ev_tstamp
ev_now (void)
{
extern ev_tstamp ev_rt_now;
return ev_rt_now;
}
/* looks weird, but ev_is_default_loop (EV_A) still works if this exists */
EV_INLINE int
ev_is_default_loop (void)
{
return 1;
}
#endif /* multiplicity */
/* destroy event loops, also works for the default loop */
void ev_loop_destroy (EV_P);
/* this needs to be called after fork, to duplicate the loop */
/* when you want to re-use it in the child */
/* you can call it in either the parent or the child */
/* you can actually call it at any time, anywhere :) */
void ev_loop_fork (EV_P);
unsigned int ev_backend (EV_P); /* backend in use by loop */
void ev_now_update (EV_P); /* update event loop time */
#if EV_WALK_ENABLE
/* walk (almost) all watchers in the loop of a given type, invoking the */
/* callback on every such watcher. The callback might stop the watcher, */
/* but do nothing else with the loop */
void ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w));
#endif
#endif /* prototypes */
/* ev_run flags values */
enum {
EVRUN_NOWAIT = 1, /* do not block/wait */
EVRUN_ONCE = 2 /* block *once* only */
};
/* ev_break how values */
enum {
EVBREAK_CANCEL = 0, /* undo unloop */
EVBREAK_ONE = 1, /* unloop once */
EVBREAK_ALL = 2 /* unloop all loops */
};
#if EV_PROTOTYPES
void ev_run (EV_P_ int flags EV_CPP (= 0));
void ev_break (EV_P_ int how EV_CPP (= EVBREAK_ONE)); /* break out of the loop */
/*
* ref/unref can be used to add or remove a refcount on the mainloop. every watcher
* keeps one reference. if you have a long-running watcher you never unregister that
* should not keep ev_loop from running, unref() after starting, and ref() before stopping.
*/
void ev_ref (EV_P);
void ev_unref (EV_P);
/*
* convenience function, wait for a single event, without registering an event watcher
* if timeout is < 0, do wait indefinitely
*/
void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg);
# if EV_FEATURE_API
unsigned int ev_iteration (EV_P); /* number of loop iterations */
unsigned int ev_depth (EV_P); /* #ev_loop enters - #ev_loop leaves */
void ev_verify (EV_P); /* abort if loop data corrupted */
void ev_set_io_collect_interval (EV_P_ ev_tstamp interval); /* sleep at least this time, default 0 */
void ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval); /* sleep at least this time, default 0 */
/* advanced stuff for threading etc. support, see docs */
void ev_set_userdata (EV_P_ void *data);
void *ev_userdata (EV_P);
void ev_set_invoke_pending_cb (EV_P_ void (*invoke_pending_cb)(EV_P));
void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P), void (*acquire)(EV_P));
unsigned int ev_pending_count (EV_P); /* number of pending events, if any */
void ev_invoke_pending (EV_P); /* invoke all pending watchers */
/*
* stop/start the timer handling.
*/
void ev_suspend (EV_P);
void ev_resume (EV_P);
#endif
#endif
/* these may evaluate ev multiple times, and the other arguments at most once */
/* either use ev_init + ev_TYPE_set, or the ev_TYPE_init macro, below, to first initialise a watcher */
#define ev_init(ev,cb_) do { \
((ev_watcher *)(void *)(ev))->active = \
((ev_watcher *)(void *)(ev))->pending = 0; \
ev_set_priority ((ev), 0); \
ev_set_cb ((ev), cb_); \
} while (0)
#define ev_io_set(ev,fd_,events_) do { (ev)->fd = (fd_); (ev)->events = (events_) | EV__IOFDSET; } while (0)
#define ev_timer_set(ev,after_,repeat_) do { ((ev_watcher_time *)(ev))->at = (after_); (ev)->repeat = (repeat_); } while (0)
#define ev_periodic_set(ev,ofs_,ival_,rcb_) do { (ev)->offset = (ofs_); (ev)->interval = (ival_); (ev)->reschedule_cb = (rcb_); } while (0)
#define ev_signal_set(ev,signum_) do { (ev)->signum = (signum_); } while (0)
#define ev_child_set(ev,pid_,trace_) do { (ev)->pid = (pid_); (ev)->flags = !!(trace_); } while (0)
#define ev_stat_set(ev,path_,interval_) do { (ev)->path = (path_); (ev)->interval = (interval_); (ev)->wd = -2; } while (0)
#define ev_idle_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_prepare_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_check_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_embed_set(ev,other_) do { (ev)->other = (other_); } while (0)
#define ev_fork_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_cleanup_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_async_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_io_init(ev,cb,fd,events) do { ev_init ((ev), (cb)); ev_io_set ((ev),(fd),(events)); } while (0)
#define ev_timer_init(ev,cb,after,repeat) do { ev_init ((ev), (cb)); ev_timer_set ((ev),(after),(repeat)); } while (0)
#define ev_periodic_init(ev,cb,ofs,ival,rcb) do { ev_init ((ev), (cb)); ev_periodic_set ((ev),(ofs),(ival),(rcb)); } while (0)
#define ev_signal_init(ev,cb,signum) do { ev_init ((ev), (cb)); ev_signal_set ((ev), (signum)); } while (0)
#define ev_child_init(ev,cb,pid,trace) do { ev_init ((ev), (cb)); ev_child_set ((ev),(pid),(trace)); } while (0)
#define ev_stat_init(ev,cb,path,interval) do { ev_init ((ev), (cb)); ev_stat_set ((ev),(path),(interval)); } while (0)
#define ev_idle_init(ev,cb) do { ev_init ((ev), (cb)); ev_idle_set ((ev)); } while (0)
#define ev_prepare_init(ev,cb) do { ev_init ((ev), (cb)); ev_prepare_set ((ev)); } while (0)
#define ev_check_init(ev,cb) do { ev_init ((ev), (cb)); ev_check_set ((ev)); } while (0)
#define ev_embed_init(ev,cb,other) do { ev_init ((ev), (cb)); ev_embed_set ((ev),(other)); } while (0)
#define ev_fork_init(ev,cb) do { ev_init ((ev), (cb)); ev_fork_set ((ev)); } while (0)
#define ev_cleanup_init(ev,cb) do { ev_init ((ev), (cb)); ev_cleanup_set ((ev)); } while (0)
#define ev_async_init(ev,cb) do { ev_init ((ev), (cb)); ev_async_set ((ev)); } while (0)
#define ev_is_pending(ev) (0 + ((ev_watcher *)(void *)(ev))->pending) /* ro, true when watcher is waiting for callback invocation */
#define ev_is_active(ev) (0 + ((ev_watcher *)(void *)(ev))->active) /* ro, true when the watcher has been started */
#define ev_cb(ev) (ev)->cb /* rw */
#if EV_MINPRI == EV_MAXPRI
# define ev_priority(ev) ((ev), EV_MINPRI)
# define ev_set_priority(ev,pri) ((ev), (pri))
#else
# define ev_priority(ev) (+(((ev_watcher *)(void *)(ev))->priority))
# define ev_set_priority(ev,pri) ( (ev_watcher *)(void *)(ev))->priority = (pri)
#endif
#define ev_periodic_at(ev) (+((ev_watcher_time *)(ev))->at)
#ifndef ev_set_cb
# define ev_set_cb(ev,cb_) ev_cb (ev) = (cb_)
#endif
/* stopping (enabling, adding) a watcher does nothing if it is already running */
/* stopping (disabling, deleting) a watcher does nothing unless its already running */
#if EV_PROTOTYPES
/* feeds an event into a watcher as if the event actually occured */
/* accepts any ev_watcher type */
void ev_feed_event (EV_P_ void *w, int revents);
void ev_feed_fd_event (EV_P_ int fd, int revents);
#if EV_SIGNAL_ENABLE
void ev_feed_signal (int signum);
void ev_feed_signal_event (EV_P_ int signum);
#endif
void ev_invoke (EV_P_ void *w, int revents);
int ev_clear_pending (EV_P_ void *w);
void ev_io_start (EV_P_ ev_io *w);
void ev_io_stop (EV_P_ ev_io *w);
void ev_timer_start (EV_P_ ev_timer *w);
void ev_timer_stop (EV_P_ ev_timer *w);
/* stops if active and no repeat, restarts if active and repeating, starts if inactive and repeating */
void ev_timer_again (EV_P_ ev_timer *w);
/* return remaining time */
ev_tstamp ev_timer_remaining (EV_P_ ev_timer *w);
#if EV_PERIODIC_ENABLE
void ev_periodic_start (EV_P_ ev_periodic *w);
void ev_periodic_stop (EV_P_ ev_periodic *w);
void ev_periodic_again (EV_P_ ev_periodic *w);
#endif
/* only supported in the default loop */
#if EV_SIGNAL_ENABLE
void ev_signal_start (EV_P_ ev_signal *w);
void ev_signal_stop (EV_P_ ev_signal *w);
#endif
/* only supported in the default loop */
# if EV_CHILD_ENABLE
void ev_child_start (EV_P_ ev_child *w);
void ev_child_stop (EV_P_ ev_child *w);
# endif
# if EV_STAT_ENABLE
void ev_stat_start (EV_P_ ev_stat *w);
void ev_stat_stop (EV_P_ ev_stat *w);
void ev_stat_stat (EV_P_ ev_stat *w);
# endif
# if EV_IDLE_ENABLE
void ev_idle_start (EV_P_ ev_idle *w);
void ev_idle_stop (EV_P_ ev_idle *w);
# endif
#if EV_PREPARE_ENABLE
void ev_prepare_start (EV_P_ ev_prepare *w);
void ev_prepare_stop (EV_P_ ev_prepare *w);
#endif
#if EV_CHECK_ENABLE
void ev_check_start (EV_P_ ev_check *w);
void ev_check_stop (EV_P_ ev_check *w);
#endif
# if EV_FORK_ENABLE
void ev_fork_start (EV_P_ ev_fork *w);
void ev_fork_stop (EV_P_ ev_fork *w);
# endif
# if EV_CLEANUP_ENABLE
void ev_cleanup_start (EV_P_ ev_cleanup *w);
void ev_cleanup_stop (EV_P_ ev_cleanup *w);
# endif
# if EV_EMBED_ENABLE
/* only supported when loop to be embedded is in fact embeddable */
void ev_embed_start (EV_P_ ev_embed *w);
void ev_embed_stop (EV_P_ ev_embed *w);
void ev_embed_sweep (EV_P_ ev_embed *w);
# endif
# if EV_ASYNC_ENABLE
void ev_async_start (EV_P_ ev_async *w);
void ev_async_stop (EV_P_ ev_async *w);
void ev_async_send (EV_P_ ev_async *w);
# endif
#if EV_COMPAT3
#define EVLOOP_NONBLOCK EVRUN_NOWAIT
#define EVLOOP_ONESHOT EVRUN_ONCE
#define EVUNLOOP_CANCEL EVBREAK_CANCEL
#define EVUNLOOP_ONE EVBREAK_ONE
#define EVUNLOOP_ALL EVBREAK_ALL
#if EV_PROTOTYPES
EV_INLINE void ev_loop (EV_P_ int flags) { ev_run (EV_A_ flags); }
EV_INLINE void ev_unloop (EV_P_ int how ) { ev_break (EV_A_ how ); }
EV_INLINE void ev_default_destroy (void) { ev_loop_destroy (EV_DEFAULT); }
EV_INLINE void ev_default_fork (void) { ev_loop_fork (EV_DEFAULT); }
#if EV_FEATURE_API
EV_INLINE unsigned int ev_loop_count (EV_P) { return ev_iteration (EV_A); }
EV_INLINE unsigned int ev_loop_depth (EV_P) { return ev_depth (EV_A); }
EV_INLINE void ev_loop_verify (EV_P) { ev_verify (EV_A); }
#endif
#endif
#else
typedef struct ev_loop ev_loop;
#endif
#endif
EV_CPP(})
#endif

5243
src/rt/libuv/ev/ev.pod Normal file

File diff suppressed because it is too large Load diff

266
src/rt/libuv/ev/ev_epoll.c Normal file
View file

@ -0,0 +1,266 @@
/*
* libev epoll fd activity backend
*
* Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, 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 MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, 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 OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
/*
* general notes about epoll:
*
* a) epoll silently removes fds from the fd set. as nothing tells us
* that an fd has been removed otherwise, we have to continually
* "rearm" fds that we suspect *might* have changed (same
* problem with kqueue, but much less costly there).
* b) the fact that ADD != MOD creates a lot of extra syscalls due to a)
* and seems not to have any advantage.
* c) the inability to handle fork or file descriptors (think dup)
* limits the applicability over poll, so this is not a generic
* poll replacement.
* d) epoll doesn't work the same as select with many file descriptors
* (such as files). while not critical, no other advanced interface
* seems to share this (rather non-unixy) limitation.
* e) epoll claims to be embeddable, but in practise you never get
* a ready event for the epoll fd (broken: <=2.6.26, working: >=2.6.32).
* f) epoll_ctl returning EPERM means the fd is always ready.
*
* lots of "weird code" and complication handling in this file is due
* to these design problems with epoll, as we try very hard to avoid
* epoll_ctl syscalls for common usage patterns and handle the breakage
* ensuing from receiving events for closed and otherwise long gone
* file descriptors.
*/
#include <sys/epoll.h>
#define EV_EMASK_EPERM 0x80
static void
epoll_modify (EV_P_ int fd, int oev, int nev)
{
struct epoll_event ev;
unsigned char oldmask;
/*
* we handle EPOLL_CTL_DEL by ignoring it here
* on the assumption that the fd is gone anyways
* if that is wrong, we have to handle the spurious
* event in epoll_poll.
* if the fd is added again, we try to ADD it, and, if that
* fails, we assume it still has the same eventmask.
*/
if (!nev)
return;
oldmask = anfds [fd].emask;
anfds [fd].emask = nev;
/* store the generation counter in the upper 32 bits, the fd in the lower 32 bits */
ev.data.u64 = (uint64_t)(uint32_t)fd
| ((uint64_t)(uint32_t)++anfds [fd].egen << 32);
ev.events = (nev & EV_READ ? EPOLLIN : 0)
| (nev & EV_WRITE ? EPOLLOUT : 0);
if (expect_true (!epoll_ctl (backend_fd, oev && oldmask != nev ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, fd, &ev)))
return;
if (expect_true (errno == ENOENT))
{
/* if ENOENT then the fd went away, so try to do the right thing */
if (!nev)
goto dec_egen;
if (!epoll_ctl (backend_fd, EPOLL_CTL_ADD, fd, &ev))
return;
}
else if (expect_true (errno == EEXIST))
{
/* EEXIST means we ignored a previous DEL, but the fd is still active */
/* if the kernel mask is the same as the new mask, we assume it hasn't changed */
if (oldmask == nev)
goto dec_egen;
if (!epoll_ctl (backend_fd, EPOLL_CTL_MOD, fd, &ev))
return;
}
else if (expect_true (errno == EPERM))
{
/* EPERM means the fd is always ready, but epoll is too snobbish */
/* to handle it, unlike select or poll. */
anfds [fd].emask = EV_EMASK_EPERM;
/* add fd to epoll_eperms, if not already inside */
if (!(oldmask & EV_EMASK_EPERM))
{
array_needsize (int, epoll_eperms, epoll_epermmax, epoll_epermcnt + 1, EMPTY2);
epoll_eperms [epoll_epermcnt++] = fd;
}
return;
}
fd_kill (EV_A_ fd);
dec_egen:
/* we didn't successfully call epoll_ctl, so decrement the generation counter again */
--anfds [fd].egen;
}
static void
epoll_poll (EV_P_ ev_tstamp timeout)
{
int i;
int eventcnt;
/* epoll wait times cannot be larger than (LONG_MAX - 999UL) / HZ msecs, which is below */
/* the default libev max wait time, however. */
EV_RELEASE_CB;
eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax,
epoll_epermcnt ? 0 : ev_timeout_to_ms (timeout));
EV_ACQUIRE_CB;
if (expect_false (eventcnt < 0))
{
if (errno != EINTR)
ev_syserr ("(libev) epoll_wait");
return;
}
for (i = 0; i < eventcnt; ++i)
{
struct epoll_event *ev = epoll_events + i;
int fd = (uint32_t)ev->data.u64; /* mask out the lower 32 bits */
int want = anfds [fd].events;
int got = (ev->events & (EPOLLOUT | EPOLLERR | EPOLLHUP) ? EV_WRITE : 0)
| (ev->events & (EPOLLIN | EPOLLERR | EPOLLHUP) ? EV_READ : 0);
/* check for spurious notification */
/* we assume that fd is always in range, as we never shrink the anfds array */
if (expect_false ((uint32_t)anfds [fd].egen != (uint32_t)(ev->data.u64 >> 32)))
{
/* recreate kernel state */
postfork = 1;
continue;
}
if (expect_false (got & ~want))
{
anfds [fd].emask = want;
/* we received an event but are not interested in it, try mod or del */
/* I don't think we ever need MOD, but let's handle it anyways */
ev->events = (want & EV_READ ? EPOLLIN : 0)
| (want & EV_WRITE ? EPOLLOUT : 0);
/* pre-2.6.9 kernels require a non-null pointer with EPOLL_CTL_DEL, */
/* which is fortunately easy to do for us. */
if (epoll_ctl (backend_fd, want ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, fd, ev))
{
postfork = 1; /* an error occurred, recreate kernel state */
continue;
}
}
fd_event (EV_A_ fd, got);
}
/* if the receive array was full, increase its size */
if (expect_false (eventcnt == epoll_eventmax))
{
ev_free (epoll_events);
epoll_eventmax = array_nextsize (sizeof (struct epoll_event), epoll_eventmax, epoll_eventmax + 1);
epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);
}
/* now synthesize events for all fds where epoll fails, while select works... */
for (i = epoll_epermcnt; i--; )
{
int fd = epoll_eperms [i];
unsigned char events = anfds [fd].events & (EV_READ | EV_WRITE);
if (anfds [fd].emask & EV_EMASK_EPERM && events)
fd_event (EV_A_ fd, events);
else
epoll_eperms [i] = epoll_eperms [--epoll_epermcnt];
}
}
int inline_size
epoll_init (EV_P_ int flags)
{
#ifdef EPOLL_CLOEXEC
backend_fd = epoll_create1 (EPOLL_CLOEXEC);
if (backend_fd <= 0)
#endif
backend_fd = epoll_create (256);
if (backend_fd < 0)
return 0;
fcntl (backend_fd, F_SETFD, FD_CLOEXEC);
backend_fudge = 0.; /* kernel sources seem to indicate this to be zero */
backend_modify = epoll_modify;
backend_poll = epoll_poll;
epoll_eventmax = 64; /* initial number of events receivable per poll */
epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);
return EVBACKEND_EPOLL;
}
void inline_size
epoll_destroy (EV_P)
{
ev_free (epoll_events);
array_free (epoll_eperm, EMPTY);
}
void inline_size
epoll_fork (EV_P)
{
close (backend_fd);
while ((backend_fd = epoll_create (256)) < 0)
ev_syserr ("(libev) epoll_create");
fcntl (backend_fd, F_SETFD, FD_CLOEXEC);
fd_rearm_all (EV_A);
}

198
src/rt/libuv/ev/ev_kqueue.c Normal file
View file

@ -0,0 +1,198 @@
/*
* libev kqueue backend
*
* Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, 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 MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, 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 OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/event.h>
#include <string.h>
#include <errno.h>
void inline_speed
kqueue_change (EV_P_ int fd, int filter, int flags, int fflags)
{
++kqueue_changecnt;
array_needsize (struct kevent, kqueue_changes, kqueue_changemax, kqueue_changecnt, EMPTY2);
EV_SET (&kqueue_changes [kqueue_changecnt - 1], fd, filter, flags, fflags, 0, 0);
}
/* OS X at least needs this */
#ifndef EV_ENABLE
# define EV_ENABLE 0
#endif
#ifndef NOTE_EOF
# define NOTE_EOF 0
#endif
static void
kqueue_modify (EV_P_ int fd, int oev, int nev)
{
if (oev != nev)
{
if (oev & EV_READ)
kqueue_change (EV_A_ fd, EVFILT_READ , EV_DELETE, 0);
if (oev & EV_WRITE)
kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_DELETE, 0);
}
/* to detect close/reopen reliably, we have to re-add */
/* event requests even when oev == nev */
if (nev & EV_READ)
kqueue_change (EV_A_ fd, EVFILT_READ , EV_ADD | EV_ENABLE, NOTE_EOF);
if (nev & EV_WRITE)
kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, NOTE_EOF);
}
static void
kqueue_poll (EV_P_ ev_tstamp timeout)
{
int res, i;
struct timespec ts;
/* need to resize so there is enough space for errors */
if (kqueue_changecnt > kqueue_eventmax)
{
ev_free (kqueue_events);
kqueue_eventmax = array_nextsize (sizeof (struct kevent), kqueue_eventmax, kqueue_changecnt);
kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
}
EV_RELEASE_CB;
EV_TS_SET (ts, timeout);
res = kevent (backend_fd, kqueue_changes, kqueue_changecnt, kqueue_events, kqueue_eventmax, &ts);
EV_ACQUIRE_CB;
kqueue_changecnt = 0;
if (expect_false (res < 0))
{
if (errno != EINTR)
ev_syserr ("(libev) kevent");
return;
}
for (i = 0; i < res; ++i)
{
int fd = kqueue_events [i].ident;
if (expect_false (kqueue_events [i].flags & EV_ERROR))
{
int err = kqueue_events [i].data;
/* we are only interested in errors for fds that we are interested in :) */
if (anfds [fd].events)
{
if (err == ENOENT) /* resubmit changes on ENOENT */
kqueue_modify (EV_A_ fd, 0, anfds [fd].events);
else if (err == EBADF) /* on EBADF, we re-check the fd */
{
if (fd_valid (fd))
kqueue_modify (EV_A_ fd, 0, anfds [fd].events);
else
fd_kill (EV_A_ fd);
}
else /* on all other errors, we error out on the fd */
fd_kill (EV_A_ fd);
}
}
else
fd_event (
EV_A_
fd,
kqueue_events [i].filter == EVFILT_READ ? EV_READ
: kqueue_events [i].filter == EVFILT_WRITE ? EV_WRITE
: 0
);
}
if (expect_false (res == kqueue_eventmax))
{
ev_free (kqueue_events);
kqueue_eventmax = array_nextsize (sizeof (struct kevent), kqueue_eventmax, kqueue_eventmax + 1);
kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
}
}
int inline_size
kqueue_init (EV_P_ int flags)
{
/* Initialize the kernel queue */
if ((backend_fd = kqueue ()) < 0)
return 0;
fcntl (backend_fd, F_SETFD, FD_CLOEXEC); /* not sure if necessary, hopefully doesn't hurt */
backend_fudge = 0.;
backend_modify = kqueue_modify;
backend_poll = kqueue_poll;
kqueue_eventmax = 64; /* initial number of events receivable per poll */
kqueue_events = (struct kevent *)ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
kqueue_changes = 0;
kqueue_changemax = 0;
kqueue_changecnt = 0;
return EVBACKEND_KQUEUE;
}
void inline_size
kqueue_destroy (EV_P)
{
ev_free (kqueue_events);
ev_free (kqueue_changes);
}
void inline_size
kqueue_fork (EV_P)
{
close (backend_fd);
while ((backend_fd = kqueue ()) < 0)
ev_syserr ("(libev) kqueue");
fcntl (backend_fd, F_SETFD, FD_CLOEXEC);
/* re-register interest in fds */
fd_rearm_all (EV_A);
}

148
src/rt/libuv/ev/ev_poll.c Normal file
View file

@ -0,0 +1,148 @@
/*
* libev poll fd activity backend
*
* Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, 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 MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, 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 OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#include <poll.h>
void inline_size
pollidx_init (int *base, int count)
{
/* consider using memset (.., -1, ...), which is practically guaranteed
* to work on all systems implementing poll */
while (count--)
*base++ = -1;
}
static void
poll_modify (EV_P_ int fd, int oev, int nev)
{
int idx;
if (oev == nev)
return;
array_needsize (int, pollidxs, pollidxmax, fd + 1, pollidx_init);
idx = pollidxs [fd];
if (idx < 0) /* need to allocate a new pollfd */
{
pollidxs [fd] = idx = pollcnt++;
array_needsize (struct pollfd, polls, pollmax, pollcnt, EMPTY2);
polls [idx].fd = fd;
}
assert (polls [idx].fd == fd);
if (nev)
polls [idx].events =
(nev & EV_READ ? POLLIN : 0)
| (nev & EV_WRITE ? POLLOUT : 0);
else /* remove pollfd */
{
pollidxs [fd] = -1;
if (expect_true (idx < --pollcnt))
{
polls [idx] = polls [pollcnt];
pollidxs [polls [idx].fd] = idx;
}
}
}
static void
poll_poll (EV_P_ ev_tstamp timeout)
{
struct pollfd *p;
int res;
EV_RELEASE_CB;
res = poll (polls, pollcnt, ev_timeout_to_ms (timeout));
EV_ACQUIRE_CB;
if (expect_false (res < 0))
{
if (errno == EBADF)
fd_ebadf (EV_A);
else if (errno == ENOMEM && !syserr_cb)
fd_enomem (EV_A);
else if (errno != EINTR)
ev_syserr ("(libev) poll");
}
else
for (p = polls; res; ++p)
{
assert (("libev: poll() returned illegal result, broken BSD kernel?", p < polls + pollcnt));
if (expect_false (p->revents)) /* this expect is debatable */
{
--res;
if (expect_false (p->revents & POLLNVAL))
fd_kill (EV_A_ p->fd);
else
fd_event (
EV_A_
p->fd,
(p->revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)
| (p->revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0)
);
}
}
}
int inline_size
poll_init (EV_P_ int flags)
{
backend_fudge = 0.; /* posix says this is zero */
backend_modify = poll_modify;
backend_poll = poll_poll;
pollidxs = 0; pollidxmax = 0;
polls = 0; pollmax = 0; pollcnt = 0;
return EVBACKEND_POLL;
}
void inline_size
poll_destroy (EV_P)
{
ev_free (pollidxs);
ev_free (polls);
}

179
src/rt/libuv/ev/ev_port.c Normal file
View file

@ -0,0 +1,179 @@
/*
* libev solaris event port backend
*
* Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, 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 MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, 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 OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
/* useful reading:
*
* http://bugs.opensolaris.org/view_bug.do?bug_id=6268715 (random results)
* http://bugs.opensolaris.org/view_bug.do?bug_id=6455223 (just totally broken)
* http://bugs.opensolaris.org/view_bug.do?bug_id=6873782 (manpage ETIME)
* http://bugs.opensolaris.org/view_bug.do?bug_id=6874410 (implementation ETIME)
* http://www.mail-archive.com/networking-discuss@opensolaris.org/msg11898.html ETIME vs. nget
* http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/gen/event_port.c (libc)
* http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/fs/portfs/port.c#1325 (kernel)
*/
#include <sys/types.h>
#include <sys/time.h>
#include <poll.h>
#include <port.h>
#include <string.h>
#include <errno.h>
void inline_speed
port_associate_and_check (EV_P_ int fd, int ev)
{
if (0 >
port_associate (
backend_fd, PORT_SOURCE_FD, fd,
(ev & EV_READ ? POLLIN : 0)
| (ev & EV_WRITE ? POLLOUT : 0),
0
)
)
{
if (errno == EBADFD)
fd_kill (EV_A_ fd);
else
ev_syserr ("(libev) port_associate");
}
}
static void
port_modify (EV_P_ int fd, int oev, int nev)
{
/* we need to reassociate no matter what, as closes are
* once more silently being discarded.
*/
if (!nev)
{
if (oev)
port_dissociate (backend_fd, PORT_SOURCE_FD, fd);
}
else
port_associate_and_check (EV_A_ fd, nev);
}
static void
port_poll (EV_P_ ev_tstamp timeout)
{
int res, i;
struct timespec ts;
uint_t nget = 1;
/* we initialise this to something we will skip in the loop, as */
/* port_getn can return with nget unchanged, but no indication */
/* whether it was the original value or has been updated :/ */
port_events [0].portev_source = 0;
EV_RELEASE_CB;
EV_TS_SET (ts, timeout);
res = port_getn (backend_fd, port_events, port_eventmax, &nget, &ts);
EV_ACQUIRE_CB;
/* port_getn may or may not set nget on error */
/* so we rely on port_events [0].portev_source not being updated */
if (res == -1 && errno != ETIME && errno != EINTR)
ev_syserr ("(libev) port_getn (see http://bugs.opensolaris.org/view_bug.do?bug_id=6268715, try LIBEV_FLAGS=3 env variable)");
for (i = 0; i < nget; ++i)
{
if (port_events [i].portev_source == PORT_SOURCE_FD)
{
int fd = port_events [i].portev_object;
fd_event (
EV_A_
fd,
(port_events [i].portev_events & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)
| (port_events [i].portev_events & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0)
);
fd_change (EV_A_ fd, EV__IOFDSET);
}
}
if (expect_false (nget == port_eventmax))
{
ev_free (port_events);
port_eventmax = array_nextsize (sizeof (port_event_t), port_eventmax, port_eventmax + 1);
port_events = (port_event_t *)ev_malloc (sizeof (port_event_t) * port_eventmax);
}
}
int inline_size
port_init (EV_P_ int flags)
{
/* Initialize the kernel queue */
if ((backend_fd = port_create ()) < 0)
return 0;
assert (("libev: PORT_SOURCE_FD must not be zero", PORT_SOURCE_FD));
fcntl (backend_fd, F_SETFD, FD_CLOEXEC); /* not sure if necessary, hopefully doesn't hurt */
backend_fudge = 1e-3; /* needed to compensate for port_getn returning early */
backend_modify = port_modify;
backend_poll = port_poll;
port_eventmax = 64; /* initial number of events receivable per poll */
port_events = (port_event_t *)ev_malloc (sizeof (port_event_t) * port_eventmax);
return EVBACKEND_PORT;
}
void inline_size
port_destroy (EV_P)
{
ev_free (port_events);
}
void inline_size
port_fork (EV_P)
{
close (backend_fd);
while ((backend_fd = port_create ()) < 0)
ev_syserr ("(libev) port");
fcntl (backend_fd, F_SETFD, FD_CLOEXEC);
/* re-register interest in fds */
fd_rearm_all (EV_A);
}

310
src/rt/libuv/ev/ev_select.c Normal file
View file

@ -0,0 +1,310 @@
/*
* libev select fd activity backend
*
* Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, 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 MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, 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 OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#ifndef _WIN32
/* for unix systems */
# include <inttypes.h>
# ifndef __hpux
/* for REAL unix systems */
# include <sys/select.h>
# endif
#endif
#ifndef EV_SELECT_USE_FD_SET
# ifdef NFDBITS
# define EV_SELECT_USE_FD_SET 0
# else
# define EV_SELECT_USE_FD_SET 1
# endif
#endif
#if EV_SELECT_IS_WINSOCKET
# undef EV_SELECT_USE_FD_SET
# define EV_SELECT_USE_FD_SET 1
# undef NFDBITS
# define NFDBITS 0
#endif
#if !EV_SELECT_USE_FD_SET
# define NFDBYTES (NFDBITS / 8)
#endif
#include <string.h>
static void
select_modify (EV_P_ int fd, int oev, int nev)
{
if (oev == nev)
return;
{
#if EV_SELECT_USE_FD_SET
#if EV_SELECT_IS_WINSOCKET
SOCKET handle = anfds [fd].handle;
#else
int handle = fd;
#endif
assert (("libev: fd >= FD_SETSIZE passed to fd_set-based select backend", fd < FD_SETSIZE));
/* FD_SET is broken on windows (it adds the fd to a set twice or more,
* which eventually leads to overflows). Need to call it only on changes.
*/
#if EV_SELECT_IS_WINSOCKET
if ((oev ^ nev) & EV_READ)
#endif
if (nev & EV_READ)
FD_SET (handle, (fd_set *)vec_ri);
else
FD_CLR (handle, (fd_set *)vec_ri);
#if EV_SELECT_IS_WINSOCKET
if ((oev ^ nev) & EV_WRITE)
#endif
if (nev & EV_WRITE)
FD_SET (handle, (fd_set *)vec_wi);
else
FD_CLR (handle, (fd_set *)vec_wi);
#else
int word = fd / NFDBITS;
fd_mask mask = 1UL << (fd % NFDBITS);
if (expect_false (vec_max <= word))
{
int new_max = word + 1;
vec_ri = ev_realloc (vec_ri, new_max * NFDBYTES);
vec_ro = ev_realloc (vec_ro, new_max * NFDBYTES); /* could free/malloc */
vec_wi = ev_realloc (vec_wi, new_max * NFDBYTES);
vec_wo = ev_realloc (vec_wo, new_max * NFDBYTES); /* could free/malloc */
#ifdef _WIN32
vec_eo = ev_realloc (vec_eo, new_max * NFDBYTES); /* could free/malloc */
#endif
for (; vec_max < new_max; ++vec_max)
((fd_mask *)vec_ri) [vec_max] =
((fd_mask *)vec_wi) [vec_max] = 0;
}
((fd_mask *)vec_ri) [word] |= mask;
if (!(nev & EV_READ))
((fd_mask *)vec_ri) [word] &= ~mask;
((fd_mask *)vec_wi) [word] |= mask;
if (!(nev & EV_WRITE))
((fd_mask *)vec_wi) [word] &= ~mask;
#endif
}
}
static void
select_poll (EV_P_ ev_tstamp timeout)
{
struct timeval tv;
int res;
int fd_setsize;
EV_RELEASE_CB;
EV_TV_SET (tv, timeout);
#if EV_SELECT_USE_FD_SET
fd_setsize = sizeof (fd_set);
#else
fd_setsize = vec_max * NFDBYTES;
#endif
memcpy (vec_ro, vec_ri, fd_setsize);
memcpy (vec_wo, vec_wi, fd_setsize);
#ifdef _WIN32
/* pass in the write set as except set.
* the idea behind this is to work around a windows bug that causes
* errors to be reported as an exception and not by setting
* the writable bit. this is so uncontrollably lame.
*/
memcpy (vec_eo, vec_wi, fd_setsize);
res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, (fd_set *)vec_eo, &tv);
#elif EV_SELECT_USE_FD_SET
fd_setsize = anfdmax < FD_SETSIZE ? anfdmax : FD_SETSIZE;
res = select (fd_setsize, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);
#else
res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);
#endif
EV_ACQUIRE_CB;
if (expect_false (res < 0))
{
#if EV_SELECT_IS_WINSOCKET
errno = WSAGetLastError ();
#endif
#ifdef WSABASEERR
/* on windows, select returns incompatible error codes, fix this */
if (errno >= WSABASEERR && errno < WSABASEERR + 1000)
if (errno == WSAENOTSOCK)
errno = EBADF;
else
errno -= WSABASEERR;
#endif
#ifdef _WIN32
/* select on windows erroneously returns EINVAL when no fd sets have been
* provided (this is documented). what microsoft doesn't tell you that this bug
* exists even when the fd sets _are_ provided, so we have to check for this bug
* here and emulate by sleeping manually.
* we also get EINVAL when the timeout is invalid, but we ignore this case here
* and assume that EINVAL always means: you have to wait manually.
*/
if (errno == EINVAL)
{
ev_sleep (timeout);
return;
}
#endif
if (errno == EBADF)
fd_ebadf (EV_A);
else if (errno == ENOMEM && !syserr_cb)
fd_enomem (EV_A);
else if (errno != EINTR)
ev_syserr ("(libev) select");
return;
}
#if EV_SELECT_USE_FD_SET
{
int fd;
for (fd = 0; fd < anfdmax; ++fd)
if (anfds [fd].events)
{
int events = 0;
#if EV_SELECT_IS_WINSOCKET
SOCKET handle = anfds [fd].handle;
#else
int handle = fd;
#endif
if (FD_ISSET (handle, (fd_set *)vec_ro)) events |= EV_READ;
if (FD_ISSET (handle, (fd_set *)vec_wo)) events |= EV_WRITE;
#ifdef _WIN32
if (FD_ISSET (handle, (fd_set *)vec_eo)) events |= EV_WRITE;
#endif
if (expect_true (events))
fd_event (EV_A_ fd, events);
}
}
#else
{
int word, bit;
for (word = vec_max; word--; )
{
fd_mask word_r = ((fd_mask *)vec_ro) [word];
fd_mask word_w = ((fd_mask *)vec_wo) [word];
#ifdef _WIN32
word_w |= ((fd_mask *)vec_eo) [word];
#endif
if (word_r || word_w)
for (bit = NFDBITS; bit--; )
{
fd_mask mask = 1UL << bit;
int events = 0;
events |= word_r & mask ? EV_READ : 0;
events |= word_w & mask ? EV_WRITE : 0;
if (expect_true (events))
fd_event (EV_A_ word * NFDBITS + bit, events);
}
}
}
#endif
}
int inline_size
select_init (EV_P_ int flags)
{
backend_fudge = 0.; /* posix says this is zero */
backend_modify = select_modify;
backend_poll = select_poll;
#if EV_SELECT_USE_FD_SET
vec_ri = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_ri);
vec_ro = ev_malloc (sizeof (fd_set));
vec_wi = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_wi);
vec_wo = ev_malloc (sizeof (fd_set));
#ifdef _WIN32
vec_eo = ev_malloc (sizeof (fd_set));
#endif
#else
vec_max = 0;
vec_ri = 0;
vec_ro = 0;
vec_wi = 0;
vec_wo = 0;
#ifdef _WIN32
vec_eo = 0;
#endif
#endif
return EVBACKEND_SELECT;
}
void inline_size
select_destroy (EV_P)
{
ev_free (vec_ri);
ev_free (vec_ro);
ev_free (vec_wi);
ev_free (vec_wo);
#ifdef _WIN32
ev_free (vec_eo);
#endif
}

203
src/rt/libuv/ev/ev_vars.h Normal file
View file

@ -0,0 +1,203 @@
/*
* loop member variable declarations
*
* Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, 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 MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, 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 OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#define VARx(type,name) VAR(name, type name)
VARx(ev_tstamp, now_floor) /* last time we refreshed rt_time */
VARx(ev_tstamp, mn_now) /* monotonic clock "now" */
VARx(ev_tstamp, rtmn_diff) /* difference realtime - monotonic time */
VARx(ev_tstamp, io_blocktime)
VARx(ev_tstamp, timeout_blocktime)
VARx(int, backend)
VARx(int, activecnt) /* total number of active events ("refcount") */
VARx(EV_ATOMIC_T, loop_done) /* signal by ev_break */
VARx(int, backend_fd)
VARx(ev_tstamp, backend_fudge) /* assumed typical timer resolution */
VAR (backend_modify, void (*backend_modify)(EV_P_ int fd, int oev, int nev))
VAR (backend_poll , void (*backend_poll)(EV_P_ ev_tstamp timeout))
VARx(ANFD *, anfds)
VARx(int, anfdmax)
VAR (pendings, ANPENDING *pendings [NUMPRI])
VAR (pendingmax, int pendingmax [NUMPRI])
VAR (pendingcnt, int pendingcnt [NUMPRI])
VARx(ev_prepare, pending_w) /* dummy pending watcher */
/* for reverse feeding of events */
VARx(W *, rfeeds)
VARx(int, rfeedmax)
VARx(int, rfeedcnt)
#if EV_USE_EVENTFD || EV_GENWRAP
VARx(int, evfd)
#endif
VAR (evpipe, int evpipe [2])
VARx(ev_io, pipe_w)
#if !defined(_WIN32) || EV_GENWRAP
VARx(pid_t, curpid)
#endif
VARx(char, postfork) /* true if we need to recreate kernel state after fork */
#if EV_USE_SELECT || EV_GENWRAP
VARx(void *, vec_ri)
VARx(void *, vec_ro)
VARx(void *, vec_wi)
VARx(void *, vec_wo)
#if defined(_WIN32) || EV_GENWRAP
VARx(void *, vec_eo)
#endif
VARx(int, vec_max)
#endif
#if EV_USE_POLL || EV_GENWRAP
VARx(struct pollfd *, polls)
VARx(int, pollmax)
VARx(int, pollcnt)
VARx(int *, pollidxs) /* maps fds into structure indices */
VARx(int, pollidxmax)
#endif
#if EV_USE_EPOLL || EV_GENWRAP
VARx(struct epoll_event *, epoll_events)
VARx(int, epoll_eventmax)
VARx(int *, epoll_eperms)
VARx(int, epoll_epermcnt)
VARx(int, epoll_epermmax)
#endif
#if EV_USE_KQUEUE || EV_GENWRAP
VARx(struct kevent *, kqueue_changes)
VARx(int, kqueue_changemax)
VARx(int, kqueue_changecnt)
VARx(struct kevent *, kqueue_events)
VARx(int, kqueue_eventmax)
#endif
#if EV_USE_PORT || EV_GENWRAP
VARx(struct port_event *, port_events)
VARx(int, port_eventmax)
#endif
#if EV_USE_IOCP || EV_GENWRAP
VARx(HANDLE, iocp)
#endif
VARx(int *, fdchanges)
VARx(int, fdchangemax)
VARx(int, fdchangecnt)
VARx(ANHE *, timers)
VARx(int, timermax)
VARx(int, timercnt)
#if EV_PERIODIC_ENABLE || EV_GENWRAP
VARx(ANHE *, periodics)
VARx(int, periodicmax)
VARx(int, periodiccnt)
#endif
#if EV_IDLE_ENABLE || EV_GENWRAP
VAR (idles, ev_idle **idles [NUMPRI])
VAR (idlemax, int idlemax [NUMPRI])
VAR (idlecnt, int idlecnt [NUMPRI])
#endif
VARx(int, idleall) /* total number */
VARx(struct ev_prepare **, prepares)
VARx(int, preparemax)
VARx(int, preparecnt)
VARx(struct ev_check **, checks)
VARx(int, checkmax)
VARx(int, checkcnt)
#if EV_FORK_ENABLE || EV_GENWRAP
VARx(struct ev_fork **, forks)
VARx(int, forkmax)
VARx(int, forkcnt)
#endif
#if EV_CLEANUP_ENABLE || EV_GENWRAP
VARx(struct ev_cleanup **, cleanups)
VARx(int, cleanupmax)
VARx(int, cleanupcnt)
#endif
#if EV_ASYNC_ENABLE || EV_GENWRAP
VARx(EV_ATOMIC_T, async_pending)
VARx(struct ev_async **, asyncs)
VARx(int, asyncmax)
VARx(int, asynccnt)
#endif
#if EV_USE_INOTIFY || EV_GENWRAP
VARx(int, fs_fd)
VARx(ev_io, fs_w)
VARx(char, fs_2625) /* whether we are running in linux 2.6.25 or newer */
VAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE])
#endif
VARx(EV_ATOMIC_T, sig_pending)
VARx(int, nosigmask)
#if EV_USE_SIGNALFD || EV_GENWRAP
VARx(int, sigfd)
VARx(ev_io, sigfd_w)
VARx(sigset_t, sigfd_set)
#endif
VARx(unsigned int, origflags) /* original loop flags */
#if EV_FEATURE_API || EV_GENWRAP
VARx(unsigned int, loop_count) /* total number of loop iterations/blocks */
VARx(unsigned int, loop_depth) /* #ev_run enters - #ev_run leaves */
VARx(void *, userdata)
VAR (release_cb, void (*release_cb)(EV_P))
VAR (acquire_cb, void (*acquire_cb)(EV_P))
VAR (invoke_cb , void (*invoke_cb) (EV_P))
#endif
#undef VARx

153
src/rt/libuv/ev/ev_win32.c Normal file
View file

@ -0,0 +1,153 @@
/*
* libev win32 compatibility cruft (_not_ a backend)
*
* Copyright (c) 2007,2008,2009 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, 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 MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, 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 OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#ifdef _WIN32
/* timeb.h is actually xsi legacy functionality */
#include <sys/timeb.h>
/* note: the comment below could not be substantiated, but what would I care */
/* MSDN says this is required to handle SIGFPE */
/* my wild guess would be that using something floating-pointy is required */
/* for the crt to do something about it */
volatile double SIGFPE_REQ = 0.0f;
/* oh, the humanity! */
static int
ev_pipe (int filedes [2])
{
struct sockaddr_in addr = { 0 };
int addr_size = sizeof (addr);
struct sockaddr_in adr2;
int adr2_size = sizeof (adr2);
SOCKET listener;
SOCKET sock [2] = { -1, -1 };
if ((listener = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
return -1;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
addr.sin_port = 0;
if (bind (listener, (struct sockaddr *)&addr, addr_size))
goto fail;
if (getsockname (listener, (struct sockaddr *)&addr, &addr_size))
goto fail;
if (listen (listener, 1))
goto fail;
if ((sock [0] = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
goto fail;
if (connect (sock [0], (struct sockaddr *)&addr, addr_size))
goto fail;
if ((sock [1] = accept (listener, 0, 0)) < 0)
goto fail;
/* windows vista returns fantasy port numbers for sockets:
* example for two interconnected tcp sockets:
*
* (Socket::unpack_sockaddr_in getsockname $sock0)[0] == 53364
* (Socket::unpack_sockaddr_in getpeername $sock0)[0] == 53363
* (Socket::unpack_sockaddr_in getsockname $sock1)[0] == 53363
* (Socket::unpack_sockaddr_in getpeername $sock1)[0] == 53365
*
* wow! tridirectional sockets!
*
* this way of checking ports seems to work:
*/
if (getpeername (sock [0], (struct sockaddr *)&addr, &addr_size))
goto fail;
if (getsockname (sock [1], (struct sockaddr *)&adr2, &adr2_size))
goto fail;
errno = WSAEINVAL;
if (addr_size != adr2_size
|| addr.sin_addr.s_addr != adr2.sin_addr.s_addr /* just to be sure, I mean, it's windows */
|| addr.sin_port != adr2.sin_port)
goto fail;
closesocket (listener);
#if EV_SELECT_IS_WINSOCKET
filedes [0] = EV_WIN32_HANDLE_TO_FD (sock [0]);
filedes [1] = EV_WIN32_HANDLE_TO_FD (sock [1]);
#else
/* when select isn't winsocket, we also expect socket, connect, accept etc.
* to work on fds */
filedes [0] = sock [0];
filedes [1] = sock [1];
#endif
return 0;
fail:
closesocket (listener);
if (sock [0] != INVALID_SOCKET) closesocket (sock [0]);
if (sock [1] != INVALID_SOCKET) closesocket (sock [1]);
return -1;
}
#undef pipe
#define pipe(filedes) ev_pipe (filedes)
#define EV_HAVE_EV_TIME 1
ev_tstamp
ev_time (void)
{
FILETIME ft;
ULARGE_INTEGER ui;
GetSystemTimeAsFileTime (&ft);
ui.u.LowPart = ft.dwLowDateTime;
ui.u.HighPart = ft.dwHighDateTime;
/* msvc cannot convert ulonglong to double... yes, it is that sucky */
return (LONGLONG)(ui.QuadPart - 116444736000000000) * 1e-7;
}
#endif

196
src/rt/libuv/ev/ev_wrap.h Normal file
View file

@ -0,0 +1,196 @@
/* DO NOT EDIT, automatically generated by update_ev_wrap */
#ifndef EV_WRAP_H
#define EV_WRAP_H
#define now_floor ((loop)->now_floor)
#define mn_now ((loop)->mn_now)
#define rtmn_diff ((loop)->rtmn_diff)
#define io_blocktime ((loop)->io_blocktime)
#define timeout_blocktime ((loop)->timeout_blocktime)
#define backend ((loop)->backend)
#define activecnt ((loop)->activecnt)
#define loop_done ((loop)->loop_done)
#define backend_fd ((loop)->backend_fd)
#define backend_fudge ((loop)->backend_fudge)
#define backend_modify ((loop)->backend_modify)
#define backend_poll ((loop)->backend_poll)
#define anfds ((loop)->anfds)
#define anfdmax ((loop)->anfdmax)
#define pendings ((loop)->pendings)
#define pendingmax ((loop)->pendingmax)
#define pendingcnt ((loop)->pendingcnt)
#define pending_w ((loop)->pending_w)
#define rfeeds ((loop)->rfeeds)
#define rfeedmax ((loop)->rfeedmax)
#define rfeedcnt ((loop)->rfeedcnt)
#define evfd ((loop)->evfd)
#define evpipe ((loop)->evpipe)
#define pipe_w ((loop)->pipe_w)
#define curpid ((loop)->curpid)
#define postfork ((loop)->postfork)
#define vec_ri ((loop)->vec_ri)
#define vec_ro ((loop)->vec_ro)
#define vec_wi ((loop)->vec_wi)
#define vec_wo ((loop)->vec_wo)
#define vec_eo ((loop)->vec_eo)
#define vec_max ((loop)->vec_max)
#define polls ((loop)->polls)
#define pollmax ((loop)->pollmax)
#define pollcnt ((loop)->pollcnt)
#define pollidxs ((loop)->pollidxs)
#define pollidxmax ((loop)->pollidxmax)
#define epoll_events ((loop)->epoll_events)
#define epoll_eventmax ((loop)->epoll_eventmax)
#define epoll_eperms ((loop)->epoll_eperms)
#define epoll_epermcnt ((loop)->epoll_epermcnt)
#define epoll_epermmax ((loop)->epoll_epermmax)
#define kqueue_changes ((loop)->kqueue_changes)
#define kqueue_changemax ((loop)->kqueue_changemax)
#define kqueue_changecnt ((loop)->kqueue_changecnt)
#define kqueue_events ((loop)->kqueue_events)
#define kqueue_eventmax ((loop)->kqueue_eventmax)
#define port_events ((loop)->port_events)
#define port_eventmax ((loop)->port_eventmax)
#define iocp ((loop)->iocp)
#define fdchanges ((loop)->fdchanges)
#define fdchangemax ((loop)->fdchangemax)
#define fdchangecnt ((loop)->fdchangecnt)
#define timers ((loop)->timers)
#define timermax ((loop)->timermax)
#define timercnt ((loop)->timercnt)
#define periodics ((loop)->periodics)
#define periodicmax ((loop)->periodicmax)
#define periodiccnt ((loop)->periodiccnt)
#define idles ((loop)->idles)
#define idlemax ((loop)->idlemax)
#define idlecnt ((loop)->idlecnt)
#define idleall ((loop)->idleall)
#define prepares ((loop)->prepares)
#define preparemax ((loop)->preparemax)
#define preparecnt ((loop)->preparecnt)
#define checks ((loop)->checks)
#define checkmax ((loop)->checkmax)
#define checkcnt ((loop)->checkcnt)
#define forks ((loop)->forks)
#define forkmax ((loop)->forkmax)
#define forkcnt ((loop)->forkcnt)
#define cleanups ((loop)->cleanups)
#define cleanupmax ((loop)->cleanupmax)
#define cleanupcnt ((loop)->cleanupcnt)
#define async_pending ((loop)->async_pending)
#define asyncs ((loop)->asyncs)
#define asyncmax ((loop)->asyncmax)
#define asynccnt ((loop)->asynccnt)
#define fs_fd ((loop)->fs_fd)
#define fs_w ((loop)->fs_w)
#define fs_2625 ((loop)->fs_2625)
#define fs_hash ((loop)->fs_hash)
#define sig_pending ((loop)->sig_pending)
#define nosigmask ((loop)->nosigmask)
#define sigfd ((loop)->sigfd)
#define sigfd_w ((loop)->sigfd_w)
#define sigfd_set ((loop)->sigfd_set)
#define origflags ((loop)->origflags)
#define loop_count ((loop)->loop_count)
#define loop_depth ((loop)->loop_depth)
#define userdata ((loop)->userdata)
#define release_cb ((loop)->release_cb)
#define acquire_cb ((loop)->acquire_cb)
#define invoke_cb ((loop)->invoke_cb)
#else
#undef EV_WRAP_H
#undef now_floor
#undef mn_now
#undef rtmn_diff
#undef io_blocktime
#undef timeout_blocktime
#undef backend
#undef activecnt
#undef loop_done
#undef backend_fd
#undef backend_fudge
#undef backend_modify
#undef backend_poll
#undef anfds
#undef anfdmax
#undef pendings
#undef pendingmax
#undef pendingcnt
#undef pending_w
#undef rfeeds
#undef rfeedmax
#undef rfeedcnt
#undef evfd
#undef evpipe
#undef pipe_w
#undef curpid
#undef postfork
#undef vec_ri
#undef vec_ro
#undef vec_wi
#undef vec_wo
#undef vec_eo
#undef vec_max
#undef polls
#undef pollmax
#undef pollcnt
#undef pollidxs
#undef pollidxmax
#undef epoll_events
#undef epoll_eventmax
#undef epoll_eperms
#undef epoll_epermcnt
#undef epoll_epermmax
#undef kqueue_changes
#undef kqueue_changemax
#undef kqueue_changecnt
#undef kqueue_events
#undef kqueue_eventmax
#undef port_events
#undef port_eventmax
#undef iocp
#undef fdchanges
#undef fdchangemax
#undef fdchangecnt
#undef timers
#undef timermax
#undef timercnt
#undef periodics
#undef periodicmax
#undef periodiccnt
#undef idles
#undef idlemax
#undef idlecnt
#undef idleall
#undef prepares
#undef preparemax
#undef preparecnt
#undef checks
#undef checkmax
#undef checkcnt
#undef forks
#undef forkmax
#undef forkcnt
#undef cleanups
#undef cleanupmax
#undef cleanupcnt
#undef async_pending
#undef asyncs
#undef asyncmax
#undef asynccnt
#undef fs_fd
#undef fs_w
#undef fs_2625
#undef fs_hash
#undef sig_pending
#undef nosigmask
#undef sigfd
#undef sigfd_w
#undef sigfd_set
#undef origflags
#undef loop_count
#undef loop_depth
#undef userdata
#undef release_cb
#undef acquire_cb
#undef invoke_cb
#endif

402
src/rt/libuv/ev/event.c Normal file
View file

@ -0,0 +1,402 @@
/*
* libevent compatibility layer
*
* Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, 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 MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, 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 OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#include <stddef.h>
#include <stdlib.h>
#include <assert.h>
#ifdef EV_EVENT_H
# include EV_EVENT_H
#else
# include "event.h"
#endif
#if EV_MULTIPLICITY
# define dLOOPev struct ev_loop *loop = (struct ev_loop *)ev->ev_base
# define dLOOPbase struct ev_loop *loop = (struct ev_loop *)base
#else
# define dLOOPev
# define dLOOPbase
#endif
/* never accessed, will always be cast from/to ev_loop */
struct event_base
{
int dummy;
};
static struct event_base *ev_x_cur;
static ev_tstamp
ev_tv_get (struct timeval *tv)
{
if (tv)
{
ev_tstamp after = tv->tv_sec + tv->tv_usec * 1e-6;
return after ? after : 1e-6;
}
else
return -1.;
}
#define EVENT_STRINGIFY(s) # s
#define EVENT_VERSION(a,b) EVENT_STRINGIFY (a) "." EVENT_STRINGIFY (b)
const char *event_get_version (void)
{
/* returns ABI, not API or library, version */
return EVENT_VERSION (EV_VERSION_MAJOR, EV_VERSION_MINOR);
}
const char *event_get_method (void)
{
return "libev";
}
void *event_init (void)
{
#if EV_MULTIPLICITY
if (ev_x_cur)
ev_x_cur = (struct event_base *)ev_loop_new (EVFLAG_AUTO);
else
ev_x_cur = (struct event_base *)ev_default_loop (EVFLAG_AUTO);
#else
assert (("libev: multiple event bases not supported when not compiled with EV_MULTIPLICITY", !ev_x_cur));
ev_x_cur = (struct event_base *)(long)ev_default_loop (EVFLAG_AUTO);
#endif
return ev_x_cur;
}
void event_base_free (struct event_base *base)
{
dLOOPbase;
#if EV_MULTIPLICITY
if (!ev_is_default_loop (loop))
ev_loop_destroy (loop);
#endif
}
int event_dispatch (void)
{
return event_base_dispatch (ev_x_cur);
}
#ifdef EV_STANDALONE
void event_set_log_callback (event_log_cb cb)
{
/* nop */
}
#endif
int event_loop (int flags)
{
return event_base_loop (ev_x_cur, flags);
}
int event_loopexit (struct timeval *tv)
{
return event_base_loopexit (ev_x_cur, tv);
}
static void
ev_x_cb (struct event *ev, int revents)
{
revents &= EV_READ | EV_WRITE | EV_TIMER | EV_SIGNAL;
ev->ev_res = revents;
ev->ev_callback (ev->ev_fd, (short)revents, ev->ev_arg);
}
static void
ev_x_cb_sig (EV_P_ struct ev_signal *w, int revents)
{
struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.sig));
if (revents & EV_ERROR)
event_del (ev);
ev_x_cb (ev, revents);
}
static void
ev_x_cb_io (EV_P_ struct ev_io *w, int revents)
{
struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.io));
if ((revents & EV_ERROR) || !(ev->ev_events & EV_PERSIST))
event_del (ev);
ev_x_cb (ev, revents);
}
static void
ev_x_cb_to (EV_P_ struct ev_timer *w, int revents)
{
struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, to));
event_del (ev);
ev_x_cb (ev, revents);
}
void event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg)
{
if (events & EV_SIGNAL)
ev_init (&ev->iosig.sig, ev_x_cb_sig);
else
ev_init (&ev->iosig.io, ev_x_cb_io);
ev_init (&ev->to, ev_x_cb_to);
ev->ev_base = ev_x_cur; /* not threadsafe, but it's how libevent works */
ev->ev_fd = fd;
ev->ev_events = events;
ev->ev_pri = 0;
ev->ev_callback = cb;
ev->ev_arg = arg;
ev->ev_res = 0;
ev->ev_flags = EVLIST_INIT;
}
int event_once (int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv)
{
return event_base_once (ev_x_cur, fd, events, cb, arg, tv);
}
int event_add (struct event *ev, struct timeval *tv)
{
dLOOPev;
if (ev->ev_events & EV_SIGNAL)
{
if (!ev_is_active (&ev->iosig.sig))
{
ev_signal_set (&ev->iosig.sig, ev->ev_fd);
ev_signal_start (EV_A_ &ev->iosig.sig);
ev->ev_flags |= EVLIST_SIGNAL;
}
}
else if (ev->ev_events & (EV_READ | EV_WRITE))
{
if (!ev_is_active (&ev->iosig.io))
{
ev_io_set (&ev->iosig.io, ev->ev_fd, ev->ev_events & (EV_READ | EV_WRITE));
ev_io_start (EV_A_ &ev->iosig.io);
ev->ev_flags |= EVLIST_INSERTED;
}
}
if (tv)
{
ev->to.repeat = ev_tv_get (tv);
ev_timer_again (EV_A_ &ev->to);
ev->ev_flags |= EVLIST_TIMEOUT;
}
else
{
ev_timer_stop (EV_A_ &ev->to);
ev->ev_flags &= ~EVLIST_TIMEOUT;
}
ev->ev_flags |= EVLIST_ACTIVE;
return 0;
}
int event_del (struct event *ev)
{
dLOOPev;
if (ev->ev_events & EV_SIGNAL)
ev_signal_stop (EV_A_ &ev->iosig.sig);
else if (ev->ev_events & (EV_READ | EV_WRITE))
ev_io_stop (EV_A_ &ev->iosig.io);
if (ev_is_active (&ev->to))
ev_timer_stop (EV_A_ &ev->to);
ev->ev_flags = EVLIST_INIT;
return 0;
}
void event_active (struct event *ev, int res, short ncalls)
{
dLOOPev;
if (res & EV_TIMEOUT)
ev_feed_event (EV_A_ &ev->to, res & EV_TIMEOUT);
if (res & EV_SIGNAL)
ev_feed_event (EV_A_ &ev->iosig.sig, res & EV_SIGNAL);
if (res & (EV_READ | EV_WRITE))
ev_feed_event (EV_A_ &ev->iosig.io, res & (EV_READ | EV_WRITE));
}
int event_pending (struct event *ev, short events, struct timeval *tv)
{
short revents = 0;
dLOOPev;
if (ev->ev_events & EV_SIGNAL)
{
/* sig */
if (ev_is_active (&ev->iosig.sig) || ev_is_pending (&ev->iosig.sig))
revents |= EV_SIGNAL;
}
else if (ev->ev_events & (EV_READ | EV_WRITE))
{
/* io */
if (ev_is_active (&ev->iosig.io) || ev_is_pending (&ev->iosig.io))
revents |= ev->ev_events & (EV_READ | EV_WRITE);
}
if (ev->ev_events & EV_TIMEOUT || ev_is_active (&ev->to) || ev_is_pending (&ev->to))
{
revents |= EV_TIMEOUT;
if (tv)
{
ev_tstamp at = ev_now (EV_A);
tv->tv_sec = (long)at;
tv->tv_usec = (long)((at - (ev_tstamp)tv->tv_sec) * 1e6);
}
}
return events & revents;
}
int event_priority_init (int npri)
{
return event_base_priority_init (ev_x_cur, npri);
}
int event_priority_set (struct event *ev, int pri)
{
ev->ev_pri = pri;
return 0;
}
int event_base_set (struct event_base *base, struct event *ev)
{
ev->ev_base = base;
return 0;
}
int event_base_loop (struct event_base *base, int flags)
{
dLOOPbase;
ev_run (EV_A_ flags);
return 0;
}
int event_base_dispatch (struct event_base *base)
{
return event_base_loop (base, 0);
}
static void
ev_x_loopexit_cb (int revents, void *base)
{
dLOOPbase;
ev_break (EV_A_ EVBREAK_ONE);
}
int event_base_loopexit (struct event_base *base, struct timeval *tv)
{
ev_tstamp after = ev_tv_get (tv);
dLOOPbase;
ev_once (EV_A_ -1, 0, after >= 0. ? after : 0., ev_x_loopexit_cb, (void *)base);
return 0;
}
struct ev_x_once
{
int fd;
void (*cb)(int, short, void *);
void *arg;
};
static void
ev_x_once_cb (int revents, void *arg)
{
struct ev_x_once *once = (struct ev_x_once *)arg;
once->cb (once->fd, (short)revents, once->arg);
free (once);
}
int event_base_once (struct event_base *base, int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv)
{
struct ev_x_once *once = (struct ev_x_once *)malloc (sizeof (struct ev_x_once));
dLOOPbase;
if (!once)
return -1;
once->fd = fd;
once->cb = cb;
once->arg = arg;
ev_once (EV_A_ fd, events & (EV_READ | EV_WRITE), ev_tv_get (tv), ev_x_once_cb, (void *)once);
return 0;
}
int event_base_priority_init (struct event_base *base, int npri)
{
/*dLOOPbase;*/
return 0;
}

170
src/rt/libuv/ev/event.h Normal file
View file

@ -0,0 +1,170 @@
/*
* libevent compatibility header, only core events supported
*
* Copyright (c) 2007,2008,2010 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, 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 MER-
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
* CIAL, 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 OTH-
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License ("GPL") version 2 or any later version,
* in which case the provisions of the GPL are applicable instead of
* the above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the BSD license, indicate your decision
* by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file under
* either the BSD or the GPL.
*/
#ifndef EVENT_H_
#define EVENT_H_
#ifdef EV_H
# include EV_H
#else
# include "ev.h"
#endif
#ifndef EVLOOP_NONBLOCK
# define EVLOOP_NONBLOCK EVRUN_NOWAIT
#endif
#ifndef EVLOOP_ONESHOT
# define EVLOOP_ONESHOT EVRUN_ONCE
#endif
#ifndef EV_TIMEOUT
# define EV_TIMEOUT EV_TIMER
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* we need sys/time.h for struct timeval only */
#if !defined (WIN32) || defined (__MINGW32__)
# include <time.h> /* mingw seems to need this, for whatever reason */
# include <sys/time.h>
#endif
struct event_base;
#define EVLIST_TIMEOUT 0x01
#define EVLIST_INSERTED 0x02
#define EVLIST_SIGNAL 0x04
#define EVLIST_ACTIVE 0x08
#define EVLIST_INTERNAL 0x10
#define EVLIST_INIT 0x80
struct event
{
/* libev watchers we map onto */
union {
struct ev_io io;
struct ev_signal sig;
} iosig;
struct ev_timer to;
/* compatibility slots */
struct event_base *ev_base;
void (*ev_callback)(int, short, void *arg);
void *ev_arg;
int ev_fd;
int ev_pri;
int ev_res;
int ev_flags;
short ev_events;
};
#define EV_READ EV_READ
#define EV_WRITE EV_WRITE
#define EV_PERSIST 0x10
#define EVENT_SIGNAL(ev) ((int) (ev)->ev_fd)
#define EVENT_FD(ev) ((int) (ev)->ev_fd)
#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
#define evtimer_add(ev,tv) event_add (ev, tv)
#define evtimer_set(ev,cb,data) event_set (ev, -1, 0, cb, data)
#define evtimer_del(ev) event_del (ev)
#define evtimer_pending(ev,tv) event_pending (ev, EV_TIMEOUT, tv)
#define evtimer_initialized(ev) event_initialized (ev)
#define timeout_add(ev,tv) evtimer_add (ev, tv)
#define timeout_set(ev,cb,data) evtimer_set (ev, cb, data)
#define timeout_del(ev) evtimer_del (ev)
#define timeout_pending(ev,tv) evtimer_pending (ev, tv)
#define timeout_initialized(ev) evtimer_initialized (ev)
#define signal_add(ev,tv) event_add (ev, tv)
#define signal_set(ev,sig,cb,data) event_set (ev, sig, EV_SIGNAL | EV_PERSIST, cb, data)
#define signal_del(ev) event_del (ev)
#define signal_pending(ev,tv) event_pending (ev, EV_SIGNAL, tv)
#define signal_initialized(ev) event_initialized (ev)
const char *event_get_version (void);
const char *event_get_method (void);
void *event_init (void);
void event_base_free (struct event_base *base);
#define EVLOOP_ONCE EVLOOP_ONESHOT
int event_loop (int);
int event_loopexit (struct timeval *tv);
int event_dispatch (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);
void event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg);
int event_once (int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv);
int event_add (struct event *ev, struct timeval *tv);
int event_del (struct event *ev);
void event_active (struct event *ev, int res, short ncalls); /* ncalls is being ignored */
int event_pending (struct event *ev, short, struct timeval *tv);
int event_priority_init (int npri);
int event_priority_set (struct event *ev, int pri);
int event_base_set (struct event_base *base, struct event *ev);
int event_base_loop (struct event_base *base, int);
int event_base_loopexit (struct event_base *base, struct timeval *tv);
int event_base_dispatch (struct event_base *base);
int event_base_once (struct event_base *base, int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv);
int event_base_priority_init (struct event_base *base, int fd);
/* next line is different in the libevent+libev version */
/*libevent-include*/
#ifdef __cplusplus
}
#endif
#endif

294
src/rt/libuv/ev/install-sh Executable file
View file

@ -0,0 +1,294 @@
#!/bin/sh
#
# install - install a program, script, or datafile
#
# 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=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd=$cpprog
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd=$stripprog
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "$0: no input file specified" >&2
exit 1
else
:
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -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 [ -f "$src" ] || [ -d "$src" ]
then
:
else
echo "$0: $src does not exist" >&2
exit 1
fi
if [ x"$dst" = x ]
then
echo "$0: no destination specified" >&2
exit 1
else
:
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d "$dst" ]
then
dst=$dst/`basename "$src"`
else
:
fi
fi
## this sed command emulates the dirname command
dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -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 [ $# -ne 0 ] ; do
pathcomp=$pathcomp$1
shift
if [ ! -d "$pathcomp" ] ;
then
$mkdirprog "$pathcomp"
else
:
fi
pathcomp=$pathcomp/
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd "$dst" &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename "$dst"`
else
dstfile=`basename "$dst" $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename "$dst"`
else
:
fi
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up 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.
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
# 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 [ -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
}

39
src/rt/libuv/ev/libev.m4 Normal file
View file

@ -0,0 +1,39 @@
dnl this file is part of libev, do not make local modifications
dnl http://software.schmorp.de/pkg/libev
dnl libev support
AC_CHECK_HEADERS(sys/inotify.h sys/epoll.h sys/event.h port.h poll.h sys/select.h sys/eventfd.h sys/signalfd.h)
AC_CHECK_FUNCS(inotify_init epoll_ctl kqueue port_create poll select eventfd signalfd)
AC_CHECK_FUNCS(clock_gettime, [], [
dnl on linux, try syscall wrapper first
if test $(uname) = Linux; then
AC_MSG_CHECKING(for clock_gettime syscall)
AC_LINK_IFELSE([AC_LANG_PROGRAM(
[#include <unistd.h>
#include <sys/syscall.h>
#include <time.h>],
[struct timespec ts; int status = syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts)])],
[ac_have_clock_syscall=1
AC_DEFINE(HAVE_CLOCK_SYSCALL, 1, "use syscall interface for clock_gettime")
AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(no)])
fi
if test -z "$LIBEV_M4_AVOID_LIBRT" && test -z "$ac_have_clock_syscall"; then
AC_CHECK_LIB(rt, clock_gettime)
unset ac_cv_func_clock_gettime
AC_CHECK_FUNCS(clock_gettime)
fi
])
AC_CHECK_FUNCS(nanosleep, [], [
if test -z "$LIBEV_M4_AVOID_LIBRT"; then
AC_CHECK_LIB(rt, nanosleep)
unset ac_cv_func_nanosleep
AC_CHECK_FUNCS(nanosleep)
fi
])
AC_CHECK_LIB(m, ceil)

8413
src/rt/libuv/ev/ltmain.sh Executable file

File diff suppressed because it is too large Load diff

336
src/rt/libuv/ev/missing Executable file
View file

@ -0,0 +1,336 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
# 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
case "$1" in
--run)
# Try to run requested program, and just exit if it succeeds.
run=
shift
"$@" && exit 0
;;
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]"
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing 0.4 - 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 missing on your system. 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 missing on your system. 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 missing on your system. 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 missing on your system. 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, and you do not seem to have it handy on your
system. 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' is missing on your system. 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 missing on your system. 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 missing on your system. 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 missing on your system. 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 you do not seem to have it handy on your
system. 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

111
src/rt/libuv/ev/mkinstalldirs Executable file
View file

@ -0,0 +1,111 @@
#! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-05-16
# Public domain
errstatus=0
dirmode=""
usage="\
Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
# process command line arguments
while test $# -gt 0 ; do
case $1 in
-h | --help | --h*) # -h for help
echo "$usage" 1>&2
exit 0
;;
-m) # -m PERM arg
shift
test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
dirmode=$1
shift
;;
--) # stop option processing
shift
break
;;
-*) # unknown option
echo "$usage" 1>&2
exit 1
;;
*) # first non-opt arg
break
;;
esac
done
for file
do
if test -d "$file"; then
shift
else
break
fi
done
case $# in
0) exit 0 ;;
esac
case $dirmode in
'')
if mkdir -p -- . 2>/dev/null; then
echo "mkdir -p -- $*"
exec mkdir -p -- "$@"
fi
;;
*)
if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
echo "mkdir -m $dirmode -p -- $*"
exec mkdir -m "$dirmode" -p -- "$@"
fi
;;
esac
for file
do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d
do
pathcomp="$pathcomp$d"
case $pathcomp in
-*) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp"
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
else
if test ! -z "$dirmode"; then
echo "chmod $dirmode $pathcomp"
lasterr=""
chmod "$dirmode" "$pathcomp" || lasterr=$?
if test ! -z "$lasterr"; then
errstatus=$lasterr
fi
fi
fi
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# End:
# mkinstalldirs ends here

View file

@ -0,0 +1,172 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</IntDir>
<OutDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</IntDir>
<OutDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</IntDir>
<OutDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</IntDir>
<OutDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\test\benchmark-ping-pongs.c" />
<ClCompile Include="..\test\benchmark-pump.c" />
<ClCompile Include="..\test\benchmark-sizes.c" />
<ClCompile Include="..\test\echo-server.c" />
<ClCompile Include="..\test\run-benchmarks.c" />
<ClCompile Include="..\test\runner-unix.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\test\runner-win.c" />
<ClCompile Include="..\test\runner.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\test\benchmark-list.h" />
<ClInclude Include="..\test\runner-unix.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="..\test\runner-win.h" />
<ClInclude Include="..\test\runner.h" />
<ClInclude Include="..\test\task.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libuv.vcxproj">
<Project>{301fe650-cd34-14e5-6b63-42e383fa02bc}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,184 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{1D7C3F6C-A4AF-DD73-2D20-B2FC919B3744}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</IntDir>
<OutDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</IntDir>
<OutDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</IntDir>
<OutDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>true</LinkIncremental>
<IntDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</IntDir>
<OutDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\test\echo-server.c" />
<ClCompile Include="..\test\runner-unix.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\test\test-async.c" />
<ClCompile Include="..\test\test-delayed-accept.c" />
<ClCompile Include="..\test\test-callback-stack.c" />
<ClCompile Include="..\test\test-connection-fail.c" />
<ClCompile Include="..\test\test-get-currentexe.c" />
<ClCompile Include="..\test\test-fail-always.c" />
<ClCompile Include="..\test\test-loop-handles.c" />
<ClCompile Include="..\test\test-pass-always.c" />
<ClCompile Include="..\test\test-ping-pong.c" />
<ClCompile Include="..\test\runner-win.c" />
<ClCompile Include="..\test\runner.c" />
<ClCompile Include="..\test\test-bind-error.c" />
<ClCompile Include="..\test\test-shutdown-eof.c" />
<ClCompile Include="..\test\test-tcp-writealot.c" />
<ClCompile Include="..\test\test-timer-again.c" />
<ClCompile Include="..\test\test-timer.c" />
<ClCompile Include="..\test\run-tests.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\test\runner-unix.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="..\test\test-list.h" />
<ClInclude Include="..\test\runner-win.h" />
<ClInclude Include="..\test\runner.h" />
<ClInclude Include="..\test\task.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="libuv.vcxproj">
<Project>{301fe650-cd34-14e5-6b63-42e383fa02bc}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,46 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libuv", "libuv.vcxproj", "{301FE650-CD34-14E5-6B63-42E383FA02BC}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libuv-test", "libuv-test.vcxproj", "{1D7C3F6C-A4AF-DD73-2D20-B2FC919B3744}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libuv-benchmark", "libuv-benchmark.vcxproj", "{6CCBDAFD-7A11-133D-357B-E2D2F4C621E4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{301FE650-CD34-14E5-6B63-42E383FA02BC}.Debug|Win32.ActiveCfg = Debug|Win32
{301FE650-CD34-14E5-6B63-42E383FA02BC}.Debug|Win32.Build.0 = Debug|Win32
{301FE650-CD34-14E5-6B63-42E383FA02BC}.Debug|x64.ActiveCfg = Debug|x64
{301FE650-CD34-14E5-6B63-42E383FA02BC}.Debug|x64.Build.0 = Debug|x64
{301FE650-CD34-14E5-6B63-42E383FA02BC}.Release|Win32.ActiveCfg = Release|Win32
{301FE650-CD34-14E5-6B63-42E383FA02BC}.Release|Win32.Build.0 = Release|Win32
{301FE650-CD34-14E5-6B63-42E383FA02BC}.Release|x64.ActiveCfg = Release|x64
{301FE650-CD34-14E5-6B63-42E383FA02BC}.Release|x64.Build.0 = Release|x64
{1D7C3F6C-A4AF-DD73-2D20-B2FC919B3744}.Debug|Win32.ActiveCfg = Debug|Win32
{1D7C3F6C-A4AF-DD73-2D20-B2FC919B3744}.Debug|Win32.Build.0 = Debug|Win32
{1D7C3F6C-A4AF-DD73-2D20-B2FC919B3744}.Debug|x64.ActiveCfg = Debug|x64
{1D7C3F6C-A4AF-DD73-2D20-B2FC919B3744}.Debug|x64.Build.0 = Debug|x64
{1D7C3F6C-A4AF-DD73-2D20-B2FC919B3744}.Release|Win32.ActiveCfg = Release|Win32
{1D7C3F6C-A4AF-DD73-2D20-B2FC919B3744}.Release|Win32.Build.0 = Release|Win32
{1D7C3F6C-A4AF-DD73-2D20-B2FC919B3744}.Release|x64.ActiveCfg = Release|x64
{1D7C3F6C-A4AF-DD73-2D20-B2FC919B3744}.Release|x64.Build.0 = Release|x64
{6CCBDAFD-7A11-133D-357B-E2D2F4C621E4}.Debug|Win32.ActiveCfg = Debug|Win32
{6CCBDAFD-7A11-133D-357B-E2D2F4C621E4}.Debug|Win32.Build.0 = Debug|Win32
{6CCBDAFD-7A11-133D-357B-E2D2F4C621E4}.Debug|x64.ActiveCfg = Debug|x64
{6CCBDAFD-7A11-133D-357B-E2D2F4C621E4}.Debug|x64.Build.0 = Debug|x64
{6CCBDAFD-7A11-133D-357B-E2D2F4C621E4}.Release|Win32.ActiveCfg = Release|Win32
{6CCBDAFD-7A11-133D-357B-E2D2F4C621E4}.Release|Win32.Build.0 = Release|Win32
{6CCBDAFD-7A11-133D-357B-E2D2F4C621E4}.Release|x64.ActiveCfg = Release|x64
{6CCBDAFD-7A11-133D-357B-E2D2F4C621E4}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,136 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{301FE650-CD34-14E5-6B63-42E383FA02BC}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)..\build\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\ngx-queue.h" />
<ClInclude Include="..\uv-unix.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="..\uv-win.h" />
<ClInclude Include="..\uv.h" />
<ClInclude Include="..\tree.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\uv-unix.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\uv-win.c" />
<ClCompile Include="..\uv-common.c" />
</ItemGroup>
<ItemGroup>
<None Include="..\AUTHORS" />
<None Include="..\config-mingw.mk" />
<None Include="..\config-unix.mk" />
<None Include="..\iocp-links.html" />
<None Include="..\LICENSE" />
<None Include="..\Makefile" />
<None Include="..\README" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

102
src/rt/libuv/ngx-queue.h Normal file
View file

@ -0,0 +1,102 @@
/*
* Copyright (C) Igor Sysoev
*/
#ifndef _NGX_QUEUE_H_INCLUDED_
#define _NGX_QUEUE_H_INCLUDED_
typedef struct ngx_queue_s ngx_queue_t;
struct ngx_queue_s {
ngx_queue_t *prev;
ngx_queue_t *next;
};
#define ngx_queue_init(q) \
(q)->prev = q; \
(q)->next = q
#define ngx_queue_empty(h) \
(h == (h)->prev)
#define ngx_queue_insert_head(h, x) \
(x)->next = (h)->next; \
(x)->next->prev = x; \
(x)->prev = h; \
(h)->next = x
#define ngx_queue_insert_after ngx_queue_insert_head
#define ngx_queue_insert_tail(h, x) \
(x)->prev = (h)->prev; \
(x)->prev->next = x; \
(x)->next = h; \
(h)->prev = x
#define ngx_queue_head(h) \
(h)->next
#define ngx_queue_last(h) \
(h)->prev
#define ngx_queue_sentinel(h) \
(h)
#define ngx_queue_next(q) \
(q)->next
#define ngx_queue_prev(q) \
(q)->prev
#if (NGX_DEBUG)
#define ngx_queue_remove(x) \
(x)->next->prev = (x)->prev; \
(x)->prev->next = (x)->next; \
(x)->prev = NULL; \
(x)->next = NULL
#else
#define ngx_queue_remove(x) \
(x)->next->prev = (x)->prev; \
(x)->prev->next = (x)->next
#endif
#define ngx_queue_split(h, q, n) \
(n)->prev = (h)->prev; \
(n)->prev->next = n; \
(n)->next = q; \
(h)->prev = (q)->prev; \
(h)->prev->next = h; \
(q)->prev = n;
#define ngx_queue_add(h, n) \
(h)->prev->next = (n)->next; \
(n)->next->prev = (h)->prev; \
(h)->prev = (n)->prev; \
(h)->prev->next = h;
#define ngx_queue_data(q, type, link) \
(type *) ((unsigned char *) q - offsetof(type, link))
#endif /* _NGX_QUEUE_H_INCLUDED_ */

View file

@ -0,0 +1,40 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
BENCHMARK_DECLARE (sizes)
BENCHMARK_DECLARE (ping_pongs)
BENCHMARK_DECLARE (pump100_client)
BENCHMARK_DECLARE (pump1_client)
HELPER_DECLARE (pump_server)
HELPER_DECLARE (echo_server)
TASK_LIST_START
BENCHMARK_ENTRY (sizes)
BENCHMARK_ENTRY (ping_pongs)
BENCHMARK_HELPER (ping_pongs, echo_server)
BENCHMARK_ENTRY (pump100_client)
BENCHMARK_HELPER (pump100_client, pump_server)
BENCHMARK_ENTRY (pump1_client)
BENCHMARK_HELPER (pump1_client, pump_server)
TASK_LIST_END

View file

@ -0,0 +1,217 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "../uv.h"
#include "task.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h> /* strlen */
/* Run the benchmark for this many ms */
#define TIME 5000
typedef struct {
int pongs;
int state;
uv_tcp_t tcp;
uv_req_t connect_req;
uv_req_t shutdown_req;
} pinger_t;
typedef struct buf_s {
uv_buf_t uv_buf_t;
struct buf_s* next;
} buf_t;
static char PING[] = "PING\n";
static buf_t* buf_freelist = NULL;
static int pinger_shutdown_cb_called;
static int completed_pingers = 0;
static int64_t start_time;
static uv_buf_t buf_alloc(uv_tcp_t* tcp, size_t size) {
buf_t* ab;
ab = buf_freelist;
if (ab != NULL) {
buf_freelist = ab->next;
return ab->uv_buf_t;
}
ab = (buf_t*) malloc(size + sizeof *ab);
ab->uv_buf_t.len = size;
ab->uv_buf_t.base = ((char*) ab) + sizeof *ab;
return ab->uv_buf_t;
}
static void buf_free(uv_buf_t uv_buf_t) {
buf_t* ab = (buf_t*) (uv_buf_t.base - sizeof *ab);
ab->next = buf_freelist;
buf_freelist = ab;
}
static void pinger_close_cb(uv_handle_t* handle) {
pinger_t* pinger;
pinger = (pinger_t*)handle->data;
LOGF("ping_pongs: %d roundtrips/s\n", (1000 * pinger->pongs) / TIME);
free(pinger);
completed_pingers++;
}
static void pinger_write_cb(uv_req_t *req, int status) {
ASSERT(status == 0);
free(req);
}
static void pinger_write_ping(pinger_t* pinger) {
uv_req_t *req;
uv_buf_t buf;
buf.base = (char*)&PING;
buf.len = strlen(PING);
req = (uv_req_t*)malloc(sizeof(*req));
uv_req_init(req, (uv_handle_t*)(&pinger->tcp), pinger_write_cb);
if (uv_write(req, &buf, 1)) {
FATAL("uv_write failed");
}
}
static void pinger_shutdown_cb(uv_handle_t* handle, int status) {
ASSERT(status == 0);
pinger_shutdown_cb_called++;
/*
* The close callback has not been triggered yet. We must wait for EOF
* until we close the connection.
*/
ASSERT(completed_pingers == 0);
}
static void pinger_read_cb(uv_tcp_t* tcp, ssize_t nread, uv_buf_t buf) {
unsigned int i;
pinger_t* pinger;
pinger = (pinger_t*)tcp->data;
if (nread < 0) {
ASSERT(uv_last_error().code == UV_EOF);
if (buf.base) {
buf_free(buf);
}
ASSERT(pinger_shutdown_cb_called == 1);
uv_close((uv_handle_t*)tcp, pinger_close_cb);
return;
}
/* Now we count the pings */
for (i = 0; i < nread; i++) {
ASSERT(buf.base[i] == PING[pinger->state]);
pinger->state = (pinger->state + 1) % (sizeof(PING) - 1);
if (pinger->state == 0) {
pinger->pongs++;
if (uv_now() - start_time > TIME) {
uv_req_init(&pinger->shutdown_req, (uv_handle_t*)tcp, pinger_shutdown_cb);
uv_shutdown(&pinger->shutdown_req);
break;
} else {
pinger_write_ping(pinger);
}
}
}
buf_free(buf);
}
static void pinger_connect_cb(uv_req_t *req, int status) {
pinger_t *pinger = (pinger_t*)req->handle->data;
ASSERT(status == 0);
pinger_write_ping(pinger);
if (uv_read_start((uv_tcp_t*)(req->handle), buf_alloc, pinger_read_cb)) {
FATAL("uv_read_start failed");
}
}
static void pinger_new() {
int r;
struct sockaddr_in client_addr = uv_ip4_addr("0.0.0.0", 0);
struct sockaddr_in server_addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
pinger_t *pinger;
pinger = (pinger_t*)malloc(sizeof(*pinger));
pinger->state = 0;
pinger->pongs = 0;
/* Try to connec to the server and do NUM_PINGS ping-pongs. */
r = uv_tcp_init(&pinger->tcp);
ASSERT(!r);
pinger->tcp.data = pinger;
/* We are never doing multiple reads/connects at a time anyway. */
/* so these handles can be pre-initialized. */
uv_req_init(&pinger->connect_req, (uv_handle_t*)&pinger->tcp,
pinger_connect_cb);
uv_bind(&pinger->tcp, client_addr);
r = uv_connect(&pinger->connect_req, server_addr);
ASSERT(!r);
}
BENCHMARK_IMPL(ping_pongs) {
uv_init();
start_time = uv_now();
pinger_new();
uv_run();
ASSERT(completed_pingers == 1);
return 0;
}

View file

@ -0,0 +1,389 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "task.h"
#include "../uv.h"
#include <math.h>
#include <stdio.h>
static int TARGET_CONNECTIONS;
#define WRITE_BUFFER_SIZE 8192
#define MAX_SIMULTANEOUS_CONNECTS 100
#define PRINT_STATS 0
#define STATS_INTERVAL 1000 /* msec */
#define STATS_COUNT 5
static void do_write(uv_tcp_t*);
static void maybe_connect_some();
static uv_req_t* req_alloc();
static void req_free(uv_req_t* uv_req);
static uv_buf_t buf_alloc(uv_tcp_t*, size_t size);
static void buf_free(uv_buf_t uv_buf_t);
static uv_tcp_t server;
static struct sockaddr_in listen_addr;
static struct sockaddr_in connect_addr;
static int64_t start_time;
static int max_connect_socket = 0;
static int max_read_sockets = 0;
static int read_sockets = 0;
static int write_sockets = 0;
static int64_t nrecv = 0;
static int64_t nrecv_total = 0;
static int64_t nsent = 0;
static int64_t nsent_total = 0;
static int stats_left = 0;
static char write_buffer[WRITE_BUFFER_SIZE];
/* Make this as large as you need. */
#define MAX_WRITE_HANDLES 1000
static uv_tcp_t write_handles[MAX_WRITE_HANDLES];
static uv_timer_t timer_handle;
static double gbit(int64_t bytes, int64_t passed_ms) {
double gbits = ((double)bytes / (1024 * 1024 * 1024)) * 8;
return gbits / ((double)passed_ms / 1000);
}
static void show_stats(uv_handle_t *handle, int status) {
int64_t diff;
#if PRINT_STATS
LOGF("connections: %d, write: %.1f gbit/s\n",
write_sockets,
gbit(nsent, STATS_INTERVAL));
#endif
/* Exit if the show is over */
if (!--stats_left) {
uv_update_time();
diff = uv_now() - start_time;
LOGF("pump%d_client: %.1f gbit/s\n", write_sockets,
gbit(nsent_total, diff));
exit(0);
}
/* Reset read and write counters */
nrecv = 0;
nsent = 0;
}
static void read_show_stats() {
int64_t diff;
uv_update_time();
diff = uv_now() - start_time;
LOGF("pump%d_server: %.1f gbit/s\n", max_read_sockets,
gbit(nrecv_total, diff));
}
void write_sockets_close_cb(uv_handle_t* handle) {
/* If any client closes, the process is done. */
exit(0);
}
void read_sockets_close_cb(uv_handle_t* handle) {
free(handle);
read_sockets--;
/* If it's past the first second and everyone has closed their connection
* Then print stats.
*/
if (uv_now() - start_time > 1000 && read_sockets == 0) {
read_show_stats();
uv_close((uv_handle_t*)&server, NULL);
}
}
static void start_stats_collection() {
uv_req_t* req = req_alloc();
int r;
/* Show-stats timer */
stats_left = STATS_COUNT;
r = uv_timer_init(&timer_handle);
ASSERT(r == 0);
r = uv_timer_start(&timer_handle, show_stats, STATS_INTERVAL, STATS_INTERVAL);
ASSERT(r == 0);
uv_update_time();
start_time = uv_now();
}
static void read_cb(uv_tcp_t* tcp, ssize_t bytes, uv_buf_t buf) {
if (nrecv_total == 0) {
ASSERT(start_time == 0);
uv_update_time();
start_time = uv_now();
}
if (bytes < 0) {
uv_close((uv_handle_t*)tcp, read_sockets_close_cb);
return;
}
buf_free(buf);
nrecv += bytes;
nrecv_total += bytes;
}
static void write_cb(uv_req_t *req, int status) {
uv_buf_t* buf = (uv_buf_t*) req->data;
ASSERT(status == 0);
req_free(req);
nsent += sizeof write_buffer;
nsent_total += sizeof write_buffer;
do_write((uv_tcp_t*)req->handle);
}
static void do_write(uv_tcp_t* tcp) {
uv_req_t* req;
uv_buf_t buf;
int r;
buf.base = (char*) &write_buffer;
buf.len = sizeof write_buffer;
while (tcp->write_queue_size == 0) {
req = req_alloc();
uv_req_init(req, (uv_handle_t*)tcp, write_cb);
r = uv_write(req, &buf, 1);
ASSERT(r == 0);
}
}
static void connect_cb(uv_req_t* req, int status) {
int i;
if (status) LOG(uv_strerror(uv_last_error()));
ASSERT(status == 0);
write_sockets++;
req_free(req);
maybe_connect_some();
if (write_sockets == TARGET_CONNECTIONS) {
start_stats_collection();
/* Yay! start writing */
for (i = 0; i < write_sockets; i++) {
do_write(&write_handles[i]);
}
}
}
static void maybe_connect_some() {
uv_req_t* req;
uv_tcp_t* tcp;
int r;
while (max_connect_socket < TARGET_CONNECTIONS &&
max_connect_socket < write_sockets + MAX_SIMULTANEOUS_CONNECTS) {
tcp = &write_handles[max_connect_socket++];
r = uv_tcp_init(tcp);
ASSERT(r == 0);
req = req_alloc();
uv_req_init(req, (uv_handle_t*)tcp, connect_cb);
r = uv_connect(req, connect_addr);
ASSERT(r == 0);
}
}
static void connection_cb(uv_tcp_t* s, int status) {
uv_tcp_t* tcp;
int r;
ASSERT(&server == s);
ASSERT(status == 0);
tcp = malloc(sizeof(uv_tcp_t));
uv_tcp_init(tcp);
r = uv_accept(s, tcp);
ASSERT(r == 0);
r = uv_read_start(tcp, buf_alloc, read_cb);
ASSERT(r == 0);
read_sockets++;
max_read_sockets++;
}
/*
* Request allocator
*/
typedef struct req_list_s {
uv_req_t uv_req;
struct req_list_s* next;
} req_list_t;
static req_list_t* req_freelist = NULL;
static uv_req_t* req_alloc() {
req_list_t* req;
req = req_freelist;
if (req != NULL) {
req_freelist = req->next;
return (uv_req_t*) req;
}
req = (req_list_t*) malloc(sizeof *req);
return (uv_req_t*) req;
}
static void req_free(uv_req_t* uv_req) {
req_list_t* req = (req_list_t*) uv_req;
req->next = req_freelist;
req_freelist = req;
}
/*
* Buffer allocator
*/
typedef struct buf_list_s {
uv_buf_t uv_buf_t;
struct buf_list_s* next;
} buf_list_t;
static buf_list_t* buf_freelist = NULL;
static uv_buf_t buf_alloc(uv_tcp_t* tcp, size_t size) {
buf_list_t* buf;
buf = buf_freelist;
if (buf != NULL) {
buf_freelist = buf->next;
return buf->uv_buf_t;
}
buf = (buf_list_t*) malloc(size + sizeof *buf);
buf->uv_buf_t.len = (unsigned int)size;
buf->uv_buf_t.base = ((char*) buf) + sizeof *buf;
return buf->uv_buf_t;
}
static void buf_free(uv_buf_t uv_buf_t) {
buf_list_t* buf = (buf_list_t*) (uv_buf_t.base - sizeof *buf);
buf->next = buf_freelist;
buf_freelist = buf;
}
HELPER_IMPL(pump_server) {
int r;
uv_init();
listen_addr = uv_ip4_addr("0.0.0.0", TEST_PORT);
/* Server */
r = uv_tcp_init(&server);
ASSERT(r == 0);
r = uv_bind(&server, listen_addr);
ASSERT(r == 0);
r = uv_listen(&server, MAX_WRITE_HANDLES, connection_cb);
ASSERT(r == 0);
uv_run();
return 0;
}
void pump(int n) {
ASSERT(n <= MAX_WRITE_HANDLES);
TARGET_CONNECTIONS = n;
uv_init();
connect_addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
/* Start making connections */
maybe_connect_some();
uv_run();
}
BENCHMARK_IMPL(pump100_client) {
pump(100);
return 0;
}
BENCHMARK_IMPL(pump1_client) {
pump(1);
return 0;
}

View file

@ -0,0 +1,35 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "task.h"
#include "../uv.h"
BENCHMARK_IMPL(sizes) {
LOGF("uv_req_t: %lu bytes\n", sizeof(uv_req_t));
LOGF("uv_tcp_t: %lu bytes\n", sizeof(uv_tcp_t));
LOGF("uv_prepare_t: %lu bytes\n", sizeof(uv_prepare_t));
LOGF("uv_check_t: %lu bytes\n", sizeof(uv_check_t));
LOGF("uv_idle_t: %lu bytes\n", sizeof(uv_idle_t));
LOGF("uv_async_t: %lu bytes\n", sizeof(uv_async_t));
LOGF("uv_timer_t: %lu bytes\n", sizeof(uv_timer_t));
return 0;
}

View file

@ -0,0 +1,188 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "../uv.h"
#include "task.h"
#include <stdio.h>
#include <stdlib.h>
typedef struct {
uv_req_t req;
uv_buf_t buf;
} write_req_t;
static int server_closed;
static uv_tcp_t server;
static void after_write(uv_req_t* req, int status);
static void after_read(uv_tcp_t*, ssize_t nread, uv_buf_t buf);
static void on_close(uv_handle_t* peer);
static void on_server_close(uv_handle_t* handle);
static void on_connection(uv_tcp_t*, int status);
static void after_write(uv_req_t* req, int status) {
write_req_t* wr;
if (status) {
uv_err_t err = uv_last_error();
fprintf(stderr, "uv_write error: %s\n", uv_strerror(err));
ASSERT(0);
}
wr = (write_req_t*) req;
/* Free the read/write buffer and the request */
free(wr->buf.base);
free(wr);
}
static void after_shutdown(uv_req_t* req, int status) {
uv_close(req->handle, on_close);
free(req);
}
static void after_read(uv_tcp_t* handle, ssize_t nread, uv_buf_t buf) {
int i;
write_req_t *wr;
uv_req_t* req;
if (nread < 0) {
/* Error or EOF */
ASSERT (uv_last_error().code == UV_EOF);
if (buf.base) {
free(buf.base);
}
req = (uv_req_t*) malloc(sizeof *req);
uv_req_init(req, (uv_handle_t*)handle, after_shutdown);
uv_shutdown(req);
return;
}
if (nread == 0) {
/* Everything OK, but nothing read. */
free(buf.base);
return;
}
/* Scan for the letter Q which signals that we should quit. */
if (!server_closed) {
for (i = 0; i < nread; i++) {
if (buf.base[i] == 'Q') {
uv_close((uv_handle_t*)&server, on_server_close);
server_closed = 1;
}
}
}
wr = (write_req_t*) malloc(sizeof *wr);
uv_req_init(&wr->req, (uv_handle_t*)handle, after_write);
wr->buf.base = buf.base;
wr->buf.len = nread;
if (uv_write(&wr->req, &wr->buf, 1)) {
FATAL("uv_write failed");
}
}
static void on_close(uv_handle_t* peer) {
free(peer);
}
static uv_buf_t echo_alloc(uv_tcp_t* handle, size_t suggested_size) {
uv_buf_t buf;
buf.base = (char*) malloc(suggested_size);
buf.len = suggested_size;
return buf;
}
static void on_connection(uv_tcp_t* server, int status) {
uv_tcp_t* handle;
int r;
ASSERT(status == 0);
handle = (uv_tcp_t*) malloc(sizeof *handle);
ASSERT(handle != NULL);
uv_tcp_init(handle);
r = uv_accept(server, handle);
ASSERT(r == 0);
r = uv_read_start(handle, echo_alloc, after_read);
ASSERT(r == 0);
}
static void on_server_close(uv_handle_t* handle) {
ASSERT(handle == (uv_handle_t*)&server);
}
static int echo_start(int port) {
struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", port);
int r;
r = uv_tcp_init(&server);
if (r) {
/* TODO: Error codes */
fprintf(stderr, "Socket creation error\n");
return 1;
}
r = uv_bind(&server, addr);
if (r) {
/* TODO: Error codes */
fprintf(stderr, "Bind error\n");
return 1;
}
r = uv_listen(&server, 128, on_connection);
if (r) {
/* TODO: Error codes */
fprintf(stderr, "Listen error\n");
return 1;
}
return 0;
}
HELPER_IMPL(echo_server) {
uv_init();
if (echo_start(TEST_PORT))
return 1;
uv_run();
return 0;
}

View file

@ -0,0 +1,59 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include "runner.h"
#include "task.h"
/* Actual benchmarks and helpers are defined in benchmark-list.h */
#include "benchmark-list.h"
/* The time in milliseconds after which a single benchmark times out. */
#define BENCHMARK_TIMEOUT 60000
int main(int argc, char **argv) {
task_entry_t *task;
platform_init(argc, argv);
if (argc > 1) {
/* A specific process was requested. */
return run_process(argv[1]);
} else {
/* Run all benchmarks. */
task = (task_entry_t*)&TASKS;
for (task = (task_entry_t*)&TASKS; task->main; task++) {
if (task->is_helper) {
continue;
}
run_task(task, BENCHMARK_TIMEOUT, 1);
}
LOG("Done.\n");
return 0;
}
}

View file

@ -0,0 +1,86 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include "runner.h"
#include "task.h"
/* Actual tests and helpers are defined in test-list.h */
#include "test-list.h"
/* The time in milliseconds after which a single test times out. */
#define TEST_TIMEOUT 5000
static void log_progress(int total, int passed, int failed, char* name) {
LOGF("[%% %3d|+ %3d|- %3d]: %s", (passed + failed) / total * 100,
passed, failed, name);
}
int main(int argc, char **argv) {
int total, passed, failed;
task_entry_t* task;
platform_init(argc, argv);
if (argc > 1) {
/* A specific process was requested. */
return run_process(argv[1]);
} else {
/* Count the number of tests. */
total = 0;
task = (task_entry_t*)&TASKS;
for (task = (task_entry_t*)&TASKS; task->main; task++) {
if (!task->is_helper) {
total++;
}
}
/* Run all tests. */
passed = 0;
failed = 0;
task = (task_entry_t*)&TASKS;
for (task = (task_entry_t*)&TASKS; task->main; task++) {
if (task->is_helper) {
continue;
}
rewind_cursor();
log_progress(total, passed, failed, task->task_name);
if (run_task(task, TEST_TIMEOUT, 0)) {
passed++;
} else {
failed++;
}
}
rewind_cursor();
log_progress(total, passed, failed, "Done.\n");
return 0;
}
}

View file

@ -0,0 +1,335 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "runner-unix.h"
#include "runner.h"
#include <stdint.h> /* uintptr_t */
#include <unistd.h> /* usleep */
#include <string.h> /* strdup */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <assert.h>
#include <sys/select.h>
#include <pthread.h>
#ifdef __APPLE__
#include <mach-o/dyld.h> /* _NSGetExecutablePath */
static void get_executable_path() {
uint32_t bufsize = sizeof(executable_path);
_NSGetExecutablePath(executable_path, &bufsize);
}
#endif
#ifdef __linux__
static void get_executable_path() {
if (!executable_path[0]) {
readlink("/proc/self/exe", executable_path, PATHMAX - 1);
}
}
#endif
/* Do platform-specific initialization. */
void platform_init(int argc, char **argv) {
/* Disable stdio output buffering. */
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
#ifdef get_executable_path
get_executable_path();
#else
strcpy(executable_path, argv[0]);
#endif
}
/* Invoke "arv[0] test-name". Store process info in *p. */
/* Make sure that all stdio output of the processes is buffered up. */
int process_start(char* name, process_info_t* p) {
FILE* stdout_file = tmpfile();
if (!stdout_file) {
perror("tmpfile");
return -1;
}
p->terminated = 0;
p->status = 0;
pid_t pid = fork();
if (pid < 0) {
perror("vfork");
return -1;
}
if (pid == 0) {
/* child */
dup2(fileno(stdout_file), STDOUT_FILENO);
dup2(fileno(stdout_file), STDERR_FILENO);
char* args[3] = { executable_path, name, NULL };
execvp(executable_path, args);
perror("execvp()");
_exit(127);
}
/* parent */
p->pid = pid;
p->name = strdup(name);
p->stdout_file = stdout_file;
return 0;
}
typedef struct {
int pipe[2];
process_info_t* vec;
int n;
} dowait_args;
/* This function is run inside a pthread. We do this so that we can possibly
* timeout.
*/
static void* dowait(void* data) {
dowait_args* args = data;
int i, status, r;
process_info_t* p;
for (i = 0; i < args->n; i++) {
p = (process_info_t*)(args->vec + i * sizeof(process_info_t));
if (p->terminated) continue;
status = 0;
r = waitpid(p->pid, &p->status, 0);
if (r < 0) {
perror("waitpid");
return NULL;
}
p->terminated = 1;
}
if (args->pipe[1] >= 0) {
/* Write a character to the main thread to notify it about this. */
char c = 0;
write(args->pipe[1], &c, 1);
}
return NULL;
}
/* Wait for all `n` processes in `vec` to terminate. */
/* Time out after `timeout` msec, or never if timeout == -1 */
/* Return 0 if all processes are terminated, -1 on error, -2 on timeout. */
int process_wait(process_info_t* vec, int n, int timeout) {
int i;
process_info_t* p;
dowait_args args;
args.vec = vec;
args.n = n;
args.pipe[0] = -1;
args.pipe[1] = -1;
/* The simple case is where there is no timeout */
if (timeout == -1) {
dowait(&args);
return 0;
}
/* Hard case. Do the wait with a timeout.
*
* Assumption: we are the only ones making this call right now. Otherwise
* we'd need to lock vec.
*/
pthread_t tid;
int retval;
int r = pipe((int*)&(args.pipe));
if (r) {
perror("pipe()");
return -1;
}
r = pthread_create(&tid, NULL, dowait, &args);
if (r) {
perror("pthread_create()");
retval = -1;
goto terminate;
}
struct timeval tv;
tv.tv_sec = timeout / 1000;
tv.tv_usec = 0;
fd_set fds;
FD_ZERO(&fds);
FD_SET(args.pipe[0], &fds);
r = select(args.pipe[0] + 1, &fds, NULL, NULL, &tv);
if (r == -1) {
perror("select()");
retval = -1;
} else if (r) {
/* The thread completed successfully. */
retval = 0;
} else {
/* Timeout. Kill all the children. */
for (i = 0; i < n; i++) {
p = (process_info_t*)(vec + i * sizeof(process_info_t));
kill(p->pid, SIGTERM);
}
retval = -2;
/* Wait for thread to finish. */
r = pthread_join(tid, NULL);
if (r) {
perror("pthread_join");
retval = -1;
}
}
terminate:
close(args.pipe[0]);
close(args.pipe[1]);
return retval;
}
/* Returns the number of bytes in the stdio output buffer for process `p`. */
long int process_output_size(process_info_t *p) {
/* Size of the p->stdout_file */
struct stat buf;
int r = fstat(fileno(p->stdout_file), &buf);
if (r < 0) {
return -1;
}
return (long)buf.st_size;
}
/* Copy the contents of the stdio output buffer to `fd`. */
int process_copy_output(process_info_t *p, int fd) {
int r = fseek(p->stdout_file, 0, SEEK_SET);
if (r < 0) {
perror("fseek");
return -1;
}
size_t nread, nwritten;
char buf[1024];
while ((nread = read(fileno(p->stdout_file), buf, 1024)) > 0) {
nwritten = write(fd, buf, nread);
/* TODO: what if write doesn't write the whole buffer... */
if (nwritten < 0) {
perror("write");
return -1;
}
}
if (nread < 0) {
perror("read");
return -1;
}
return 0;
}
/* Return the name that was specified when `p` was started by process_start */
char* process_get_name(process_info_t *p) {
return p->name;
}
/* Terminate process `p`. */
int process_terminate(process_info_t *p) {
return kill(p->pid, SIGTERM);
}
/* Return the exit code of process p. */
/* On error, return -1. */
int process_reap(process_info_t *p) {
if (WIFEXITED(p->status)) {
return WEXITSTATUS(p->status);
} else {
return p->status; /* ? */
}
}
/* Clean up after terminating process `p` (e.g. free the output buffer etc.). */
void process_cleanup(process_info_t *p) {
fclose(p->stdout_file);
free(p->name);
}
/* Move the console cursor one line up and back to the first column. */
void rewind_cursor() {
fprintf(stderr, "\033[2K\r");
}
typedef void* (*uv_thread_cb)(void* arg);
uintptr_t uv_create_thread(void (*entry)(void* arg), void* arg) {
pthread_t t;
uv_thread_cb cb = (uv_thread_cb)entry;
int r = pthread_create(&t, NULL, cb, arg);
if (r) {
return 0;
}
return (uintptr_t)t;
}
/* Wait for a thread to terminate. Should return 0 if the thread ended, -1 on
* error.
*/
int uv_wait_thread(uintptr_t thread_id) {
return pthread_join((pthread_t)thread_id, NULL);
}
/* Pause the calling thread for a number of milliseconds. */
void uv_sleep(int msec) {
usleep(msec);
}

View file

@ -0,0 +1,36 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef TEST_RUNNER_UNIX_H
#define TEST_RUNNER_UNIX_H
#include <sys/types.h>
#include <stdio.h> /* FILE */
typedef struct {
FILE* stdout_file;
pid_t pid;
char* name;
int status;
int terminated;
} process_info_t;
#endif /* TEST_RUNNER_UNIX_H */

View file

@ -0,0 +1,331 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <io.h>
#include <malloc.h>
#include <stdio.h>
#include <process.h>
#include <windows.h>
#include "task.h"
#include "runner.h"
/*
* Define the stuff that MinGW doesn't have
*/
#ifndef GetFileSizeEx
WINBASEAPI BOOL WINAPI GetFileSizeEx(HANDLE hFile,
PLARGE_INTEGER lpFileSize);
#endif
/* Do platform-specific initialization. */
void platform_init(int argc, char **argv) {
/* Disable the "application crashed" popup. */
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
SEM_NOOPENFILEERRORBOX);
/* Disable stdio output buffering. */
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
strcpy(executable_path, argv[0]);
}
int process_start(char *name, process_info_t *p) {
HANDLE file = INVALID_HANDLE_VALUE;
HANDLE nul = INVALID_HANDLE_VALUE;
WCHAR path[MAX_PATH], filename[MAX_PATH];
WCHAR image[MAX_PATH + 1];
WCHAR args[MAX_PATH * 2];
STARTUPINFOW si;
PROCESS_INFORMATION pi;
DWORD result;
if (GetTempPathW(sizeof(path) / sizeof(WCHAR), (WCHAR*)&path) == 0)
goto error;
if (GetTempFileNameW((WCHAR*)&path, L"uv", 0, (WCHAR*)&filename) == 0)
goto error;
file = CreateFileW((WCHAR*)filename,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
NULL);
if (file == INVALID_HANDLE_VALUE)
goto error;
if (!SetHandleInformation(file, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
goto error;
nul = CreateFileA("nul",
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (nul == INVALID_HANDLE_VALUE)
goto error;
if (!SetHandleInformation(nul, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
goto error;
result = GetModuleFileNameW(NULL, (WCHAR*)&image, sizeof(image) / sizeof(WCHAR));
if (result == 0 || result == sizeof(image))
goto error;
if (_snwprintf((wchar_t*)&args,
sizeof(args) / sizeof(wchar_t),
L"\"%s\" %S",
image,
name) < 0)
goto error;
memset((void*)&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = nul;
si.hStdOutput = file;
si.hStdError = file;
if (!CreateProcessW(image, args, NULL, NULL, TRUE,
0, NULL, NULL, &si, &pi))
goto error;
CloseHandle(pi.hThread);
SetHandleInformation(nul, HANDLE_FLAG_INHERIT, 0);
SetHandleInformation(file, HANDLE_FLAG_INHERIT, 0);
p->stdio_in = nul;
p->stdio_out = file;
p->process = pi.hProcess;
p->name = name;
return 0;
error:
if (file != INVALID_HANDLE_VALUE)
CloseHandle(file);
if (nul != INVALID_HANDLE_VALUE)
CloseHandle(nul);
return -1;
}
/* Timeout is is msecs. Set timeout < 0 to never time out. */
/* Returns 0 when all processes are terminated, -2 on timeout. */
int process_wait(process_info_t *vec, int n, int timeout) {
int i;
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
DWORD timeout_api, result;
/* If there's nothing to wait for, return immedately. */
if (n == 0)
return 0;
ASSERT(n <= MAXIMUM_WAIT_OBJECTS);
for (i = 0; i < n; i++)
handles[i] = vec[i].process;
if (timeout >= 0) {
timeout_api = (DWORD)timeout;
} else {
timeout_api = INFINITE;
}
result = WaitForMultipleObjects(n, handles, TRUE, timeout_api);
if (result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + n) {
/* All processes are terminated. */
return 0;
}
if (result == WAIT_TIMEOUT) {
return -2;
}
return -1;
}
long int process_output_size(process_info_t *p) {
LARGE_INTEGER size;
if (!GetFileSizeEx(p->stdio_out, &size))
return -1;
return (long int)size.QuadPart;
}
int process_copy_output(process_info_t *p, int fd) {
DWORD read;
char buf[1024];
if (SetFilePointer(p->stdio_out, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
return -1;
while (ReadFile(p->stdio_out, (void*)&buf, sizeof(buf), &read, NULL) &&
read > 0)
write(fd, buf, read);
if (GetLastError() != ERROR_HANDLE_EOF)
return -1;
return 0;
}
char* process_get_name(process_info_t *p) {
return p->name;
}
int process_terminate(process_info_t *p) {
if (!TerminateProcess(p->process, 1))
return -1;
return 0;
}
int process_reap(process_info_t *p) {
DWORD exitCode;
if (!GetExitCodeProcess(p->process, &exitCode))
return -1;
return (int)exitCode;
}
void process_cleanup(process_info_t *p) {
CloseHandle(p->process);
CloseHandle(p->stdio_in);
CloseHandle(p->stdio_out);
}
static int clear_line() {
HANDLE handle;
CONSOLE_SCREEN_BUFFER_INFO info;
COORD coord;
DWORD written;
handle = (HANDLE)_get_osfhandle(fileno(stderr));
if (handle == INVALID_HANDLE_VALUE)
return -1;
if (!GetConsoleScreenBufferInfo(handle, &info))
return -1;
coord = info.dwCursorPosition;
if (coord.Y <= 0)
return -1;
coord.X = 0;
if (!SetConsoleCursorPosition(handle, coord))
return -1;
if (!FillConsoleOutputCharacterW(handle, 0x20, info.dwSize.X, coord, &written))
return -1;
return 0;
}
void rewind_cursor() {
if (clear_line() == -1) {
/* If clear_line fails (stdout is not a console), print a newline. */
fprintf(stderr, "\n");
}
}
typedef struct {
void (*entry)(void* arg);
void* arg;
} thread_info_t;
static unsigned __stdcall create_thread_helper(void* info) {
/* Copy thread info locally, then free it */
void (*entry)(void* arg) = ((thread_info_t*) info)->entry;
void* arg = ((thread_info_t*) info)->arg;
free(info);
/* Run the actual thread proc */
entry(arg);
/* Finalize */
_endthreadex(0);
return 0;
}
/* Create a thread. Returns the thread identifier, or 0 on failure. */
uintptr_t uv_create_thread(void (*entry)(void* arg), void* arg) {
uintptr_t result;
thread_info_t* info;
info = (thread_info_t*) malloc(sizeof *info);
if (info == NULL) {
return 0;
}
info->entry = entry;
info->arg = arg;
result = _beginthreadex(NULL,
0,
&create_thread_helper,
(void*) info,
0,
NULL);
if (result == 0) {
free(info);
return 0;
}
return result;
}
/* Wait for a thread to terminate. Should return 0 if the thread ended, -1 on
* error.
*/
int uv_wait_thread(uintptr_t thread_id) {
if (WaitForSingleObject((HANDLE)thread_id, INFINITE) != WAIT_OBJECT_0) {
return -1;
}
return 0;
}
/* Pause the calling thread for a number of milliseconds. */
void uv_sleep(int msec) {
Sleep(msec);
}

View file

@ -0,0 +1,42 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
/* Don't complain about _snprintf being unsecure. */
#define _CRT_SECURE_NO_WARNINGS
/* Dont complain about write(), fileno() etc. being deprecated. */
#pragma warning(disable : 4996)
#include <windows.h>
#include <stdio.h>
/* Windows has no snprintf, only _snprintf. */
#define snprintf _snprintf
typedef struct {
HANDLE process;
HANDLE stdio_in;
HANDLE stdio_out;
char *name;
} process_info_t;

171
src/rt/libuv/test/runner.c Normal file
View file

@ -0,0 +1,171 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <string.h>
#include "runner.h"
#include "task.h"
char executable_path[PATHMAX] = { '\0' };
/* Start a specific process declared by TEST_ENTRY or TEST_HELPER. */
/* Returns the exit code of the specific process. */
int run_process(char* name) {
task_entry_t *test;
for (test = (task_entry_t*)&TASKS; test->main; test++) {
if (strcmp(name, test->process_name) == 0) {
return test->main();
}
}
LOGF("Test process %s not found!\n", name);
return 255;
}
/*
* Runs all processes associated with a particular test or benchmark.
* It returns 1 if the test succeeded, 0 if it failed.
* If the test fails it prints diagnostic information.
* If benchmark_output is nonzero, the output from the main process is
* always shown.
*/
int run_task(task_entry_t *test, int timeout, int benchmark_output) {
int i, result, success;
char errmsg[256];
task_entry_t *helper;
int process_count;
process_info_t processes[MAX_PROCESSES];
process_info_t *main_process;
success = 0;
process_count = 0;
/* Start all helpers for this test first. */
for (helper = (task_entry_t*)&TASKS; helper->main; helper++) {
if (helper->is_helper &&
strcmp(test->task_name, helper->task_name) == 0) {
if (process_start(helper->process_name, &processes[process_count]) == -1) {
snprintf((char*)&errmsg,
sizeof(errmsg),
"process `%s` failed to start.",
helper->process_name);
goto finalize;
}
process_count++;
}
}
/* Wait a little bit to allow servers to start. Racy. */
uv_sleep(100);
/* Start the main test process. */
if (process_start(test->process_name, &processes[process_count]) == -1) {
snprintf((char*)&errmsg, sizeof(errmsg), "process `%s` failed to start.",
test->process_name);
goto finalize;
}
main_process = &processes[process_count];
process_count++;
/* Wait for the main process to terminate. */
result = process_wait(main_process, 1, timeout);
if (result == -1) {
FATAL("process_wait failed");
} else if (result == -2) {
snprintf((char*)&errmsg, sizeof(errmsg), "timeout.");
goto finalize;
}
/* Reap the main process. */
result = process_reap(main_process);
if (result != 0) {
snprintf((char*)&errmsg, sizeof(errmsg), "exit code %d.", result);
goto finalize;
}
/* Yes! did it. */
success = 1;
finalize:
/* Kill all (helper) processes that are still running. */
for (i = 0; i < process_count; i++) {
/* If terminate fails the process is probably already closed. */
process_terminate(&processes[i]);
}
/* Wait until all processes have really terminated. */
if (process_wait((process_info_t*)&processes, process_count, -1) < 0) {
FATAL("process_wait failed");
}
/* Show error and output from processes if the test failed. */
if (!success) {
LOGF("\n`%s` failed: %s\n", test->task_name, errmsg);
for (i = 0; i < process_count; i++) {
switch (process_output_size(&processes[i])) {
case -1:
LOGF("Output from process `%s`: (unavailable)\n",
process_get_name(&processes[i]));
break;
case 0:
LOGF("Output from process `%s`: (no output)\n",
process_get_name(&processes[i]));
break;
default:
LOGF("Output from process `%s`:\n", process_get_name(&processes[i]));
process_copy_output(&processes[i], fileno(stderr));
break;
}
}
LOG("=============================================================\n");
/* In benchmark mode show concise output from the main process. */
} else if (benchmark_output) {
switch (process_output_size(main_process)) {
case -1:
LOGF("%s: (unavailabe)\n", test->task_name);
break;
case 0:
LOGF("%s: (no output)\n", test->task_name);
break;
default:
for (i = 0; i < process_count; i++) {
process_copy_output(&processes[i], fileno(stderr));
}
break;
}
}
/* Clean up all process handles. */
for (i = 0; i < process_count; i++) {
process_cleanup(&processes[i]);
}
return success;
}

147
src/rt/libuv/test/runner.h Normal file
View file

@ -0,0 +1,147 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef RUNNER_H_
#define RUNNER_H_
/*
* The maximum number of processes (main + helpers) that a test / benchmark
* can have.
*/
#define MAX_PROCESSES 8
/*
* Struct to store both tests and to define helper processes for tasks.
*/
typedef struct {
char *task_name;
char *process_name;
int (*main)();
int is_helper;
} task_entry_t, bench_entry_t;
/* Runs an individual task; returns 1 if the test succeeded, 0 if it failed. */
/* If the test fails it prints diagnostic information. */
/* If benchmark_output is nonzero, the output from the main process is
/* always shown. */
int run_task(task_entry_t *test, int timeout, int benchmark_output);
/*
* Macros used by test-list.h and benchmark-list.h.
*/
#define TASK_LIST_START \
task_entry_t TASKS[] = {
#define TASK_LIST_END \
{ 0, 0, 0, 0 } \
};
#define TEST_DECLARE(name) \
int run_test_##name();
#define TEST_ENTRY(name) \
{ #name, #name, &run_test_##name, 0 },
#define BENCHMARK_DECLARE(name) \
int run_benchmark_##name();
#define BENCHMARK_ENTRY(name) \
{ #name, #name, &run_benchmark_##name, 0 },
#define HELPER_DECLARE(name) \
int run_helper_##name();
#define HELPER_ENTRY(task_name, name) \
{ #task_name, #name, &run_helper_##name, 1 },
#define TEST_HELPER HELPER_ENTRY
#define BENCHMARK_HELPER HELPER_ENTRY
#define PATHMAX 1024
extern char executable_path[PATHMAX];
/*
* Include platform-dependent definitions
*/
#ifdef _WIN32
# include "runner-win.h"
#else
# include "runner-unix.h"
#endif
/* The array that is filled by test-list.h or benchmark-list.h */
extern task_entry_t TASKS[];
/* Start a specific process declared by TEST_ENTRY or TEST_HELPER. */
/* Returns the exit code of the specific process. */
int run_task(task_entry_t *test, int timeout, int benchmark_output);
/* Start a specific process declared by TEST_ENTRY or TEST_HELPER. */
/* Returns the exit code of the specific process. */
int run_process(char* name);
/*
* Stuff that should be implemented by test-runner-<platform>.h
* All functions return 0 on success, -1 on failure, unless specified
* otherwise.
*/
/* Do platform-specific initialization. */
void platform_init();
/* Invoke "arv[0] test-name". Store process info in *p. */
/* Make sure that all stdio output of the processes is buffered up. */
int process_start(char *name, process_info_t *p);
/* Wait for all `n` processes in `vec` to terminate. */
/* Time out after `timeout` msec, or never if timeout == -1 */
/* Return 0 if all processes are terminated, -1 on error, -2 on timeout. */
int process_wait(process_info_t *vec, int n, int timeout);
/* Returns the number of bytes in the stdio output buffer for process `p`. */
long int process_output_size(process_info_t *p);
/* Copy the contents of the stdio output buffer to `fd`. */
int process_copy_output(process_info_t *p, int fd);
/* Return the name that was specified when `p` was started by process_start */
char* process_get_name(process_info_t *p);
/* Terminate process `p`. */
int process_terminate(process_info_t *p);
/* Return the exit code of process p. */
/* On error, return -1. */
int process_reap(process_info_t *p);
/* Clean up after terminating process `p` (e.g. free the output buffer etc.). */
void process_cleanup(process_info_t *p);
/* Move the console cursor one line up and back to the first column. */
void rewind_cursor();
#endif /* RUNNER_H_ */

89
src/rt/libuv/test/task.h Normal file
View file

@ -0,0 +1,89 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef TASK_H_
#define TASK_H_
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define TEST_PORT 9123
#define TEST_PORT_2 9124
/* Log to stderr. */
#define LOG(...) fprintf(stderr, "%s", __VA_ARGS__)
#define LOGF(...) fprintf(stderr, __VA_ARGS__)
/* Die with fatal error. */
#define FATAL(msg) \
do { \
fprintf(stderr, \
"Fatal error in %s on line %d: %s\n", \
__FILE__, \
__LINE__, \
msg); \
abort(); \
} while (0)
/* Have our own assert, so we are sure it does not get optimized away in
* a release build.
*/
#define ASSERT(expr) \
do { \
if (!(expr)) { \
fprintf(stderr, \
"Assertion failed in %s on line %d: %s\n", \
__FILE__, \
__LINE__, \
#expr); \
abort(); \
} \
} while (0)
/* Just sugar for wrapping the main() for a task or helper. */
#define TEST_IMPL(name) \
int run_test_##name()
#define BENCHMARK_IMPL(name) \
int run_benchmark_##name()
#define HELPER_IMPL(name) \
int run_helper_##name()
/* Create a thread. Returns the thread identifier, or 0 on failure. */
uintptr_t uv_create_thread(void (*entry)(void* arg), void* arg);
/* Wait for a thread to terminate. Should return 0 if the thread ended, -1 on
* error.
*/
int uv_wait_thread(uintptr_t thread_id);
/* Pause the calling thread for a number of milliseconds. */
void uv_sleep(int msec);
#endif /* TASK_H_ */

View file

@ -0,0 +1,223 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "../uv.h"
#include "task.h"
#include <stdio.h>
#include <stdlib.h>
static uv_prepare_t prepare_handle;
static uv_async_t async1_handle;
/* static uv_handle_t async2_handle; */
static int prepare_cb_called = 0;
static volatile int async1_cb_called = 0;
static int async1_closed = 0;
/* static volatile int async2_cb_called = 0; */
static int close_cb_called = 0;
static uintptr_t thread1_id = 0;
#if 0
static uintptr_t thread2_id = 0;
static uintptr_t thread3_id = 0;
#endif
/* Thread 1 makes sure that async1_cb_called reaches 3 before exiting. */
void thread1_entry(void *arg) {
int state = 0;
uv_sleep(50);
while (1) {
switch (async1_cb_called) {
case 0:
uv_async_send(&async1_handle);
break;
case 1:
uv_async_send(&async1_handle);
break;
case 2:
uv_async_send(&async1_handle);
break;
default:
return;
}
}
}
#if 0
/* Thread 2 calls uv_async_send on async_handle_2 8 times. */
void thread2_entry(void *arg) {
int i;
while (1) {
switch (async1_cb_called) {
case 0:
uv_async_send(&async2_handle);
break;
case 1:
uv_async_send(&async2_handle);
break;
case 2:
uv_async_send(&async2_handle);
break;
}
uv_sleep(5);
}
if (async1_cb_called == 20) {
uv_close(handle);
}
}
/* Thread 3 calls uv_async_send on async_handle_2 8 times
* after waiting half a second first.
*/
void thread3_entry(void *arg) {
int i;
for (i = 0; i < 8; i++) {
uv_async_send(&async2_handle);
}
}
#endif
static void close_cb(uv_handle_t* handle) {
ASSERT(handle != NULL);
close_cb_called++;
}
static void async1_cb(uv_handle_t* handle, int status) {
ASSERT(handle == (uv_handle_t*)&async1_handle);
ASSERT(status == 0);
async1_cb_called++;
printf("async1_cb #%d\n", async1_cb_called);
if (async1_cb_called > 2 && !async1_closed) {
async1_closed = 1;
uv_close(handle, close_cb);
}
}
#if 0
static void async2_cb(uv_handle_t* handle, int status) {
ASSERT(handle == &async2_handle);
ASSERT(status == 0);
async2_cb_called++;
printf("async2_cb #%d\n", async2_cb_called);
if (async2_cb_called == 16) {
uv_close(handle);
}
}
#endif
static void prepare_cb(uv_handle_t* handle, int status) {
int r;
ASSERT(handle == (uv_handle_t*)&prepare_handle);
ASSERT(status == 0);
switch (prepare_cb_called) {
case 0:
thread1_id = uv_create_thread(thread1_entry, NULL);
ASSERT(thread1_id != 0);
break;
#if 0
case 1:
thread2_id = uv_create_thread(thread2_entry, NULL);
ASSERT(thread2_id != 0);
break;
case 2:
thread3_id = uv_create_thread(thread3_entry, NULL);
ASSERT(thread3_id != 0);
break;
#endif
case 1:
r = uv_close(handle, close_cb);
ASSERT(r == 0);
break;
default:
FATAL("Should never get here");
}
prepare_cb_called++;
}
TEST_IMPL(async) {
int r;
uv_init();
r = uv_prepare_init(&prepare_handle);
ASSERT(r == 0);
r = uv_prepare_start(&prepare_handle, prepare_cb);
ASSERT(r == 0);
r = uv_async_init(&async1_handle, async1_cb);
ASSERT(r == 0);
#if 0
r = uv_async_init(&async2_handle, async2_cb, close_cb, NULL);
ASSERT(r == 0);
#endif
r = uv_run();
ASSERT(r == 0);
r = uv_wait_thread(thread1_id);
ASSERT(r == 0);
#if 0
r = uv_wait_thread(thread2_id);
ASSERT(r == 0);
r = uv_wait_thread(thread3_id);
ASSERT(r == 0);
#endif
ASSERT(prepare_cb_called == 2);
ASSERT(async1_cb_called > 2);
/* ASSERT(async2_cb_called = 16); */
ASSERT(close_cb_called == 2);
return 0;
}

View file

@ -0,0 +1,173 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "../uv.h"
#include "task.h"
#include <stdio.h>
#include <stdlib.h>
static int close_cb_called = 0;
static void close_cb(uv_handle_t* handle) {
ASSERT(handle != NULL);
close_cb_called++;
}
TEST_IMPL(bind_error_addrinuse) {
struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", TEST_PORT);
uv_tcp_t server1, server2;
int r;
uv_init();
r = uv_tcp_init(&server1);
ASSERT(r == 0);
r = uv_bind(&server1, addr);
ASSERT(r == 0);
r = uv_tcp_init(&server2);
ASSERT(r == 0);
r = uv_bind(&server2, addr);
ASSERT(r == 0);
r = uv_listen(&server1, 128, NULL);
ASSERT(r == 0);
r = uv_listen(&server2, 128, NULL);
ASSERT(r == -1);
ASSERT(uv_last_error().code == UV_EADDRINUSE);
uv_close((uv_handle_t*)&server1, close_cb);
uv_close((uv_handle_t*)&server2, close_cb);
uv_run();
ASSERT(close_cb_called == 2);
return 0;
}
TEST_IMPL(bind_error_addrnotavail_1) {
struct sockaddr_in addr = uv_ip4_addr("127.255.255.255", TEST_PORT);
uv_tcp_t server;
int r;
uv_init();
r = uv_tcp_init(&server);
ASSERT(r == 0);
r = uv_bind(&server, addr);
/* It seems that Linux is broken here - bind succeeds. */
if (r == -1) {
ASSERT(uv_last_error().code == UV_EADDRNOTAVAIL);
}
uv_close((uv_handle_t*)&server, close_cb);
uv_run();
ASSERT(close_cb_called == 1);
return 0;
}
TEST_IMPL(bind_error_addrnotavail_2) {
struct sockaddr_in addr = uv_ip4_addr("4.4.4.4", TEST_PORT);
uv_tcp_t server;
int r;
uv_init();
r = uv_tcp_init(&server);
ASSERT(r == 0);
r = uv_bind(&server, addr);
ASSERT(r == -1);
ASSERT(uv_last_error().code == UV_EADDRNOTAVAIL);
uv_close((uv_handle_t*)&server, close_cb);
uv_run();
ASSERT(close_cb_called == 1);
return 0;
}
TEST_IMPL(bind_error_fault) {
char garbage[] = "blah blah blah blah blah blah blah blah blah blah blah blah";
struct sockaddr_in* garbage_addr;
uv_tcp_t server;
int r;
garbage_addr = (struct sockaddr_in*) &garbage;
uv_init();
r = uv_tcp_init(&server);
ASSERT(r == 0);
r = uv_bind(&server, *garbage_addr);
ASSERT(r == -1);
ASSERT(uv_last_error().code == UV_EFAULT);
uv_close((uv_handle_t*)&server, close_cb);
uv_run();
ASSERT(close_cb_called == 1);
return 0;
}
/* Notes: On Linux uv_bind(server, NULL) will segfault the program. */
TEST_IMPL(bind_error_inval) {
struct sockaddr_in addr1 = uv_ip4_addr("0.0.0.0", TEST_PORT);
struct sockaddr_in addr2 = uv_ip4_addr("0.0.0.0", TEST_PORT_2);
uv_tcp_t server;
int r;
uv_init();
r = uv_tcp_init(&server);
ASSERT(r == 0);
r = uv_bind(&server, addr1);
ASSERT(r == 0);
r = uv_bind(&server, addr2);
ASSERT(r == -1);
ASSERT(uv_last_error().code == UV_EINVAL);
uv_close((uv_handle_t*)&server, close_cb);
uv_run();
ASSERT(close_cb_called == 1);
return 0;
}

View file

@ -0,0 +1,211 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
/*
* TODO: Add explanation of why we want on_close to be called from fresh
* stack.
*/
#include "../uv.h"
#include "task.h"
static const char MESSAGE[] = "Failure is for the weak. Everyone dies alone.";
static uv_tcp_t client;
static uv_timer_t timer;
static uv_req_t connect_req, write_req, shutdown_req;
static int nested = 0;
static int close_cb_called = 0;
static int connect_cb_called = 0;
static int write_cb_called = 0;
static int timer_cb_called = 0;
static int bytes_received = 0;
static int shutdown_cb_called = 0;
static uv_buf_t alloc_cb(uv_tcp_t* tcp, size_t size) {
uv_buf_t buf;
buf.len = size;
buf.base = (char*) malloc(size);
ASSERT(buf.base);
return buf;
}
static void close_cb(uv_handle_t* handle) {
ASSERT(nested == 0 && "close_cb must be called from a fresh stack");
close_cb_called++;
}
static void shutdown_cb(uv_req_t* req, int status) {
ASSERT(status == 0);
ASSERT(nested == 0 && "shutdown_cb must be called from a fresh stack");
shutdown_cb_called++;
}
static void read_cb(uv_tcp_t* tcp, ssize_t nread, uv_buf_t buf) {
ASSERT(nested == 0 && "read_cb must be called from a fresh stack");
printf("Read. nread == %d\n", nread);
free(buf.base);
if (nread == 0) {
ASSERT(uv_last_error().code == UV_EAGAIN);
return;
} else if (nread == -1) {
ASSERT(uv_last_error().code == UV_EOF);
nested++;
if (uv_close((uv_handle_t*)tcp, close_cb)) {
FATAL("uv_close failed");
}
nested--;
return;
}
bytes_received += nread;
/* We call shutdown here because when bytes_received == sizeof MESSAGE */
/* there will be no more data sent nor received, so here it would be */
/* possible for a backend to to call shutdown_cb immediately and *not* */
/* from a fresh stack. */
if (bytes_received == sizeof MESSAGE) {
nested++;
uv_req_init(&shutdown_req, (uv_handle_t*)tcp, shutdown_cb);
puts("Shutdown");
if (uv_shutdown(&shutdown_req)) {
FATAL("uv_shutdown failed");
}
nested--;
}
}
static void timer_cb(uv_handle_t* handle, int status) {
int r;
ASSERT(handle == (uv_handle_t*)&timer);
ASSERT(status == 0);
ASSERT(nested == 0 && "timer_cb must be called from a fresh stack");
puts("Timeout complete. Now read data...");
nested++;
if (uv_read_start(&client, alloc_cb, read_cb)) {
FATAL("uv_read_start failed");
}
nested--;
timer_cb_called++;
r = uv_close(handle, close_cb);
ASSERT(r == 0);
}
static void write_cb(uv_req_t* req, int status) {
int r;
ASSERT(status == 0);
ASSERT(nested == 0 && "write_cb must be called from a fresh stack");
puts("Data written. 500ms timeout...");
/* After the data has been sent, we're going to wait for a while, then */
/* start reading. This makes us certain that the message has been echoed */
/* back to our receive buffer when we start reading. This maximizes the */
/* tempation for the backend to use dirty stack for calling read_cb. */
nested++;
r = uv_timer_init(&timer);
ASSERT(r == 0);
r = uv_timer_start(&timer, timer_cb, 500, 0);
ASSERT(r == 0);
nested--;
write_cb_called++;
}
static void connect_cb(uv_req_t* req, int status) {
uv_buf_t buf;
puts("Connected. Write some data to echo server...");
ASSERT(status == 0);
ASSERT(nested == 0 && "connect_cb must be called from a fresh stack");
nested++;
buf.base = (char*) &MESSAGE;
buf.len = sizeof MESSAGE;
uv_req_init(&write_req, req->handle, write_cb);
if (uv_write(&write_req, &buf, 1)) {
FATAL("uv_write failed");
}
nested--;
connect_cb_called++;
}
TEST_IMPL(callback_stack) {
struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
uv_init();
if (uv_tcp_init(&client)) {
FATAL("uv_tcp_init failed");
}
puts("Connecting...");
nested++;
uv_req_init(&connect_req, (uv_handle_t*)&client, connect_cb);
if (uv_connect(&connect_req, addr)) {
FATAL("uv_connect failed");
}
nested--;
uv_run();
ASSERT(nested == 0);
ASSERT(connect_cb_called == 1 && "connect_cb must be called exactly once");
ASSERT(write_cb_called == 1 && "write_cb must be called exactly once");
ASSERT(timer_cb_called == 1 && "timer_cb must be called exactly once");
ASSERT(bytes_received == sizeof MESSAGE);
ASSERT(shutdown_cb_called == 1 && "shutdown_cb must be called exactly once");
ASSERT(close_cb_called == 2 && "close_cb must be called exactly twice");
return 0;
}

View file

@ -0,0 +1,151 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "../uv.h"
#include "task.h"
#include <stdlib.h>
#include <stdio.h>
static uv_tcp_t tcp;
static uv_req_t req;
static int connect_cb_calls;
static int close_cb_calls;
static uv_timer_t timer;
static int timer_close_cb_calls;
static int timer_cb_calls;
static void on_close(uv_handle_t* handle) {
close_cb_calls++;
}
static void timer_close_cb(uv_handle_t* handle) {
timer_close_cb_calls++;
}
static void timer_cb(uv_handle_t* handle, int status) {
ASSERT(status == 0);
timer_cb_calls++;
/*
* These are the important asserts. The connection callback has been made,
* but libuv hasn't automatically closed the socket. The user must
* uv_close the handle manually.
*/
ASSERT(close_cb_calls == 0);
ASSERT(connect_cb_calls == 1);
/* Close the tcp handle. */
uv_close((uv_handle_t*)&tcp, on_close);
/* Close the timer. */
uv_close(handle, timer_close_cb);
}
static void on_connect_with_close(uv_req_t *req, int status) {
ASSERT(&tcp == (uv_tcp_t*) req->handle);
ASSERT(status == -1);
ASSERT(uv_last_error().code == UV_ECONNREFUSED);
connect_cb_calls++;
ASSERT(close_cb_calls == 0);
uv_close(req->handle, on_close);
}
static void on_connect_without_close(uv_req_t *req, int status) {
ASSERT(status == -1);
ASSERT(uv_last_error().code == UV_ECONNREFUSED);
connect_cb_calls++;
uv_timer_start(&timer, timer_cb, 100, 0);
ASSERT(close_cb_calls == 0);
}
void connection_fail(uv_connect_cb connect_cb) {
struct sockaddr_in client_addr, server_addr;
int r;
client_addr = uv_ip4_addr("0.0.0.0", 0);
/* There should be no servers listening on this port. */
server_addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
/* Try to connec to the server and do NUM_PINGS ping-pongs. */
r = uv_tcp_init(&tcp);
ASSERT(!r);
/* We are never doing multiple reads/connects at a time anyway. */
/* so these handles can be pre-initialized. */
uv_req_init(&req, (uv_handle_t*)&tcp, connect_cb);
uv_bind(&tcp, client_addr);
r = uv_connect(&req, server_addr);
ASSERT(!r);
uv_run();
ASSERT(connect_cb_calls == 1);
ASSERT(close_cb_calls == 1);
}
/*
* This test attempts to connect to a port where no server is running. We
* expect an error.
*/
TEST_IMPL(connection_fail) {
uv_init();
connection_fail(on_connect_with_close);
ASSERT(timer_close_cb_calls == 0);
ASSERT(timer_cb_calls == 0);
return 0;
}
/*
* This test is the same as the first except it check that the close
* callback of the tcp handle hasn't been made after the failed connection
* attempt.
*/
TEST_IMPL(connection_fail_doesnt_auto_close) {
uv_init();
uv_timer_init(&timer);
connection_fail(on_connect_without_close);
ASSERT(timer_close_cb_calls == 1);
ASSERT(timer_cb_calls == 1);
return 0;
}

View file

@ -0,0 +1,199 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "../uv.h"
#include "task.h"
#include <stdio.h>
#include <stdlib.h>
static char BUFFER[1024];
static int connection_cb_called = 0;
static int do_accept_called = 0;
static int close_cb_called = 0;
static int connect_cb_called = 0;
static uv_buf_t alloc_cb(uv_tcp_t* tcp, size_t size) {
uv_buf_t buf;
buf.base = (char*)malloc(size);
buf.len = size;
return buf;
}
static void close_cb(uv_handle_t* handle) {
ASSERT(handle != NULL);
free(handle);
close_cb_called++;
}
static void do_accept(uv_handle_t* timer_handle, int status) {
uv_tcp_t* server;
uv_tcp_t* accepted_handle = (uv_tcp_t*)malloc(sizeof *accepted_handle);
int r;
int tcpcnt;
ASSERT(timer_handle != NULL);
ASSERT(status == 0);
ASSERT(accepted_handle != NULL);
uv_tcp_init(accepted_handle);
/* Test to that uv_counters()->tcp_init does not increase across the uv_accept. */
tcpcnt = uv_counters()->tcp_init;
server = (uv_tcp_t*)timer_handle->data;
r = uv_accept(server, accepted_handle);
ASSERT(r == 0);
ASSERT(uv_counters()->tcp_init == tcpcnt);
do_accept_called++;
/* Immediately close the accepted handle. */
r = uv_close((uv_handle_t*)accepted_handle, close_cb);
ASSERT(r == 0);
/* After accepting the two clients close the server handle */
if (do_accept_called == 2) {
r = uv_close((uv_handle_t*)server, close_cb);
ASSERT(r == 0);
}
/* Dispose the timer. */
r = uv_close(timer_handle, close_cb);
ASSERT(r == 0);
}
static void connection_cb(uv_tcp_t* tcp, int status) {
int r;
uv_timer_t* timer_handle;
ASSERT(status == 0);
timer_handle = (uv_timer_t*)malloc(sizeof *timer_handle);
ASSERT(timer_handle != NULL);
/* Accept the client after 1 second */
r = uv_timer_init(timer_handle);
ASSERT(r == 0);
timer_handle->data = tcp;
r = uv_timer_start(timer_handle, do_accept, 1000, 0);
ASSERT(r == 0);
connection_cb_called++;
}
static void start_server() {
struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", TEST_PORT);
uv_tcp_t* server = (uv_tcp_t*)malloc(sizeof *server);
int r;
ASSERT(server != NULL);
r = uv_tcp_init(server);
ASSERT(r == 0);
ASSERT(uv_counters()->tcp_init == 1);
ASSERT(uv_counters()->handle_init == 1);
r = uv_bind(server, addr);
ASSERT(r == 0);
r = uv_listen(server, 128, connection_cb);
ASSERT(r == 0);
}
static void read_cb(uv_tcp_t* tcp, ssize_t nread, uv_buf_t buf) {
/* The server will not send anything, it should close gracefully. */
ASSERT(tcp != NULL);
ASSERT(nread == -1);
ASSERT(uv_last_error().code == UV_EOF);
if (buf.base) {
free(buf.base);
}
uv_close((uv_handle_t*)tcp, close_cb);
}
static void connect_cb(uv_req_t* req, int status) {
int r;
ASSERT(req != NULL);
ASSERT(status == 0);
/* Not that the server will send anything, but otherwise we'll never know */
/* when te server closes the connection. */
r = uv_read_start((uv_tcp_t*)(req->handle), alloc_cb, read_cb);
ASSERT(r == 0);
connect_cb_called++;
free(req);
}
static void client_connect() {
struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
uv_tcp_t* client = (uv_tcp_t*)malloc(sizeof *client);
uv_req_t* connect_req = (uv_req_t*)malloc(sizeof *connect_req);
int r;
ASSERT(client != NULL);
ASSERT(connect_req != NULL);
r = uv_tcp_init(client);
ASSERT(r == 0);
uv_req_init(connect_req, (uv_handle_t*)client, connect_cb);
r = uv_connect(connect_req, addr);
ASSERT(r == 0);
}
TEST_IMPL(delayed_accept) {
uv_init();
start_server();
client_connect();
client_connect();
uv_run();
ASSERT(connection_cb_called == 2);
ASSERT(do_accept_called == 2);
ASSERT(connect_cb_called == 2);
ASSERT(close_cb_called == 7);
return 0;
}

View file

@ -0,0 +1,29 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "task.h"
TEST_IMPL(fail_always) {
/* This test always fails. It is used to test the test runner. */
FATAL("Yes, it always fails");
return 2;
}

View file

@ -0,0 +1,53 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "../uv.h"
#include "task.h"
#include <string.h>
#define PATHMAX 1024
extern char executable_path[];
TEST_IMPL(get_currentexe) {
char buffer[PATHMAX];
size_t size;
char* match;
int r;
size = sizeof(buffer) / sizeof(buffer[0]);
r = uv_get_exepath(buffer, &size);
ASSERT(!r);
match = strstr(buffer, executable_path);
/* Verify that the path returned from uv_get_exepath is a subdirectory of executable_path */
ASSERT(match && !strcmp(match, executable_path));
ASSERT(size == strlen(buffer));
/* Negative tests */
size = sizeof(buffer) / sizeof(buffer[0]);
r = uv_get_exepath(NULL, &size);
ASSERT(r == -1);
r = uv_get_exepath(buffer, NULL);
ASSERT(r == -1);
return 0;
}

View file

@ -0,0 +1,98 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
TEST_DECLARE (ping_pong)
TEST_DECLARE (delayed_accept)
TEST_DECLARE (tcp_writealot)
TEST_DECLARE (bind_error_addrinuse)
TEST_DECLARE (bind_error_addrnotavail_1)
TEST_DECLARE (bind_error_addrnotavail_2)
TEST_DECLARE (bind_error_fault)
TEST_DECLARE (bind_error_inval)
TEST_DECLARE (connection_fail)
TEST_DECLARE (connection_fail_doesnt_auto_close)
TEST_DECLARE (shutdown_eof)
TEST_DECLARE (callback_stack)
TEST_DECLARE (timer)
TEST_DECLARE (timer_again)
TEST_DECLARE (loop_handles)
TEST_DECLARE (ref)
TEST_DECLARE (idle_ref)
TEST_DECLARE (async_ref)
TEST_DECLARE (prepare_ref)
TEST_DECLARE (check_ref)
TEST_DECLARE (async)
TEST_DECLARE (get_currentexe)
TEST_DECLARE (fail_always)
TEST_DECLARE (pass_always)
HELPER_DECLARE (echo_server)
TASK_LIST_START
TEST_ENTRY (ping_pong)
TEST_HELPER (ping_pong, echo_server)
TEST_ENTRY (delayed_accept)
TEST_ENTRY (tcp_writealot)
TEST_HELPER (tcp_writealot, echo_server)
TEST_ENTRY (bind_error_addrinuse)
TEST_ENTRY (bind_error_addrnotavail_1)
TEST_ENTRY (bind_error_addrnotavail_2)
TEST_ENTRY (bind_error_fault)
TEST_ENTRY (bind_error_inval)
TEST_ENTRY (connection_fail)
TEST_ENTRY (connection_fail_doesnt_auto_close)
TEST_ENTRY (shutdown_eof)
TEST_HELPER (shutdown_eof, echo_server)
TEST_ENTRY (callback_stack)
TEST_HELPER (callback_stack, echo_server)
TEST_ENTRY (timer)
TEST_ENTRY (timer_again)
TEST_ENTRY (ref)
TEST_ENTRY (idle_ref)
TEST_ENTRY (async_ref)
TEST_ENTRY (prepare_ref)
TEST_ENTRY (check_ref)
TEST_ENTRY (loop_handles)
TEST_ENTRY (async)
TEST_ENTRY (get_currentexe)
#if 0
/* These are for testing the test runner. */
TEST_ENTRY (fail_always)
TEST_ENTRY (pass_always)
#endif
TASK_LIST_END

View file

@ -0,0 +1,419 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
/* Tests commented out with XXX are ones that are failing on Linux */
/*
* Purpose of this test is to check semantics of starting and stopping
* prepare, check and idle watchers.
*
* - A watcher must be able to safely stop or close itself;
* - Once a watcher is stopped or closed its callback should never be called.
* - If a watcher is closed, it is implicitly stopped and its close_cb should
* be called exactly once.
* - A watcher can safely start and stop other watchers of the same type.
* - Prepare and check watchers are called once per event loop iterations.
* - All active idle watchers are queued when the event loop has no more work
* to do. This is done repeatedly until all idle watchers are inactive.
* - If a watcher starts another watcher of the same type its callback is not
* immediately queued. For check and prepare watchers, that means that if
* a watcher makes another of the same type active, it'll not be called until
* the next event loop iteration. For idle. watchers this means that the
* newly activated idle watcher might not be queued immediately.
* - Prepare, check, idle watchers keep the event loop alive even when they're
* not active.
*
* This is what the test globally does:
*
* - prepare_1 is always active and counts event loop iterations. It also
* creates and starts prepare_2 every other iteration. Finally it verifies
* that no idle watchers are active before polling.
* - prepare_2 is started by prepare_1 every other iteration. It immediately
* stops itself. It verifies that a watcher is not queued immediately
* if created by another watcher of the same type.
* - There's a check watcher that stops the event loop after a certain number
* of iterations. It starts a varying number of idle_1 watchers.
* - Idle_1 watchers stop themselves after being called a few times. All idle_1
* watchers try to start the idle_2 watcher if it is not already started or
* awaiting its close callback.
* - The idle_2 watcher always exists but immediately closes itself after
* being started by a check_1 watcher. It verifies that a watcher is
* implicitly stopped when closed, and that a watcher can close itself
* safely.
* - There is a repeating timer. It does not keep te event loop alive
* (ev_unref) but makes sure that the loop keeps polling the system for
* events.
*/
#include "../uv.h"
#include "task.h"
#include <math.h>
#define IDLE_COUNT 7
#define ITERATIONS 21
#define TIMEOUT 100
static uv_prepare_t prepare_1_handle;
static uv_prepare_t prepare_2_handle;
static uv_check_t check_handle;
static uv_idle_t idle_1_handles[IDLE_COUNT];
static uv_idle_t idle_2_handle;
static uv_timer_t timer_handle;
static int loop_iteration = 0;
static int prepare_1_cb_called = 0;
static int prepare_1_close_cb_called = 0;
static int prepare_2_cb_called = 0;
static int prepare_2_close_cb_called = 0;
static int check_cb_called = 0;
static int check_close_cb_called = 0;
static int idle_1_cb_called = 0;
static int idle_1_close_cb_called = 0;
static int idles_1_active = 0;
static int idle_2_cb_called = 0;
static int idle_2_close_cb_called = 0;
static int idle_2_cb_started = 0;
static int idle_2_is_active = 0;
static int timer_cb_called = 0;
static void timer_cb(uv_handle_t* handle, int status) {
ASSERT(handle == (uv_handle_t*)&timer_handle);
ASSERT(status == 0);
timer_cb_called++;
}
static void idle_2_close_cb(uv_handle_t* handle) {
LOG("IDLE_2_CLOSE_CB\n");
ASSERT(handle == (uv_handle_t*)&idle_2_handle);
ASSERT(idle_2_is_active);
idle_2_close_cb_called++;
idle_2_is_active = 0;
}
static void idle_2_cb(uv_handle_t* handle, int status) {
int r;
LOG("IDLE_2_CB\n");
ASSERT(handle == (uv_handle_t*)&idle_2_handle);
ASSERT(status == 0);
idle_2_cb_called++;
r = uv_close(handle, idle_2_close_cb);
ASSERT(r == 0);
}
static void idle_1_cb(uv_handle_t* handle, int status) {
int r;
LOG("IDLE_1_CB\n");
ASSERT(handle != NULL);
ASSERT(status == 0);
ASSERT(idles_1_active > 0);
/* Init idle_2 and make it active */
if (!idle_2_is_active) {
r = uv_idle_init(&idle_2_handle);
ASSERT(r == 0);
r = uv_idle_start(&idle_2_handle, idle_2_cb);
ASSERT(r == 0);
idle_2_is_active = 1;
idle_2_cb_started++;
}
idle_1_cb_called++;
if (idle_1_cb_called % 5 == 0) {
r = uv_idle_stop((uv_idle_t*)handle);
ASSERT(r == 0);
idles_1_active--;
}
}
static void idle_1_close_cb(uv_handle_t* handle) {
LOG("IDLE_1_CLOSE_CB\n");
ASSERT(handle != NULL);
idle_1_close_cb_called++;
}
static void prepare_1_close_cb(uv_handle_t* handle) {
LOG("PREPARE_1_CLOSE_CB");
ASSERT(handle == (uv_handle_t*)&prepare_1_handle);
prepare_1_close_cb_called++;
}
static void check_close_cb(uv_handle_t* handle) {
LOG("CHECK_CLOSE_CB\n");
ASSERT(handle == (uv_handle_t*)&check_handle);
check_close_cb_called++;
}
static void prepare_2_close_cb(uv_handle_t* handle) {
LOG("PREPARE_2_CLOSE_CB\n");
ASSERT(handle == (uv_handle_t*)&prepare_2_handle);
prepare_2_close_cb_called++;
}
static void check_cb(uv_handle_t* handle, int status) {
int i, r;
LOG("CHECK_CB\n");
ASSERT(handle == (uv_handle_t*)&check_handle);
ASSERT(status == 0);
/* XXX
ASSERT(idles_1_active == 0);
ASSERT(idle_2_is_active == 0);
*/
if (loop_iteration < ITERATIONS) {
/* Make some idle watchers active */
for (i = 0; i < 1 + (loop_iteration % IDLE_COUNT); i++) {
r = uv_idle_start(&idle_1_handles[i], idle_1_cb);
ASSERT(r == 0);
idles_1_active++;
}
} else {
/* End of the test - close all handles */
r = uv_close((uv_handle_t*)&prepare_1_handle, prepare_1_close_cb);
ASSERT(r == 0);
r = uv_close((uv_handle_t*)&check_handle, check_close_cb);
ASSERT(r == 0);
r = uv_close((uv_handle_t*)&prepare_2_handle, prepare_2_close_cb);
ASSERT(r == 0);
for (i = 0; i < IDLE_COUNT; i++) {
r = uv_close((uv_handle_t*)&idle_1_handles[i], idle_1_close_cb);
ASSERT(r == 0);
}
/* This handle is closed/recreated every time, close it only if it is */
/* active.*/
if (idle_2_is_active) {
r = uv_close((uv_handle_t*)&idle_2_handle, idle_2_close_cb);
ASSERT(r == 0);
}
}
check_cb_called++;
}
static void prepare_2_cb(uv_handle_t* handle, int status) {
int r;
LOG("PREPARE_2_CB\n");
ASSERT(handle == (uv_handle_t*)&prepare_2_handle);
ASSERT(status == 0);
/* XXX ASSERT(idles_1_active == 0); */
/* XXX ASSERT(idle_2_is_active == 0); */
/* prepare_2 gets started by prepare_1 when (loop_iteration % 2 == 0), */
/* and it stops itself immediately. A started watcher is not queued */
/* until the next round, so when this callback is made */
/* (loop_iteration % 2 == 0) cannot be true. */
ASSERT(loop_iteration % 2 != 0);
r = uv_prepare_stop((uv_prepare_t*)handle);
ASSERT(r == 0);
prepare_2_cb_called++;
}
static void prepare_1_cb(uv_handle_t* handle, int status) {
int r;
LOG("PREPARE_1_CB\n");
ASSERT(handle == (uv_handle_t*)&prepare_1_handle);
ASSERT(status == 0);
/* XXX
ASSERT(idles_1_active == 0);
ASSERT(idle_2_is_active == 0);
*/
if (loop_iteration % 2 == 0) {
r = uv_prepare_start(&prepare_2_handle, prepare_2_cb);
ASSERT(r == 0);
}
prepare_1_cb_called++;
loop_iteration++;
printf("Loop iteration %d of %d.\n", loop_iteration, ITERATIONS);
}
TEST_IMPL(loop_handles) {
int i;
int r;
uv_init();
r = uv_prepare_init(&prepare_1_handle);
ASSERT(r == 0);
r = uv_prepare_start(&prepare_1_handle, prepare_1_cb);
ASSERT(r == 0);
r = uv_check_init(&check_handle);
ASSERT(r == 0);
r = uv_check_start(&check_handle, check_cb);
ASSERT(r == 0);
/* initialize only, prepare_2 is started by prepare_1_cb */
r = uv_prepare_init(&prepare_2_handle);
ASSERT(r == 0);
for (i = 0; i < IDLE_COUNT; i++) {
/* initialize only, idle_1 handles are started by check_cb */
r = uv_idle_init(&idle_1_handles[i]);
ASSERT(r == 0);
}
/* don't init or start idle_2, both is done by idle_1_cb */
/* the timer callback is there to keep the event loop polling */
/* unref it as it is not supposed to keep the loop alive */
r = uv_timer_init(&timer_handle);
ASSERT(r == 0);
r = uv_timer_start(&timer_handle, timer_cb, TIMEOUT, TIMEOUT);
ASSERT(r == 0);
uv_unref();
r = uv_run();
ASSERT(r == 0);
ASSERT(loop_iteration == ITERATIONS);
ASSERT(prepare_1_cb_called == ITERATIONS);
ASSERT(prepare_1_close_cb_called == 1);
ASSERT(prepare_2_cb_called == floor(ITERATIONS / 2.0));
ASSERT(prepare_2_close_cb_called == 1);
ASSERT(check_cb_called == ITERATIONS);
ASSERT(check_close_cb_called == 1);
/* idle_1_cb should be called a lot */
/* XXX ASSERT(idle_1_cb_called >= ITERATIONS * IDLE_COUNT * 2); */
ASSERT(idle_1_close_cb_called == IDLE_COUNT);
/* XXX ASSERT(idles_1_active == 0); */
/* XXX ASSERT(idle_2_cb_started >= ITERATIONS); */
/* XXX ASSERT(idle_2_cb_called == idle_2_cb_started); */
ASSERT(idle_2_close_cb_called == idle_2_cb_started);
ASSERT(idle_2_is_active == 0);
ASSERT(timer_cb_called > 0);
return 0;
}
TEST_IMPL(ref) {
uv_init();
uv_run();
return 0;
}
TEST_IMPL(idle_ref) {
uv_idle_t h;
uv_init();
uv_idle_init(&h);
uv_idle_start(&h, NULL);
uv_unref();
uv_run();
return 0;
}
TEST_IMPL(async_ref) {
uv_async_t h;
uv_init();
uv_async_init(&h, NULL);
uv_unref();
uv_run();
return 0;
}
TEST_IMPL(prepare_ref) {
uv_prepare_t h;
uv_init();
uv_prepare_init(&h);
uv_prepare_start(&h, NULL);
uv_unref();
uv_run();
return 0;
}
TEST_IMPL(check_ref) {
uv_check_t h;
uv_init();
uv_check_init(&h);
uv_check_start(&h, NULL);
uv_unref();
uv_run();
return 0;
}

View file

@ -0,0 +1,28 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "task.h"
TEST_IMPL(pass_always) {
/* This test always passes. It is used to test the test runner. */
return 0;
}

View file

@ -0,0 +1,177 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "../uv.h"
#include "task.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h> /* strlen */
static int completed_pingers = 0;
#define NUM_PINGS 1000
/* 64 bytes is enough for a pinger */
#define BUFSIZE 10240
static char PING[] = "PING\n";
typedef struct {
int pongs;
int state;
uv_tcp_t tcp;
uv_req_t connect_req;
uv_req_t read_req;
char read_buffer[BUFSIZE];
} pinger_t;
void pinger_try_read(pinger_t* pinger);
static uv_buf_t alloc_cb(uv_tcp_t* tcp, size_t size) {
uv_buf_t buf;
buf.base = (char*)malloc(size);
buf.len = size;
return buf;
}
static void pinger_on_close(uv_handle_t* handle) {
pinger_t* pinger = (pinger_t*)handle->data;
ASSERT(NUM_PINGS == pinger->pongs);
free(pinger);
completed_pingers++;
}
static void pinger_after_write(uv_req_t *req, int status) {
ASSERT(status == 0);
free(req);
}
static void pinger_write_ping(pinger_t* pinger) {
uv_req_t *req;
uv_buf_t buf;
buf.base = (char*)&PING;
buf.len = strlen(PING);
req = (uv_req_t*)malloc(sizeof(*req));
uv_req_init(req, (uv_handle_t*)(&pinger->tcp), pinger_after_write);
if (uv_write(req, &buf, 1)) {
FATAL("uv_write failed");
}
puts("PING");
}
static void pinger_read_cb(uv_tcp_t* tcp, ssize_t nread, uv_buf_t buf) {
unsigned int i;
pinger_t* pinger;
pinger = (pinger_t*)tcp->data;
if (nread < 0) {
ASSERT(uv_last_error().code == UV_EOF);
puts("got EOF");
if (buf.base) {
free(buf.base);
}
uv_close((uv_handle_t*)(&pinger->tcp), pinger_on_close);
return;
}
/* Now we count the pings */
for (i = 0; i < nread; i++) {
ASSERT(buf.base[i] == PING[pinger->state]);
pinger->state = (pinger->state + 1) % (sizeof(PING) - 1);
if (pinger->state == 0) {
printf("PONG %d\n", pinger->pongs);
pinger->pongs++;
if (pinger->pongs < NUM_PINGS) {
pinger_write_ping(pinger);
} else {
uv_close((uv_handle_t*)(&pinger->tcp), pinger_on_close);
return;
}
}
}
}
static void pinger_on_connect(uv_req_t *req, int status) {
pinger_t *pinger = (pinger_t*)req->handle->data;
ASSERT(status == 0);
pinger_write_ping(pinger);
uv_read_start((uv_tcp_t*)(req->handle), alloc_cb, pinger_read_cb);
}
static void pinger_new() {
int r;
struct sockaddr_in server_addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
pinger_t *pinger;
pinger = (pinger_t*)malloc(sizeof(*pinger));
pinger->state = 0;
pinger->pongs = 0;
/* Try to connec to the server and do NUM_PINGS ping-pongs. */
r = uv_tcp_init(&pinger->tcp);
pinger->tcp.data = pinger;
ASSERT(!r);
/* We are never doing multiple reads/connects at a time anyway. */
/* so these handles can be pre-initialized. */
uv_req_init(&pinger->connect_req, (uv_handle_t*)(&pinger->tcp),
pinger_on_connect);
r = uv_connect(&pinger->connect_req, server_addr);
ASSERT(!r);
}
TEST_IMPL(ping_pong) {
uv_init();
pinger_new();
uv_run();
ASSERT(completed_pingers == 1);
return 0;
}

View file

@ -0,0 +1,176 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "../uv.h"
#include "task.h"
#include <stdio.h>
#include <stdlib.h>
static uv_timer_t timer;
static uv_tcp_t tcp;
static uv_req_t connect_req, write_req, shutdown_req;
static uv_buf_t qbuf;
static int got_q;
static int got_eof;
static int called_connect_cb;
static int called_shutdown_cb;
static int called_tcp_close_cb;
static int called_timer_close_cb;
static int called_timer_cb;
static uv_buf_t alloc_cb(uv_tcp_t* tcp, size_t size) {
uv_buf_t buf;
buf.base = (char*)malloc(size);
buf.len = size;
return buf;
}
static void read_cb(uv_tcp_t* t, ssize_t nread, uv_buf_t buf) {
ASSERT(t == &tcp);
if (!got_q) {
ASSERT(nread == 1);
ASSERT(!got_eof);
ASSERT(buf.base[0] == 'Q');
free(buf.base);
got_q = 1;
puts("got Q");
} else {
ASSERT(uv_last_error().code == UV_EOF);
if (buf.base) {
free(buf.base);
}
got_eof = 1;
puts("got EOF");
}
}
static void shutdown_cb(uv_req_t *req, int status) {
ASSERT(req == &shutdown_req);
ASSERT(called_connect_cb == 1);
ASSERT(!got_eof);
ASSERT(called_tcp_close_cb == 0);
ASSERT(called_timer_close_cb == 0);
ASSERT(called_timer_cb == 0);
called_shutdown_cb++;
}
static void connect_cb(uv_req_t *req, int status) {
ASSERT(status == 0);
ASSERT(req == &connect_req);
/* Start reading from our connection so we can receive the EOF. */
uv_read_start(&tcp, alloc_cb, read_cb);
/*
* Write the letter 'Q' to gracefully kill the echo-server. This will not
* effect our connection.
*/
uv_req_init(&write_req, (uv_handle_t*)&tcp, NULL);
uv_write(&write_req, &qbuf, 1);
/* Shutdown our end of the connection. */
uv_req_init(&shutdown_req, (uv_handle_t*)&tcp, shutdown_cb);
uv_shutdown(&shutdown_req);
called_connect_cb++;
ASSERT(called_shutdown_cb == 0);
}
void tcp_close_cb(uv_handle_t* handle) {
ASSERT(handle == (uv_handle_t*) &tcp);
ASSERT(called_connect_cb == 1);
ASSERT(got_q);
ASSERT(got_eof);
ASSERT(called_timer_cb == 1);
called_tcp_close_cb++;
}
void timer_close_cb(uv_handle_t* handle) {
ASSERT(handle == (uv_handle_t*) &timer);
called_timer_close_cb++;
}
void timer_cb(uv_handle_t* handle, int status) {
ASSERT(handle == (uv_handle_t*) &timer);
uv_close(handle, timer_close_cb);
/*
* The most important assert of the test: we have not received
* tcp_close_cb yet.
*/
ASSERT(called_tcp_close_cb == 0);
uv_close((uv_handle_t*) &tcp, tcp_close_cb);
called_timer_cb++;
}
/*
* This test has a client which connects to the echo_server and immediately
* issues a shutdown. The echo-server, in response, will also shutdown their
* connection. We check, with a timer, that libuv is not automatically
* calling uv_close when the client receives the EOF from echo-server.
*/
TEST_IMPL(shutdown_eof) {
struct sockaddr_in server_addr;
int r;
uv_init();
qbuf.base = "Q";
qbuf.len = 1;
uv_timer_init(&timer);
uv_timer_start(&timer, timer_cb, 100, 0);
server_addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
r = uv_tcp_init(&tcp);
ASSERT(!r);
uv_req_init(&connect_req, (uv_handle_t*) &tcp, connect_cb);
r = uv_connect(&connect_req, server_addr);
ASSERT(!r);
uv_run();
ASSERT(called_connect_cb == 1);
ASSERT(called_shutdown_cb == 1);
ASSERT(got_eof);
ASSERT(got_q);
ASSERT(called_tcp_close_cb == 1);
ASSERT(called_timer_close_cb == 1);
ASSERT(called_timer_cb == 1);
return 0;
}

View file

@ -0,0 +1,202 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "../uv.h"
#include "task.h"
#include <stdio.h>
#include <stdlib.h>
#define WRITES 3
#define CHUNKS_PER_WRITE 3
#define CHUNK_SIZE 10485760 /* 10 MB */
#define TOTAL_BYTES (WRITES * CHUNKS_PER_WRITE * CHUNK_SIZE)
static char* send_buffer;
static int shutdown_cb_called = 0;
static int connect_cb_called = 0;
static int write_cb_called = 0;
static int close_cb_called = 0;
static int bytes_sent = 0;
static int bytes_sent_done = 0;
static int bytes_received = 0;
static int bytes_received_done = 0;
static uv_buf_t alloc_cb(uv_tcp_t* tcp, size_t size) {
uv_buf_t buf;
buf.base = (char*)malloc(size);
buf.len = size;
return buf;
}
static void close_cb(uv_handle_t* handle) {
ASSERT(handle != NULL);
free(handle);
close_cb_called++;
}
static void shutdown_cb(uv_req_t* req, int status) {
uv_tcp_t* tcp;
ASSERT(req);
ASSERT(status == 0);
tcp = (uv_tcp_t*)(req->handle);
/* The write buffer should be empty by now. */
ASSERT(tcp->write_queue_size == 0);
/* Now we wait for the EOF */
shutdown_cb_called++;
/* We should have had all the writes called already. */
ASSERT(write_cb_called == WRITES);
free(req);
}
static void read_cb(uv_tcp_t* tcp, ssize_t nread, uv_buf_t buf) {
ASSERT(tcp != NULL);
if (nread < 0) {
ASSERT(uv_last_error().code == UV_EOF);
printf("GOT EOF\n");
if (buf.base) {
free(buf.base);
}
uv_close((uv_handle_t*)tcp, close_cb);
return;
}
bytes_received_done += nread;
free(buf.base);
}
static void write_cb(uv_req_t* req, int status) {
ASSERT(req != NULL);
if (status) {
uv_err_t err = uv_last_error();
fprintf(stderr, "uv_write error: %s\n", uv_strerror(err));
ASSERT(0);
}
bytes_sent_done += CHUNKS_PER_WRITE * CHUNK_SIZE;
write_cb_called++;
free(req);
}
static void connect_cb(uv_req_t* req, int status) {
uv_buf_t send_bufs[CHUNKS_PER_WRITE];
uv_tcp_t* tcp;
int i, j, r;
ASSERT(req != NULL);
ASSERT(status == 0);
tcp = (uv_tcp_t*)req->handle;
connect_cb_called++;
free(req);
/* Write a lot of data */
for (i = 0; i < WRITES; i++) {
for (j = 0; j < CHUNKS_PER_WRITE; j++) {
send_bufs[j].len = CHUNK_SIZE;
send_bufs[j].base = send_buffer + bytes_sent;
bytes_sent += CHUNK_SIZE;
}
req = (uv_req_t*)malloc(sizeof *req);
ASSERT(req != NULL);
uv_req_init(req, (uv_handle_t*)tcp, write_cb);
r = uv_write(req, (uv_buf_t*)&send_bufs, CHUNKS_PER_WRITE);
ASSERT(r == 0);
}
/* Shutdown on drain. FIXME: dealloc req? */
req = (uv_req_t*) malloc(sizeof(uv_req_t));
ASSERT(req != NULL);
uv_req_init(req, (uv_handle_t*)tcp, shutdown_cb);
r = uv_shutdown(req);
ASSERT(r == 0);
/* Start reading */
req = (uv_req_t*)malloc(sizeof *req);
ASSERT(req != NULL);
uv_req_init(req, (uv_handle_t*)tcp, read_cb);
r = uv_read_start(tcp, alloc_cb, read_cb);
ASSERT(r == 0);
}
TEST_IMPL(tcp_writealot) {
struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
uv_tcp_t* client = (uv_tcp_t*)malloc(sizeof *client);
uv_req_t* connect_req = (uv_req_t*)malloc(sizeof *connect_req);
int r;
ASSERT(client != NULL);
ASSERT(connect_req != NULL);
send_buffer = (char*)malloc(TOTAL_BYTES + 1);
ASSERT(send_buffer != NULL);
uv_init();
r = uv_tcp_init(client);
ASSERT(r == 0);
uv_req_init(connect_req, (uv_handle_t*)client, connect_cb);
r = uv_connect(connect_req, addr);
ASSERT(r == 0);
uv_run();
ASSERT(shutdown_cb_called == 1);
ASSERT(connect_cb_called == 1);
ASSERT(write_cb_called == WRITES);
ASSERT(close_cb_called == 1);
ASSERT(bytes_sent == TOTAL_BYTES);
ASSERT(bytes_sent_done == TOTAL_BYTES);
ASSERT(bytes_received_done == TOTAL_BYTES);
return 0;
}

View file

@ -0,0 +1,141 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "../uv.h"
#include "task.h"
static int close_cb_called = 0;
static int repeat_1_cb_called = 0;
static int repeat_2_cb_called = 0;
static int repeat_2_cb_allowed = 0;
static uv_timer_t dummy, repeat_1, repeat_2;
static int64_t start_time;
static void close_cb(uv_handle_t* handle) {
ASSERT(handle != NULL);
close_cb_called++;
}
static void repeat_1_cb(uv_handle_t* handle, int status) {
int r;
ASSERT(handle == (uv_handle_t*)&repeat_1);
ASSERT(status == 0);
ASSERT(uv_timer_get_repeat((uv_timer_t*)handle) == 50);
LOGF("repeat_1_cb called after %ld ms\n", (long int)(uv_now() - start_time));
repeat_1_cb_called++;
r = uv_timer_again(&repeat_2);
ASSERT(r == 0);
if (uv_now() >= start_time + 500) {
uv_close(handle, close_cb);
/* We're not calling uv_timer_again on repeat_2 any more, so after this */
/* timer_2_cb is expected. */
repeat_2_cb_allowed = 1;
return;
}
}
static void repeat_2_cb(uv_handle_t* handle, int status) {
ASSERT(handle == (uv_handle_t*) &repeat_2);
ASSERT(status == 0);
ASSERT(repeat_2_cb_allowed);
LOGF("repeat_2_cb called after %ld ms\n", (long int)(uv_now() - start_time));
repeat_2_cb_called++;
if (uv_timer_get_repeat(&repeat_2) == 0) {
ASSERT(!uv_is_active(handle));
uv_close(handle, close_cb);
return;
}
LOGF("uv_timer_get_repeat %ld ms\n",
(long int)uv_timer_get_repeat(&repeat_2));
ASSERT(uv_timer_get_repeat(&repeat_2) == 100);
/* This shouldn't take effect immediately. */
uv_timer_set_repeat(&repeat_2, 0);
}
TEST_IMPL(timer_again) {
int r;
uv_init();
start_time = uv_now();
ASSERT(0 < start_time);
/* Verify that it is not possible to uv_timer_again a never-started timer. */
r = uv_timer_init(&dummy);
ASSERT(r == 0);
r = uv_timer_again(&dummy);
ASSERT(r == -1);
ASSERT(uv_last_error().code == UV_EINVAL);
uv_unref();
/* Start timer repeat_1. */
r = uv_timer_init(&repeat_1);
ASSERT(r == 0);
r = uv_timer_start(&repeat_1, repeat_1_cb, 50, 0);
ASSERT(r == 0);
ASSERT(uv_timer_get_repeat(&repeat_1) == 0);
/* Actually make repeat_1 repeating. */
uv_timer_set_repeat(&repeat_1, 50);
ASSERT(uv_timer_get_repeat(&repeat_1) == 50);
/*
* Start another repeating timer. It'll be again()ed by the repeat_1 so
* it should not time out until repeat_1 stops.
*/
r = uv_timer_init(&repeat_2);
ASSERT(r == 0);
r = uv_timer_start(&repeat_2, repeat_2_cb, 100, 100);
ASSERT(r == 0);
ASSERT(uv_timer_get_repeat(&repeat_2) == 100);
uv_run();
ASSERT(repeat_1_cb_called == 10);
ASSERT(repeat_2_cb_called == 2);
ASSERT(close_cb_called == 2);
LOGF("Test took %ld ms (expected ~700 ms)\n",
(long int)(uv_now() - start_time));
ASSERT(700 <= uv_now() - start_time);
return 0;
}

View file

@ -0,0 +1,134 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "../uv.h"
#include "task.h"
static int once_cb_called = 0;
static int once_close_cb_called = 0;
static int repeat_cb_called = 0;
static int repeat_close_cb_called = 0;
static int64_t start_time;
static void once_close_cb(uv_handle_t* handle) {
printf("ONCE_CLOSE_CB\n");
ASSERT(handle != NULL);
once_close_cb_called++;
free(handle);
}
static void once_cb(uv_handle_t* handle, int status) {
printf("ONCE_CB %d\n", once_cb_called);
ASSERT(handle != NULL);
ASSERT(status == 0);
once_cb_called++;
uv_close(handle, once_close_cb);
/* Just call this randomly for the code coverage. */
uv_update_time();
}
static void repeat_close_cb(uv_handle_t* handle) {
printf("REPEAT_CLOSE_CB\n");
ASSERT(handle != NULL);
repeat_close_cb_called++;
}
static void repeat_cb(uv_handle_t* handle, int status) {
printf("REPEAT_CB\n");
ASSERT(handle != NULL);
ASSERT(status == 0);
repeat_cb_called++;
if (repeat_cb_called == 5) {
uv_close(handle, repeat_close_cb);
}
}
static void never_cb(uv_handle_t* handle, int status) {
FATAL("never_cb should never be called");
}
TEST_IMPL(timer) {
uv_timer_t *once;
uv_timer_t repeat, never;
int i, r;
uv_init();
start_time = uv_now();
ASSERT(0 < start_time);
/* Let 10 timers time out in 500 ms total. */
for (i = 0; i < 10; i++) {
once = (uv_timer_t*)malloc(sizeof(*once));
ASSERT(once != NULL);
r = uv_timer_init(once);
ASSERT(r == 0);
r = uv_timer_start(once, once_cb, i * 50, 0);
ASSERT(r == 0);
}
/* The 11th timer is a repeating timer that runs 4 times */
r = uv_timer_init(&repeat);
ASSERT(r == 0);
r = uv_timer_start(&repeat, repeat_cb, 100, 100);
ASSERT(r == 0);
/* The 12th timer should not do anything. */
r = uv_timer_init(&never);
ASSERT(r == 0);
r = uv_timer_start(&never, never_cb, 100, 100);
ASSERT(r == 0);
r = uv_timer_stop(&never);
ASSERT(r == 0);
uv_unref();
uv_run();
ASSERT(once_cb_called == 10);
ASSERT(once_close_cb_called == 10);
printf("repeat_cb_called %d\n", repeat_cb_called);
ASSERT(repeat_cb_called == 5);
ASSERT(repeat_close_cb_called == 1);
ASSERT(500 <= uv_now() - start_time);
return 0;
}

762
src/rt/libuv/tree.h Normal file
View file

@ -0,0 +1,762 @@
/*-
* 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 _UV_TREE_H_
#define _UV_TREE_H_
#define __unused
/*
* 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 (/*CONSTCOND*/ 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 (/*CONSTCOND*/ 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 (/*CONSTCOND*/ 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 (/*CONSTCOND*/ 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 (/*CONSTCOND*/ 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 (/*CONSTCOND*/ 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)) != 0) { \
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-black 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 (/*CONSTCOND*/ 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 (/*CONSTCOND*/ 0)
#define RB_SET_BLACKRED(black, red, field) do { \
RB_COLOR(black, field) = RB_BLACK; \
RB_COLOR(red, field) = RB_RED; \
} while (/*CONSTCOND*/ 0)
#ifndef RB_AUGMENT
#define RB_AUGMENT(x) do {} while (0)
#endif
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
(tmp) = RB_RIGHT(elm, field); \
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
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 (/*CONSTCOND*/ 0)
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
(tmp) = RB_LEFT(elm, field); \
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
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 (/*CONSTCOND*/ 0)
/* Generates prototypes and inline functions */
#define RB_PROTOTYPE(name, type, field, cmp) \
RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
attr struct type *name##_RB_REMOVE(struct name *, struct type *); \
attr struct type *name##_RB_INSERT(struct name *, struct type *); \
attr struct type *name##_RB_FIND(struct name *, struct type *); \
attr struct type *name##_RB_NFIND(struct name *, struct type *); \
attr struct type *name##_RB_NEXT(struct type *); \
attr struct type *name##_RB_PREV(struct type *); \
attr 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) \
RB_GENERATE_INTERNAL(name, type, field, cmp,)
#define RB_GENERATE_STATIC(name, type, field, cmp) \
RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
attr void \
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
{ \
struct type *parent, *gparent, *tmp; \
while ((parent = RB_PARENT(elm, field)) != NULL && \
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; \
} \
\
attr 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)) \
!= NULL) \
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)) \
!= NULL) \
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; \
} \
\
attr 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)) != NULL) \
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)) != NULL); \
} \
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 */ \
attr 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 */ \
attr 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); \
} \
\
/* Finds the first node greater than or equal to the search key */ \
attr struct type * \
name##_RB_NFIND(struct name *head, struct type *elm) \
{ \
struct type *tmp = RB_ROOT(head); \
struct type *res = NULL; \
int comp; \
while (tmp) { \
comp = cmp(elm, tmp); \
if (comp < 0) { \
res = tmp; \
tmp = RB_LEFT(tmp, field); \
} \
else if (comp > 0) \
tmp = RB_RIGHT(tmp, field); \
else \
return (tmp); \
} \
return (res); \
} \
\
/* ARGSUSED */ \
attr 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); \
} \
\
/* ARGSUSED */ \
attr struct type * \
name##_RB_PREV(struct type *elm) \
{ \
if (RB_LEFT(elm, field)) { \
elm = RB_LEFT(elm, field); \
while (RB_RIGHT(elm, field)) \
elm = RB_RIGHT(elm, field); \
} else { \
if (RB_PARENT(elm, field) && \
(elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
elm = RB_PARENT(elm, field); \
else { \
while (RB_PARENT(elm, field) && \
(elm == RB_LEFT(RB_PARENT(elm, field), field))) \
elm = RB_PARENT(elm, field); \
elm = RB_PARENT(elm, field); \
} \
} \
return (elm); \
} \
\
attr 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_NFIND(name, x, y) name##_RB_NFIND(x, y)
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
#define RB_PREV(name, x, y) name##_RB_PREV(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))
#define RB_FOREACH_FROM(x, name, y) \
for ((x) = (y); \
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
(x) = (y))
#define RB_FOREACH_SAFE(x, name, head, y) \
for ((x) = RB_MIN(name, head); \
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
(x) = (y))
#define RB_FOREACH_REVERSE(x, name, head) \
for ((x) = RB_MAX(name, head); \
(x) != NULL; \
(x) = name##_RB_PREV(x))
#define RB_FOREACH_REVERSE_FROM(x, name, y) \
for ((x) = (y); \
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
(x) = (y))
#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \
for ((x) = RB_MAX(name, head); \
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
(x) = (y))
#endif /* _UV_TREE_H_ */

77
src/rt/libuv/uv-common.c Normal file
View file

@ -0,0 +1,77 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "uv.h"
#include <assert.h>
#include <stddef.h> /* NULL */
static uv_counters_t counters;
uv_counters_t* const uv_counters() {
return &counters;
}
const char* uv_err_name(uv_err_t err) {
switch (err.code) {
case UV_UNKNOWN: return "UNKNOWN";
case UV_OK: return "OK";
case UV_EOF: return "EOF";
case UV_EACCESS: return "EACCESS";
case UV_EAGAIN: return "EAGAIN";
case UV_EADDRINUSE: return "EADDRINUSE";
case UV_EADDRNOTAVAIL: return "EADDRNOTAVAIL";
case UV_EAFNOSUPPORT: return "EAFNOSUPPORT";
case UV_EALREADY: return "EALREADY";
case UV_EBADF: return "EBADF";
case UV_EBUSY: return "EBUSY";
case UV_ECONNABORTED: return "ECONNABORTED";
case UV_ECONNREFUSED: return "ECONNREFUSED";
case UV_ECONNRESET: return "ECONNRESET";
case UV_EDESTADDRREQ: return "EDESTADDRREQ";
case UV_EFAULT: return "EFAULT";
case UV_EHOSTUNREACH: return "EHOSTUNREACH";
case UV_EINTR: return "EINTR";
case UV_EINVAL: return "EINVAL";
case UV_EISCONN: return "EISCONN";
case UV_EMFILE: return "EMFILE";
case UV_ENETDOWN: return "ENETDOWN";
case UV_ENETUNREACH: return "ENETUNREACH";
case UV_ENFILE: return "ENFILE";
case UV_ENOBUFS: return "ENOBUFS";
case UV_ENOMEM: return "ENOMEM";
case UV_ENONET: return "ENONET";
case UV_ENOPROTOOPT: return "ENOPROTOOPT";
case UV_ENOTCONN: return "ENOTCONN";
case UV_ENOTSOCK: return "ENOTSOCK";
case UV_ENOTSUP: return "ENOTSUP";
case UV_EPROTO: return "EPROTO";
case UV_EPROTONOSUPPORT: return "EPROTONOSUPPORT";
case UV_EPROTOTYPE: return "EPROTOTYPE";
case UV_ETIMEDOUT: return "ETIMEDOUT";
default:
assert(0);
return NULL;
}
}

1301
src/rt/libuv/uv-unix.c Normal file

File diff suppressed because it is too large Load diff

100
src/rt/libuv/uv-unix.h Normal file
View file

@ -0,0 +1,100 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef UV_UNIX_H
#define UV_UNIX_H
#include "ngx-queue.h"
#include "ev/ev.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
/* Note: May be cast to struct iovec. See writev(2). */
typedef struct {
char* base;
size_t len;
} uv_buf_t;
#define UV_REQ_PRIVATE_FIELDS \
int write_index; \
ev_timer timer; \
ngx_queue_t queue; \
uv_buf_t* bufs; \
int bufcnt;
/* TODO: union or classes please! */
#define UV_HANDLE_PRIVATE_FIELDS \
int fd; \
int flags; \
ev_idle next_watcher;
/* UV_TCP */
#define UV_TCP_PRIVATE_FIELDS \
int delayed_error; \
uv_read_cb read_cb; \
uv_alloc_cb alloc_cb; \
uv_connection_cb connection_cb; \
int accepted_fd; \
uv_req_t *connect_req; \
uv_req_t *shutdown_req; \
ev_io read_watcher; \
ev_io write_watcher; \
ngx_queue_t write_queue;
/* UV_PREPARE */ \
#define UV_PREPARE_PRIVATE_FIELDS \
ev_prepare prepare_watcher; \
uv_loop_cb prepare_cb;
/* UV_CHECK */
#define UV_CHECK_PRIVATE_FIELDS \
ev_check check_watcher; \
uv_loop_cb check_cb;
/* UV_IDLE */
#define UV_IDLE_PRIVATE_FIELDS \
ev_idle idle_watcher; \
uv_loop_cb idle_cb;
/* UV_ASYNC */
#define UV_ASYNC_PRIVATE_FIELDS \
ev_async async_watcher; \
uv_loop_cb async_cb;
/* UV_TIMER */
#define UV_TIMER_PRIVATE_FIELDS \
ev_timer timer_watcher; \
uv_loop_cb timer_cb;
#endif /* UV_UNIX_H */

1766
src/rt/libuv/uv-win.c Normal file

File diff suppressed because it is too large Load diff

112
src/rt/libuv/uv-win.h Normal file
View file

@ -0,0 +1,112 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0501
#endif
#include <stdint.h>
#include <winsock2.h>
#include <mswsock.h>
#include <ws2tcpip.h>
#include <windows.h>
#include "tree.h"
/**
* It should be possible to cast uv_buf_t[] to WSABUF[]
* see http://msdn.microsoft.com/en-us/library/ms741542(v=vs.85).aspx
*/
typedef struct uv_buf_t {
ULONG len;
char* base;
} uv_buf_t;
#define UV_REQ_PRIVATE_FIELDS \
union { \
/* Used by I/O operations */ \
struct { \
OVERLAPPED overlapped; \
size_t queued_bytes; \
}; \
}; \
int flags; \
uv_err_t error; \
struct uv_req_s* next_req;
#define uv_tcp_connection_fields \
uv_alloc_cb alloc_cb; \
uv_read_cb read_cb; \
struct uv_req_s read_req; \
unsigned int write_reqs_pending; \
uv_req_t* shutdown_req;
#define uv_tcp_server_fields \
uv_connection_cb connection_cb; \
SOCKET accept_socket; \
struct uv_req_s accept_req; \
char accept_buffer[sizeof(struct sockaddr_storage) * 2 + 32];
#define UV_TCP_PRIVATE_FIELDS \
unsigned int reqs_pending; \
union { \
SOCKET socket; \
HANDLE handle; \
}; \
union { \
struct { uv_tcp_connection_fields }; \
struct { uv_tcp_server_fields }; \
};
#define UV_TIMER_PRIVATE_FIELDS \
RB_ENTRY(uv_timer_s) tree_entry; \
int64_t due; \
int64_t repeat; \
uv_loop_cb timer_cb;
#define UV_LOOP_PRIVATE_FIELDS \
uv_handle_t* loop_prev; \
uv_handle_t* loop_next; \
uv_loop_cb loop_cb;
#define UV_ASYNC_PRIVATE_FIELDS \
struct uv_req_s async_req; \
/* char to avoid alignment issues */ \
char volatile async_sent;
#define UV_PREPARE_PRIVATE_FIELDS /* empty */
#define UV_CHECK_PRIVATE_FIELDS /* empty */
#define UV_IDLE_PRIVATE_FIELDS /* empty */
/*
* TODO: remove UV_LOOP_PRIVATE_FIELDS from UV_HANDLE_PRIVATE_FIELDS and
* use it in UV_(PREPARE|CHECK|IDLE)_PRIVATE_FIELDS instead.
*/
#define UV_HANDLE_PRIVATE_FIELDS \
uv_handle_t* endgame_next; \
unsigned int flags; \
uv_err_t error; \
UV_LOOP_PRIVATE_FIELDS
int uv_utf16_to_utf8(wchar_t* utf16Buffer, size_t utf16Size, char* utf8Buffer, size_t utf8Size);

394
src/rt/libuv/uv.h Normal file
View file

@ -0,0 +1,394 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* 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
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef UV_H
#define UV_H
#ifdef __cplusplus
extern "C" {
#endif
#define UV_VERSION_MAJOR 0
#define UV_VERSION_MINOR 1
#include <stdint.h> /* int64_t */
#include <sys/types.h> /* size_t */
#ifndef ssize_t
typedef intptr_t ssize_t;
#endif
typedef struct uv_err_s uv_err_t;
typedef struct uv_handle_s uv_handle_t;
typedef struct uv_tcp_s uv_tcp_t;
typedef struct uv_timer_s uv_timer_t;
typedef struct uv_prepare_s uv_prepare_t;
typedef struct uv_check_s uv_check_t;
typedef struct uv_idle_s uv_idle_t;
typedef struct uv_req_s uv_req_t;
#if defined(__unix__) || defined(__POSIX__) || defined(__APPLE__)
# include "uv-unix.h"
#else
# include "uv-win.h"
#endif
/* The status parameter is 0 if the request completed successfully,
* and should be -1 if the request was cancelled or failed.
* For uv_close_cb, -1 means that the handle was closed due to an error.
* Error details can be obtained by calling uv_last_error().
*
* In the case of uv_read_cb the uv_buf_t returned should be freed by the
* user.
*/
typedef uv_buf_t (*uv_alloc_cb)(uv_tcp_t* tcp, size_t suggested_size);
typedef void (*uv_read_cb)(uv_tcp_t* tcp, ssize_t nread, uv_buf_t buf);
typedef void (*uv_write_cb)(uv_req_t* req, int status);
typedef void (*uv_connect_cb)(uv_req_t* req, int status);
typedef void (*uv_shutdown_cb)(uv_req_t* req, int status);
typedef void (*uv_connection_cb)(uv_tcp_t* server, int status);
typedef void (*uv_close_cb)(uv_handle_t* handle);
/* TODO: do loop_cb and async_cb really need a status argument? */
typedef void (*uv_loop_cb)(uv_handle_t* handle, int status);
typedef void (*uv_async_cb)(uv_handle_t* handle, int status);
/* Expand this list if necessary. */
typedef enum {
UV_UNKNOWN = -1,
UV_OK = 0,
UV_EOF,
UV_EACCESS,
UV_EAGAIN,
UV_EADDRINUSE,
UV_EADDRNOTAVAIL,
UV_EAFNOSUPPORT,
UV_EALREADY,
UV_EBADF,
UV_EBUSY,
UV_ECONNABORTED,
UV_ECONNREFUSED,
UV_ECONNRESET,
UV_EDESTADDRREQ,
UV_EFAULT,
UV_EHOSTUNREACH,
UV_EINTR,
UV_EINVAL,
UV_EISCONN,
UV_EMFILE,
UV_ENETDOWN,
UV_ENETUNREACH,
UV_ENFILE,
UV_ENOBUFS,
UV_ENOMEM,
UV_ENONET,
UV_ENOPROTOOPT,
UV_ENOTCONN,
UV_ENOTSOCK,
UV_ENOTSUP,
UV_EPROTO,
UV_EPROTONOSUPPORT,
UV_EPROTOTYPE,
UV_ETIMEDOUT
} uv_err_code;
typedef enum {
UV_UNKNOWN_HANDLE = 0,
UV_TCP,
UV_NAMED_PIPE,
UV_TTY,
UV_FILE,
UV_TIMER,
UV_PREPARE,
UV_CHECK,
UV_IDLE,
UV_ASYNC
} uv_handle_type;
typedef enum {
UV_UNKNOWN_REQ = 0,
UV_CONNECT,
UV_ACCEPT,
UV_READ,
UV_WRITE,
UV_SHUTDOWN,
UV_WAKEUP
} uv_req_type;
struct uv_err_s {
/* read-only */
uv_err_code code;
/* private */
int sys_errno_;
};
struct uv_req_s {
/* read-only */
uv_req_type type;
/* public */
uv_handle_t* handle;
void* cb;
void* data;
/* private */
UV_REQ_PRIVATE_FIELDS
};
/*
* Initialize a request for use with uv_write, uv_shutdown, or uv_connect.
*/
void uv_req_init(uv_req_t* req, uv_handle_t* handle, void* cb);
#define UV_HANDLE_FIELDS \
/* read-only */ \
uv_handle_type type; \
/* public */ \
uv_close_cb close_cb; \
void* data; \
/* private */ \
UV_HANDLE_PRIVATE_FIELDS \
/* The abstract base class of all handles. */
struct uv_handle_s {
UV_HANDLE_FIELDS
};
/*
* Returns 1 if the prepare/check/idle handle has been started, 0 otherwise.
* For other handle types this always returns 1.
*/
int uv_is_active(uv_handle_t* handle);
/*
* Request handle to be closed. close_cb will be called asynchronously after
* this call. This MUST be called on each handle before memory is released.
*/
int uv_close(uv_handle_t* handle, uv_close_cb close_cb);
/*
* A subclass of uv_handle_t representing a TCP stream or TCP server. In the
* future this will probably be split into two classes - one a stream and
* the other a server.
*/
struct uv_tcp_s {
UV_HANDLE_FIELDS
size_t write_queue_size; /* number of bytes queued for writing */
UV_TCP_PRIVATE_FIELDS
};
int uv_tcp_init(uv_tcp_t* handle);
int uv_bind(uv_tcp_t* handle, struct sockaddr_in);
int uv_connect(uv_req_t* req, struct sockaddr_in);
int uv_shutdown(uv_req_t* req);
int uv_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb);
/* This call is used in conjunction with uv_listen() to accept incoming TCP
* connections. Call uv_accept after receiving a uv_connection_cb to accept
* the connection. Before calling uv_accept use uv_tcp_init() must be
* called on the client. Non-zero return value indicates an error.
*/
int uv_accept(uv_tcp_t* server, uv_tcp_t* client);
/* Read data from an incoming stream. The callback will be made several
* several times until there is no more data to read or uv_read_stop is
* called. When we've reached EOF nread will be set to -1 and the error is
* set to UV_EOF. When nread == -1 the buf parameter might not point to a
* valid buffer; in that case buf.len and buf.base are both set to 0.
* Note that nread might also be 0, which does *not* indicate an error or
* eof; it happens when libuv requested a buffer through the alloc callback
* but then decided that it didn't need that buffer.
*/
int uv_read_start(uv_tcp_t*, uv_alloc_cb alloc_cb, uv_read_cb read_cb);
int uv_read_stop(uv_tcp_t*);
int uv_write(uv_req_t* req, uv_buf_t bufs[], int bufcnt);
/*
* Subclass of uv_handle_t. libev wrapper. Every active prepare handle gets
* its callback called exactly once per loop iteration, just before the
* system blocks to wait for completed i/o.
*/
struct uv_prepare_s {
UV_HANDLE_FIELDS
UV_PREPARE_PRIVATE_FIELDS
};
int uv_prepare_init(uv_prepare_t* prepare);
int uv_prepare_start(uv_prepare_t* prepare, uv_loop_cb cb);
int uv_prepare_stop(uv_prepare_t* prepare);
/*
* Subclass of uv_handle_t. libev wrapper. Every active check handle gets
* its callback called exactly once per loop iteration, just after the
* system returns from blocking.
*/
struct uv_check_s {
UV_HANDLE_FIELDS
UV_CHECK_PRIVATE_FIELDS
};
int uv_check_init(uv_check_t* check);
int uv_check_start(uv_check_t* check, uv_loop_cb cb);
int uv_check_stop(uv_check_t* check);
/*
* Subclass of uv_handle_t. libev wrapper. Every active idle handle gets its
* callback called repeatedly until it is stopped. This happens after all
* other types of callbacks are processed. When there are multiple "idle"
* handles active, their callbacks are called in turn.
*/
struct uv_idle_s {
UV_HANDLE_FIELDS
UV_IDLE_PRIVATE_FIELDS
};
int uv_idle_init(uv_idle_t* idle);
int uv_idle_start(uv_idle_t* idle, uv_loop_cb cb);
int uv_idle_stop(uv_idle_t* idle);
/*
* Subclass of uv_handle_t. libev wrapper. uv_async_send wakes up the event
* loop and calls the async handle's callback There is no guarantee that
* every uv_async_send call leads to exactly one invocation of the callback;
* The only guarantee is that the callback function is called at least once
* after the call to async_send. Unlike all other libuv functions,
* uv_async_send can be called from another thread.
*/
typedef struct {
UV_HANDLE_FIELDS
UV_ASYNC_PRIVATE_FIELDS
} uv_async_t;
int uv_async_init(uv_async_t* async, uv_async_cb async_cb);
int uv_async_send(uv_async_t* async);
/*
* Subclass of uv_handle_t. Wraps libev's ev_timer watcher. Used to get
* woken up at a specified time in the future.
*/
struct uv_timer_s {
UV_HANDLE_FIELDS
UV_TIMER_PRIVATE_FIELDS
};
int uv_timer_init(uv_timer_t* timer);
int uv_timer_start(uv_timer_t* timer, uv_loop_cb cb, int64_t timeout, int64_t repeat);
int uv_timer_stop(uv_timer_t* timer);
/*
* Stop the timer, and if it is repeating restart it using the repeat value
* as the timeout. If the timer has never been started before it returns -1 and
* sets the error to UV_EINVAL.
*/
int uv_timer_again(uv_timer_t* timer);
/*
* Set the repeat value. Note that if the repeat value is set from a timer
* callback it does not immediately take effect. If the timer was nonrepeating
* before, it will have been stopped. If it was repeating, then the old repeat
* value will have been used to schedule the next timeout.
*/
void uv_timer_set_repeat(uv_timer_t* timer, int64_t repeat);
int64_t uv_timer_get_repeat(uv_timer_t* timer);
/*
* Most functions return boolean: 0 for success and -1 for failure.
* On error the user should then call uv_last_error() to determine
* the error code.
*/
uv_err_t uv_last_error();
char* uv_strerror(uv_err_t err);
const char* uv_err_name(uv_err_t err);
void uv_init();
int uv_run();
/*
* Manually modify the event loop's reference count. Useful if the user wants
* to have a handle or timeout that doesn't keep the loop alive.
*/
void uv_ref();
void uv_unref();
void uv_update_time();
int64_t uv_now();
/* Utility */
struct sockaddr_in uv_ip4_addr(char* ip, int port);
/* Gets the executable path */
int uv_get_exepath(char* buffer, size_t* size);
/* the presence of this union forces similar struct layout */
union uv_any_handle {
uv_tcp_t tcp;
uv_prepare_t prepare;
uv_check_t check;
uv_idle_t idle;
uv_async_t async;
uv_timer_t timer;
};
/* Diagnostic counters */
typedef struct {
uint64_t req_init;
uint64_t handle_init;
uint64_t tcp_init;
uint64_t prepare_init;
uint64_t check_init;
uint64_t idle_init;
uint64_t async_init;
uint64_t timer_init;
} uv_counters_t;
uv_counters_t* const uv_counters();
#ifdef __cplusplus
}
#endif
#endif /* UV_H */