nio4r 0.2.2-java → 0.3.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +6 -2
- data/CHANGES.md +10 -0
- data/LICENSE.txt +1 -1
- data/README.md +16 -11
- data/Rakefile +2 -2
- data/examples/echo_server.rb +9 -0
- data/ext/libev/Changes +34 -2
- data/ext/libev/ev.c +694 -131
- data/ext/libev/ev.h +89 -79
- data/ext/libev/ev_epoll.c +23 -10
- data/ext/libev/ev_kqueue.c +4 -4
- data/ext/libev/ev_poll.c +4 -4
- data/ext/libev/ev_port.c +9 -3
- data/ext/libev/ev_select.c +10 -6
- data/ext/libev/ev_vars.h +3 -2
- data/ext/libev/ev_wrap.h +6 -4
- data/ext/nio4r/monitor.c +23 -6
- data/ext/nio4r/org/nio4r/Nio4r.java +409 -0
- data/ext/nio4r/selector.c +36 -8
- data/lib/nio.rb +4 -7
- data/lib/nio/monitor.rb +15 -4
- data/lib/nio/selector.rb +23 -6
- data/lib/nio/version.rb +1 -1
- data/lib/nio4r_ext.jar +0 -0
- data/nio4r.gemspec +4 -3
- data/spec/nio/acceptables_spec.rb +30 -0
- data/spec/nio/monitor_spec.rb +37 -22
- data/spec/nio/selectables_spec.rb +178 -0
- data/spec/nio/selector_spec.rb +71 -173
- data/tasks/extension.rake +6 -5
- metadata +33 -29
- data/lib/nio/jruby/monitor.rb +0 -42
- data/lib/nio/jruby/selector.rb +0 -136
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
0.3.0
|
2
|
+
-----
|
3
|
+
* NIO::Selector#select now takes a block and behaves like select_each
|
4
|
+
* NIO::Selector#select_each is now deprecated and will be removed
|
5
|
+
* Closing monitors detaches them from their selector
|
6
|
+
* Java extension for JRuby
|
7
|
+
* Upgrade to libev 4.11
|
8
|
+
* Bugfixes for zero/negative select timeouts
|
9
|
+
* Handle OP_CONNECT properly on JRuby
|
10
|
+
|
1
11
|
0.2.2
|
2
12
|
-----
|
3
13
|
* Raise IOError if asked to wake up a closed selector
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -24,6 +24,7 @@ Supported Platforms
|
|
24
24
|
nio4r is known to work on the following Ruby implementations:
|
25
25
|
|
26
26
|
* MRI/YARV 1.8.7, 1.9.2, 1.9.3
|
27
|
+
* REE (2011.12)
|
27
28
|
* JRuby 1.6.x (and likely earlier versions too)
|
28
29
|
* Rubinius 1.x/2.0
|
29
30
|
* A pure Ruby implementation based on Kernel.select is also provided
|
@@ -32,7 +33,7 @@ Platform notes:
|
|
32
33
|
|
33
34
|
* MRI/YARV and Rubinius implement nio4j with a C extension based on libev,
|
34
35
|
which provides a high performance binding to native IO APIs
|
35
|
-
* JRuby uses a
|
36
|
+
* JRuby uses a Java extension based on the high performance Java NIO subsystem
|
36
37
|
* A pure Ruby implementation is also provided for Ruby implementations which
|
37
38
|
don't implement the MRI C extension API
|
38
39
|
|
@@ -99,11 +100,12 @@ ready = selector.select(15) # Wait 15 seconds
|
|
99
100
|
If a timeout occurs, ready will be nil.
|
100
101
|
|
101
102
|
You can avoid allocating an array each time you call NIO::Selector#select by
|
102
|
-
|
103
|
-
|
103
|
+
passing a block to select. The block will be called for each ready monitor
|
104
|
+
object, with that object passed as an argument. The number of ready monitors
|
105
|
+
is returned as a Fixnum:
|
104
106
|
|
105
107
|
```ruby
|
106
|
-
>> selector.
|
108
|
+
>> selector.select { |m| m.value.call }
|
107
109
|
Got some data: Hi there!
|
108
110
|
=> 1
|
109
111
|
```
|
@@ -119,9 +121,9 @@ selector.deregister(reader)
|
|
119
121
|
|
120
122
|
Monitors provide methods which let you introspect on why a particular IO
|
121
123
|
object was selected. These methods are not thread safe unless you are holding
|
122
|
-
the selector lock (i.e. if you're in a #
|
123
|
-
if you aren't concerned with thread safety, or you're within a #
|
124
|
-
|
124
|
+
the selector lock (i.e. if you're in a block pased to #select). Only use them
|
125
|
+
if you aren't concerned with thread safety, or you're within a #select
|
126
|
+
block:
|
125
127
|
|
126
128
|
- ***#interests***: what this monitor is interested in (:r, :w, or :rw)
|
127
129
|
- ***#readiness***: what the monitored IO object is ready for according to the last select operation
|
@@ -152,9 +154,12 @@ nio4r is not a full-featured event framework like EventMachine or Cool.io.
|
|
152
154
|
Instead, nio4r is the sort of thing you might write a library like that on
|
153
155
|
top of. nio4r provides a minimal API such that individual Ruby implementers
|
154
156
|
may choose to produce optimized versions for their platform, without having
|
155
|
-
to maintain a large codebase.
|
156
|
-
|
157
|
-
|
157
|
+
to maintain a large codebase.
|
158
|
+
|
159
|
+
As of the time of writing, the current implementation is
|
160
|
+
* ~200 lines of Ruby code
|
161
|
+
* ~700 lines of "custom" C code (not counting libev)
|
162
|
+
* ~400 lines of Java code
|
158
163
|
|
159
164
|
nio4r is also not a replacement for Kinder Gentler IO (KGIO), a set of
|
160
165
|
advanced Ruby IO APIs. At some point in the future nio4r might provide a
|
@@ -164,7 +169,7 @@ however this is not the case today.
|
|
164
169
|
License
|
165
170
|
-------
|
166
171
|
|
167
|
-
Copyright (c) 2011 Tony Arcieri. Distributed under the MIT License. See
|
172
|
+
Copyright (c) 2011-12 Tony Arcieri. Distributed under the MIT License. See
|
168
173
|
LICENSE.txt for further details.
|
169
174
|
|
170
175
|
Includes libev. Copyright (C)2007-09 Marc Alexander Lehmann. Distributed under
|
data/Rakefile
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
require "bundler/gem_tasks"
|
3
3
|
require "rake/clean"
|
4
4
|
|
5
|
-
Dir["tasks/**/*.rake"].each { |task| load task }
|
5
|
+
Dir[File.expand_path("../tasks/**/*.rake", __FILE__)].each { |task| load task }
|
6
6
|
|
7
7
|
task :default => %w(compile spec)
|
8
8
|
|
9
|
-
CLEAN.include "**/*.o", "**/*.so", "**/*.bundle", "pkg"
|
9
|
+
CLEAN.include "**/*.o", "**/*.so", "**/*.bundle", "**/*.jar", "pkg", "tmp"
|
data/examples/echo_server.rb
CHANGED
@@ -23,6 +23,9 @@ class EchoServer
|
|
23
23
|
|
24
24
|
def accept
|
25
25
|
socket = @server.accept
|
26
|
+
_, port, host = socket.peeraddr
|
27
|
+
puts "*** #{host}:#{port} connected"
|
28
|
+
|
26
29
|
monitor = @selector.register(socket, :r)
|
27
30
|
monitor.value = proc { read(socket) }
|
28
31
|
end
|
@@ -30,6 +33,12 @@ class EchoServer
|
|
30
33
|
def read(socket)
|
31
34
|
data = socket.read_nonblock(4096)
|
32
35
|
socket.write_nonblock(data)
|
36
|
+
rescue EOFError
|
37
|
+
_, port, host = socket.peeraddr
|
38
|
+
puts "*** #{host}:#{port} disconnected"
|
39
|
+
|
40
|
+
@selector.deregister(socket)
|
41
|
+
socket.close
|
33
42
|
end
|
34
43
|
end
|
35
44
|
|
data/ext/libev/Changes
CHANGED
@@ -1,5 +1,37 @@
|
|
1
1
|
Revision history for libev, a high-performance and full-featured event loop.
|
2
2
|
|
3
|
+
TODO: ev_loop_wakeup
|
4
|
+
TODO: EV_STANDALONE == NO_HASSEL (do not use clock_gettime in ev_standalone)
|
5
|
+
|
6
|
+
4.11 Sat Feb 4 19:52:39 CET 2012
|
7
|
+
- INCOMPATIBLE CHANGE: ev_timer_again now clears the pending status, as
|
8
|
+
was documented already, but not implemented in the repeating case.
|
9
|
+
- new compiletime symbols: EV_NO_SMP and EV_NO_THREADS.
|
10
|
+
- fix a race where the workaround against the epoll fork bugs
|
11
|
+
caused signals to not be handled anymore.
|
12
|
+
- correct backend_fudge for most backends, and implement a windows
|
13
|
+
specific workaround to avoid looping because we call both
|
14
|
+
select and Sleep, both with different time resolutions.
|
15
|
+
- document range and guarantees of ev_sleep.
|
16
|
+
- document reasonable ranges for periodics interval and offset.
|
17
|
+
- rename backend_fudge to backend_mintime to avoid future confusion :)
|
18
|
+
- change the default periodic reschedule function to hopefully be more
|
19
|
+
exact and correct even in corner cases or in the far future.
|
20
|
+
- do not rely on -lm anymore: use it when available but use our
|
21
|
+
own floor () if it is missing. This should make it easier to embed,
|
22
|
+
as no external libraries are required.
|
23
|
+
- strategically import macros from libecb and mark rarely-used functions
|
24
|
+
as cache-cold (saving almost 2k code size on typical amd64 setups).
|
25
|
+
- add Symbols.ev and Symbols.event files, that were missing.
|
26
|
+
- fix backend_mintime value for epoll (was 1/1024, is 1/1000 now).
|
27
|
+
- fix #3 "be smart about timeouts" to not "deadlock" when
|
28
|
+
timeout == now, also improve the section overall.
|
29
|
+
- avoid "AVOIDING FINISHING BEFORE RETURNING" idiom.
|
30
|
+
- support new EV_API_STATIC mode to make all libev symbols
|
31
|
+
static.
|
32
|
+
- supply default CFLAGS of -g -O3 with gcc when original CFLAGS
|
33
|
+
were empty.
|
34
|
+
|
3
35
|
4.04 Wed Feb 16 09:01:51 CET 2011
|
4
36
|
- fix two problems in the native win32 backend, where reuse of fd's
|
5
37
|
with different underlying handles caused handles not to be removed
|
@@ -94,7 +126,7 @@ Revision history for libev, a high-performance and full-featured event loop.
|
|
94
126
|
that this is a race condition regardless of EV_SIGNALFD.
|
95
127
|
- backport inotify code to C89.
|
96
128
|
- inotify file descriptors could leak into child processes.
|
97
|
-
- ev_stat watchers could keep an
|
129
|
+
- ev_stat watchers could keep an erroneous extra ref on the loop,
|
98
130
|
preventing exit when unregistering all watchers (testcases
|
99
131
|
provided by ry@tinyclouds.org).
|
100
132
|
- implement EV_WIN32_HANDLE_TO_FD and EV_WIN32_CLOSE_FD configuration
|
@@ -162,7 +194,7 @@ Revision history for libev, a high-performance and full-featured event loop.
|
|
162
194
|
Malek Hadj-Ali).
|
163
195
|
- implement ev_suspend and ev_resume.
|
164
196
|
- new EV_CUSTOM revents flag for use by applications.
|
165
|
-
- add documentation section about
|
197
|
+
- add documentation section about priorities.
|
166
198
|
- add a glossary to the dcoumentation.
|
167
199
|
- extend the ev_fork description slightly.
|
168
200
|
- optimize a jump out of call_pending.
|
data/ext/libev/ev.c
CHANGED
@@ -45,6 +45,12 @@
|
|
45
45
|
# include "config.h"
|
46
46
|
# endif
|
47
47
|
|
48
|
+
#if HAVE_FLOOR
|
49
|
+
# ifndef EV_USE_FLOOR
|
50
|
+
# define EV_USE_FLOOR 1
|
51
|
+
# endif
|
52
|
+
#endif
|
53
|
+
|
48
54
|
# if HAVE_CLOCK_SYSCALL
|
49
55
|
# ifndef EV_USE_CLOCK_SYSCALL
|
50
56
|
# define EV_USE_CLOCK_SYSCALL 1
|
@@ -158,7 +164,6 @@
|
|
158
164
|
|
159
165
|
#endif
|
160
166
|
|
161
|
-
#include <math.h>
|
162
167
|
#include <stdlib.h>
|
163
168
|
#include <string.h>
|
164
169
|
#include <fcntl.h>
|
@@ -180,7 +185,16 @@
|
|
180
185
|
# include "ev.h"
|
181
186
|
#endif
|
182
187
|
|
183
|
-
|
188
|
+
#if EV_NO_THREADS
|
189
|
+
# undef EV_NO_SMP
|
190
|
+
# define EV_NO_SMP 1
|
191
|
+
# undef ECB_NO_THREADS
|
192
|
+
# define ECB_NO_THREADS 1
|
193
|
+
#endif
|
194
|
+
#if EV_NO_SMP
|
195
|
+
# undef EV_NO_SMP
|
196
|
+
# define ECB_NO_SMP 1
|
197
|
+
#endif
|
184
198
|
|
185
199
|
#ifndef _WIN32
|
186
200
|
# include <sys/time.h>
|
@@ -234,6 +248,10 @@ EV_CPP(extern "C" {)
|
|
234
248
|
# define EV_NSIG 65
|
235
249
|
#endif
|
236
250
|
|
251
|
+
#ifndef EV_USE_FLOOR
|
252
|
+
# define EV_USE_FLOOR 0
|
253
|
+
#endif
|
254
|
+
|
237
255
|
#ifndef EV_USE_CLOCK_SYSCALL
|
238
256
|
# if __linux && __GLIBC__ >= 2
|
239
257
|
# define EV_USE_CLOCK_SYSCALL EV_FEATURE_OS
|
@@ -445,14 +463,11 @@ struct signalfd_siginfo
|
|
445
463
|
#endif
|
446
464
|
|
447
465
|
/*
|
448
|
-
* This is used to
|
449
|
-
* It is added to ev_rt_now when scheduling periodics
|
450
|
-
* to ensure progress, time-wise, even when rounding
|
451
|
-
* errors are against us.
|
466
|
+
* This is used to work around floating point rounding problems.
|
452
467
|
* This value is good at least till the year 4000.
|
453
|
-
* Better solutions welcome.
|
454
468
|
*/
|
455
|
-
#define
|
469
|
+
#define MIN_INTERVAL 0.0001220703125 /* 1/2**13, good till 4000 */
|
470
|
+
/*#define MIN_INTERVAL 0.00000095367431640625 /* 1/2**20, good till 2200 */
|
456
471
|
|
457
472
|
#define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */
|
458
473
|
#define MAX_BLOCKTIME 59.743 /* never wait longer than this time (to detect time jumps) */
|
@@ -460,23 +475,486 @@ struct signalfd_siginfo
|
|
460
475
|
#define EV_TV_SET(tv,t) do { tv.tv_sec = (long)t; tv.tv_usec = (long)((t - tv.tv_sec) * 1e6); } while (0)
|
461
476
|
#define EV_TS_SET(ts,t) do { ts.tv_sec = (long)t; ts.tv_nsec = (long)((t - ts.tv_sec) * 1e9); } while (0)
|
462
477
|
|
463
|
-
|
464
|
-
|
465
|
-
|
478
|
+
/* the following is ecb.h embedded into libev - use update_ev_c to update from an external copy */
|
479
|
+
/* ECB.H BEGIN */
|
480
|
+
/*
|
481
|
+
* libecb - http://software.schmorp.de/pkg/libecb
|
482
|
+
*
|
483
|
+
* Copyright (©) 2009-2012 Marc Alexander Lehmann <libecb@schmorp.de>
|
484
|
+
* Copyright (©) 2011 Emanuele Giaquinta
|
485
|
+
* All rights reserved.
|
486
|
+
*
|
487
|
+
* Redistribution and use in source and binary forms, with or without modifica-
|
488
|
+
* tion, are permitted provided that the following conditions are met:
|
489
|
+
*
|
490
|
+
* 1. Redistributions of source code must retain the above copyright notice,
|
491
|
+
* this list of conditions and the following disclaimer.
|
492
|
+
*
|
493
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
494
|
+
* notice, this list of conditions and the following disclaimer in the
|
495
|
+
* documentation and/or other materials provided with the distribution.
|
496
|
+
*
|
497
|
+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
498
|
+
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
|
499
|
+
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
500
|
+
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
|
501
|
+
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
502
|
+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
503
|
+
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
504
|
+
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
|
505
|
+
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
506
|
+
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
507
|
+
*/
|
508
|
+
|
509
|
+
#ifndef ECB_H
|
510
|
+
#define ECB_H
|
511
|
+
|
512
|
+
#ifdef _WIN32
|
513
|
+
typedef signed char int8_t;
|
514
|
+
typedef unsigned char uint8_t;
|
515
|
+
typedef signed short int16_t;
|
516
|
+
typedef unsigned short uint16_t;
|
517
|
+
typedef signed int int32_t;
|
518
|
+
typedef unsigned int uint32_t;
|
519
|
+
#if __GNUC__
|
520
|
+
typedef signed long long int64_t;
|
521
|
+
typedef unsigned long long uint64_t;
|
522
|
+
#else /* _MSC_VER || __BORLANDC__ */
|
523
|
+
typedef signed __int64 int64_t;
|
524
|
+
typedef unsigned __int64 uint64_t;
|
525
|
+
#endif
|
466
526
|
#else
|
467
|
-
#
|
468
|
-
#
|
469
|
-
|
470
|
-
|
471
|
-
|
527
|
+
#include <inttypes.h>
|
528
|
+
#endif
|
529
|
+
|
530
|
+
/* many compilers define _GNUC_ to some versions but then only implement
|
531
|
+
* what their idiot authors think are the "more important" extensions,
|
532
|
+
* causing enormous grief in return for some better fake benchmark numbers.
|
533
|
+
* or so.
|
534
|
+
* we try to detect these and simply assume they are not gcc - if they have
|
535
|
+
* an issue with that they should have done it right in the first place.
|
536
|
+
*/
|
537
|
+
#ifndef ECB_GCC_VERSION
|
538
|
+
#if !defined(__GNUC_MINOR__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__llvm__) || defined(__clang__)
|
539
|
+
#define ECB_GCC_VERSION(major,minor) 0
|
540
|
+
#else
|
541
|
+
#define ECB_GCC_VERSION(major,minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
|
542
|
+
#endif
|
543
|
+
#endif
|
544
|
+
|
545
|
+
/*****************************************************************************/
|
546
|
+
|
547
|
+
/* ECB_NO_THREADS - ecb is not used by multiple threads, ever */
|
548
|
+
/* ECB_NO_SMP - ecb might be used in multiple threads, but only on a single cpu */
|
549
|
+
|
550
|
+
#if ECB_NO_THREADS
|
551
|
+
# define ECB_NO_SMP 1
|
552
|
+
#endif
|
553
|
+
|
554
|
+
#if ECB_NO_THREADS || ECB_NO_SMP
|
555
|
+
#define ECB_MEMORY_FENCE do { } while (0)
|
556
|
+
#endif
|
557
|
+
|
558
|
+
#ifndef ECB_MEMORY_FENCE
|
559
|
+
#if ECB_GCC_VERSION(2,5) || defined(__INTEL_COMPILER) || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
|
560
|
+
#if __i386 || __i386__
|
561
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory")
|
562
|
+
#define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE /* non-lock xchg might be enough */
|
563
|
+
#define ECB_MEMORY_FENCE_RELEASE do { } while (0) /* unlikely to change in future cpus */
|
564
|
+
#elif __amd64 || __amd64__ || __x86_64 || __x86_64__
|
565
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("mfence" : : : "memory")
|
566
|
+
#define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("lfence" : : : "memory")
|
567
|
+
#define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("sfence") /* play safe - not needed in any current cpu */
|
568
|
+
#elif __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__
|
569
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("sync" : : : "memory")
|
570
|
+
#elif defined(__ARM_ARCH_6__ ) || defined(__ARM_ARCH_6J__ ) \
|
571
|
+
|| defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6ZK__)
|
572
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("mcr p15,0,%0,c7,c10,5" : : "r" (0) : "memory")
|
573
|
+
#elif defined(__ARM_ARCH_7__ ) || defined(__ARM_ARCH_7A__ ) \
|
574
|
+
|| defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7R__ )
|
575
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("dmb" : : : "memory")
|
576
|
+
#elif __sparc || __sparc__
|
577
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad | #StoreStore | #StoreLoad | " : : : "memory")
|
578
|
+
#define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad" : : : "memory")
|
579
|
+
#define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("membar #LoadStore | #StoreStore")
|
580
|
+
#elif defined(__s390__) || defined(__s390x__)
|
581
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("bcr 15,0" : : : "memory")
|
582
|
+
#endif
|
583
|
+
#endif
|
584
|
+
#endif
|
585
|
+
|
586
|
+
#ifndef ECB_MEMORY_FENCE
|
587
|
+
#if ECB_GCC_VERSION(4,4) || defined(__INTEL_COMPILER) || defined(__clang__)
|
588
|
+
#define ECB_MEMORY_FENCE __sync_synchronize ()
|
589
|
+
/*#define ECB_MEMORY_FENCE_ACQUIRE ({ char dummy = 0; __sync_lock_test_and_set (&dummy, 1); }) */
|
590
|
+
/*#define ECB_MEMORY_FENCE_RELEASE ({ char dummy = 1; __sync_lock_release (&dummy ); }) */
|
591
|
+
#elif _MSC_VER >= 1400 /* VC++ 2005 */
|
592
|
+
#pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier)
|
593
|
+
#define ECB_MEMORY_FENCE _ReadWriteBarrier ()
|
594
|
+
#define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier () /* according to msdn, _ReadBarrier is not a load fence */
|
595
|
+
#define ECB_MEMORY_FENCE_RELEASE _WriteBarrier ()
|
596
|
+
#elif defined(_WIN32)
|
597
|
+
#include <WinNT.h>
|
598
|
+
#define ECB_MEMORY_FENCE MemoryBarrier () /* actually just xchg on x86... scary */
|
599
|
+
#elif __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
|
600
|
+
#include <mbarrier.h>
|
601
|
+
#define ECB_MEMORY_FENCE __machine_rw_barrier ()
|
602
|
+
#define ECB_MEMORY_FENCE_ACQUIRE __machine_r_barrier ()
|
603
|
+
#define ECB_MEMORY_FENCE_RELEASE __machine_w_barrier ()
|
604
|
+
#endif
|
605
|
+
#endif
|
606
|
+
|
607
|
+
#ifndef ECB_MEMORY_FENCE
|
608
|
+
#if !ECB_AVOID_PTHREADS
|
609
|
+
/*
|
610
|
+
* if you get undefined symbol references to pthread_mutex_lock,
|
611
|
+
* or failure to find pthread.h, then you should implement
|
612
|
+
* the ECB_MEMORY_FENCE operations for your cpu/compiler
|
613
|
+
* OR provide pthread.h and link against the posix thread library
|
614
|
+
* of your system.
|
615
|
+
*/
|
616
|
+
#include <pthread.h>
|
617
|
+
#define ECB_NEEDS_PTHREADS 1
|
618
|
+
#define ECB_MEMORY_FENCE_NEEDS_PTHREADS 1
|
619
|
+
|
620
|
+
static pthread_mutex_t ecb_mf_lock = PTHREAD_MUTEX_INITIALIZER;
|
621
|
+
#define ECB_MEMORY_FENCE do { pthread_mutex_lock (&ecb_mf_lock); pthread_mutex_unlock (&ecb_mf_lock); } while (0)
|
622
|
+
#endif
|
623
|
+
#endif
|
624
|
+
|
625
|
+
#if !defined(ECB_MEMORY_FENCE_ACQUIRE) && defined(ECB_MEMORY_FENCE)
|
626
|
+
#define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE
|
627
|
+
#endif
|
628
|
+
|
629
|
+
#if !defined(ECB_MEMORY_FENCE_RELEASE) && defined(ECB_MEMORY_FENCE)
|
630
|
+
#define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE
|
631
|
+
#endif
|
632
|
+
|
633
|
+
/*****************************************************************************/
|
634
|
+
|
635
|
+
#define ECB_C99 (__STDC_VERSION__ >= 199901L)
|
636
|
+
|
637
|
+
#if __cplusplus
|
638
|
+
#define ecb_inline static inline
|
639
|
+
#elif ECB_GCC_VERSION(2,5)
|
640
|
+
#define ecb_inline static __inline__
|
641
|
+
#elif ECB_C99
|
642
|
+
#define ecb_inline static inline
|
643
|
+
#else
|
644
|
+
#define ecb_inline static
|
645
|
+
#endif
|
646
|
+
|
647
|
+
#if ECB_GCC_VERSION(3,3)
|
648
|
+
#define ecb_restrict __restrict__
|
649
|
+
#elif ECB_C99
|
650
|
+
#define ecb_restrict restrict
|
651
|
+
#else
|
652
|
+
#define ecb_restrict
|
653
|
+
#endif
|
654
|
+
|
655
|
+
typedef int ecb_bool;
|
656
|
+
|
657
|
+
#define ECB_CONCAT_(a, b) a ## b
|
658
|
+
#define ECB_CONCAT(a, b) ECB_CONCAT_(a, b)
|
659
|
+
#define ECB_STRINGIFY_(a) # a
|
660
|
+
#define ECB_STRINGIFY(a) ECB_STRINGIFY_(a)
|
661
|
+
|
662
|
+
#define ecb_function_ ecb_inline
|
663
|
+
|
664
|
+
#if ECB_GCC_VERSION(3,1)
|
665
|
+
#define ecb_attribute(attrlist) __attribute__(attrlist)
|
666
|
+
#define ecb_is_constant(expr) __builtin_constant_p (expr)
|
667
|
+
#define ecb_expect(expr,value) __builtin_expect ((expr),(value))
|
668
|
+
#define ecb_prefetch(addr,rw,locality) __builtin_prefetch (addr, rw, locality)
|
669
|
+
#else
|
670
|
+
#define ecb_attribute(attrlist)
|
671
|
+
#define ecb_is_constant(expr) 0
|
672
|
+
#define ecb_expect(expr,value) (expr)
|
673
|
+
#define ecb_prefetch(addr,rw,locality)
|
674
|
+
#endif
|
675
|
+
|
676
|
+
/* no emulation for ecb_decltype */
|
677
|
+
#if ECB_GCC_VERSION(4,5)
|
678
|
+
#define ecb_decltype(x) __decltype(x)
|
679
|
+
#elif ECB_GCC_VERSION(3,0)
|
680
|
+
#define ecb_decltype(x) __typeof(x)
|
681
|
+
#endif
|
682
|
+
|
683
|
+
#define ecb_noinline ecb_attribute ((__noinline__))
|
684
|
+
#define ecb_noreturn ecb_attribute ((__noreturn__))
|
685
|
+
#define ecb_unused ecb_attribute ((__unused__))
|
686
|
+
#define ecb_const ecb_attribute ((__const__))
|
687
|
+
#define ecb_pure ecb_attribute ((__pure__))
|
688
|
+
|
689
|
+
#if ECB_GCC_VERSION(4,3)
|
690
|
+
#define ecb_artificial ecb_attribute ((__artificial__))
|
691
|
+
#define ecb_hot ecb_attribute ((__hot__))
|
692
|
+
#define ecb_cold ecb_attribute ((__cold__))
|
693
|
+
#else
|
694
|
+
#define ecb_artificial
|
695
|
+
#define ecb_hot
|
696
|
+
#define ecb_cold
|
697
|
+
#endif
|
698
|
+
|
699
|
+
/* put around conditional expressions if you are very sure that the */
|
700
|
+
/* expression is mostly true or mostly false. note that these return */
|
701
|
+
/* booleans, not the expression. */
|
702
|
+
#define ecb_expect_false(expr) ecb_expect (!!(expr), 0)
|
703
|
+
#define ecb_expect_true(expr) ecb_expect (!!(expr), 1)
|
704
|
+
/* for compatibility to the rest of the world */
|
705
|
+
#define ecb_likely(expr) ecb_expect_true (expr)
|
706
|
+
#define ecb_unlikely(expr) ecb_expect_false (expr)
|
707
|
+
|
708
|
+
/* count trailing zero bits and count # of one bits */
|
709
|
+
#if ECB_GCC_VERSION(3,4)
|
710
|
+
/* we assume int == 32 bit, long == 32 or 64 bit and long long == 64 bit */
|
711
|
+
#define ecb_ld32(x) (__builtin_clz (x) ^ 31)
|
712
|
+
#define ecb_ld64(x) (__builtin_clzll (x) ^ 63)
|
713
|
+
#define ecb_ctz32(x) __builtin_ctz (x)
|
714
|
+
#define ecb_ctz64(x) __builtin_ctzll (x)
|
715
|
+
#define ecb_popcount32(x) __builtin_popcount (x)
|
716
|
+
/* no popcountll */
|
717
|
+
#else
|
718
|
+
ecb_function_ int ecb_ctz32 (uint32_t x) ecb_const;
|
719
|
+
ecb_function_ int
|
720
|
+
ecb_ctz32 (uint32_t x)
|
721
|
+
{
|
722
|
+
int r = 0;
|
723
|
+
|
724
|
+
x &= ~x + 1; /* this isolates the lowest bit */
|
725
|
+
|
726
|
+
#if ECB_branchless_on_i386
|
727
|
+
r += !!(x & 0xaaaaaaaa) << 0;
|
728
|
+
r += !!(x & 0xcccccccc) << 1;
|
729
|
+
r += !!(x & 0xf0f0f0f0) << 2;
|
730
|
+
r += !!(x & 0xff00ff00) << 3;
|
731
|
+
r += !!(x & 0xffff0000) << 4;
|
732
|
+
#else
|
733
|
+
if (x & 0xaaaaaaaa) r += 1;
|
734
|
+
if (x & 0xcccccccc) r += 2;
|
735
|
+
if (x & 0xf0f0f0f0) r += 4;
|
736
|
+
if (x & 0xff00ff00) r += 8;
|
737
|
+
if (x & 0xffff0000) r += 16;
|
738
|
+
#endif
|
739
|
+
|
740
|
+
return r;
|
741
|
+
}
|
742
|
+
|
743
|
+
ecb_function_ int ecb_ctz64 (uint64_t x) ecb_const;
|
744
|
+
ecb_function_ int
|
745
|
+
ecb_ctz64 (uint64_t x)
|
746
|
+
{
|
747
|
+
int shift = x & 0xffffffffU ? 0 : 32;
|
748
|
+
return ecb_ctz32 (x >> shift) + shift;
|
749
|
+
}
|
750
|
+
|
751
|
+
ecb_function_ int ecb_popcount32 (uint32_t x) ecb_const;
|
752
|
+
ecb_function_ int
|
753
|
+
ecb_popcount32 (uint32_t x)
|
754
|
+
{
|
755
|
+
x -= (x >> 1) & 0x55555555;
|
756
|
+
x = ((x >> 2) & 0x33333333) + (x & 0x33333333);
|
757
|
+
x = ((x >> 4) + x) & 0x0f0f0f0f;
|
758
|
+
x *= 0x01010101;
|
759
|
+
|
760
|
+
return x >> 24;
|
761
|
+
}
|
762
|
+
|
763
|
+
ecb_function_ int ecb_ld32 (uint32_t x) ecb_const;
|
764
|
+
ecb_function_ int ecb_ld32 (uint32_t x)
|
765
|
+
{
|
766
|
+
int r = 0;
|
767
|
+
|
768
|
+
if (x >> 16) { x >>= 16; r += 16; }
|
769
|
+
if (x >> 8) { x >>= 8; r += 8; }
|
770
|
+
if (x >> 4) { x >>= 4; r += 4; }
|
771
|
+
if (x >> 2) { x >>= 2; r += 2; }
|
772
|
+
if (x >> 1) { r += 1; }
|
773
|
+
|
774
|
+
return r;
|
775
|
+
}
|
776
|
+
|
777
|
+
ecb_function_ int ecb_ld64 (uint64_t x) ecb_const;
|
778
|
+
ecb_function_ int ecb_ld64 (uint64_t x)
|
779
|
+
{
|
780
|
+
int r = 0;
|
781
|
+
|
782
|
+
if (x >> 32) { x >>= 32; r += 32; }
|
783
|
+
|
784
|
+
return r + ecb_ld32 (x);
|
785
|
+
}
|
786
|
+
#endif
|
787
|
+
|
788
|
+
ecb_function_ uint8_t ecb_bitrev8 (uint8_t x) ecb_const;
|
789
|
+
ecb_function_ uint8_t ecb_bitrev8 (uint8_t x)
|
790
|
+
{
|
791
|
+
return ( (x * 0x0802U & 0x22110U)
|
792
|
+
| (x * 0x8020U & 0x88440U)) * 0x10101U >> 16;
|
793
|
+
}
|
794
|
+
|
795
|
+
ecb_function_ uint16_t ecb_bitrev16 (uint16_t x) ecb_const;
|
796
|
+
ecb_function_ uint16_t ecb_bitrev16 (uint16_t x)
|
797
|
+
{
|
798
|
+
x = ((x >> 1) & 0x5555) | ((x & 0x5555) << 1);
|
799
|
+
x = ((x >> 2) & 0x3333) | ((x & 0x3333) << 2);
|
800
|
+
x = ((x >> 4) & 0x0f0f) | ((x & 0x0f0f) << 4);
|
801
|
+
x = ( x >> 8 ) | ( x << 8);
|
802
|
+
|
803
|
+
return x;
|
804
|
+
}
|
805
|
+
|
806
|
+
ecb_function_ uint32_t ecb_bitrev32 (uint32_t x) ecb_const;
|
807
|
+
ecb_function_ uint32_t ecb_bitrev32 (uint32_t x)
|
808
|
+
{
|
809
|
+
x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1);
|
810
|
+
x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2);
|
811
|
+
x = ((x >> 4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) << 4);
|
812
|
+
x = ((x >> 8) & 0x00ff00ff) | ((x & 0x00ff00ff) << 8);
|
813
|
+
x = ( x >> 16 ) | ( x << 16);
|
814
|
+
|
815
|
+
return x;
|
816
|
+
}
|
817
|
+
|
818
|
+
/* popcount64 is only available on 64 bit cpus as gcc builtin */
|
819
|
+
/* so for this version we are lazy */
|
820
|
+
ecb_function_ int ecb_popcount64 (uint64_t x) ecb_const;
|
821
|
+
ecb_function_ int
|
822
|
+
ecb_popcount64 (uint64_t x)
|
823
|
+
{
|
824
|
+
return ecb_popcount32 (x) + ecb_popcount32 (x >> 32);
|
825
|
+
}
|
826
|
+
|
827
|
+
ecb_inline uint8_t ecb_rotl8 (uint8_t x, unsigned int count) ecb_const;
|
828
|
+
ecb_inline uint8_t ecb_rotr8 (uint8_t x, unsigned int count) ecb_const;
|
829
|
+
ecb_inline uint16_t ecb_rotl16 (uint16_t x, unsigned int count) ecb_const;
|
830
|
+
ecb_inline uint16_t ecb_rotr16 (uint16_t x, unsigned int count) ecb_const;
|
831
|
+
ecb_inline uint32_t ecb_rotl32 (uint32_t x, unsigned int count) ecb_const;
|
832
|
+
ecb_inline uint32_t ecb_rotr32 (uint32_t x, unsigned int count) ecb_const;
|
833
|
+
ecb_inline uint64_t ecb_rotl64 (uint64_t x, unsigned int count) ecb_const;
|
834
|
+
ecb_inline uint64_t ecb_rotr64 (uint64_t x, unsigned int count) ecb_const;
|
835
|
+
|
836
|
+
ecb_inline uint8_t ecb_rotl8 (uint8_t x, unsigned int count) { return (x >> ( 8 - count)) | (x << count); }
|
837
|
+
ecb_inline uint8_t ecb_rotr8 (uint8_t x, unsigned int count) { return (x << ( 8 - count)) | (x >> count); }
|
838
|
+
ecb_inline uint16_t ecb_rotl16 (uint16_t x, unsigned int count) { return (x >> (16 - count)) | (x << count); }
|
839
|
+
ecb_inline uint16_t ecb_rotr16 (uint16_t x, unsigned int count) { return (x << (16 - count)) | (x >> count); }
|
840
|
+
ecb_inline uint32_t ecb_rotl32 (uint32_t x, unsigned int count) { return (x >> (32 - count)) | (x << count); }
|
841
|
+
ecb_inline uint32_t ecb_rotr32 (uint32_t x, unsigned int count) { return (x << (32 - count)) | (x >> count); }
|
842
|
+
ecb_inline uint64_t ecb_rotl64 (uint64_t x, unsigned int count) { return (x >> (64 - count)) | (x << count); }
|
843
|
+
ecb_inline uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (64 - count)) | (x >> count); }
|
844
|
+
|
845
|
+
#if ECB_GCC_VERSION(4,3)
|
846
|
+
#define ecb_bswap16(x) (__builtin_bswap32 (x) >> 16)
|
847
|
+
#define ecb_bswap32(x) __builtin_bswap32 (x)
|
848
|
+
#define ecb_bswap64(x) __builtin_bswap64 (x)
|
849
|
+
#else
|
850
|
+
ecb_function_ uint16_t ecb_bswap16 (uint16_t x) ecb_const;
|
851
|
+
ecb_function_ uint16_t
|
852
|
+
ecb_bswap16 (uint16_t x)
|
853
|
+
{
|
854
|
+
return ecb_rotl16 (x, 8);
|
855
|
+
}
|
856
|
+
|
857
|
+
ecb_function_ uint32_t ecb_bswap32 (uint32_t x) ecb_const;
|
858
|
+
ecb_function_ uint32_t
|
859
|
+
ecb_bswap32 (uint32_t x)
|
860
|
+
{
|
861
|
+
return (((uint32_t)ecb_bswap16 (x)) << 16) | ecb_bswap16 (x >> 16);
|
862
|
+
}
|
863
|
+
|
864
|
+
ecb_function_ uint64_t ecb_bswap64 (uint64_t x) ecb_const;
|
865
|
+
ecb_function_ uint64_t
|
866
|
+
ecb_bswap64 (uint64_t x)
|
867
|
+
{
|
868
|
+
return (((uint64_t)ecb_bswap32 (x)) << 32) | ecb_bswap32 (x >> 32);
|
869
|
+
}
|
870
|
+
#endif
|
871
|
+
|
872
|
+
#if ECB_GCC_VERSION(4,5)
|
873
|
+
#define ecb_unreachable() __builtin_unreachable ()
|
874
|
+
#else
|
875
|
+
/* this seems to work fine, but gcc always emits a warning for it :/ */
|
876
|
+
ecb_inline void ecb_unreachable (void) ecb_noreturn;
|
877
|
+
ecb_inline void ecb_unreachable (void) { }
|
878
|
+
#endif
|
879
|
+
|
880
|
+
/* try to tell the compiler that some condition is definitely true */
|
881
|
+
#define ecb_assume(cond) do { if (!(cond)) ecb_unreachable (); } while (0)
|
882
|
+
|
883
|
+
ecb_inline unsigned char ecb_byteorder_helper (void) ecb_const;
|
884
|
+
ecb_inline unsigned char
|
885
|
+
ecb_byteorder_helper (void)
|
886
|
+
{
|
887
|
+
const uint32_t u = 0x11223344;
|
888
|
+
return *(unsigned char *)&u;
|
889
|
+
}
|
890
|
+
|
891
|
+
ecb_inline ecb_bool ecb_big_endian (void) ecb_const;
|
892
|
+
ecb_inline ecb_bool ecb_big_endian (void) { return ecb_byteorder_helper () == 0x11; }
|
893
|
+
ecb_inline ecb_bool ecb_little_endian (void) ecb_const;
|
894
|
+
ecb_inline ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44; }
|
895
|
+
|
896
|
+
#if ECB_GCC_VERSION(3,0) || ECB_C99
|
897
|
+
#define ecb_mod(m,n) ((m) % (n) + ((m) % (n) < 0 ? (n) : 0))
|
898
|
+
#else
|
899
|
+
#define ecb_mod(m,n) ((m) < 0 ? ((n) - 1 - ((-1 - (m)) % (n))) : ((m) % (n)))
|
900
|
+
#endif
|
901
|
+
|
902
|
+
#if __cplusplus
|
903
|
+
template<typename T>
|
904
|
+
static inline T ecb_div_rd (T val, T div)
|
905
|
+
{
|
906
|
+
return val < 0 ? - ((-val + div - 1) / div) : (val ) / div;
|
907
|
+
}
|
908
|
+
template<typename T>
|
909
|
+
static inline T ecb_div_ru (T val, T div)
|
910
|
+
{
|
911
|
+
return val < 0 ? - ((-val ) / div) : (val + div - 1) / div;
|
912
|
+
}
|
913
|
+
#else
|
914
|
+
#define ecb_div_rd(val,div) ((val) < 0 ? - ((-(val) + (div) - 1) / (div)) : ((val) ) / (div))
|
915
|
+
#define ecb_div_ru(val,div) ((val) < 0 ? - ((-(val) ) / (div)) : ((val) + (div) - 1) / (div))
|
916
|
+
#endif
|
917
|
+
|
918
|
+
#if ecb_cplusplus_does_not_suck
|
919
|
+
/* does not work for local types (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm) */
|
920
|
+
template<typename T, int N>
|
921
|
+
static inline int ecb_array_length (const T (&arr)[N])
|
922
|
+
{
|
923
|
+
return N;
|
924
|
+
}
|
925
|
+
#else
|
926
|
+
#define ecb_array_length(name) (sizeof (name) / sizeof (name [0]))
|
927
|
+
#endif
|
928
|
+
|
929
|
+
#endif
|
930
|
+
|
931
|
+
/* ECB.H END */
|
932
|
+
|
933
|
+
#if ECB_MEMORY_FENCE_NEEDS_PTHREADS
|
934
|
+
/* if your architecture doesn't need memory fences, e.g. because it is
|
935
|
+
* single-cpu/core, or if you use libev in a project that doesn't use libev
|
936
|
+
* from multiple threads, then you can define ECB_AVOID_PTHREADS when compiling
|
937
|
+
* libev, in which cases the memory fences become nops.
|
938
|
+
* alternatively, you can remove this #error and link against libpthread,
|
939
|
+
* which will then provide the memory fences.
|
940
|
+
*/
|
941
|
+
# error "memory fences not defined for your architecture, please report"
|
942
|
+
#endif
|
943
|
+
|
944
|
+
#ifndef ECB_MEMORY_FENCE
|
945
|
+
# define ECB_MEMORY_FENCE do { } while (0)
|
946
|
+
# define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE
|
947
|
+
# define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE
|
472
948
|
#endif
|
473
949
|
|
474
|
-
#define expect_false(
|
475
|
-
#define expect_true(
|
476
|
-
#define
|
950
|
+
#define expect_false(cond) ecb_expect_false (cond)
|
951
|
+
#define expect_true(cond) ecb_expect_true (cond)
|
952
|
+
#define noinline ecb_noinline
|
953
|
+
|
954
|
+
#define inline_size ecb_inline
|
477
955
|
|
478
956
|
#if EV_FEATURE_CODE
|
479
|
-
# define inline_speed
|
957
|
+
# define inline_speed ecb_inline
|
480
958
|
#else
|
481
959
|
# define inline_speed static noinline
|
482
960
|
#endif
|
@@ -525,11 +1003,59 @@ static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work?
|
|
525
1003
|
|
526
1004
|
/*****************************************************************************/
|
527
1005
|
|
1006
|
+
/* define a suitable floor function (only used by periodics atm) */
|
1007
|
+
|
1008
|
+
#if EV_USE_FLOOR
|
1009
|
+
# include <math.h>
|
1010
|
+
# define ev_floor(v) floor (v)
|
1011
|
+
#else
|
1012
|
+
|
1013
|
+
#include <float.h>
|
1014
|
+
|
1015
|
+
/* a floor() replacement function, should be independent of ev_tstamp type */
|
1016
|
+
static ev_tstamp noinline
|
1017
|
+
ev_floor (ev_tstamp v)
|
1018
|
+
{
|
1019
|
+
/* the choice of shift factor is not terribly important */
|
1020
|
+
#if FLT_RADIX != 2 /* assume FLT_RADIX == 10 */
|
1021
|
+
const ev_tstamp shift = sizeof (unsigned long) >= 8 ? 10000000000000000000. : 1000000000.;
|
1022
|
+
#else
|
1023
|
+
const ev_tstamp shift = sizeof (unsigned long) >= 8 ? 18446744073709551616. : 4294967296.;
|
1024
|
+
#endif
|
1025
|
+
|
1026
|
+
/* argument too large for an unsigned long? */
|
1027
|
+
if (expect_false (v >= shift))
|
1028
|
+
{
|
1029
|
+
ev_tstamp f;
|
1030
|
+
|
1031
|
+
if (v == v - 1.)
|
1032
|
+
return v; /* very large number */
|
1033
|
+
|
1034
|
+
f = shift * ev_floor (v * (1. / shift));
|
1035
|
+
return f + ev_floor (v - f);
|
1036
|
+
}
|
1037
|
+
|
1038
|
+
/* special treatment for negative args? */
|
1039
|
+
if (expect_false (v < 0.))
|
1040
|
+
{
|
1041
|
+
ev_tstamp f = -ev_floor (-v);
|
1042
|
+
|
1043
|
+
return f - (f == v ? 0 : 1);
|
1044
|
+
}
|
1045
|
+
|
1046
|
+
/* fits into an unsigned long */
|
1047
|
+
return (unsigned long)v;
|
1048
|
+
}
|
1049
|
+
|
1050
|
+
#endif
|
1051
|
+
|
1052
|
+
/*****************************************************************************/
|
1053
|
+
|
528
1054
|
#ifdef __linux
|
529
1055
|
# include <sys/utsname.h>
|
530
1056
|
#endif
|
531
1057
|
|
532
|
-
static unsigned int noinline
|
1058
|
+
static unsigned int noinline ecb_cold
|
533
1059
|
ev_linux_version (void)
|
534
1060
|
{
|
535
1061
|
#ifdef __linux
|
@@ -568,7 +1094,7 @@ ev_linux_version (void)
|
|
568
1094
|
/*****************************************************************************/
|
569
1095
|
|
570
1096
|
#if EV_AVOID_STDIO
|
571
|
-
static void noinline
|
1097
|
+
static void noinline ecb_cold
|
572
1098
|
ev_printerr (const char *msg)
|
573
1099
|
{
|
574
1100
|
write (STDERR_FILENO, msg, strlen (msg));
|
@@ -577,13 +1103,13 @@ ev_printerr (const char *msg)
|
|
577
1103
|
|
578
1104
|
static void (*syserr_cb)(const char *msg);
|
579
1105
|
|
580
|
-
void
|
1106
|
+
void ecb_cold
|
581
1107
|
ev_set_syserr_cb (void (*cb)(const char *msg))
|
582
1108
|
{
|
583
1109
|
syserr_cb = cb;
|
584
1110
|
}
|
585
1111
|
|
586
|
-
static void noinline
|
1112
|
+
static void noinline ecb_cold
|
587
1113
|
ev_syserr (const char *msg)
|
588
1114
|
{
|
589
1115
|
if (!msg)
|
@@ -626,7 +1152,7 @@ ev_realloc_emul (void *ptr, long size)
|
|
626
1152
|
|
627
1153
|
static void *(*alloc)(void *ptr, long size) = ev_realloc_emul;
|
628
1154
|
|
629
|
-
void
|
1155
|
+
void ecb_cold
|
630
1156
|
ev_set_allocator (void *(*cb)(void *ptr, long size))
|
631
1157
|
{
|
632
1158
|
alloc = cb;
|
@@ -725,11 +1251,11 @@ typedef struct
|
|
725
1251
|
#include "ev_wrap.h"
|
726
1252
|
|
727
1253
|
static struct ev_loop default_loop_struct;
|
728
|
-
struct ev_loop *ev_default_loop_ptr;
|
1254
|
+
EV_API_DECL struct ev_loop *ev_default_loop_ptr = 0; /* needs to be initialised to make it a definition despite extern */
|
729
1255
|
|
730
1256
|
#else
|
731
1257
|
|
732
|
-
ev_tstamp ev_rt_now;
|
1258
|
+
EV_API_DECL ev_tstamp ev_rt_now = 0; /* needs to be initialised to make it a definition despite extern */
|
733
1259
|
#define VAR(name,decl) static decl;
|
734
1260
|
#include "ev_vars.h"
|
735
1261
|
#undef VAR
|
@@ -818,14 +1344,6 @@ ev_sleep (ev_tstamp delay)
|
|
818
1344
|
}
|
819
1345
|
}
|
820
1346
|
|
821
|
-
inline_speed int
|
822
|
-
ev_timeout_to_ms (ev_tstamp timeout)
|
823
|
-
{
|
824
|
-
int ms = timeout * 1000. + .999999;
|
825
|
-
|
826
|
-
return expect_true (ms) ? ms : timeout < 1e-6 ? 0 : 1;
|
827
|
-
}
|
828
|
-
|
829
1347
|
/*****************************************************************************/
|
830
1348
|
|
831
1349
|
#define MALLOC_ROUND 4096 /* prefer to allocate in chunks of this size, must be 2**n and >> 4 longs */
|
@@ -841,7 +1359,7 @@ array_nextsize (int elem, int cur, int cnt)
|
|
841
1359
|
ncur <<= 1;
|
842
1360
|
while (cnt > ncur);
|
843
1361
|
|
844
|
-
/* if size is large, round to MALLOC_ROUND - 4 * longs to
|
1362
|
+
/* if size is large, round to MALLOC_ROUND - 4 * longs to accommodate malloc overhead */
|
845
1363
|
if (elem * ncur > MALLOC_ROUND - sizeof (void *) * 4)
|
846
1364
|
{
|
847
1365
|
ncur *= elem;
|
@@ -853,7 +1371,7 @@ array_nextsize (int elem, int cur, int cnt)
|
|
853
1371
|
return ncur;
|
854
1372
|
}
|
855
1373
|
|
856
|
-
static
|
1374
|
+
static void * noinline ecb_cold
|
857
1375
|
array_realloc (int elem, void *base, int *cur, int cnt)
|
858
1376
|
{
|
859
1377
|
*cur = array_nextsize (elem, *cur, cnt);
|
@@ -866,7 +1384,7 @@ array_realloc (int elem, void *base, int *cur, int cnt)
|
|
866
1384
|
#define array_needsize(type,base,cur,cnt,init) \
|
867
1385
|
if (expect_false ((cnt) > (cur))) \
|
868
1386
|
{ \
|
869
|
-
int ocur_ = (cur); \
|
1387
|
+
int ecb_unused ocur_ = (cur); \
|
870
1388
|
(base) = (type *)array_realloc \
|
871
1389
|
(sizeof (type), (base), &(cur), (cnt)); \
|
872
1390
|
init ((base) + (ocur_), (cur) - ocur_); \
|
@@ -982,7 +1500,7 @@ fd_reify (EV_P)
|
|
982
1500
|
int fd = fdchanges [i];
|
983
1501
|
ANFD *anfd = anfds + fd;
|
984
1502
|
|
985
|
-
if (anfd->reify & EV__IOFDSET)
|
1503
|
+
if (anfd->reify & EV__IOFDSET && anfd->head)
|
986
1504
|
{
|
987
1505
|
SOCKET handle = EV_FD_TO_WIN32_HANDLE (fd);
|
988
1506
|
|
@@ -1046,7 +1564,7 @@ fd_change (EV_P_ int fd, int flags)
|
|
1046
1564
|
}
|
1047
1565
|
|
1048
1566
|
/* the given fd is invalid/unusable, so make sure it doesn't hurt us anymore */
|
1049
|
-
inline_speed void
|
1567
|
+
inline_speed void ecb_cold
|
1050
1568
|
fd_kill (EV_P_ int fd)
|
1051
1569
|
{
|
1052
1570
|
ev_io *w;
|
@@ -1059,7 +1577,7 @@ fd_kill (EV_P_ int fd)
|
|
1059
1577
|
}
|
1060
1578
|
|
1061
1579
|
/* check whether the given fd is actually valid, for error recovery */
|
1062
|
-
inline_size int
|
1580
|
+
inline_size int ecb_cold
|
1063
1581
|
fd_valid (int fd)
|
1064
1582
|
{
|
1065
1583
|
#ifdef _WIN32
|
@@ -1070,7 +1588,7 @@ fd_valid (int fd)
|
|
1070
1588
|
}
|
1071
1589
|
|
1072
1590
|
/* called on EBADF to verify fds */
|
1073
|
-
static void noinline
|
1591
|
+
static void noinline ecb_cold
|
1074
1592
|
fd_ebadf (EV_P)
|
1075
1593
|
{
|
1076
1594
|
int fd;
|
@@ -1082,7 +1600,7 @@ fd_ebadf (EV_P)
|
|
1082
1600
|
}
|
1083
1601
|
|
1084
1602
|
/* called on ENOMEM in select/poll to kill some fds and retry */
|
1085
|
-
static void noinline
|
1603
|
+
static void noinline ecb_cold
|
1086
1604
|
fd_enomem (EV_P)
|
1087
1605
|
{
|
1088
1606
|
int fd;
|
@@ -1287,7 +1805,7 @@ static ANSIG signals [EV_NSIG - 1];
|
|
1287
1805
|
|
1288
1806
|
#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
|
1289
1807
|
|
1290
|
-
static void noinline
|
1808
|
+
static void noinline ecb_cold
|
1291
1809
|
evpipe_init (EV_P)
|
1292
1810
|
{
|
1293
1811
|
if (!ev_is_active (&pipe_w))
|
@@ -1319,15 +1837,27 @@ evpipe_init (EV_P)
|
|
1319
1837
|
}
|
1320
1838
|
}
|
1321
1839
|
|
1322
|
-
|
1840
|
+
inline_speed void
|
1323
1841
|
evpipe_write (EV_P_ EV_ATOMIC_T *flag)
|
1324
1842
|
{
|
1325
|
-
if (
|
1843
|
+
if (expect_true (*flag))
|
1844
|
+
return;
|
1845
|
+
|
1846
|
+
*flag = 1;
|
1847
|
+
|
1848
|
+
ECB_MEMORY_FENCE_RELEASE; /* make sure flag is visible before the wakeup */
|
1849
|
+
|
1850
|
+
pipe_write_skipped = 1;
|
1851
|
+
|
1852
|
+
ECB_MEMORY_FENCE; /* make sure pipe_write_skipped is visible before we check pipe_write_wanted */
|
1853
|
+
|
1854
|
+
if (pipe_write_wanted)
|
1326
1855
|
{
|
1327
|
-
int old_errno
|
1328
|
-
char dummy;
|
1856
|
+
int old_errno;
|
1329
1857
|
|
1330
|
-
|
1858
|
+
pipe_write_skipped = 0; /* just an optimisation, no fence needed */
|
1859
|
+
|
1860
|
+
old_errno = errno; /* save errno because write will clobber it */
|
1331
1861
|
|
1332
1862
|
#if EV_USE_EVENTFD
|
1333
1863
|
if (evfd >= 0)
|
@@ -1337,12 +1867,14 @@ evpipe_write (EV_P_ EV_ATOMIC_T *flag)
|
|
1337
1867
|
}
|
1338
1868
|
else
|
1339
1869
|
#endif
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1870
|
+
{
|
1871
|
+
/* win32 people keep sending patches that change this write() to send() */
|
1872
|
+
/* and then run away. but send() is wrong, it wants a socket handle on win32 */
|
1873
|
+
/* so when you think this write should be a send instead, please find out */
|
1874
|
+
/* where your send() is from - it's definitely not the microsoft send, and */
|
1875
|
+
/* tell me. thank you. */
|
1876
|
+
write (evpipe [1], &(evpipe [1]), 1);
|
1877
|
+
}
|
1346
1878
|
|
1347
1879
|
errno = old_errno;
|
1348
1880
|
}
|
@@ -1355,20 +1887,25 @@ pipecb (EV_P_ ev_io *iow, int revents)
|
|
1355
1887
|
{
|
1356
1888
|
int i;
|
1357
1889
|
|
1358
|
-
|
1359
|
-
if (evfd >= 0)
|
1890
|
+
if (revents & EV_READ)
|
1360
1891
|
{
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1892
|
+
#if EV_USE_EVENTFD
|
1893
|
+
if (evfd >= 0)
|
1894
|
+
{
|
1895
|
+
uint64_t counter;
|
1896
|
+
read (evfd, &counter, sizeof (uint64_t));
|
1897
|
+
}
|
1898
|
+
else
|
1365
1899
|
#endif
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1900
|
+
{
|
1901
|
+
char dummy;
|
1902
|
+
/* see discussion in evpipe_write when you think this read should be recv in win32 */
|
1903
|
+
read (evpipe [0], &dummy, 1);
|
1904
|
+
}
|
1370
1905
|
}
|
1371
1906
|
|
1907
|
+
pipe_write_skipped = 0;
|
1908
|
+
|
1372
1909
|
#if EV_SIGNAL_ENABLE
|
1373
1910
|
if (sig_pending)
|
1374
1911
|
{
|
@@ -1407,6 +1944,9 @@ ev_feed_signal (int signum)
|
|
1407
1944
|
return;
|
1408
1945
|
#endif
|
1409
1946
|
|
1947
|
+
if (!ev_active (&pipe_w))
|
1948
|
+
return;
|
1949
|
+
|
1410
1950
|
signals [signum - 1].pending = 1;
|
1411
1951
|
evpipe_write (EV_A_ &sig_pending);
|
1412
1952
|
}
|
@@ -1547,20 +2087,20 @@ childcb (EV_P_ ev_signal *sw, int revents)
|
|
1547
2087
|
# include "ev_select.c"
|
1548
2088
|
#endif
|
1549
2089
|
|
1550
|
-
int
|
2090
|
+
int ecb_cold
|
1551
2091
|
ev_version_major (void)
|
1552
2092
|
{
|
1553
2093
|
return EV_VERSION_MAJOR;
|
1554
2094
|
}
|
1555
2095
|
|
1556
|
-
int
|
2096
|
+
int ecb_cold
|
1557
2097
|
ev_version_minor (void)
|
1558
2098
|
{
|
1559
2099
|
return EV_VERSION_MINOR;
|
1560
2100
|
}
|
1561
2101
|
|
1562
2102
|
/* return true if we are running with elevated privileges and should ignore env variables */
|
1563
|
-
int inline_size
|
2103
|
+
int inline_size ecb_cold
|
1564
2104
|
enable_secure (void)
|
1565
2105
|
{
|
1566
2106
|
#ifdef _WIN32
|
@@ -1571,7 +2111,7 @@ enable_secure (void)
|
|
1571
2111
|
#endif
|
1572
2112
|
}
|
1573
2113
|
|
1574
|
-
unsigned int
|
2114
|
+
unsigned int ecb_cold
|
1575
2115
|
ev_supported_backends (void)
|
1576
2116
|
{
|
1577
2117
|
unsigned int flags = 0;
|
@@ -1585,7 +2125,7 @@ ev_supported_backends (void)
|
|
1585
2125
|
return flags;
|
1586
2126
|
}
|
1587
2127
|
|
1588
|
-
unsigned int
|
2128
|
+
unsigned int ecb_cold
|
1589
2129
|
ev_recommended_backends (void)
|
1590
2130
|
{
|
1591
2131
|
unsigned int flags = ev_supported_backends ();
|
@@ -1607,7 +2147,7 @@ ev_recommended_backends (void)
|
|
1607
2147
|
return flags;
|
1608
2148
|
}
|
1609
2149
|
|
1610
|
-
unsigned int
|
2150
|
+
unsigned int ecb_cold
|
1611
2151
|
ev_embeddable_backends (void)
|
1612
2152
|
{
|
1613
2153
|
int flags = EVBACKEND_EPOLL | EVBACKEND_KQUEUE | EVBACKEND_PORT;
|
@@ -1662,12 +2202,14 @@ ev_userdata (EV_P)
|
|
1662
2202
|
return userdata;
|
1663
2203
|
}
|
1664
2204
|
|
1665
|
-
void
|
2205
|
+
void
|
2206
|
+
ev_set_invoke_pending_cb (EV_P_ void (*invoke_pending_cb)(EV_P))
|
1666
2207
|
{
|
1667
2208
|
invoke_cb = invoke_pending_cb;
|
1668
2209
|
}
|
1669
2210
|
|
1670
|
-
void
|
2211
|
+
void
|
2212
|
+
ev_set_loop_release_cb (EV_P_ void (*release)(EV_P), void (*acquire)(EV_P))
|
1671
2213
|
{
|
1672
2214
|
release_cb = release;
|
1673
2215
|
acquire_cb = acquire;
|
@@ -1675,7 +2217,7 @@ void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P), void (*acquire)(EV_P))
|
|
1675
2217
|
#endif
|
1676
2218
|
|
1677
2219
|
/* initialise a loop structure, must be zero-initialised */
|
1678
|
-
static void noinline
|
2220
|
+
static void noinline ecb_cold
|
1679
2221
|
loop_init (EV_P_ unsigned int flags)
|
1680
2222
|
{
|
1681
2223
|
if (!backend)
|
@@ -1713,27 +2255,29 @@ loop_init (EV_P_ unsigned int flags)
|
|
1713
2255
|
&& getenv ("LIBEV_FLAGS"))
|
1714
2256
|
flags = atoi (getenv ("LIBEV_FLAGS"));
|
1715
2257
|
|
1716
|
-
ev_rt_now
|
1717
|
-
mn_now
|
1718
|
-
now_floor
|
1719
|
-
rtmn_diff
|
2258
|
+
ev_rt_now = ev_time ();
|
2259
|
+
mn_now = get_clock ();
|
2260
|
+
now_floor = mn_now;
|
2261
|
+
rtmn_diff = ev_rt_now - mn_now;
|
1720
2262
|
#if EV_FEATURE_API
|
1721
|
-
invoke_cb
|
2263
|
+
invoke_cb = ev_invoke_pending;
|
1722
2264
|
#endif
|
1723
2265
|
|
1724
|
-
io_blocktime
|
1725
|
-
timeout_blocktime
|
1726
|
-
backend
|
1727
|
-
backend_fd
|
1728
|
-
sig_pending
|
2266
|
+
io_blocktime = 0.;
|
2267
|
+
timeout_blocktime = 0.;
|
2268
|
+
backend = 0;
|
2269
|
+
backend_fd = -1;
|
2270
|
+
sig_pending = 0;
|
1729
2271
|
#if EV_ASYNC_ENABLE
|
1730
|
-
async_pending
|
2272
|
+
async_pending = 0;
|
1731
2273
|
#endif
|
2274
|
+
pipe_write_skipped = 0;
|
2275
|
+
pipe_write_wanted = 0;
|
1732
2276
|
#if EV_USE_INOTIFY
|
1733
|
-
fs_fd
|
2277
|
+
fs_fd = flags & EVFLAG_NOINOTIFY ? -1 : -2;
|
1734
2278
|
#endif
|
1735
2279
|
#if EV_USE_SIGNALFD
|
1736
|
-
sigfd
|
2280
|
+
sigfd = flags & EVFLAG_SIGNALFD ? -2 : -1;
|
1737
2281
|
#endif
|
1738
2282
|
|
1739
2283
|
if (!(flags & EVBACKEND_MASK))
|
@@ -1768,7 +2312,7 @@ loop_init (EV_P_ unsigned int flags)
|
|
1768
2312
|
}
|
1769
2313
|
|
1770
2314
|
/* free up a loop structure */
|
1771
|
-
void
|
2315
|
+
void ecb_cold
|
1772
2316
|
ev_loop_destroy (EV_P)
|
1773
2317
|
{
|
1774
2318
|
int i;
|
@@ -1908,12 +2452,7 @@ loop_fork (EV_P)
|
|
1908
2452
|
|
1909
2453
|
if (ev_is_active (&pipe_w))
|
1910
2454
|
{
|
1911
|
-
/*
|
1912
|
-
/* while we modify the fd vars */
|
1913
|
-
sig_pending = 1;
|
1914
|
-
#if EV_ASYNC_ENABLE
|
1915
|
-
async_pending = 1;
|
1916
|
-
#endif
|
2455
|
+
/* pipe_write_wanted must be false now, so modifying fd vars should be safe */
|
1917
2456
|
|
1918
2457
|
ev_ref (EV_A);
|
1919
2458
|
ev_io_stop (EV_A_ &pipe_w);
|
@@ -1941,7 +2480,7 @@ loop_fork (EV_P)
|
|
1941
2480
|
|
1942
2481
|
#if EV_MULTIPLICITY
|
1943
2482
|
|
1944
|
-
struct ev_loop *
|
2483
|
+
struct ev_loop * ecb_cold
|
1945
2484
|
ev_loop_new (unsigned int flags)
|
1946
2485
|
{
|
1947
2486
|
EV_P = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop));
|
@@ -1959,7 +2498,7 @@ ev_loop_new (unsigned int flags)
|
|
1959
2498
|
#endif /* multiplicity */
|
1960
2499
|
|
1961
2500
|
#if EV_VERIFY
|
1962
|
-
static void noinline
|
2501
|
+
static void noinline ecb_cold
|
1963
2502
|
verify_watcher (EV_P_ W w)
|
1964
2503
|
{
|
1965
2504
|
assert (("libev: watcher has invalid priority", ABSPRI (w) >= 0 && ABSPRI (w) < NUMPRI));
|
@@ -1968,7 +2507,7 @@ verify_watcher (EV_P_ W w)
|
|
1968
2507
|
assert (("libev: pending watcher not on pending queue", pendings [ABSPRI (w)][w->pending - 1].w == w));
|
1969
2508
|
}
|
1970
2509
|
|
1971
|
-
static void noinline
|
2510
|
+
static void noinline ecb_cold
|
1972
2511
|
verify_heap (EV_P_ ANHE *heap, int N)
|
1973
2512
|
{
|
1974
2513
|
int i;
|
@@ -1983,7 +2522,7 @@ verify_heap (EV_P_ ANHE *heap, int N)
|
|
1983
2522
|
}
|
1984
2523
|
}
|
1985
2524
|
|
1986
|
-
static void noinline
|
2525
|
+
static void noinline ecb_cold
|
1987
2526
|
array_verify (EV_P_ W *ws, int cnt)
|
1988
2527
|
{
|
1989
2528
|
while (cnt--)
|
@@ -1995,7 +2534,7 @@ array_verify (EV_P_ W *ws, int cnt)
|
|
1995
2534
|
#endif
|
1996
2535
|
|
1997
2536
|
#if EV_FEATURE_API
|
1998
|
-
void
|
2537
|
+
void ecb_cold
|
1999
2538
|
ev_verify (EV_P)
|
2000
2539
|
{
|
2001
2540
|
#if EV_VERIFY
|
@@ -2071,7 +2610,7 @@ ev_verify (EV_P)
|
|
2071
2610
|
#endif
|
2072
2611
|
|
2073
2612
|
#if EV_MULTIPLICITY
|
2074
|
-
struct ev_loop *
|
2613
|
+
struct ev_loop * ecb_cold
|
2075
2614
|
#else
|
2076
2615
|
int
|
2077
2616
|
#endif
|
@@ -2210,12 +2749,28 @@ timers_reify (EV_P)
|
|
2210
2749
|
|
2211
2750
|
#if EV_PERIODIC_ENABLE
|
2212
2751
|
|
2213
|
-
|
2752
|
+
static void noinline
|
2214
2753
|
periodic_recalc (EV_P_ ev_periodic *w)
|
2215
2754
|
{
|
2216
|
-
|
2217
|
-
|
2218
|
-
|
2755
|
+
ev_tstamp interval = w->interval > MIN_INTERVAL ? w->interval : MIN_INTERVAL;
|
2756
|
+
ev_tstamp at = w->offset + interval * ev_floor ((ev_rt_now - w->offset) / interval);
|
2757
|
+
|
2758
|
+
/* the above almost always errs on the low side */
|
2759
|
+
while (at <= ev_rt_now)
|
2760
|
+
{
|
2761
|
+
ev_tstamp nat = at + w->interval;
|
2762
|
+
|
2763
|
+
/* when resolution fails us, we use ev_rt_now */
|
2764
|
+
if (expect_false (nat == at))
|
2765
|
+
{
|
2766
|
+
at = ev_rt_now;
|
2767
|
+
break;
|
2768
|
+
}
|
2769
|
+
|
2770
|
+
at = nat;
|
2771
|
+
}
|
2772
|
+
|
2773
|
+
ev_at (w) = at;
|
2219
2774
|
}
|
2220
2775
|
|
2221
2776
|
/* make periodics pending */
|
@@ -2247,20 +2802,6 @@ periodics_reify (EV_P)
|
|
2247
2802
|
else if (w->interval)
|
2248
2803
|
{
|
2249
2804
|
periodic_recalc (EV_A_ w);
|
2250
|
-
|
2251
|
-
/* if next trigger time is not sufficiently in the future, put it there */
|
2252
|
-
/* this might happen because of floating point inexactness */
|
2253
|
-
if (ev_at (w) - ev_rt_now < TIME_EPSILON)
|
2254
|
-
{
|
2255
|
-
ev_at (w) += w->interval;
|
2256
|
-
|
2257
|
-
/* if interval is unreasonably low we might still have a time in the past */
|
2258
|
-
/* so correct this. this will make the periodic very inexact, but the user */
|
2259
|
-
/* has effectively asked to get triggered more often than possible */
|
2260
|
-
if (ev_at (w) < ev_rt_now)
|
2261
|
-
ev_at (w) = ev_rt_now;
|
2262
|
-
}
|
2263
|
-
|
2264
2805
|
ANHE_at_cache (periodics [HEAP0]);
|
2265
2806
|
downheap (periodics, periodiccnt, HEAP0);
|
2266
2807
|
}
|
@@ -2278,7 +2819,7 @@ periodics_reify (EV_P)
|
|
2278
2819
|
|
2279
2820
|
/* simply recalculate all periodics */
|
2280
2821
|
/* TODO: maybe ensure that at least one event happens when jumping forward? */
|
2281
|
-
static void noinline
|
2822
|
+
static void noinline ecb_cold
|
2282
2823
|
periodics_reschedule (EV_P)
|
2283
2824
|
{
|
2284
2825
|
int i;
|
@@ -2301,7 +2842,7 @@ periodics_reschedule (EV_P)
|
|
2301
2842
|
#endif
|
2302
2843
|
|
2303
2844
|
/* adjust all timers by a given offset */
|
2304
|
-
static void noinline
|
2845
|
+
static void noinline ecb_cold
|
2305
2846
|
timers_reschedule (EV_P_ ev_tstamp adjust)
|
2306
2847
|
{
|
2307
2848
|
int i;
|
@@ -2348,9 +2889,12 @@ time_update (EV_P_ ev_tstamp max_block)
|
|
2348
2889
|
*/
|
2349
2890
|
for (i = 4; --i; )
|
2350
2891
|
{
|
2892
|
+
ev_tstamp diff;
|
2351
2893
|
rtmn_diff = ev_rt_now - mn_now;
|
2352
2894
|
|
2353
|
-
|
2895
|
+
diff = odiff - rtmn_diff;
|
2896
|
+
|
2897
|
+
if (expect_true ((diff < 0. ? -diff : diff) < MIN_TIMEJUMP))
|
2354
2898
|
return; /* all is well */
|
2355
2899
|
|
2356
2900
|
ev_rt_now = ev_time ();
|
@@ -2450,20 +2994,25 @@ ev_run (EV_P_ int flags)
|
|
2450
2994
|
/* update time to cancel out callback processing overhead */
|
2451
2995
|
time_update (EV_A_ 1e100);
|
2452
2996
|
|
2453
|
-
|
2997
|
+
/* from now on, we want a pipe-wake-up */
|
2998
|
+
pipe_write_wanted = 1;
|
2999
|
+
|
3000
|
+
ECB_MEMORY_FENCE; /* make sure pipe_write_wanted is visible before we check for potential skips */
|
3001
|
+
|
3002
|
+
if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt || pipe_write_skipped)))
|
2454
3003
|
{
|
2455
3004
|
waittime = MAX_BLOCKTIME;
|
2456
3005
|
|
2457
3006
|
if (timercnt)
|
2458
3007
|
{
|
2459
|
-
ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now
|
3008
|
+
ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now;
|
2460
3009
|
if (waittime > to) waittime = to;
|
2461
3010
|
}
|
2462
3011
|
|
2463
3012
|
#if EV_PERIODIC_ENABLE
|
2464
3013
|
if (periodiccnt)
|
2465
3014
|
{
|
2466
|
-
ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now
|
3015
|
+
ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now;
|
2467
3016
|
if (waittime > to) waittime = to;
|
2468
3017
|
}
|
2469
3018
|
#endif
|
@@ -2472,13 +3021,18 @@ ev_run (EV_P_ int flags)
|
|
2472
3021
|
if (expect_false (waittime < timeout_blocktime))
|
2473
3022
|
waittime = timeout_blocktime;
|
2474
3023
|
|
3024
|
+
/* at this point, we NEED to wait, so we have to ensure */
|
3025
|
+
/* to pass a minimum nonzero value to the backend */
|
3026
|
+
if (expect_false (waittime < backend_mintime))
|
3027
|
+
waittime = backend_mintime;
|
3028
|
+
|
2475
3029
|
/* extra check because io_blocktime is commonly 0 */
|
2476
3030
|
if (expect_false (io_blocktime))
|
2477
3031
|
{
|
2478
3032
|
sleeptime = io_blocktime - (mn_now - prev_mn_now);
|
2479
3033
|
|
2480
|
-
if (sleeptime > waittime -
|
2481
|
-
sleeptime = waittime -
|
3034
|
+
if (sleeptime > waittime - backend_mintime)
|
3035
|
+
sleeptime = waittime - backend_mintime;
|
2482
3036
|
|
2483
3037
|
if (expect_true (sleeptime > 0.))
|
2484
3038
|
{
|
@@ -2495,6 +3049,15 @@ ev_run (EV_P_ int flags)
|
|
2495
3049
|
backend_poll (EV_A_ waittime);
|
2496
3050
|
assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */
|
2497
3051
|
|
3052
|
+
pipe_write_wanted = 0; /* just an optimisation, no fence needed */
|
3053
|
+
|
3054
|
+
if (pipe_write_skipped)
|
3055
|
+
{
|
3056
|
+
assert (("libev: pipe_w not active, but pipe not written", ev_is_active (&pipe_w)));
|
3057
|
+
ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);
|
3058
|
+
}
|
3059
|
+
|
3060
|
+
|
2498
3061
|
/* update ev_rt_now, do magic */
|
2499
3062
|
time_update (EV_A_ waittime + sleeptime);
|
2500
3063
|
}
|
@@ -2755,6 +3318,8 @@ ev_timer_again (EV_P_ ev_timer *w)
|
|
2755
3318
|
{
|
2756
3319
|
EV_FREQUENT_CHECK;
|
2757
3320
|
|
3321
|
+
clear_pending (EV_A_ (W)w);
|
3322
|
+
|
2758
3323
|
if (ev_is_active (w))
|
2759
3324
|
{
|
2760
3325
|
if (w->repeat)
|
@@ -3157,7 +3722,7 @@ infy_cb (EV_P_ ev_io *w, int revents)
|
|
3157
3722
|
}
|
3158
3723
|
}
|
3159
3724
|
|
3160
|
-
inline_size void
|
3725
|
+
inline_size void ecb_cold
|
3161
3726
|
ev_check_2625 (EV_P)
|
3162
3727
|
{
|
3163
3728
|
/* kernels < 2.6.25 are borked
|
@@ -3792,7 +4357,7 @@ ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, vo
|
|
3792
4357
|
/*****************************************************************************/
|
3793
4358
|
|
3794
4359
|
#if EV_WALK_ENABLE
|
3795
|
-
void
|
4360
|
+
void ecb_cold
|
3796
4361
|
ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
|
3797
4362
|
{
|
3798
4363
|
int i, j;
|
@@ -3846,7 +4411,7 @@ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
|
|
3846
4411
|
|
3847
4412
|
#if EV_IDLE_ENABLE
|
3848
4413
|
if (types & EV_IDLE)
|
3849
|
-
for (j = NUMPRI;
|
4414
|
+
for (j = NUMPRI; j--; )
|
3850
4415
|
for (i = idlecnt [j]; i--; )
|
3851
4416
|
cb (EV_A_ EV_IDLE, idles [j][i]);
|
3852
4417
|
#endif
|
@@ -3909,5 +4474,3 @@ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
|
|
3909
4474
|
#include "ev_wrap.h"
|
3910
4475
|
#endif
|
3911
4476
|
|
3912
|
-
EV_CPP(})
|
3913
|
-
|