cool.io 1.0.0 → 1.9.0
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.
- checksums.yaml +7 -0
- data/.github/workflows/test.yaml +54 -0
- data/.gitignore +30 -0
- data/.rspec +3 -0
- data/{CHANGES → CHANGES.md} +175 -79
- data/{README.markdown → README.md} +43 -49
- data/Rakefile +44 -69
- data/appveyor.yml +18 -0
- data/cool.io.gemspec +18 -131
- data/examples/callbacked_echo_server.rb +24 -0
- data/ext/cool.io/buffer.c +781 -0
- data/ext/cool.io/cool.io.h +13 -0
- data/ext/cool.io/cool.io_ext.c +1 -0
- data/ext/cool.io/ev_wrap.h +4 -2
- data/ext/cool.io/extconf.rb +27 -16
- data/ext/cool.io/iowatcher.c +17 -8
- data/ext/cool.io/loop.c +36 -84
- data/ext/cool.io/stat_watcher.c +103 -25
- data/ext/cool.io/timer_watcher.c +3 -3
- data/ext/cool.io/utils.c +5 -0
- data/ext/cool.io/watcher.h +1 -1
- data/ext/libev/Changes +152 -3
- data/ext/libev/LICENSE +2 -1
- data/ext/libev/README +8 -8
- data/ext/libev/ev.c +1719 -348
- data/ext/libev/ev.h +146 -118
- data/ext/libev/ev_epoll.c +71 -20
- data/ext/libev/ev_kqueue.c +36 -16
- data/ext/libev/ev_poll.c +14 -11
- data/ext/libev/ev_port.c +43 -18
- data/ext/libev/ev_select.c +82 -25
- data/ext/libev/ev_vars.h +28 -21
- data/ext/libev/ev_win32.c +19 -10
- data/ext/libev/ev_wrap.h +166 -152
- data/ext/libev/test_libev_win32.c +1 -1
- data/gems.rb +9 -0
- data/lib/cool.io/async_watcher.rb +1 -1
- data/lib/cool.io/custom_require.rb +9 -0
- data/lib/cool.io/dns_resolver.rb +30 -22
- data/lib/cool.io/dsl.rb +32 -28
- data/lib/cool.io/io.rb +55 -35
- data/lib/cool.io/iowatcher.rb +1 -1
- data/lib/cool.io/listener.rb +35 -17
- data/lib/cool.io/loop.rb +17 -25
- data/lib/cool.io/meta.rb +6 -5
- data/lib/cool.io/server.rb +5 -4
- data/lib/cool.io/socket.rb +41 -30
- data/lib/cool.io/timer_watcher.rb +1 -1
- data/lib/cool.io/version.rb +7 -0
- data/lib/cool.io.rb +11 -10
- data/lib/coolio.rb +1 -1
- data/libev_ruby_gil.diff +175 -0
- data/libev_win_select.diff +130 -0
- data/spec/async_watcher_spec.rb +5 -5
- data/spec/dns_spec.rb +27 -8
- data/spec/iobuffer_spec.rb +147 -0
- data/spec/spec_helper.rb +15 -1
- data/spec/stat_watcher_spec.rb +81 -0
- data/spec/tcp_server_spec.rb +225 -0
- data/spec/tcp_socket_spec.rb +185 -0
- data/spec/timer_watcher_spec.rb +23 -19
- data/spec/udp_socket_spec.rb +58 -0
- data/spec/unix_listener_spec.rb +8 -8
- data/spec/unix_server_spec.rb +10 -8
- metadata +109 -112
- data/VERSION +0 -1
- data/examples/httpclient.rb +0 -38
- data/ext/http11_client/.gitignore +0 -5
- data/ext/http11_client/LICENSE +0 -31
- data/ext/http11_client/ext_help.h +0 -14
- data/ext/http11_client/extconf.rb +0 -6
- data/ext/http11_client/http11_client.c +0 -300
- data/ext/http11_client/http11_parser.c +0 -403
- data/ext/http11_client/http11_parser.h +0 -48
- data/ext/http11_client/http11_parser.rl +0 -173
- data/lib/cool.io/eventmachine.rb +0 -234
- data/lib/cool.io/http_client.rb +0 -419
- data/lib/rev.rb +0 -4
- data/spec/possible_tests/schedules_other_threads.rb +0 -48
- data/spec/possible_tests/test_on_resolve_failed.rb +0 -9
- data/spec/possible_tests/test_resolves.rb +0 -27
- data/spec/possible_tests/test_write_during_resolve.rb +0 -27
- data/spec/possible_tests/works_straight.rb +0 -71
data/ext/libev/ev.c
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* libev event processing core, watcher management
|
|
3
3
|
*
|
|
4
|
-
* Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev@schmorp.de>
|
|
4
|
+
* Copyright (c) 2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann <libev@schmorp.de>
|
|
5
5
|
* All rights reserved.
|
|
6
6
|
*
|
|
7
7
|
* Redistribution and use in source and binary forms, with or without modifica-
|
|
8
8
|
* tion, are permitted provided that the following conditions are met:
|
|
9
|
-
*
|
|
9
|
+
*
|
|
10
10
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
11
11
|
* this list of conditions and the following disclaimer.
|
|
12
|
-
*
|
|
12
|
+
*
|
|
13
13
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
14
14
|
* notice, this list of conditions and the following disclaimer in the
|
|
15
15
|
* documentation and/or other materials provided with the distribution.
|
|
16
|
-
*
|
|
16
|
+
*
|
|
17
17
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
18
18
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
|
|
19
19
|
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
|
@@ -37,6 +37,13 @@
|
|
|
37
37
|
* either the BSD or the GPL.
|
|
38
38
|
*/
|
|
39
39
|
|
|
40
|
+
/* ########## COOLIO PATCHERY HO! ########## */
|
|
41
|
+
#include "ruby.h"
|
|
42
|
+
#if defined(HAVE_RUBY_THREAD_H)
|
|
43
|
+
#include "ruby/thread.h"
|
|
44
|
+
#endif
|
|
45
|
+
/* ######################################## */
|
|
46
|
+
|
|
40
47
|
/* this big block deduces configuration from config.h */
|
|
41
48
|
#ifndef EV_STANDALONE
|
|
42
49
|
# ifdef EV_CONFIG_H
|
|
@@ -45,6 +52,12 @@
|
|
|
45
52
|
# include "config.h"
|
|
46
53
|
# endif
|
|
47
54
|
|
|
55
|
+
# if HAVE_FLOOR
|
|
56
|
+
# ifndef EV_USE_FLOOR
|
|
57
|
+
# define EV_USE_FLOOR 1
|
|
58
|
+
# endif
|
|
59
|
+
# endif
|
|
60
|
+
|
|
48
61
|
# if HAVE_CLOCK_SYSCALL
|
|
49
62
|
# ifndef EV_USE_CLOCK_SYSCALL
|
|
50
63
|
# define EV_USE_CLOCK_SYSCALL 1
|
|
@@ -55,7 +68,7 @@
|
|
|
55
68
|
# define EV_USE_MONOTONIC 1
|
|
56
69
|
# endif
|
|
57
70
|
# endif
|
|
58
|
-
# elif !defined
|
|
71
|
+
# elif !defined EV_USE_CLOCK_SYSCALL
|
|
59
72
|
# define EV_USE_CLOCK_SYSCALL 0
|
|
60
73
|
# endif
|
|
61
74
|
|
|
@@ -101,7 +114,7 @@
|
|
|
101
114
|
# undef EV_USE_POLL
|
|
102
115
|
# define EV_USE_POLL 0
|
|
103
116
|
# endif
|
|
104
|
-
|
|
117
|
+
|
|
105
118
|
# if HAVE_EPOLL_CTL && HAVE_SYS_EPOLL_H
|
|
106
119
|
# ifndef EV_USE_EPOLL
|
|
107
120
|
# define EV_USE_EPOLL EV_FEATURE_BACKENDS
|
|
@@ -110,7 +123,7 @@
|
|
|
110
123
|
# undef EV_USE_EPOLL
|
|
111
124
|
# define EV_USE_EPOLL 0
|
|
112
125
|
# endif
|
|
113
|
-
|
|
126
|
+
|
|
114
127
|
# if HAVE_KQUEUE && HAVE_SYS_EVENT_H
|
|
115
128
|
# ifndef EV_USE_KQUEUE
|
|
116
129
|
# define EV_USE_KQUEUE EV_FEATURE_BACKENDS
|
|
@@ -119,7 +132,7 @@
|
|
|
119
132
|
# undef EV_USE_KQUEUE
|
|
120
133
|
# define EV_USE_KQUEUE 0
|
|
121
134
|
# endif
|
|
122
|
-
|
|
135
|
+
|
|
123
136
|
# if HAVE_PORT_H && HAVE_PORT_CREATE
|
|
124
137
|
# ifndef EV_USE_PORT
|
|
125
138
|
# define EV_USE_PORT EV_FEATURE_BACKENDS
|
|
@@ -155,10 +168,9 @@
|
|
|
155
168
|
# undef EV_USE_EVENTFD
|
|
156
169
|
# define EV_USE_EVENTFD 0
|
|
157
170
|
# endif
|
|
158
|
-
|
|
171
|
+
|
|
159
172
|
#endif
|
|
160
173
|
|
|
161
|
-
#include <math.h>
|
|
162
174
|
#include <stdlib.h>
|
|
163
175
|
#include <string.h>
|
|
164
176
|
#include <fcntl.h>
|
|
@@ -180,7 +192,16 @@
|
|
|
180
192
|
# include "ev.h"
|
|
181
193
|
#endif
|
|
182
194
|
|
|
183
|
-
|
|
195
|
+
#if EV_NO_THREADS
|
|
196
|
+
# undef EV_NO_SMP
|
|
197
|
+
# define EV_NO_SMP 1
|
|
198
|
+
# undef ECB_NO_THREADS
|
|
199
|
+
# define ECB_NO_THREADS 1
|
|
200
|
+
#endif
|
|
201
|
+
#if EV_NO_SMP
|
|
202
|
+
# undef EV_NO_SMP
|
|
203
|
+
# define ECB_NO_SMP 1
|
|
204
|
+
#endif
|
|
184
205
|
|
|
185
206
|
#ifndef _WIN32
|
|
186
207
|
# include <sys/time.h>
|
|
@@ -189,6 +210,8 @@ EV_CPP(extern "C" {)
|
|
|
189
210
|
#else
|
|
190
211
|
# include <io.h>
|
|
191
212
|
# define WIN32_LEAN_AND_MEAN
|
|
213
|
+
# define FD_SETSIZE 1024
|
|
214
|
+
# include <winsock2.h>
|
|
192
215
|
# include <windows.h>
|
|
193
216
|
# ifndef EV_SELECT_IS_WINSOCKET
|
|
194
217
|
# define EV_SELECT_IS_WINSOCKET 1
|
|
@@ -207,43 +230,53 @@ EV_CPP(extern "C" {)
|
|
|
207
230
|
/* this block tries to deduce configuration from header-defined symbols and defaults */
|
|
208
231
|
|
|
209
232
|
/* try to deduce the maximum number of signals on this platform */
|
|
210
|
-
#if defined
|
|
233
|
+
#if defined EV_NSIG
|
|
211
234
|
/* use what's provided */
|
|
212
|
-
#elif defined
|
|
235
|
+
#elif defined NSIG
|
|
213
236
|
# define EV_NSIG (NSIG)
|
|
214
|
-
#elif defined
|
|
237
|
+
#elif defined _NSIG
|
|
215
238
|
# define EV_NSIG (_NSIG)
|
|
216
|
-
#elif defined
|
|
239
|
+
#elif defined SIGMAX
|
|
217
240
|
# define EV_NSIG (SIGMAX+1)
|
|
218
|
-
#elif defined
|
|
241
|
+
#elif defined SIG_MAX
|
|
219
242
|
# define EV_NSIG (SIG_MAX+1)
|
|
220
|
-
#elif defined
|
|
243
|
+
#elif defined _SIG_MAX
|
|
221
244
|
# define EV_NSIG (_SIG_MAX+1)
|
|
222
|
-
#elif defined
|
|
245
|
+
#elif defined MAXSIG
|
|
223
246
|
# define EV_NSIG (MAXSIG+1)
|
|
224
|
-
#elif defined
|
|
247
|
+
#elif defined MAX_SIG
|
|
225
248
|
# define EV_NSIG (MAX_SIG+1)
|
|
226
|
-
#elif defined
|
|
249
|
+
#elif defined SIGARRAYSIZE
|
|
227
250
|
# define EV_NSIG (SIGARRAYSIZE) /* Assume ary[SIGARRAYSIZE] */
|
|
228
|
-
#elif defined
|
|
251
|
+
#elif defined _sys_nsig
|
|
229
252
|
# define EV_NSIG (_sys_nsig) /* Solaris 2.5 */
|
|
230
253
|
#else
|
|
231
|
-
#
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
#
|
|
254
|
+
# define EV_NSIG (8 * sizeof (sigset_t) + 1)
|
|
255
|
+
#endif
|
|
256
|
+
|
|
257
|
+
#ifndef EV_USE_FLOOR
|
|
258
|
+
# define EV_USE_FLOOR 0
|
|
235
259
|
#endif
|
|
236
260
|
|
|
237
261
|
#ifndef EV_USE_CLOCK_SYSCALL
|
|
238
|
-
# if __linux && __GLIBC__
|
|
262
|
+
# if __linux && __GLIBC__ == 2 && __GLIBC_MINOR__ < 17
|
|
239
263
|
# define EV_USE_CLOCK_SYSCALL EV_FEATURE_OS
|
|
240
264
|
# else
|
|
241
265
|
# define EV_USE_CLOCK_SYSCALL 0
|
|
242
266
|
# endif
|
|
243
267
|
#endif
|
|
244
268
|
|
|
269
|
+
#if !(_POSIX_TIMERS > 0)
|
|
270
|
+
# ifndef EV_USE_MONOTONIC
|
|
271
|
+
# define EV_USE_MONOTONIC 0
|
|
272
|
+
# endif
|
|
273
|
+
# ifndef EV_USE_REALTIME
|
|
274
|
+
# define EV_USE_REALTIME 0
|
|
275
|
+
# endif
|
|
276
|
+
#endif
|
|
277
|
+
|
|
245
278
|
#ifndef EV_USE_MONOTONIC
|
|
246
|
-
# if defined
|
|
279
|
+
# if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
|
|
247
280
|
# define EV_USE_MONOTONIC EV_FEATURE_OS
|
|
248
281
|
# else
|
|
249
282
|
# define EV_USE_MONOTONIC 0
|
|
@@ -340,10 +373,26 @@ EV_CPP(extern "C" {)
|
|
|
340
373
|
# define EV_HEAP_CACHE_AT EV_FEATURE_DATA
|
|
341
374
|
#endif
|
|
342
375
|
|
|
376
|
+
#ifdef ANDROID
|
|
377
|
+
/* supposedly, android doesn't typedef fd_mask */
|
|
378
|
+
# undef EV_USE_SELECT
|
|
379
|
+
# define EV_USE_SELECT 0
|
|
380
|
+
/* supposedly, we need to include syscall.h, not sys/syscall.h, so just disable */
|
|
381
|
+
# undef EV_USE_CLOCK_SYSCALL
|
|
382
|
+
# define EV_USE_CLOCK_SYSCALL 0
|
|
383
|
+
#endif
|
|
384
|
+
|
|
385
|
+
/* aix's poll.h seems to cause lots of trouble */
|
|
386
|
+
#ifdef _AIX
|
|
387
|
+
/* AIX has a completely broken poll.h header */
|
|
388
|
+
# undef EV_USE_POLL
|
|
389
|
+
# define EV_USE_POLL 0
|
|
390
|
+
#endif
|
|
391
|
+
|
|
343
392
|
/* on linux, we can use a (slow) syscall to avoid a dependency on pthread, */
|
|
344
393
|
/* which makes programs even slower. might work on other unices, too. */
|
|
345
394
|
#if EV_USE_CLOCK_SYSCALL
|
|
346
|
-
# include <syscall.h>
|
|
395
|
+
# include <sys/syscall.h>
|
|
347
396
|
# ifdef SYS_clock_gettime
|
|
348
397
|
# define clock_gettime(id, ts) syscall (SYS_clock_gettime, (id), (ts))
|
|
349
398
|
# undef EV_USE_MONOTONIC
|
|
@@ -356,12 +405,6 @@ EV_CPP(extern "C" {)
|
|
|
356
405
|
|
|
357
406
|
/* this block fixes any misconfiguration where we know we run into trouble otherwise */
|
|
358
407
|
|
|
359
|
-
#ifdef _AIX
|
|
360
|
-
/* AIX has a completely broken poll.h header */
|
|
361
|
-
# undef EV_USE_POLL
|
|
362
|
-
# define EV_USE_POLL 0
|
|
363
|
-
#endif
|
|
364
|
-
|
|
365
408
|
#ifndef CLOCK_MONOTONIC
|
|
366
409
|
# undef EV_USE_MONOTONIC
|
|
367
410
|
# define EV_USE_MONOTONIC 0
|
|
@@ -378,7 +421,8 @@ EV_CPP(extern "C" {)
|
|
|
378
421
|
#endif
|
|
379
422
|
|
|
380
423
|
#if !EV_USE_NANOSLEEP
|
|
381
|
-
|
|
424
|
+
/* hp-ux has it in sys/time.h, which we unconditionally include above */
|
|
425
|
+
# if !defined _WIN32 && !defined __hpux
|
|
382
426
|
# include <sys/select.h>
|
|
383
427
|
# endif
|
|
384
428
|
#endif
|
|
@@ -393,10 +437,6 @@ EV_CPP(extern "C" {)
|
|
|
393
437
|
# endif
|
|
394
438
|
#endif
|
|
395
439
|
|
|
396
|
-
#if EV_SELECT_IS_WINSOCKET
|
|
397
|
-
# include <winsock.h>
|
|
398
|
-
#endif
|
|
399
|
-
|
|
400
440
|
#if EV_USE_EVENTFD
|
|
401
441
|
/* our minimum requirement is glibc 2.7 which has the stub, but not the header */
|
|
402
442
|
# include <stdint.h>
|
|
@@ -444,14 +484,11 @@ struct signalfd_siginfo
|
|
|
444
484
|
#endif
|
|
445
485
|
|
|
446
486
|
/*
|
|
447
|
-
* This is used to
|
|
448
|
-
* It is added to ev_rt_now when scheduling periodics
|
|
449
|
-
* to ensure progress, time-wise, even when rounding
|
|
450
|
-
* errors are against us.
|
|
487
|
+
* This is used to work around floating point rounding problems.
|
|
451
488
|
* This value is good at least till the year 4000.
|
|
452
|
-
* Better solutions welcome.
|
|
453
489
|
*/
|
|
454
|
-
#define
|
|
490
|
+
#define MIN_INTERVAL 0.0001220703125 /* 1/2**13, good till 4000 */
|
|
491
|
+
/*#define MIN_INTERVAL 0.00000095367431640625 /* 1/2**20, good till 2200 */
|
|
455
492
|
|
|
456
493
|
#define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */
|
|
457
494
|
#define MAX_BLOCKTIME 59.743 /* never wait longer than this time (to detect time jumps) */
|
|
@@ -459,25 +496,1048 @@ struct signalfd_siginfo
|
|
|
459
496
|
#define EV_TV_SET(tv,t) do { tv.tv_sec = (long)t; tv.tv_usec = (long)((t - tv.tv_sec) * 1e6); } while (0)
|
|
460
497
|
#define EV_TS_SET(ts,t) do { ts.tv_sec = (long)t; ts.tv_nsec = (long)((t - ts.tv_sec) * 1e9); } while (0)
|
|
461
498
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
499
|
+
/* the following is ecb.h embedded into libev - use update_ev_c to update from an external copy */
|
|
500
|
+
/* ECB.H BEGIN */
|
|
501
|
+
/*
|
|
502
|
+
* libecb - http://software.schmorp.de/pkg/libecb
|
|
503
|
+
*
|
|
504
|
+
* Copyright (©) 2009-2015 Marc Alexander Lehmann <libecb@schmorp.de>
|
|
505
|
+
* Copyright (©) 2011 Emanuele Giaquinta
|
|
506
|
+
* All rights reserved.
|
|
507
|
+
*
|
|
508
|
+
* Redistribution and use in source and binary forms, with or without modifica-
|
|
509
|
+
* tion, are permitted provided that the following conditions are met:
|
|
510
|
+
*
|
|
511
|
+
* 1. Redistributions of source code must retain the above copyright notice,
|
|
512
|
+
* this list of conditions and the following disclaimer.
|
|
513
|
+
*
|
|
514
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
|
515
|
+
* notice, this list of conditions and the following disclaimer in the
|
|
516
|
+
* documentation and/or other materials provided with the distribution.
|
|
517
|
+
*
|
|
518
|
+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
519
|
+
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
|
|
520
|
+
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
|
521
|
+
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
|
|
522
|
+
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
523
|
+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
524
|
+
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
525
|
+
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
|
|
526
|
+
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
527
|
+
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
528
|
+
*
|
|
529
|
+
* Alternatively, the contents of this file may be used under the terms of
|
|
530
|
+
* the GNU General Public License ("GPL") version 2 or any later version,
|
|
531
|
+
* in which case the provisions of the GPL are applicable instead of
|
|
532
|
+
* the above. If you wish to allow the use of your version of this file
|
|
533
|
+
* only under the terms of the GPL and not to allow others to use your
|
|
534
|
+
* version of this file under the BSD license, indicate your decision
|
|
535
|
+
* by deleting the provisions above and replace them with the notice
|
|
536
|
+
* and other provisions required by the GPL. If you do not delete the
|
|
537
|
+
* provisions above, a recipient may use your version of this file under
|
|
538
|
+
* either the BSD or the GPL.
|
|
539
|
+
*/
|
|
540
|
+
|
|
541
|
+
#ifndef ECB_H
|
|
542
|
+
#define ECB_H
|
|
543
|
+
|
|
544
|
+
/* 16 bits major, 16 bits minor */
|
|
545
|
+
#define ECB_VERSION 0x00010005
|
|
546
|
+
|
|
547
|
+
#ifdef _WIN32
|
|
548
|
+
typedef signed char int8_t;
|
|
549
|
+
typedef unsigned char uint8_t;
|
|
550
|
+
typedef signed short int16_t;
|
|
551
|
+
typedef unsigned short uint16_t;
|
|
552
|
+
typedef signed int int32_t;
|
|
553
|
+
typedef unsigned int uint32_t;
|
|
554
|
+
#if __GNUC__
|
|
555
|
+
typedef signed long long int64_t;
|
|
556
|
+
typedef unsigned long long uint64_t;
|
|
557
|
+
#else /* _MSC_VER || __BORLANDC__ */
|
|
558
|
+
typedef signed __int64 int64_t;
|
|
559
|
+
typedef unsigned __int64 uint64_t;
|
|
560
|
+
#endif
|
|
561
|
+
#ifdef _WIN64
|
|
562
|
+
#define ECB_PTRSIZE 8
|
|
563
|
+
typedef uint64_t uintptr_t;
|
|
564
|
+
typedef int64_t intptr_t;
|
|
565
|
+
#else
|
|
566
|
+
#define ECB_PTRSIZE 4
|
|
567
|
+
typedef uint32_t uintptr_t;
|
|
568
|
+
typedef int32_t intptr_t;
|
|
569
|
+
#endif
|
|
465
570
|
#else
|
|
466
|
-
#
|
|
467
|
-
#
|
|
468
|
-
#
|
|
469
|
-
#
|
|
470
|
-
#
|
|
571
|
+
#include <inttypes.h>
|
|
572
|
+
#if (defined INTPTR_MAX ? INTPTR_MAX : ULONG_MAX) > 0xffffffffU
|
|
573
|
+
#define ECB_PTRSIZE 8
|
|
574
|
+
#else
|
|
575
|
+
#define ECB_PTRSIZE 4
|
|
576
|
+
#endif
|
|
577
|
+
#endif
|
|
578
|
+
|
|
579
|
+
#define ECB_GCC_AMD64 (__amd64 || __amd64__ || __x86_64 || __x86_64__)
|
|
580
|
+
#define ECB_MSVC_AMD64 (_M_AMD64 || _M_X64)
|
|
581
|
+
|
|
582
|
+
/* work around x32 idiocy by defining proper macros */
|
|
583
|
+
#if ECB_GCC_AMD64 || ECB_MSVC_AMD64
|
|
584
|
+
#if _ILP32
|
|
585
|
+
#define ECB_AMD64_X32 1
|
|
586
|
+
#else
|
|
587
|
+
#define ECB_AMD64 1
|
|
588
|
+
#endif
|
|
589
|
+
#endif
|
|
590
|
+
|
|
591
|
+
/* many compilers define _GNUC_ to some versions but then only implement
|
|
592
|
+
* what their idiot authors think are the "more important" extensions,
|
|
593
|
+
* causing enormous grief in return for some better fake benchmark numbers.
|
|
594
|
+
* or so.
|
|
595
|
+
* we try to detect these and simply assume they are not gcc - if they have
|
|
596
|
+
* an issue with that they should have done it right in the first place.
|
|
597
|
+
*/
|
|
598
|
+
#if !defined __GNUC_MINOR__ || defined __INTEL_COMPILER || defined __SUNPRO_C || defined __SUNPRO_CC || defined __llvm__ || defined __clang__
|
|
599
|
+
#define ECB_GCC_VERSION(major,minor) 0
|
|
600
|
+
#else
|
|
601
|
+
#define ECB_GCC_VERSION(major,minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
|
|
602
|
+
#endif
|
|
603
|
+
|
|
604
|
+
#define ECB_CLANG_VERSION(major,minor) (__clang_major__ > (major) || (__clang_major__ == (major) && __clang_minor__ >= (minor)))
|
|
605
|
+
|
|
606
|
+
#if __clang__ && defined __has_builtin
|
|
607
|
+
#define ECB_CLANG_BUILTIN(x) __has_builtin (x)
|
|
608
|
+
#else
|
|
609
|
+
#define ECB_CLANG_BUILTIN(x) 0
|
|
610
|
+
#endif
|
|
611
|
+
|
|
612
|
+
#if __clang__ && defined __has_extension
|
|
613
|
+
#define ECB_CLANG_EXTENSION(x) __has_extension (x)
|
|
614
|
+
#else
|
|
615
|
+
#define ECB_CLANG_EXTENSION(x) 0
|
|
616
|
+
#endif
|
|
617
|
+
|
|
618
|
+
#define ECB_CPP (__cplusplus+0)
|
|
619
|
+
#define ECB_CPP11 (__cplusplus >= 201103L)
|
|
620
|
+
|
|
621
|
+
#if ECB_CPP
|
|
622
|
+
#define ECB_C 0
|
|
623
|
+
#define ECB_STDC_VERSION 0
|
|
624
|
+
#else
|
|
625
|
+
#define ECB_C 1
|
|
626
|
+
#define ECB_STDC_VERSION __STDC_VERSION__
|
|
627
|
+
#endif
|
|
628
|
+
|
|
629
|
+
#define ECB_C99 (ECB_STDC_VERSION >= 199901L)
|
|
630
|
+
#define ECB_C11 (ECB_STDC_VERSION >= 201112L)
|
|
631
|
+
|
|
632
|
+
#if ECB_CPP
|
|
633
|
+
#define ECB_EXTERN_C extern "C"
|
|
634
|
+
#define ECB_EXTERN_C_BEG ECB_EXTERN_C {
|
|
635
|
+
#define ECB_EXTERN_C_END }
|
|
636
|
+
#else
|
|
637
|
+
#define ECB_EXTERN_C extern
|
|
638
|
+
#define ECB_EXTERN_C_BEG
|
|
639
|
+
#define ECB_EXTERN_C_END
|
|
640
|
+
#endif
|
|
641
|
+
|
|
642
|
+
/*****************************************************************************/
|
|
643
|
+
|
|
644
|
+
/* ECB_NO_THREADS - ecb is not used by multiple threads, ever */
|
|
645
|
+
/* ECB_NO_SMP - ecb might be used in multiple threads, but only on a single cpu */
|
|
646
|
+
|
|
647
|
+
#if ECB_NO_THREADS
|
|
648
|
+
#define ECB_NO_SMP 1
|
|
649
|
+
#endif
|
|
650
|
+
|
|
651
|
+
#if ECB_NO_SMP
|
|
652
|
+
#define ECB_MEMORY_FENCE do { } while (0)
|
|
653
|
+
#endif
|
|
654
|
+
|
|
655
|
+
/* http://www-01.ibm.com/support/knowledgecenter/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/compiler_ref/compiler_builtins.html */
|
|
656
|
+
#if __xlC__ && ECB_CPP
|
|
657
|
+
#include <builtins.h>
|
|
658
|
+
#endif
|
|
659
|
+
|
|
660
|
+
#if 1400 <= _MSC_VER
|
|
661
|
+
#include <intrin.h> /* fence functions _ReadBarrier, also bit search functions _BitScanReverse */
|
|
662
|
+
#endif
|
|
663
|
+
|
|
664
|
+
#ifndef ECB_MEMORY_FENCE
|
|
665
|
+
#if ECB_GCC_VERSION(2,5) || defined __INTEL_COMPILER || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
|
|
666
|
+
#if __i386 || __i386__
|
|
667
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory")
|
|
668
|
+
#define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory")
|
|
669
|
+
#define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
|
|
670
|
+
#elif ECB_GCC_AMD64
|
|
671
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("mfence" : : : "memory")
|
|
672
|
+
#define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory")
|
|
673
|
+
#define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
|
|
674
|
+
#elif __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__
|
|
675
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("sync" : : : "memory")
|
|
676
|
+
#elif defined __ARM_ARCH_2__ \
|
|
677
|
+
|| defined __ARM_ARCH_3__ || defined __ARM_ARCH_3M__ \
|
|
678
|
+
|| defined __ARM_ARCH_4__ || defined __ARM_ARCH_4T__ \
|
|
679
|
+
|| defined __ARM_ARCH_5__ || defined __ARM_ARCH_5E__ \
|
|
680
|
+
|| defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__ \
|
|
681
|
+
|| defined __ARM_ARCH_5TEJ__
|
|
682
|
+
/* should not need any, unless running old code on newer cpu - arm doesn't support that */
|
|
683
|
+
#elif defined __ARM_ARCH_6__ || defined __ARM_ARCH_6J__ \
|
|
684
|
+
|| defined __ARM_ARCH_6K__ || defined __ARM_ARCH_6ZK__ \
|
|
685
|
+
|| defined __ARM_ARCH_6T2__
|
|
686
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("mcr p15,0,%0,c7,c10,5" : : "r" (0) : "memory")
|
|
687
|
+
#elif defined __ARM_ARCH_7__ || defined __ARM_ARCH_7A__ \
|
|
688
|
+
|| defined __ARM_ARCH_7R__ || defined __ARM_ARCH_7M__
|
|
689
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("dmb" : : : "memory")
|
|
690
|
+
#elif __aarch64__
|
|
691
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("dmb ish" : : : "memory")
|
|
692
|
+
#elif (__sparc || __sparc__) && !(__sparc_v8__ || defined __sparcv8)
|
|
693
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad | #StoreStore | #StoreLoad" : : : "memory")
|
|
694
|
+
#define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad" : : : "memory")
|
|
695
|
+
#define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("membar #LoadStore | #StoreStore")
|
|
696
|
+
#elif defined __s390__ || defined __s390x__
|
|
697
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("bcr 15,0" : : : "memory")
|
|
698
|
+
#elif defined __mips__
|
|
699
|
+
/* GNU/Linux emulates sync on mips1 architectures, so we force its use */
|
|
700
|
+
/* anybody else who still uses mips1 is supposed to send in their version, with detection code. */
|
|
701
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ (".set mips2; sync; .set mips0" : : : "memory")
|
|
702
|
+
#elif defined __alpha__
|
|
703
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("mb" : : : "memory")
|
|
704
|
+
#elif defined __hppa__
|
|
705
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("" : : : "memory")
|
|
706
|
+
#define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
|
|
707
|
+
#elif defined __ia64__
|
|
708
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("mf" : : : "memory")
|
|
709
|
+
#elif defined __m68k__
|
|
710
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("" : : : "memory")
|
|
711
|
+
#elif defined __m88k__
|
|
712
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("tb1 0,%%r0,128" : : : "memory")
|
|
713
|
+
#elif defined __sh__
|
|
714
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("" : : : "memory")
|
|
715
|
+
#endif
|
|
716
|
+
#endif
|
|
717
|
+
#endif
|
|
718
|
+
|
|
719
|
+
#ifndef ECB_MEMORY_FENCE
|
|
720
|
+
#if ECB_GCC_VERSION(4,7)
|
|
721
|
+
/* see comment below (stdatomic.h) about the C11 memory model. */
|
|
722
|
+
#define ECB_MEMORY_FENCE __atomic_thread_fence (__ATOMIC_SEQ_CST)
|
|
723
|
+
#define ECB_MEMORY_FENCE_ACQUIRE __atomic_thread_fence (__ATOMIC_ACQUIRE)
|
|
724
|
+
#define ECB_MEMORY_FENCE_RELEASE __atomic_thread_fence (__ATOMIC_RELEASE)
|
|
725
|
+
|
|
726
|
+
#elif ECB_CLANG_EXTENSION(c_atomic)
|
|
727
|
+
/* see comment below (stdatomic.h) about the C11 memory model. */
|
|
728
|
+
#define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST)
|
|
729
|
+
#define ECB_MEMORY_FENCE_ACQUIRE __c11_atomic_thread_fence (__ATOMIC_ACQUIRE)
|
|
730
|
+
#define ECB_MEMORY_FENCE_RELEASE __c11_atomic_thread_fence (__ATOMIC_RELEASE)
|
|
731
|
+
|
|
732
|
+
#elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__
|
|
733
|
+
#define ECB_MEMORY_FENCE __sync_synchronize ()
|
|
734
|
+
#elif _MSC_VER >= 1500 /* VC++ 2008 */
|
|
735
|
+
/* apparently, microsoft broke all the memory barrier stuff in Visual Studio 2008... */
|
|
736
|
+
#pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier)
|
|
737
|
+
#define ECB_MEMORY_FENCE _ReadWriteBarrier (); MemoryBarrier()
|
|
738
|
+
#define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier (); MemoryBarrier() /* according to msdn, _ReadBarrier is not a load fence */
|
|
739
|
+
#define ECB_MEMORY_FENCE_RELEASE _WriteBarrier (); MemoryBarrier()
|
|
740
|
+
#elif _MSC_VER >= 1400 /* VC++ 2005 */
|
|
741
|
+
#pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier)
|
|
742
|
+
#define ECB_MEMORY_FENCE _ReadWriteBarrier ()
|
|
743
|
+
#define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier () /* according to msdn, _ReadBarrier is not a load fence */
|
|
744
|
+
#define ECB_MEMORY_FENCE_RELEASE _WriteBarrier ()
|
|
745
|
+
#elif defined _WIN32
|
|
746
|
+
#include <WinNT.h>
|
|
747
|
+
#define ECB_MEMORY_FENCE MemoryBarrier () /* actually just xchg on x86... scary */
|
|
748
|
+
#elif __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
|
|
749
|
+
#include <mbarrier.h>
|
|
750
|
+
#define ECB_MEMORY_FENCE __machine_rw_barrier ()
|
|
751
|
+
#define ECB_MEMORY_FENCE_ACQUIRE __machine_r_barrier ()
|
|
752
|
+
#define ECB_MEMORY_FENCE_RELEASE __machine_w_barrier ()
|
|
753
|
+
#elif __xlC__
|
|
754
|
+
#define ECB_MEMORY_FENCE __sync ()
|
|
755
|
+
#endif
|
|
756
|
+
#endif
|
|
757
|
+
|
|
758
|
+
#ifndef ECB_MEMORY_FENCE
|
|
759
|
+
#if ECB_C11 && !defined __STDC_NO_ATOMICS__
|
|
760
|
+
/* we assume that these memory fences work on all variables/all memory accesses, */
|
|
761
|
+
/* not just C11 atomics and atomic accesses */
|
|
762
|
+
#include <stdatomic.h>
|
|
763
|
+
/* Unfortunately, neither gcc 4.7 nor clang 3.1 generate any instructions for */
|
|
764
|
+
/* any fence other than seq_cst, which isn't very efficient for us. */
|
|
765
|
+
/* Why that is, we don't know - either the C11 memory model is quite useless */
|
|
766
|
+
/* for most usages, or gcc and clang have a bug */
|
|
767
|
+
/* I *currently* lean towards the latter, and inefficiently implement */
|
|
768
|
+
/* all three of ecb's fences as a seq_cst fence */
|
|
769
|
+
/* Update, gcc-4.8 generates mfence for all c++ fences, but nothing */
|
|
770
|
+
/* for all __atomic_thread_fence's except seq_cst */
|
|
771
|
+
#define ECB_MEMORY_FENCE atomic_thread_fence (memory_order_seq_cst)
|
|
772
|
+
#endif
|
|
773
|
+
#endif
|
|
774
|
+
|
|
775
|
+
#ifndef ECB_MEMORY_FENCE
|
|
776
|
+
#if !ECB_AVOID_PTHREADS
|
|
777
|
+
/*
|
|
778
|
+
* if you get undefined symbol references to pthread_mutex_lock,
|
|
779
|
+
* or failure to find pthread.h, then you should implement
|
|
780
|
+
* the ECB_MEMORY_FENCE operations for your cpu/compiler
|
|
781
|
+
* OR provide pthread.h and link against the posix thread library
|
|
782
|
+
* of your system.
|
|
783
|
+
*/
|
|
784
|
+
#include <pthread.h>
|
|
785
|
+
#define ECB_NEEDS_PTHREADS 1
|
|
786
|
+
#define ECB_MEMORY_FENCE_NEEDS_PTHREADS 1
|
|
787
|
+
|
|
788
|
+
static pthread_mutex_t ecb_mf_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
789
|
+
#define ECB_MEMORY_FENCE do { pthread_mutex_lock (&ecb_mf_lock); pthread_mutex_unlock (&ecb_mf_lock); } while (0)
|
|
790
|
+
#endif
|
|
791
|
+
#endif
|
|
792
|
+
|
|
793
|
+
#if !defined ECB_MEMORY_FENCE_ACQUIRE && defined ECB_MEMORY_FENCE
|
|
794
|
+
#define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE
|
|
795
|
+
#endif
|
|
796
|
+
|
|
797
|
+
#if !defined ECB_MEMORY_FENCE_RELEASE && defined ECB_MEMORY_FENCE
|
|
798
|
+
#define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE
|
|
799
|
+
#endif
|
|
800
|
+
|
|
801
|
+
/*****************************************************************************/
|
|
802
|
+
|
|
803
|
+
#if ECB_CPP
|
|
804
|
+
#define ecb_inline static inline
|
|
805
|
+
#elif ECB_GCC_VERSION(2,5)
|
|
806
|
+
#define ecb_inline static __inline__
|
|
807
|
+
#elif ECB_C99
|
|
808
|
+
#define ecb_inline static inline
|
|
809
|
+
#else
|
|
810
|
+
#define ecb_inline static
|
|
811
|
+
#endif
|
|
812
|
+
|
|
813
|
+
#if ECB_GCC_VERSION(3,3)
|
|
814
|
+
#define ecb_restrict __restrict__
|
|
815
|
+
#elif ECB_C99
|
|
816
|
+
#define ecb_restrict restrict
|
|
817
|
+
#else
|
|
818
|
+
#define ecb_restrict
|
|
819
|
+
#endif
|
|
820
|
+
|
|
821
|
+
typedef int ecb_bool;
|
|
822
|
+
|
|
823
|
+
#define ECB_CONCAT_(a, b) a ## b
|
|
824
|
+
#define ECB_CONCAT(a, b) ECB_CONCAT_(a, b)
|
|
825
|
+
#define ECB_STRINGIFY_(a) # a
|
|
826
|
+
#define ECB_STRINGIFY(a) ECB_STRINGIFY_(a)
|
|
827
|
+
#define ECB_STRINGIFY_EXPR(expr) ((expr), ECB_STRINGIFY_ (expr))
|
|
828
|
+
|
|
829
|
+
#define ecb_function_ ecb_inline
|
|
830
|
+
|
|
831
|
+
#if ECB_GCC_VERSION(3,1) || ECB_CLANG_VERSION(2,8)
|
|
832
|
+
#define ecb_attribute(attrlist) __attribute__ (attrlist)
|
|
833
|
+
#else
|
|
834
|
+
#define ecb_attribute(attrlist)
|
|
835
|
+
#endif
|
|
836
|
+
|
|
837
|
+
#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_constant_p)
|
|
838
|
+
#define ecb_is_constant(expr) __builtin_constant_p (expr)
|
|
839
|
+
#else
|
|
840
|
+
/* possible C11 impl for integral types
|
|
841
|
+
typedef struct ecb_is_constant_struct ecb_is_constant_struct;
|
|
842
|
+
#define ecb_is_constant(expr) _Generic ((1 ? (struct ecb_is_constant_struct *)0 : (void *)((expr) - (expr)), ecb_is_constant_struct *: 0, default: 1)) */
|
|
843
|
+
|
|
844
|
+
#define ecb_is_constant(expr) 0
|
|
845
|
+
#endif
|
|
846
|
+
|
|
847
|
+
#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_expect)
|
|
848
|
+
#define ecb_expect(expr,value) __builtin_expect ((expr),(value))
|
|
849
|
+
#else
|
|
850
|
+
#define ecb_expect(expr,value) (expr)
|
|
851
|
+
#endif
|
|
852
|
+
|
|
853
|
+
#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_prefetch)
|
|
854
|
+
#define ecb_prefetch(addr,rw,locality) __builtin_prefetch (addr, rw, locality)
|
|
855
|
+
#else
|
|
856
|
+
#define ecb_prefetch(addr,rw,locality)
|
|
857
|
+
#endif
|
|
858
|
+
|
|
859
|
+
/* no emulation for ecb_decltype */
|
|
860
|
+
#if ECB_CPP11
|
|
861
|
+
// older implementations might have problems with decltype(x)::type, work around it
|
|
862
|
+
template<class T> struct ecb_decltype_t { typedef T type; };
|
|
863
|
+
#define ecb_decltype(x) ecb_decltype_t<decltype (x)>::type
|
|
864
|
+
#elif ECB_GCC_VERSION(3,0) || ECB_CLANG_VERSION(2,8)
|
|
865
|
+
#define ecb_decltype(x) __typeof__ (x)
|
|
866
|
+
#endif
|
|
867
|
+
|
|
868
|
+
#if _MSC_VER >= 1300
|
|
869
|
+
#define ecb_deprecated __declspec (deprecated)
|
|
870
|
+
#else
|
|
871
|
+
#define ecb_deprecated ecb_attribute ((__deprecated__))
|
|
872
|
+
#endif
|
|
873
|
+
|
|
874
|
+
#if _MSC_VER >= 1500
|
|
875
|
+
#define ecb_deprecated_message(msg) __declspec (deprecated (msg))
|
|
876
|
+
#elif ECB_GCC_VERSION(4,5)
|
|
877
|
+
#define ecb_deprecated_message(msg) ecb_attribute ((__deprecated__ (msg))
|
|
878
|
+
#else
|
|
879
|
+
#define ecb_deprecated_message(msg) ecb_deprecated
|
|
880
|
+
#endif
|
|
881
|
+
|
|
882
|
+
#if _MSC_VER >= 1400
|
|
883
|
+
#define ecb_noinline __declspec (noinline)
|
|
884
|
+
#else
|
|
885
|
+
#define ecb_noinline ecb_attribute ((__noinline__))
|
|
886
|
+
#endif
|
|
887
|
+
|
|
888
|
+
#define ecb_unused ecb_attribute ((__unused__))
|
|
889
|
+
#define ecb_const ecb_attribute ((__const__))
|
|
890
|
+
#define ecb_pure ecb_attribute ((__pure__))
|
|
891
|
+
|
|
892
|
+
#if ECB_C11 || __IBMC_NORETURN
|
|
893
|
+
/* http://www-01.ibm.com/support/knowledgecenter/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/language_ref/noreturn.html */
|
|
894
|
+
#define ecb_noreturn _Noreturn
|
|
895
|
+
#elif ECB_CPP11
|
|
896
|
+
#define ecb_noreturn [[noreturn]]
|
|
897
|
+
#elif _MSC_VER >= 1200
|
|
898
|
+
/* http://msdn.microsoft.com/en-us/library/k6ktzx3s.aspx */
|
|
899
|
+
#define ecb_noreturn __declspec (noreturn)
|
|
900
|
+
#else
|
|
901
|
+
#define ecb_noreturn ecb_attribute ((__noreturn__))
|
|
902
|
+
#endif
|
|
903
|
+
|
|
904
|
+
#if ECB_GCC_VERSION(4,3)
|
|
905
|
+
#define ecb_artificial ecb_attribute ((__artificial__))
|
|
906
|
+
#define ecb_hot ecb_attribute ((__hot__))
|
|
907
|
+
#define ecb_cold ecb_attribute ((__cold__))
|
|
908
|
+
#else
|
|
909
|
+
#define ecb_artificial
|
|
910
|
+
#define ecb_hot
|
|
911
|
+
#define ecb_cold
|
|
912
|
+
#endif
|
|
913
|
+
|
|
914
|
+
/* put around conditional expressions if you are very sure that the */
|
|
915
|
+
/* expression is mostly true or mostly false. note that these return */
|
|
916
|
+
/* booleans, not the expression. */
|
|
917
|
+
#define ecb_expect_false(expr) ecb_expect (!!(expr), 0)
|
|
918
|
+
#define ecb_expect_true(expr) ecb_expect (!!(expr), 1)
|
|
919
|
+
/* for compatibility to the rest of the world */
|
|
920
|
+
#define ecb_likely(expr) ecb_expect_true (expr)
|
|
921
|
+
#define ecb_unlikely(expr) ecb_expect_false (expr)
|
|
922
|
+
|
|
923
|
+
/* count trailing zero bits and count # of one bits */
|
|
924
|
+
#if ECB_GCC_VERSION(3,4) \
|
|
925
|
+
|| (ECB_CLANG_BUILTIN(__builtin_clz) && ECB_CLANG_BUILTIN(__builtin_clzll) \
|
|
926
|
+
&& ECB_CLANG_BUILTIN(__builtin_ctz) && ECB_CLANG_BUILTIN(__builtin_ctzll) \
|
|
927
|
+
&& ECB_CLANG_BUILTIN(__builtin_popcount))
|
|
928
|
+
/* we assume int == 32 bit, long == 32 or 64 bit and long long == 64 bit */
|
|
929
|
+
#define ecb_ld32(x) (__builtin_clz (x) ^ 31)
|
|
930
|
+
#define ecb_ld64(x) (__builtin_clzll (x) ^ 63)
|
|
931
|
+
#define ecb_ctz32(x) __builtin_ctz (x)
|
|
932
|
+
#define ecb_ctz64(x) __builtin_ctzll (x)
|
|
933
|
+
#define ecb_popcount32(x) __builtin_popcount (x)
|
|
934
|
+
/* no popcountll */
|
|
935
|
+
#else
|
|
936
|
+
ecb_function_ ecb_const int ecb_ctz32 (uint32_t x);
|
|
937
|
+
ecb_function_ ecb_const int
|
|
938
|
+
ecb_ctz32 (uint32_t x)
|
|
939
|
+
{
|
|
940
|
+
#if 1400 <= _MSC_VER && (_M_IX86 || _M_X64 || _M_IA64 || _M_ARM)
|
|
941
|
+
unsigned long r;
|
|
942
|
+
_BitScanForward (&r, x);
|
|
943
|
+
return (int)r;
|
|
944
|
+
#else
|
|
945
|
+
int r = 0;
|
|
946
|
+
|
|
947
|
+
x &= ~x + 1; /* this isolates the lowest bit */
|
|
948
|
+
|
|
949
|
+
#if ECB_branchless_on_i386
|
|
950
|
+
r += !!(x & 0xaaaaaaaa) << 0;
|
|
951
|
+
r += !!(x & 0xcccccccc) << 1;
|
|
952
|
+
r += !!(x & 0xf0f0f0f0) << 2;
|
|
953
|
+
r += !!(x & 0xff00ff00) << 3;
|
|
954
|
+
r += !!(x & 0xffff0000) << 4;
|
|
955
|
+
#else
|
|
956
|
+
if (x & 0xaaaaaaaa) r += 1;
|
|
957
|
+
if (x & 0xcccccccc) r += 2;
|
|
958
|
+
if (x & 0xf0f0f0f0) r += 4;
|
|
959
|
+
if (x & 0xff00ff00) r += 8;
|
|
960
|
+
if (x & 0xffff0000) r += 16;
|
|
961
|
+
#endif
|
|
962
|
+
|
|
963
|
+
return r;
|
|
964
|
+
#endif
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
ecb_function_ ecb_const int ecb_ctz64 (uint64_t x);
|
|
968
|
+
ecb_function_ ecb_const int
|
|
969
|
+
ecb_ctz64 (uint64_t x)
|
|
970
|
+
{
|
|
971
|
+
#if 1400 <= _MSC_VER && (_M_X64 || _M_IA64 || _M_ARM)
|
|
972
|
+
unsigned long r;
|
|
973
|
+
_BitScanForward64 (&r, x);
|
|
974
|
+
return (int)r;
|
|
975
|
+
#else
|
|
976
|
+
int shift = x & 0xffffffff ? 0 : 32;
|
|
977
|
+
return ecb_ctz32 (x >> shift) + shift;
|
|
978
|
+
#endif
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
ecb_function_ ecb_const int ecb_popcount32 (uint32_t x);
|
|
982
|
+
ecb_function_ ecb_const int
|
|
983
|
+
ecb_popcount32 (uint32_t x)
|
|
984
|
+
{
|
|
985
|
+
x -= (x >> 1) & 0x55555555;
|
|
986
|
+
x = ((x >> 2) & 0x33333333) + (x & 0x33333333);
|
|
987
|
+
x = ((x >> 4) + x) & 0x0f0f0f0f;
|
|
988
|
+
x *= 0x01010101;
|
|
989
|
+
|
|
990
|
+
return x >> 24;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
ecb_function_ ecb_const int ecb_ld32 (uint32_t x);
|
|
994
|
+
ecb_function_ ecb_const int ecb_ld32 (uint32_t x)
|
|
995
|
+
{
|
|
996
|
+
#if 1400 <= _MSC_VER && (_M_IX86 || _M_X64 || _M_IA64 || _M_ARM)
|
|
997
|
+
unsigned long r;
|
|
998
|
+
_BitScanReverse (&r, x);
|
|
999
|
+
return (int)r;
|
|
1000
|
+
#else
|
|
1001
|
+
int r = 0;
|
|
1002
|
+
|
|
1003
|
+
if (x >> 16) { x >>= 16; r += 16; }
|
|
1004
|
+
if (x >> 8) { x >>= 8; r += 8; }
|
|
1005
|
+
if (x >> 4) { x >>= 4; r += 4; }
|
|
1006
|
+
if (x >> 2) { x >>= 2; r += 2; }
|
|
1007
|
+
if (x >> 1) { r += 1; }
|
|
1008
|
+
|
|
1009
|
+
return r;
|
|
1010
|
+
#endif
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
ecb_function_ ecb_const int ecb_ld64 (uint64_t x);
|
|
1014
|
+
ecb_function_ ecb_const int ecb_ld64 (uint64_t x)
|
|
1015
|
+
{
|
|
1016
|
+
#if 1400 <= _MSC_VER && (_M_X64 || _M_IA64 || _M_ARM)
|
|
1017
|
+
unsigned long r;
|
|
1018
|
+
_BitScanReverse64 (&r, x);
|
|
1019
|
+
return (int)r;
|
|
1020
|
+
#else
|
|
1021
|
+
int r = 0;
|
|
1022
|
+
|
|
1023
|
+
if (x >> 32) { x >>= 32; r += 32; }
|
|
1024
|
+
|
|
1025
|
+
return r + ecb_ld32 (x);
|
|
1026
|
+
#endif
|
|
1027
|
+
}
|
|
1028
|
+
#endif
|
|
1029
|
+
|
|
1030
|
+
ecb_function_ ecb_const ecb_bool ecb_is_pot32 (uint32_t x);
|
|
1031
|
+
ecb_function_ ecb_const ecb_bool ecb_is_pot32 (uint32_t x) { return !(x & (x - 1)); }
|
|
1032
|
+
ecb_function_ ecb_const ecb_bool ecb_is_pot64 (uint64_t x);
|
|
1033
|
+
ecb_function_ ecb_const ecb_bool ecb_is_pot64 (uint64_t x) { return !(x & (x - 1)); }
|
|
1034
|
+
|
|
1035
|
+
ecb_function_ ecb_const uint8_t ecb_bitrev8 (uint8_t x);
|
|
1036
|
+
ecb_function_ ecb_const uint8_t ecb_bitrev8 (uint8_t x)
|
|
1037
|
+
{
|
|
1038
|
+
return ( (x * 0x0802U & 0x22110U)
|
|
1039
|
+
| (x * 0x8020U & 0x88440U)) * 0x10101U >> 16;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
ecb_function_ ecb_const uint16_t ecb_bitrev16 (uint16_t x);
|
|
1043
|
+
ecb_function_ ecb_const uint16_t ecb_bitrev16 (uint16_t x)
|
|
1044
|
+
{
|
|
1045
|
+
x = ((x >> 1) & 0x5555) | ((x & 0x5555) << 1);
|
|
1046
|
+
x = ((x >> 2) & 0x3333) | ((x & 0x3333) << 2);
|
|
1047
|
+
x = ((x >> 4) & 0x0f0f) | ((x & 0x0f0f) << 4);
|
|
1048
|
+
x = ( x >> 8 ) | ( x << 8);
|
|
1049
|
+
|
|
1050
|
+
return x;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
ecb_function_ ecb_const uint32_t ecb_bitrev32 (uint32_t x);
|
|
1054
|
+
ecb_function_ ecb_const uint32_t ecb_bitrev32 (uint32_t x)
|
|
1055
|
+
{
|
|
1056
|
+
x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1);
|
|
1057
|
+
x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2);
|
|
1058
|
+
x = ((x >> 4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) << 4);
|
|
1059
|
+
x = ((x >> 8) & 0x00ff00ff) | ((x & 0x00ff00ff) << 8);
|
|
1060
|
+
x = ( x >> 16 ) | ( x << 16);
|
|
1061
|
+
|
|
1062
|
+
return x;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
/* popcount64 is only available on 64 bit cpus as gcc builtin */
|
|
1066
|
+
/* so for this version we are lazy */
|
|
1067
|
+
ecb_function_ ecb_const int ecb_popcount64 (uint64_t x);
|
|
1068
|
+
ecb_function_ ecb_const int
|
|
1069
|
+
ecb_popcount64 (uint64_t x)
|
|
1070
|
+
{
|
|
1071
|
+
return ecb_popcount32 (x) + ecb_popcount32 (x >> 32);
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
ecb_inline ecb_const uint8_t ecb_rotl8 (uint8_t x, unsigned int count);
|
|
1075
|
+
ecb_inline ecb_const uint8_t ecb_rotr8 (uint8_t x, unsigned int count);
|
|
1076
|
+
ecb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count);
|
|
1077
|
+
ecb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count);
|
|
1078
|
+
ecb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count);
|
|
1079
|
+
ecb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count);
|
|
1080
|
+
ecb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count);
|
|
1081
|
+
ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count);
|
|
1082
|
+
|
|
1083
|
+
ecb_inline ecb_const uint8_t ecb_rotl8 (uint8_t x, unsigned int count) { return (x >> ( 8 - count)) | (x << count); }
|
|
1084
|
+
ecb_inline ecb_const uint8_t ecb_rotr8 (uint8_t x, unsigned int count) { return (x << ( 8 - count)) | (x >> count); }
|
|
1085
|
+
ecb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count) { return (x >> (16 - count)) | (x << count); }
|
|
1086
|
+
ecb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count) { return (x << (16 - count)) | (x >> count); }
|
|
1087
|
+
ecb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count) { return (x >> (32 - count)) | (x << count); }
|
|
1088
|
+
ecb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count) { return (x << (32 - count)) | (x >> count); }
|
|
1089
|
+
ecb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count) { return (x >> (64 - count)) | (x << count); }
|
|
1090
|
+
ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (64 - count)) | (x >> count); }
|
|
1091
|
+
|
|
1092
|
+
#if ECB_GCC_VERSION(4,3) || (ECB_CLANG_BUILTIN(__builtin_bswap32) && ECB_CLANG_BUILTIN(__builtin_bswap64))
|
|
1093
|
+
#if ECB_GCC_VERSION(4,8) || ECB_CLANG_BUILTIN(__builtin_bswap16)
|
|
1094
|
+
#define ecb_bswap16(x) __builtin_bswap16 (x)
|
|
1095
|
+
#else
|
|
1096
|
+
#define ecb_bswap16(x) (__builtin_bswap32 (x) >> 16)
|
|
1097
|
+
#endif
|
|
1098
|
+
#define ecb_bswap32(x) __builtin_bswap32 (x)
|
|
1099
|
+
#define ecb_bswap64(x) __builtin_bswap64 (x)
|
|
1100
|
+
#elif _MSC_VER
|
|
1101
|
+
#include <stdlib.h>
|
|
1102
|
+
#define ecb_bswap16(x) ((uint16_t)_byteswap_ushort ((uint16_t)(x)))
|
|
1103
|
+
#define ecb_bswap32(x) ((uint32_t)_byteswap_ulong ((uint32_t)(x)))
|
|
1104
|
+
#define ecb_bswap64(x) ((uint64_t)_byteswap_uint64 ((uint64_t)(x)))
|
|
1105
|
+
#else
|
|
1106
|
+
ecb_function_ ecb_const uint16_t ecb_bswap16 (uint16_t x);
|
|
1107
|
+
ecb_function_ ecb_const uint16_t
|
|
1108
|
+
ecb_bswap16 (uint16_t x)
|
|
1109
|
+
{
|
|
1110
|
+
return ecb_rotl16 (x, 8);
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
ecb_function_ ecb_const uint32_t ecb_bswap32 (uint32_t x);
|
|
1114
|
+
ecb_function_ ecb_const uint32_t
|
|
1115
|
+
ecb_bswap32 (uint32_t x)
|
|
1116
|
+
{
|
|
1117
|
+
return (((uint32_t)ecb_bswap16 (x)) << 16) | ecb_bswap16 (x >> 16);
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
ecb_function_ ecb_const uint64_t ecb_bswap64 (uint64_t x);
|
|
1121
|
+
ecb_function_ ecb_const uint64_t
|
|
1122
|
+
ecb_bswap64 (uint64_t x)
|
|
1123
|
+
{
|
|
1124
|
+
return (((uint64_t)ecb_bswap32 (x)) << 32) | ecb_bswap32 (x >> 32);
|
|
1125
|
+
}
|
|
1126
|
+
#endif
|
|
1127
|
+
|
|
1128
|
+
#if ECB_GCC_VERSION(4,5) || ECB_CLANG_BUILTIN(__builtin_unreachable)
|
|
1129
|
+
#define ecb_unreachable() __builtin_unreachable ()
|
|
1130
|
+
#else
|
|
1131
|
+
/* this seems to work fine, but gcc always emits a warning for it :/ */
|
|
1132
|
+
ecb_inline ecb_noreturn void ecb_unreachable (void);
|
|
1133
|
+
ecb_inline ecb_noreturn void ecb_unreachable (void) { }
|
|
1134
|
+
#endif
|
|
1135
|
+
|
|
1136
|
+
/* try to tell the compiler that some condition is definitely true */
|
|
1137
|
+
#define ecb_assume(cond) if (!(cond)) ecb_unreachable (); else 0
|
|
1138
|
+
|
|
1139
|
+
ecb_inline ecb_const uint32_t ecb_byteorder_helper (void);
|
|
1140
|
+
ecb_inline ecb_const uint32_t
|
|
1141
|
+
ecb_byteorder_helper (void)
|
|
1142
|
+
{
|
|
1143
|
+
/* the union code still generates code under pressure in gcc, */
|
|
1144
|
+
/* but less than using pointers, and always seems to */
|
|
1145
|
+
/* successfully return a constant. */
|
|
1146
|
+
/* the reason why we have this horrible preprocessor mess */
|
|
1147
|
+
/* is to avoid it in all cases, at least on common architectures */
|
|
1148
|
+
/* or when using a recent enough gcc version (>= 4.6) */
|
|
1149
|
+
#if (defined __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \
|
|
1150
|
+
|| ((__i386 || __i386__ || _M_IX86 || ECB_GCC_AMD64 || ECB_MSVC_AMD64) && !__VOS__)
|
|
1151
|
+
#define ECB_LITTLE_ENDIAN 1
|
|
1152
|
+
return 0x44332211;
|
|
1153
|
+
#elif (defined __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) \
|
|
1154
|
+
|| ((__AARCH64EB__ || __MIPSEB__ || __ARMEB__) && !__VOS__)
|
|
1155
|
+
#define ECB_BIG_ENDIAN 1
|
|
1156
|
+
return 0x11223344;
|
|
1157
|
+
#else
|
|
1158
|
+
union
|
|
1159
|
+
{
|
|
1160
|
+
uint8_t c[4];
|
|
1161
|
+
uint32_t u;
|
|
1162
|
+
} u = { 0x11, 0x22, 0x33, 0x44 };
|
|
1163
|
+
return u.u;
|
|
1164
|
+
#endif
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
ecb_inline ecb_const ecb_bool ecb_big_endian (void);
|
|
1168
|
+
ecb_inline ecb_const ecb_bool ecb_big_endian (void) { return ecb_byteorder_helper () == 0x11223344; }
|
|
1169
|
+
ecb_inline ecb_const ecb_bool ecb_little_endian (void);
|
|
1170
|
+
ecb_inline ecb_const ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44332211; }
|
|
1171
|
+
|
|
1172
|
+
#if ECB_GCC_VERSION(3,0) || ECB_C99
|
|
1173
|
+
#define ecb_mod(m,n) ((m) % (n) + ((m) % (n) < 0 ? (n) : 0))
|
|
1174
|
+
#else
|
|
1175
|
+
#define ecb_mod(m,n) ((m) < 0 ? ((n) - 1 - ((-1 - (m)) % (n))) : ((m) % (n)))
|
|
471
1176
|
#endif
|
|
472
1177
|
|
|
473
|
-
#
|
|
474
|
-
|
|
475
|
-
|
|
1178
|
+
#if ECB_CPP
|
|
1179
|
+
template<typename T>
|
|
1180
|
+
static inline T ecb_div_rd (T val, T div)
|
|
1181
|
+
{
|
|
1182
|
+
return val < 0 ? - ((-val + div - 1) / div) : (val ) / div;
|
|
1183
|
+
}
|
|
1184
|
+
template<typename T>
|
|
1185
|
+
static inline T ecb_div_ru (T val, T div)
|
|
1186
|
+
{
|
|
1187
|
+
return val < 0 ? - ((-val ) / div) : (val + div - 1) / div;
|
|
1188
|
+
}
|
|
1189
|
+
#else
|
|
1190
|
+
#define ecb_div_rd(val,div) ((val) < 0 ? - ((-(val) + (div) - 1) / (div)) : ((val) ) / (div))
|
|
1191
|
+
#define ecb_div_ru(val,div) ((val) < 0 ? - ((-(val) ) / (div)) : ((val) + (div) - 1) / (div))
|
|
1192
|
+
#endif
|
|
1193
|
+
|
|
1194
|
+
#if ecb_cplusplus_does_not_suck
|
|
1195
|
+
/* does not work for local types (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm) */
|
|
1196
|
+
template<typename T, int N>
|
|
1197
|
+
static inline int ecb_array_length (const T (&arr)[N])
|
|
1198
|
+
{
|
|
1199
|
+
return N;
|
|
1200
|
+
}
|
|
1201
|
+
#else
|
|
1202
|
+
#define ecb_array_length(name) (sizeof (name) / sizeof (name [0]))
|
|
1203
|
+
#endif
|
|
1204
|
+
|
|
1205
|
+
ecb_function_ ecb_const uint32_t ecb_binary16_to_binary32 (uint32_t x);
|
|
1206
|
+
ecb_function_ ecb_const uint32_t
|
|
1207
|
+
ecb_binary16_to_binary32 (uint32_t x)
|
|
1208
|
+
{
|
|
1209
|
+
unsigned int s = (x & 0x8000) << (31 - 15);
|
|
1210
|
+
int e = (x >> 10) & 0x001f;
|
|
1211
|
+
unsigned int m = x & 0x03ff;
|
|
1212
|
+
|
|
1213
|
+
if (ecb_expect_false (e == 31))
|
|
1214
|
+
/* infinity or NaN */
|
|
1215
|
+
e = 255 - (127 - 15);
|
|
1216
|
+
else if (ecb_expect_false (!e))
|
|
1217
|
+
{
|
|
1218
|
+
if (ecb_expect_true (!m))
|
|
1219
|
+
/* zero, handled by code below by forcing e to 0 */
|
|
1220
|
+
e = 0 - (127 - 15);
|
|
1221
|
+
else
|
|
1222
|
+
{
|
|
1223
|
+
/* subnormal, renormalise */
|
|
1224
|
+
unsigned int s = 10 - ecb_ld32 (m);
|
|
1225
|
+
|
|
1226
|
+
m = (m << s) & 0x3ff; /* mask implicit bit */
|
|
1227
|
+
e -= s - 1;
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
/* e and m now are normalised, or zero, (or inf or nan) */
|
|
1232
|
+
e += 127 - 15;
|
|
1233
|
+
|
|
1234
|
+
return s | (e << 23) | (m << (23 - 10));
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
ecb_function_ ecb_const uint16_t ecb_binary32_to_binary16 (uint32_t x);
|
|
1238
|
+
ecb_function_ ecb_const uint16_t
|
|
1239
|
+
ecb_binary32_to_binary16 (uint32_t x)
|
|
1240
|
+
{
|
|
1241
|
+
unsigned int s = (x >> 16) & 0x00008000; /* sign bit, the easy part */
|
|
1242
|
+
unsigned int e = ((x >> 23) & 0x000000ff) - (127 - 15); /* the desired exponent */
|
|
1243
|
+
unsigned int m = x & 0x007fffff;
|
|
1244
|
+
|
|
1245
|
+
x &= 0x7fffffff;
|
|
1246
|
+
|
|
1247
|
+
/* if it's within range of binary16 normals, use fast path */
|
|
1248
|
+
if (ecb_expect_true (0x38800000 <= x && x <= 0x477fefff))
|
|
1249
|
+
{
|
|
1250
|
+
/* mantissa round-to-even */
|
|
1251
|
+
m += 0x00000fff + ((m >> (23 - 10)) & 1);
|
|
1252
|
+
|
|
1253
|
+
/* handle overflow */
|
|
1254
|
+
if (ecb_expect_false (m >= 0x00800000))
|
|
1255
|
+
{
|
|
1256
|
+
m >>= 1;
|
|
1257
|
+
e += 1;
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
return s | (e << 10) | (m >> (23 - 10));
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
/* handle large numbers and infinity */
|
|
1264
|
+
if (ecb_expect_true (0x477fefff < x && x <= 0x7f800000))
|
|
1265
|
+
return s | 0x7c00;
|
|
1266
|
+
|
|
1267
|
+
/* handle zero, subnormals and small numbers */
|
|
1268
|
+
if (ecb_expect_true (x < 0x38800000))
|
|
1269
|
+
{
|
|
1270
|
+
/* zero */
|
|
1271
|
+
if (ecb_expect_true (!x))
|
|
1272
|
+
return s;
|
|
1273
|
+
|
|
1274
|
+
/* handle subnormals */
|
|
1275
|
+
|
|
1276
|
+
/* too small, will be zero */
|
|
1277
|
+
if (e < (14 - 24)) /* might not be sharp, but is good enough */
|
|
1278
|
+
return s;
|
|
1279
|
+
|
|
1280
|
+
m |= 0x00800000; /* make implicit bit explicit */
|
|
1281
|
+
|
|
1282
|
+
/* very tricky - we need to round to the nearest e (+10) bit value */
|
|
1283
|
+
{
|
|
1284
|
+
unsigned int bits = 14 - e;
|
|
1285
|
+
unsigned int half = (1 << (bits - 1)) - 1;
|
|
1286
|
+
unsigned int even = (m >> bits) & 1;
|
|
1287
|
+
|
|
1288
|
+
/* if this overflows, we will end up with a normalised number */
|
|
1289
|
+
m = (m + half + even) >> bits;
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
return s | m;
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
/* handle NaNs, preserve leftmost nan bits, but make sure we don't turn them into infinities */
|
|
1296
|
+
m >>= 13;
|
|
1297
|
+
|
|
1298
|
+
return s | 0x7c00 | m | !m;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
/*******************************************************************************/
|
|
1302
|
+
/* floating point stuff, can be disabled by defining ECB_NO_LIBM */
|
|
1303
|
+
|
|
1304
|
+
/* basically, everything uses "ieee pure-endian" floating point numbers */
|
|
1305
|
+
/* the only noteworthy exception is ancient armle, which uses order 43218765 */
|
|
1306
|
+
#if 0 \
|
|
1307
|
+
|| __i386 || __i386__ \
|
|
1308
|
+
|| ECB_GCC_AMD64 \
|
|
1309
|
+
|| __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__ \
|
|
1310
|
+
|| defined __s390__ || defined __s390x__ \
|
|
1311
|
+
|| defined __mips__ \
|
|
1312
|
+
|| defined __alpha__ \
|
|
1313
|
+
|| defined __hppa__ \
|
|
1314
|
+
|| defined __ia64__ \
|
|
1315
|
+
|| defined __m68k__ \
|
|
1316
|
+
|| defined __m88k__ \
|
|
1317
|
+
|| defined __sh__ \
|
|
1318
|
+
|| defined _M_IX86 || defined ECB_MSVC_AMD64 || defined _M_IA64 \
|
|
1319
|
+
|| (defined __arm__ && (defined __ARM_EABI__ || defined __EABI__ || defined __VFP_FP__ || defined _WIN32_WCE || defined __ANDROID__)) \
|
|
1320
|
+
|| defined __aarch64__
|
|
1321
|
+
#define ECB_STDFP 1
|
|
1322
|
+
#include <string.h> /* for memcpy */
|
|
1323
|
+
#else
|
|
1324
|
+
#define ECB_STDFP 0
|
|
1325
|
+
#endif
|
|
1326
|
+
|
|
1327
|
+
#ifndef ECB_NO_LIBM
|
|
1328
|
+
|
|
1329
|
+
#include <math.h> /* for frexp*, ldexp*, INFINITY, NAN */
|
|
1330
|
+
|
|
1331
|
+
/* only the oldest of old doesn't have this one. solaris. */
|
|
1332
|
+
#ifdef INFINITY
|
|
1333
|
+
#define ECB_INFINITY INFINITY
|
|
1334
|
+
#else
|
|
1335
|
+
#define ECB_INFINITY HUGE_VAL
|
|
1336
|
+
#endif
|
|
1337
|
+
|
|
1338
|
+
#ifdef NAN
|
|
1339
|
+
#define ECB_NAN NAN
|
|
1340
|
+
#else
|
|
1341
|
+
#define ECB_NAN ECB_INFINITY
|
|
1342
|
+
#endif
|
|
1343
|
+
|
|
1344
|
+
#if ECB_C99 || _XOPEN_VERSION >= 600 || _POSIX_VERSION >= 200112L
|
|
1345
|
+
#define ecb_ldexpf(x,e) ldexpf ((x), (e))
|
|
1346
|
+
#define ecb_frexpf(x,e) frexpf ((x), (e))
|
|
1347
|
+
#else
|
|
1348
|
+
#define ecb_ldexpf(x,e) (float) ldexp ((double) (x), (e))
|
|
1349
|
+
#define ecb_frexpf(x,e) (float) frexp ((double) (x), (e))
|
|
1350
|
+
#endif
|
|
1351
|
+
|
|
1352
|
+
/* convert a float to ieee single/binary32 */
|
|
1353
|
+
ecb_function_ ecb_const uint32_t ecb_float_to_binary32 (float x);
|
|
1354
|
+
ecb_function_ ecb_const uint32_t
|
|
1355
|
+
ecb_float_to_binary32 (float x)
|
|
1356
|
+
{
|
|
1357
|
+
uint32_t r;
|
|
1358
|
+
|
|
1359
|
+
#if ECB_STDFP
|
|
1360
|
+
memcpy (&r, &x, 4);
|
|
1361
|
+
#else
|
|
1362
|
+
/* slow emulation, works for anything but -0 */
|
|
1363
|
+
uint32_t m;
|
|
1364
|
+
int e;
|
|
1365
|
+
|
|
1366
|
+
if (x == 0e0f ) return 0x00000000U;
|
|
1367
|
+
if (x > +3.40282346638528860e+38f) return 0x7f800000U;
|
|
1368
|
+
if (x < -3.40282346638528860e+38f) return 0xff800000U;
|
|
1369
|
+
if (x != x ) return 0x7fbfffffU;
|
|
1370
|
+
|
|
1371
|
+
m = ecb_frexpf (x, &e) * 0x1000000U;
|
|
1372
|
+
|
|
1373
|
+
r = m & 0x80000000U;
|
|
1374
|
+
|
|
1375
|
+
if (r)
|
|
1376
|
+
m = -m;
|
|
1377
|
+
|
|
1378
|
+
if (e <= -126)
|
|
1379
|
+
{
|
|
1380
|
+
m &= 0xffffffU;
|
|
1381
|
+
m >>= (-125 - e);
|
|
1382
|
+
e = -126;
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
r |= (e + 126) << 23;
|
|
1386
|
+
r |= m & 0x7fffffU;
|
|
1387
|
+
#endif
|
|
1388
|
+
|
|
1389
|
+
return r;
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
/* converts an ieee single/binary32 to a float */
|
|
1393
|
+
ecb_function_ ecb_const float ecb_binary32_to_float (uint32_t x);
|
|
1394
|
+
ecb_function_ ecb_const float
|
|
1395
|
+
ecb_binary32_to_float (uint32_t x)
|
|
1396
|
+
{
|
|
1397
|
+
float r;
|
|
1398
|
+
|
|
1399
|
+
#if ECB_STDFP
|
|
1400
|
+
memcpy (&r, &x, 4);
|
|
1401
|
+
#else
|
|
1402
|
+
/* emulation, only works for normals and subnormals and +0 */
|
|
1403
|
+
int neg = x >> 31;
|
|
1404
|
+
int e = (x >> 23) & 0xffU;
|
|
1405
|
+
|
|
1406
|
+
x &= 0x7fffffU;
|
|
1407
|
+
|
|
1408
|
+
if (e)
|
|
1409
|
+
x |= 0x800000U;
|
|
1410
|
+
else
|
|
1411
|
+
e = 1;
|
|
1412
|
+
|
|
1413
|
+
/* we distrust ldexpf a bit and do the 2**-24 scaling by an extra multiply */
|
|
1414
|
+
r = ecb_ldexpf (x * (0.5f / 0x800000U), e - 126);
|
|
1415
|
+
|
|
1416
|
+
r = neg ? -r : r;
|
|
1417
|
+
#endif
|
|
1418
|
+
|
|
1419
|
+
return r;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
/* convert a double to ieee double/binary64 */
|
|
1423
|
+
ecb_function_ ecb_const uint64_t ecb_double_to_binary64 (double x);
|
|
1424
|
+
ecb_function_ ecb_const uint64_t
|
|
1425
|
+
ecb_double_to_binary64 (double x)
|
|
1426
|
+
{
|
|
1427
|
+
uint64_t r;
|
|
1428
|
+
|
|
1429
|
+
#if ECB_STDFP
|
|
1430
|
+
memcpy (&r, &x, 8);
|
|
1431
|
+
#else
|
|
1432
|
+
/* slow emulation, works for anything but -0 */
|
|
1433
|
+
uint64_t m;
|
|
1434
|
+
int e;
|
|
1435
|
+
|
|
1436
|
+
if (x == 0e0 ) return 0x0000000000000000U;
|
|
1437
|
+
if (x > +1.79769313486231470e+308) return 0x7ff0000000000000U;
|
|
1438
|
+
if (x < -1.79769313486231470e+308) return 0xfff0000000000000U;
|
|
1439
|
+
if (x != x ) return 0X7ff7ffffffffffffU;
|
|
1440
|
+
|
|
1441
|
+
m = frexp (x, &e) * 0x20000000000000U;
|
|
1442
|
+
|
|
1443
|
+
r = m & 0x8000000000000000;;
|
|
1444
|
+
|
|
1445
|
+
if (r)
|
|
1446
|
+
m = -m;
|
|
1447
|
+
|
|
1448
|
+
if (e <= -1022)
|
|
1449
|
+
{
|
|
1450
|
+
m &= 0x1fffffffffffffU;
|
|
1451
|
+
m >>= (-1021 - e);
|
|
1452
|
+
e = -1022;
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
r |= ((uint64_t)(e + 1022)) << 52;
|
|
1456
|
+
r |= m & 0xfffffffffffffU;
|
|
1457
|
+
#endif
|
|
1458
|
+
|
|
1459
|
+
return r;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
/* converts an ieee double/binary64 to a double */
|
|
1463
|
+
ecb_function_ ecb_const double ecb_binary64_to_double (uint64_t x);
|
|
1464
|
+
ecb_function_ ecb_const double
|
|
1465
|
+
ecb_binary64_to_double (uint64_t x)
|
|
1466
|
+
{
|
|
1467
|
+
double r;
|
|
1468
|
+
|
|
1469
|
+
#if ECB_STDFP
|
|
1470
|
+
memcpy (&r, &x, 8);
|
|
1471
|
+
#else
|
|
1472
|
+
/* emulation, only works for normals and subnormals and +0 */
|
|
1473
|
+
int neg = x >> 63;
|
|
1474
|
+
int e = (x >> 52) & 0x7ffU;
|
|
1475
|
+
|
|
1476
|
+
x &= 0xfffffffffffffU;
|
|
1477
|
+
|
|
1478
|
+
if (e)
|
|
1479
|
+
x |= 0x10000000000000U;
|
|
1480
|
+
else
|
|
1481
|
+
e = 1;
|
|
1482
|
+
|
|
1483
|
+
/* we distrust ldexp a bit and do the 2**-53 scaling by an extra multiply */
|
|
1484
|
+
r = ldexp (x * (0.5 / 0x10000000000000U), e - 1022);
|
|
1485
|
+
|
|
1486
|
+
r = neg ? -r : r;
|
|
1487
|
+
#endif
|
|
1488
|
+
|
|
1489
|
+
return r;
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
/* convert a float to ieee half/binary16 */
|
|
1493
|
+
ecb_function_ ecb_const uint16_t ecb_float_to_binary16 (float x);
|
|
1494
|
+
ecb_function_ ecb_const uint16_t
|
|
1495
|
+
ecb_float_to_binary16 (float x)
|
|
1496
|
+
{
|
|
1497
|
+
return ecb_binary32_to_binary16 (ecb_float_to_binary32 (x));
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
/* convert an ieee half/binary16 to float */
|
|
1501
|
+
ecb_function_ ecb_const float ecb_binary16_to_float (uint16_t x);
|
|
1502
|
+
ecb_function_ ecb_const float
|
|
1503
|
+
ecb_binary16_to_float (uint16_t x)
|
|
1504
|
+
{
|
|
1505
|
+
return ecb_binary32_to_float (ecb_binary16_to_binary32 (x));
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
#endif
|
|
1509
|
+
|
|
1510
|
+
#endif
|
|
1511
|
+
|
|
1512
|
+
/* ECB.H END */
|
|
1513
|
+
|
|
1514
|
+
#if ECB_MEMORY_FENCE_NEEDS_PTHREADS
|
|
1515
|
+
/* if your architecture doesn't need memory fences, e.g. because it is
|
|
1516
|
+
* single-cpu/core, or if you use libev in a project that doesn't use libev
|
|
1517
|
+
* from multiple threads, then you can define ECB_AVOID_PTHREADS when compiling
|
|
1518
|
+
* libev, in which cases the memory fences become nops.
|
|
1519
|
+
* alternatively, you can remove this #error and link against libpthread,
|
|
1520
|
+
* which will then provide the memory fences.
|
|
1521
|
+
*/
|
|
1522
|
+
# error "memory fences not defined for your architecture, please report"
|
|
1523
|
+
#endif
|
|
1524
|
+
|
|
1525
|
+
#ifndef ECB_MEMORY_FENCE
|
|
1526
|
+
# define ECB_MEMORY_FENCE do { } while (0)
|
|
1527
|
+
# define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE
|
|
1528
|
+
# define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE
|
|
1529
|
+
#endif
|
|
1530
|
+
|
|
1531
|
+
#define expect_false(cond) ecb_expect_false (cond)
|
|
1532
|
+
#define expect_true(cond) ecb_expect_true (cond)
|
|
1533
|
+
#define noinline ecb_noinline
|
|
1534
|
+
|
|
1535
|
+
#define inline_size ecb_inline
|
|
476
1536
|
|
|
477
1537
|
#if EV_FEATURE_CODE
|
|
478
|
-
# define inline_speed
|
|
1538
|
+
# define inline_speed ecb_inline
|
|
479
1539
|
#else
|
|
480
|
-
# define inline_speed static
|
|
1540
|
+
# define inline_speed noinline static
|
|
481
1541
|
#endif
|
|
482
1542
|
|
|
483
1543
|
#define NUMPRI (EV_MAXPRI - EV_MINPRI + 1)
|
|
@@ -508,18 +1568,67 @@ static EV_ATOMIC_T have_realtime; /* did clock_gettime (CLOCK_REALTIME) work? */
|
|
|
508
1568
|
static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */
|
|
509
1569
|
#endif
|
|
510
1570
|
|
|
511
|
-
#ifndef EV_FD_TO_WIN32_HANDLE
|
|
512
|
-
# define EV_FD_TO_WIN32_HANDLE(fd) _get_osfhandle (fd)
|
|
513
|
-
#endif
|
|
514
|
-
#ifndef EV_WIN32_HANDLE_TO_FD
|
|
515
|
-
# define EV_WIN32_HANDLE_TO_FD(handle) _open_osfhandle (handle, 0)
|
|
516
|
-
#endif
|
|
517
|
-
#ifndef EV_WIN32_CLOSE_FD
|
|
518
|
-
# define EV_WIN32_CLOSE_FD(fd) close (fd)
|
|
519
|
-
#endif
|
|
1571
|
+
#ifndef EV_FD_TO_WIN32_HANDLE
|
|
1572
|
+
# define EV_FD_TO_WIN32_HANDLE(fd) _get_osfhandle (fd)
|
|
1573
|
+
#endif
|
|
1574
|
+
#ifndef EV_WIN32_HANDLE_TO_FD
|
|
1575
|
+
# define EV_WIN32_HANDLE_TO_FD(handle) _open_osfhandle (handle, 0)
|
|
1576
|
+
#endif
|
|
1577
|
+
#ifndef EV_WIN32_CLOSE_FD
|
|
1578
|
+
# define EV_WIN32_CLOSE_FD(fd) close (fd)
|
|
1579
|
+
#endif
|
|
1580
|
+
|
|
1581
|
+
#ifdef _WIN32
|
|
1582
|
+
# include "ev_win32.c"
|
|
1583
|
+
#endif
|
|
1584
|
+
|
|
1585
|
+
/*****************************************************************************/
|
|
1586
|
+
|
|
1587
|
+
/* define a suitable floor function (only used by periodics atm) */
|
|
1588
|
+
|
|
1589
|
+
#if EV_USE_FLOOR
|
|
1590
|
+
# include <math.h>
|
|
1591
|
+
# define ev_floor(v) floor (v)
|
|
1592
|
+
#else
|
|
1593
|
+
|
|
1594
|
+
#include <float.h>
|
|
1595
|
+
|
|
1596
|
+
/* a floor() replacement function, should be independent of ev_tstamp type */
|
|
1597
|
+
noinline
|
|
1598
|
+
static ev_tstamp
|
|
1599
|
+
ev_floor (ev_tstamp v)
|
|
1600
|
+
{
|
|
1601
|
+
/* the choice of shift factor is not terribly important */
|
|
1602
|
+
#if FLT_RADIX != 2 /* assume FLT_RADIX == 10 */
|
|
1603
|
+
const ev_tstamp shift = sizeof (unsigned long) >= 8 ? 10000000000000000000. : 1000000000.;
|
|
1604
|
+
#else
|
|
1605
|
+
const ev_tstamp shift = sizeof (unsigned long) >= 8 ? 18446744073709551616. : 4294967296.;
|
|
1606
|
+
#endif
|
|
1607
|
+
|
|
1608
|
+
/* argument too large for an unsigned long? */
|
|
1609
|
+
if (expect_false (v >= shift))
|
|
1610
|
+
{
|
|
1611
|
+
ev_tstamp f;
|
|
1612
|
+
|
|
1613
|
+
if (v == v - 1.)
|
|
1614
|
+
return v; /* very large number */
|
|
1615
|
+
|
|
1616
|
+
f = shift * ev_floor (v * (1. / shift));
|
|
1617
|
+
return f + ev_floor (v - f);
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
/* special treatment for negative args? */
|
|
1621
|
+
if (expect_false (v < 0.))
|
|
1622
|
+
{
|
|
1623
|
+
ev_tstamp f = -ev_floor (-v);
|
|
1624
|
+
|
|
1625
|
+
return f - (f == v ? 0 : 1);
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
/* fits into an unsigned long */
|
|
1629
|
+
return (unsigned long)v;
|
|
1630
|
+
}
|
|
520
1631
|
|
|
521
|
-
#ifdef _WIN32
|
|
522
|
-
# include "ev_win32.c"
|
|
523
1632
|
#endif
|
|
524
1633
|
|
|
525
1634
|
/*****************************************************************************/
|
|
@@ -528,7 +1637,8 @@ static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work?
|
|
|
528
1637
|
# include <sys/utsname.h>
|
|
529
1638
|
#endif
|
|
530
1639
|
|
|
531
|
-
|
|
1640
|
+
noinline ecb_cold
|
|
1641
|
+
static unsigned int
|
|
532
1642
|
ev_linux_version (void)
|
|
533
1643
|
{
|
|
534
1644
|
#ifdef __linux
|
|
@@ -567,22 +1677,25 @@ ev_linux_version (void)
|
|
|
567
1677
|
/*****************************************************************************/
|
|
568
1678
|
|
|
569
1679
|
#if EV_AVOID_STDIO
|
|
570
|
-
|
|
1680
|
+
noinline ecb_cold
|
|
1681
|
+
static void
|
|
571
1682
|
ev_printerr (const char *msg)
|
|
572
1683
|
{
|
|
573
1684
|
write (STDERR_FILENO, msg, strlen (msg));
|
|
574
1685
|
}
|
|
575
1686
|
#endif
|
|
576
1687
|
|
|
577
|
-
static void (*syserr_cb)(const char *msg);
|
|
1688
|
+
static void (*syserr_cb)(const char *msg) EV_THROW;
|
|
578
1689
|
|
|
1690
|
+
ecb_cold
|
|
579
1691
|
void
|
|
580
|
-
ev_set_syserr_cb (void (*cb)(const char *msg))
|
|
1692
|
+
ev_set_syserr_cb (void (*cb)(const char *msg) EV_THROW) EV_THROW
|
|
581
1693
|
{
|
|
582
1694
|
syserr_cb = cb;
|
|
583
1695
|
}
|
|
584
1696
|
|
|
585
|
-
|
|
1697
|
+
noinline ecb_cold
|
|
1698
|
+
static void
|
|
586
1699
|
ev_syserr (const char *msg)
|
|
587
1700
|
{
|
|
588
1701
|
if (!msg)
|
|
@@ -605,14 +1718,13 @@ ev_syserr (const char *msg)
|
|
|
605
1718
|
}
|
|
606
1719
|
|
|
607
1720
|
static void *
|
|
608
|
-
ev_realloc_emul (void *ptr, long size)
|
|
1721
|
+
ev_realloc_emul (void *ptr, long size) EV_THROW
|
|
609
1722
|
{
|
|
610
|
-
#if __GLIBC__
|
|
611
|
-
return realloc (ptr, size);
|
|
612
|
-
#else
|
|
613
1723
|
/* some systems, notably openbsd and darwin, fail to properly
|
|
614
1724
|
* implement realloc (x, 0) (as required by both ansi c-89 and
|
|
615
1725
|
* the single unix specification, so work around them here.
|
|
1726
|
+
* recently, also (at least) fedora and debian started breaking it,
|
|
1727
|
+
* despite documenting it otherwise.
|
|
616
1728
|
*/
|
|
617
1729
|
|
|
618
1730
|
if (size)
|
|
@@ -620,13 +1732,13 @@ ev_realloc_emul (void *ptr, long size)
|
|
|
620
1732
|
|
|
621
1733
|
free (ptr);
|
|
622
1734
|
return 0;
|
|
623
|
-
#endif
|
|
624
1735
|
}
|
|
625
1736
|
|
|
626
|
-
static void *(*alloc)(void *ptr, long size) = ev_realloc_emul;
|
|
1737
|
+
static void *(*alloc)(void *ptr, long size) EV_THROW = ev_realloc_emul;
|
|
627
1738
|
|
|
1739
|
+
ecb_cold
|
|
628
1740
|
void
|
|
629
|
-
ev_set_allocator (void *(*cb)(void *ptr, long size))
|
|
1741
|
+
ev_set_allocator (void *(*cb)(void *ptr, long size) EV_THROW) EV_THROW
|
|
630
1742
|
{
|
|
631
1743
|
alloc = cb;
|
|
632
1744
|
}
|
|
@@ -724,11 +1836,11 @@ typedef struct
|
|
|
724
1836
|
#include "ev_wrap.h"
|
|
725
1837
|
|
|
726
1838
|
static struct ev_loop default_loop_struct;
|
|
727
|
-
struct ev_loop *ev_default_loop_ptr;
|
|
1839
|
+
EV_API_DECL struct ev_loop *ev_default_loop_ptr = 0; /* needs to be initialised to make it a definition despite extern */
|
|
728
1840
|
|
|
729
1841
|
#else
|
|
730
1842
|
|
|
731
|
-
ev_tstamp ev_rt_now;
|
|
1843
|
+
EV_API_DECL ev_tstamp ev_rt_now = 0; /* needs to be initialised to make it a definition despite extern */
|
|
732
1844
|
#define VAR(name,decl) static decl;
|
|
733
1845
|
#include "ev_vars.h"
|
|
734
1846
|
#undef VAR
|
|
@@ -753,7 +1865,7 @@ typedef struct
|
|
|
753
1865
|
|
|
754
1866
|
#ifndef EV_HAVE_EV_TIME
|
|
755
1867
|
ev_tstamp
|
|
756
|
-
ev_time (void)
|
|
1868
|
+
ev_time (void) EV_THROW
|
|
757
1869
|
{
|
|
758
1870
|
#if EV_USE_REALTIME
|
|
759
1871
|
if (expect_true (have_realtime))
|
|
@@ -787,14 +1899,14 @@ get_clock (void)
|
|
|
787
1899
|
|
|
788
1900
|
#if EV_MULTIPLICITY
|
|
789
1901
|
ev_tstamp
|
|
790
|
-
ev_now (EV_P)
|
|
1902
|
+
ev_now (EV_P) EV_THROW
|
|
791
1903
|
{
|
|
792
1904
|
return ev_rt_now;
|
|
793
1905
|
}
|
|
794
1906
|
#endif
|
|
795
1907
|
|
|
796
1908
|
void
|
|
797
|
-
ev_sleep (ev_tstamp delay)
|
|
1909
|
+
ev_sleep (ev_tstamp delay) EV_THROW
|
|
798
1910
|
{
|
|
799
1911
|
if (delay > 0.)
|
|
800
1912
|
{
|
|
@@ -803,7 +1915,7 @@ ev_sleep (ev_tstamp delay)
|
|
|
803
1915
|
|
|
804
1916
|
EV_TS_SET (ts, delay);
|
|
805
1917
|
nanosleep (&ts, 0);
|
|
806
|
-
#elif defined
|
|
1918
|
+
#elif defined _WIN32
|
|
807
1919
|
Sleep ((unsigned long)(delay * 1e3));
|
|
808
1920
|
#else
|
|
809
1921
|
struct timeval tv;
|
|
@@ -832,7 +1944,7 @@ array_nextsize (int elem, int cur, int cnt)
|
|
|
832
1944
|
ncur <<= 1;
|
|
833
1945
|
while (cnt > ncur);
|
|
834
1946
|
|
|
835
|
-
/* if size is large, round to MALLOC_ROUND - 4 * longs to
|
|
1947
|
+
/* if size is large, round to MALLOC_ROUND - 4 * longs to accommodate malloc overhead */
|
|
836
1948
|
if (elem * ncur > MALLOC_ROUND - sizeof (void *) * 4)
|
|
837
1949
|
{
|
|
838
1950
|
ncur *= elem;
|
|
@@ -844,7 +1956,8 @@ array_nextsize (int elem, int cur, int cnt)
|
|
|
844
1956
|
return ncur;
|
|
845
1957
|
}
|
|
846
1958
|
|
|
847
|
-
|
|
1959
|
+
noinline ecb_cold
|
|
1960
|
+
static void *
|
|
848
1961
|
array_realloc (int elem, void *base, int *cur, int cnt)
|
|
849
1962
|
{
|
|
850
1963
|
*cur = array_nextsize (elem, *cur, cnt);
|
|
@@ -857,7 +1970,7 @@ array_realloc (int elem, void *base, int *cur, int cnt)
|
|
|
857
1970
|
#define array_needsize(type,base,cur,cnt,init) \
|
|
858
1971
|
if (expect_false ((cnt) > (cur))) \
|
|
859
1972
|
{ \
|
|
860
|
-
int ocur_ = (cur);
|
|
1973
|
+
ecb_unused int ocur_ = (cur); \
|
|
861
1974
|
(base) = (type *)array_realloc \
|
|
862
1975
|
(sizeof (type), (base), &(cur), (cnt)); \
|
|
863
1976
|
init ((base) + (ocur_), (cur) - ocur_); \
|
|
@@ -879,13 +1992,15 @@ array_realloc (int elem, void *base, int *cur, int cnt)
|
|
|
879
1992
|
/*****************************************************************************/
|
|
880
1993
|
|
|
881
1994
|
/* dummy callback for pending events */
|
|
882
|
-
|
|
1995
|
+
noinline
|
|
1996
|
+
static void
|
|
883
1997
|
pendingcb (EV_P_ ev_prepare *w, int revents)
|
|
884
1998
|
{
|
|
885
1999
|
}
|
|
886
2000
|
|
|
887
|
-
|
|
888
|
-
|
|
2001
|
+
noinline
|
|
2002
|
+
void
|
|
2003
|
+
ev_feed_event (EV_P_ void *w, int revents) EV_THROW
|
|
889
2004
|
{
|
|
890
2005
|
W w_ = (W)w;
|
|
891
2006
|
int pri = ABSPRI (w_);
|
|
@@ -899,6 +2014,8 @@ ev_feed_event (EV_P_ void *w, int revents)
|
|
|
899
2014
|
pendings [pri][w_->pending - 1].w = w_;
|
|
900
2015
|
pendings [pri][w_->pending - 1].events = revents;
|
|
901
2016
|
}
|
|
2017
|
+
|
|
2018
|
+
pendingpri = NUMPRI - 1;
|
|
902
2019
|
}
|
|
903
2020
|
|
|
904
2021
|
inline_speed void
|
|
@@ -954,7 +2071,7 @@ fd_event (EV_P_ int fd, int revents)
|
|
|
954
2071
|
}
|
|
955
2072
|
|
|
956
2073
|
void
|
|
957
|
-
ev_feed_fd_event (EV_P_ int fd, int revents)
|
|
2074
|
+
ev_feed_fd_event (EV_P_ int fd, int revents) EV_THROW
|
|
958
2075
|
{
|
|
959
2076
|
if (fd >= 0 && fd < anfdmax)
|
|
960
2077
|
fd_event_nocheck (EV_A_ fd, revents);
|
|
@@ -967,6 +2084,31 @@ fd_reify (EV_P)
|
|
|
967
2084
|
{
|
|
968
2085
|
int i;
|
|
969
2086
|
|
|
2087
|
+
#if EV_SELECT_IS_WINSOCKET || EV_USE_IOCP
|
|
2088
|
+
for (i = 0; i < fdchangecnt; ++i)
|
|
2089
|
+
{
|
|
2090
|
+
int fd = fdchanges [i];
|
|
2091
|
+
ANFD *anfd = anfds + fd;
|
|
2092
|
+
|
|
2093
|
+
if (anfd->reify & EV__IOFDSET && anfd->head)
|
|
2094
|
+
{
|
|
2095
|
+
SOCKET handle = EV_FD_TO_WIN32_HANDLE (fd);
|
|
2096
|
+
|
|
2097
|
+
if (handle != anfd->handle)
|
|
2098
|
+
{
|
|
2099
|
+
unsigned long arg;
|
|
2100
|
+
|
|
2101
|
+
assert (("libev: only socket fds supported in this configuration", ioctlsocket (handle, FIONREAD, &arg) == 0));
|
|
2102
|
+
|
|
2103
|
+
/* handle changed, but fd didn't - we need to do it in two steps */
|
|
2104
|
+
backend_modify (EV_A_ fd, anfd->events, 0);
|
|
2105
|
+
anfd->events = 0;
|
|
2106
|
+
anfd->handle = handle;
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
}
|
|
2110
|
+
#endif
|
|
2111
|
+
|
|
970
2112
|
for (i = 0; i < fdchangecnt; ++i)
|
|
971
2113
|
{
|
|
972
2114
|
int fd = fdchanges [i];
|
|
@@ -978,16 +2120,6 @@ fd_reify (EV_P)
|
|
|
978
2120
|
|
|
979
2121
|
anfd->reify = 0;
|
|
980
2122
|
|
|
981
|
-
#if EV_SELECT_IS_WINSOCKET || EV_USE_IOCP
|
|
982
|
-
if (o_reify & EV__IOFDSET)
|
|
983
|
-
{
|
|
984
|
-
unsigned long arg;
|
|
985
|
-
anfd->handle = EV_FD_TO_WIN32_HANDLE (fd);
|
|
986
|
-
assert (("libev: only socket fds supported in this configuration", ioctlsocket (anfd->handle, FIONREAD, &arg) == 0));
|
|
987
|
-
printf ("oi %d %x\n", fd, anfd->handle);//D
|
|
988
|
-
}
|
|
989
|
-
#endif
|
|
990
|
-
|
|
991
2123
|
/*if (expect_true (o_reify & EV_ANFD_REIFY)) probably a deoptimisation */
|
|
992
2124
|
{
|
|
993
2125
|
anfd->events = 0;
|
|
@@ -1007,7 +2139,8 @@ fd_reify (EV_P)
|
|
|
1007
2139
|
}
|
|
1008
2140
|
|
|
1009
2141
|
/* something about the given fd changed */
|
|
1010
|
-
inline_size
|
|
2142
|
+
inline_size
|
|
2143
|
+
void
|
|
1011
2144
|
fd_change (EV_P_ int fd, int flags)
|
|
1012
2145
|
{
|
|
1013
2146
|
unsigned char reify = anfds [fd].reify;
|
|
@@ -1022,7 +2155,7 @@ fd_change (EV_P_ int fd, int flags)
|
|
|
1022
2155
|
}
|
|
1023
2156
|
|
|
1024
2157
|
/* the given fd is invalid/unusable, so make sure it doesn't hurt us anymore */
|
|
1025
|
-
inline_speed void
|
|
2158
|
+
inline_speed ecb_cold void
|
|
1026
2159
|
fd_kill (EV_P_ int fd)
|
|
1027
2160
|
{
|
|
1028
2161
|
ev_io *w;
|
|
@@ -1035,7 +2168,7 @@ fd_kill (EV_P_ int fd)
|
|
|
1035
2168
|
}
|
|
1036
2169
|
|
|
1037
2170
|
/* check whether the given fd is actually valid, for error recovery */
|
|
1038
|
-
inline_size int
|
|
2171
|
+
inline_size ecb_cold int
|
|
1039
2172
|
fd_valid (int fd)
|
|
1040
2173
|
{
|
|
1041
2174
|
#ifdef _WIN32
|
|
@@ -1046,7 +2179,8 @@ fd_valid (int fd)
|
|
|
1046
2179
|
}
|
|
1047
2180
|
|
|
1048
2181
|
/* called on EBADF to verify fds */
|
|
1049
|
-
|
|
2182
|
+
noinline ecb_cold
|
|
2183
|
+
static void
|
|
1050
2184
|
fd_ebadf (EV_P)
|
|
1051
2185
|
{
|
|
1052
2186
|
int fd;
|
|
@@ -1058,7 +2192,8 @@ fd_ebadf (EV_P)
|
|
|
1058
2192
|
}
|
|
1059
2193
|
|
|
1060
2194
|
/* called on ENOMEM in select/poll to kill some fds and retry */
|
|
1061
|
-
|
|
2195
|
+
noinline ecb_cold
|
|
2196
|
+
static void
|
|
1062
2197
|
fd_enomem (EV_P)
|
|
1063
2198
|
{
|
|
1064
2199
|
int fd;
|
|
@@ -1072,7 +2207,8 @@ fd_enomem (EV_P)
|
|
|
1072
2207
|
}
|
|
1073
2208
|
|
|
1074
2209
|
/* usually called after fork if backend needs to re-arm all fds from scratch */
|
|
1075
|
-
|
|
2210
|
+
noinline
|
|
2211
|
+
static void
|
|
1076
2212
|
fd_rearm_all (EV_P)
|
|
1077
2213
|
{
|
|
1078
2214
|
int fd;
|
|
@@ -1192,7 +2328,7 @@ downheap (ANHE *heap, int N, int k)
|
|
|
1192
2328
|
|
|
1193
2329
|
heap [k] = heap [c];
|
|
1194
2330
|
ev_active (ANHE_w (heap [k])) = k;
|
|
1195
|
-
|
|
2331
|
+
|
|
1196
2332
|
k = c;
|
|
1197
2333
|
}
|
|
1198
2334
|
|
|
@@ -1263,62 +2399,95 @@ static ANSIG signals [EV_NSIG - 1];
|
|
|
1263
2399
|
|
|
1264
2400
|
#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
|
|
1265
2401
|
|
|
1266
|
-
|
|
2402
|
+
noinline ecb_cold
|
|
2403
|
+
static void
|
|
1267
2404
|
evpipe_init (EV_P)
|
|
1268
2405
|
{
|
|
1269
2406
|
if (!ev_is_active (&pipe_w))
|
|
1270
2407
|
{
|
|
2408
|
+
int fds [2];
|
|
2409
|
+
|
|
1271
2410
|
# if EV_USE_EVENTFD
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
2411
|
+
fds [0] = -1;
|
|
2412
|
+
fds [1] = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
|
|
2413
|
+
if (fds [1] < 0 && errno == EINVAL)
|
|
2414
|
+
fds [1] = eventfd (0, 0);
|
|
1275
2415
|
|
|
1276
|
-
if (
|
|
2416
|
+
if (fds [1] < 0)
|
|
2417
|
+
# endif
|
|
1277
2418
|
{
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
2419
|
+
while (pipe (fds))
|
|
2420
|
+
ev_syserr ("(libev) error creating signal/async pipe");
|
|
2421
|
+
|
|
2422
|
+
fd_intern (fds [0]);
|
|
1281
2423
|
}
|
|
2424
|
+
|
|
2425
|
+
evpipe [0] = fds [0];
|
|
2426
|
+
|
|
2427
|
+
if (evpipe [1] < 0)
|
|
2428
|
+
evpipe [1] = fds [1]; /* first call, set write fd */
|
|
1282
2429
|
else
|
|
1283
|
-
# endif
|
|
1284
2430
|
{
|
|
1285
|
-
|
|
1286
|
-
|
|
2431
|
+
/* on subsequent calls, do not change evpipe [1] */
|
|
2432
|
+
/* so that evpipe_write can always rely on its value. */
|
|
2433
|
+
/* this branch does not do anything sensible on windows, */
|
|
2434
|
+
/* so must not be executed on windows */
|
|
1287
2435
|
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
ev_io_set (&pipe_w, evpipe [0], EV_READ);
|
|
2436
|
+
dup2 (fds [1], evpipe [1]);
|
|
2437
|
+
close (fds [1]);
|
|
1291
2438
|
}
|
|
1292
2439
|
|
|
2440
|
+
fd_intern (evpipe [1]);
|
|
2441
|
+
|
|
2442
|
+
ev_io_set (&pipe_w, evpipe [0] < 0 ? evpipe [1] : evpipe [0], EV_READ);
|
|
1293
2443
|
ev_io_start (EV_A_ &pipe_w);
|
|
1294
2444
|
ev_unref (EV_A); /* watcher should not keep loop alive */
|
|
1295
2445
|
}
|
|
1296
2446
|
}
|
|
1297
2447
|
|
|
1298
|
-
|
|
2448
|
+
inline_speed void
|
|
1299
2449
|
evpipe_write (EV_P_ EV_ATOMIC_T *flag)
|
|
1300
2450
|
{
|
|
1301
|
-
|
|
2451
|
+
ECB_MEMORY_FENCE; /* push out the write before this function was called, acquire flag */
|
|
2452
|
+
|
|
2453
|
+
if (expect_true (*flag))
|
|
2454
|
+
return;
|
|
2455
|
+
|
|
2456
|
+
*flag = 1;
|
|
2457
|
+
ECB_MEMORY_FENCE_RELEASE; /* make sure flag is visible before the wakeup */
|
|
2458
|
+
|
|
2459
|
+
pipe_write_skipped = 1;
|
|
2460
|
+
|
|
2461
|
+
ECB_MEMORY_FENCE; /* make sure pipe_write_skipped is visible before we check pipe_write_wanted */
|
|
2462
|
+
|
|
2463
|
+
if (pipe_write_wanted)
|
|
1302
2464
|
{
|
|
1303
|
-
int old_errno
|
|
1304
|
-
|
|
2465
|
+
int old_errno;
|
|
2466
|
+
|
|
2467
|
+
pipe_write_skipped = 0;
|
|
2468
|
+
ECB_MEMORY_FENCE_RELEASE;
|
|
1305
2469
|
|
|
1306
|
-
|
|
2470
|
+
old_errno = errno; /* save errno because write will clobber it */
|
|
1307
2471
|
|
|
1308
2472
|
#if EV_USE_EVENTFD
|
|
1309
|
-
if (
|
|
2473
|
+
if (evpipe [0] < 0)
|
|
1310
2474
|
{
|
|
1311
2475
|
uint64_t counter = 1;
|
|
1312
|
-
write (
|
|
2476
|
+
write (evpipe [1], &counter, sizeof (uint64_t));
|
|
1313
2477
|
}
|
|
1314
2478
|
else
|
|
1315
2479
|
#endif
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
2480
|
+
{
|
|
2481
|
+
#ifdef _WIN32
|
|
2482
|
+
WSABUF buf;
|
|
2483
|
+
DWORD sent;
|
|
2484
|
+
buf.buf = (char *)&buf;
|
|
2485
|
+
buf.len = 1;
|
|
2486
|
+
WSASend (EV_FD_TO_WIN32_HANDLE (evpipe [1]), &buf, 1, &sent, 0, 0, 0);
|
|
2487
|
+
#else
|
|
2488
|
+
write (evpipe [1], &(evpipe [1]), 1);
|
|
2489
|
+
#endif
|
|
2490
|
+
}
|
|
1322
2491
|
|
|
1323
2492
|
errno = old_errno;
|
|
1324
2493
|
}
|
|
@@ -1331,38 +2500,60 @@ pipecb (EV_P_ ev_io *iow, int revents)
|
|
|
1331
2500
|
{
|
|
1332
2501
|
int i;
|
|
1333
2502
|
|
|
1334
|
-
|
|
1335
|
-
if (evfd >= 0)
|
|
2503
|
+
if (revents & EV_READ)
|
|
1336
2504
|
{
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
2505
|
+
#if EV_USE_EVENTFD
|
|
2506
|
+
if (evpipe [0] < 0)
|
|
2507
|
+
{
|
|
2508
|
+
uint64_t counter;
|
|
2509
|
+
read (evpipe [1], &counter, sizeof (uint64_t));
|
|
2510
|
+
}
|
|
2511
|
+
else
|
|
1341
2512
|
#endif
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
2513
|
+
{
|
|
2514
|
+
char dummy[4];
|
|
2515
|
+
#ifdef _WIN32
|
|
2516
|
+
WSABUF buf;
|
|
2517
|
+
DWORD recvd;
|
|
2518
|
+
DWORD flags = 0;
|
|
2519
|
+
buf.buf = dummy;
|
|
2520
|
+
buf.len = sizeof (dummy);
|
|
2521
|
+
WSARecv (EV_FD_TO_WIN32_HANDLE (evpipe [0]), &buf, 1, &recvd, &flags, 0, 0);
|
|
2522
|
+
#else
|
|
2523
|
+
read (evpipe [0], &dummy, sizeof (dummy));
|
|
2524
|
+
#endif
|
|
2525
|
+
}
|
|
1346
2526
|
}
|
|
1347
2527
|
|
|
2528
|
+
pipe_write_skipped = 0;
|
|
2529
|
+
|
|
2530
|
+
ECB_MEMORY_FENCE; /* push out skipped, acquire flags */
|
|
2531
|
+
|
|
2532
|
+
#if EV_SIGNAL_ENABLE
|
|
1348
2533
|
if (sig_pending)
|
|
1349
|
-
{
|
|
2534
|
+
{
|
|
1350
2535
|
sig_pending = 0;
|
|
1351
2536
|
|
|
2537
|
+
ECB_MEMORY_FENCE;
|
|
2538
|
+
|
|
1352
2539
|
for (i = EV_NSIG - 1; i--; )
|
|
1353
2540
|
if (expect_false (signals [i].pending))
|
|
1354
2541
|
ev_feed_signal_event (EV_A_ i + 1);
|
|
1355
2542
|
}
|
|
2543
|
+
#endif
|
|
1356
2544
|
|
|
1357
2545
|
#if EV_ASYNC_ENABLE
|
|
1358
2546
|
if (async_pending)
|
|
1359
2547
|
{
|
|
1360
2548
|
async_pending = 0;
|
|
1361
2549
|
|
|
2550
|
+
ECB_MEMORY_FENCE;
|
|
2551
|
+
|
|
1362
2552
|
for (i = asynccnt; i--; )
|
|
1363
2553
|
if (asyncs [i]->sent)
|
|
1364
2554
|
{
|
|
1365
2555
|
asyncs [i]->sent = 0;
|
|
2556
|
+
ECB_MEMORY_FENCE_RELEASE;
|
|
1366
2557
|
ev_feed_event (EV_A_ asyncs [i], EV_ASYNC);
|
|
1367
2558
|
}
|
|
1368
2559
|
}
|
|
@@ -1371,27 +2562,39 @@ pipecb (EV_P_ ev_io *iow, int revents)
|
|
|
1371
2562
|
|
|
1372
2563
|
/*****************************************************************************/
|
|
1373
2564
|
|
|
1374
|
-
|
|
1375
|
-
|
|
2565
|
+
void
|
|
2566
|
+
ev_feed_signal (int signum) EV_THROW
|
|
1376
2567
|
{
|
|
1377
2568
|
#if EV_MULTIPLICITY
|
|
1378
|
-
EV_P
|
|
2569
|
+
EV_P;
|
|
2570
|
+
ECB_MEMORY_FENCE_ACQUIRE;
|
|
2571
|
+
EV_A = signals [signum - 1].loop;
|
|
2572
|
+
|
|
2573
|
+
if (!EV_A)
|
|
2574
|
+
return;
|
|
1379
2575
|
#endif
|
|
1380
2576
|
|
|
2577
|
+
signals [signum - 1].pending = 1;
|
|
2578
|
+
evpipe_write (EV_A_ &sig_pending);
|
|
2579
|
+
}
|
|
2580
|
+
|
|
2581
|
+
static void
|
|
2582
|
+
ev_sighandler (int signum)
|
|
2583
|
+
{
|
|
1381
2584
|
#ifdef _WIN32
|
|
1382
2585
|
signal (signum, ev_sighandler);
|
|
1383
2586
|
#endif
|
|
1384
2587
|
|
|
1385
|
-
|
|
1386
|
-
evpipe_write (EV_A_ &sig_pending);
|
|
2588
|
+
ev_feed_signal (signum);
|
|
1387
2589
|
}
|
|
1388
2590
|
|
|
1389
|
-
|
|
1390
|
-
|
|
2591
|
+
noinline
|
|
2592
|
+
void
|
|
2593
|
+
ev_feed_signal_event (EV_P_ int signum) EV_THROW
|
|
1391
2594
|
{
|
|
1392
2595
|
WL w;
|
|
1393
2596
|
|
|
1394
|
-
if (expect_false (signum <= 0 || signum
|
|
2597
|
+
if (expect_false (signum <= 0 || signum >= EV_NSIG))
|
|
1395
2598
|
return;
|
|
1396
2599
|
|
|
1397
2600
|
--signum;
|
|
@@ -1405,6 +2608,7 @@ ev_feed_signal_event (EV_P_ int signum)
|
|
|
1405
2608
|
#endif
|
|
1406
2609
|
|
|
1407
2610
|
signals [signum].pending = 0;
|
|
2611
|
+
ECB_MEMORY_FENCE_RELEASE;
|
|
1408
2612
|
|
|
1409
2613
|
for (w = signals [signum].head; w; w = w->next)
|
|
1410
2614
|
ev_feed_event (EV_A_ (W)w, EV_SIGNAL);
|
|
@@ -1512,20 +2716,20 @@ childcb (EV_P_ ev_signal *sw, int revents)
|
|
|
1512
2716
|
# include "ev_select.c"
|
|
1513
2717
|
#endif
|
|
1514
2718
|
|
|
1515
|
-
int
|
|
1516
|
-
ev_version_major (void)
|
|
2719
|
+
ecb_cold int
|
|
2720
|
+
ev_version_major (void) EV_THROW
|
|
1517
2721
|
{
|
|
1518
2722
|
return EV_VERSION_MAJOR;
|
|
1519
2723
|
}
|
|
1520
2724
|
|
|
1521
|
-
int
|
|
1522
|
-
ev_version_minor (void)
|
|
2725
|
+
ecb_cold int
|
|
2726
|
+
ev_version_minor (void) EV_THROW
|
|
1523
2727
|
{
|
|
1524
2728
|
return EV_VERSION_MINOR;
|
|
1525
2729
|
}
|
|
1526
2730
|
|
|
1527
2731
|
/* return true if we are running with elevated privileges and should ignore env variables */
|
|
1528
|
-
int
|
|
2732
|
+
inline_size ecb_cold int
|
|
1529
2733
|
enable_secure (void)
|
|
1530
2734
|
{
|
|
1531
2735
|
#ifdef _WIN32
|
|
@@ -1536,8 +2740,9 @@ enable_secure (void)
|
|
|
1536
2740
|
#endif
|
|
1537
2741
|
}
|
|
1538
2742
|
|
|
2743
|
+
ecb_cold
|
|
1539
2744
|
unsigned int
|
|
1540
|
-
ev_supported_backends (void)
|
|
2745
|
+
ev_supported_backends (void) EV_THROW
|
|
1541
2746
|
{
|
|
1542
2747
|
unsigned int flags = 0;
|
|
1543
2748
|
|
|
@@ -1546,12 +2751,13 @@ ev_supported_backends (void)
|
|
|
1546
2751
|
if (EV_USE_EPOLL ) flags |= EVBACKEND_EPOLL;
|
|
1547
2752
|
if (EV_USE_POLL ) flags |= EVBACKEND_POLL;
|
|
1548
2753
|
if (EV_USE_SELECT) flags |= EVBACKEND_SELECT;
|
|
1549
|
-
|
|
2754
|
+
|
|
1550
2755
|
return flags;
|
|
1551
2756
|
}
|
|
1552
2757
|
|
|
2758
|
+
ecb_cold
|
|
1553
2759
|
unsigned int
|
|
1554
|
-
ev_recommended_backends (void)
|
|
2760
|
+
ev_recommended_backends (void) EV_THROW
|
|
1555
2761
|
{
|
|
1556
2762
|
unsigned int flags = ev_supported_backends ();
|
|
1557
2763
|
|
|
@@ -1572,8 +2778,9 @@ ev_recommended_backends (void)
|
|
|
1572
2778
|
return flags;
|
|
1573
2779
|
}
|
|
1574
2780
|
|
|
2781
|
+
ecb_cold
|
|
1575
2782
|
unsigned int
|
|
1576
|
-
ev_embeddable_backends (void)
|
|
2783
|
+
ev_embeddable_backends (void) EV_THROW
|
|
1577
2784
|
{
|
|
1578
2785
|
int flags = EVBACKEND_EPOLL | EVBACKEND_KQUEUE | EVBACKEND_PORT;
|
|
1579
2786
|
|
|
@@ -1585,54 +2792,56 @@ ev_embeddable_backends (void)
|
|
|
1585
2792
|
}
|
|
1586
2793
|
|
|
1587
2794
|
unsigned int
|
|
1588
|
-
ev_backend (EV_P)
|
|
2795
|
+
ev_backend (EV_P) EV_THROW
|
|
1589
2796
|
{
|
|
1590
2797
|
return backend;
|
|
1591
2798
|
}
|
|
1592
2799
|
|
|
1593
2800
|
#if EV_FEATURE_API
|
|
1594
2801
|
unsigned int
|
|
1595
|
-
ev_iteration (EV_P)
|
|
2802
|
+
ev_iteration (EV_P) EV_THROW
|
|
1596
2803
|
{
|
|
1597
2804
|
return loop_count;
|
|
1598
2805
|
}
|
|
1599
2806
|
|
|
1600
2807
|
unsigned int
|
|
1601
|
-
ev_depth (EV_P)
|
|
2808
|
+
ev_depth (EV_P) EV_THROW
|
|
1602
2809
|
{
|
|
1603
2810
|
return loop_depth;
|
|
1604
2811
|
}
|
|
1605
2812
|
|
|
1606
2813
|
void
|
|
1607
|
-
ev_set_io_collect_interval (EV_P_ ev_tstamp interval)
|
|
2814
|
+
ev_set_io_collect_interval (EV_P_ ev_tstamp interval) EV_THROW
|
|
1608
2815
|
{
|
|
1609
2816
|
io_blocktime = interval;
|
|
1610
2817
|
}
|
|
1611
2818
|
|
|
1612
2819
|
void
|
|
1613
|
-
ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval)
|
|
2820
|
+
ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval) EV_THROW
|
|
1614
2821
|
{
|
|
1615
2822
|
timeout_blocktime = interval;
|
|
1616
2823
|
}
|
|
1617
2824
|
|
|
1618
2825
|
void
|
|
1619
|
-
ev_set_userdata (EV_P_ void *data)
|
|
2826
|
+
ev_set_userdata (EV_P_ void *data) EV_THROW
|
|
1620
2827
|
{
|
|
1621
2828
|
userdata = data;
|
|
1622
2829
|
}
|
|
1623
2830
|
|
|
1624
2831
|
void *
|
|
1625
|
-
ev_userdata (EV_P)
|
|
2832
|
+
ev_userdata (EV_P) EV_THROW
|
|
1626
2833
|
{
|
|
1627
2834
|
return userdata;
|
|
1628
2835
|
}
|
|
1629
2836
|
|
|
1630
|
-
void
|
|
2837
|
+
void
|
|
2838
|
+
ev_set_invoke_pending_cb (EV_P_ ev_loop_callback invoke_pending_cb) EV_THROW
|
|
1631
2839
|
{
|
|
1632
2840
|
invoke_cb = invoke_pending_cb;
|
|
1633
2841
|
}
|
|
1634
2842
|
|
|
1635
|
-
void
|
|
2843
|
+
void
|
|
2844
|
+
ev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_THROW, void (*acquire)(EV_P) EV_THROW) EV_THROW
|
|
1636
2845
|
{
|
|
1637
2846
|
release_cb = release;
|
|
1638
2847
|
acquire_cb = acquire;
|
|
@@ -1640,11 +2849,14 @@ void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P), void (*acquire)(EV_P))
|
|
|
1640
2849
|
#endif
|
|
1641
2850
|
|
|
1642
2851
|
/* initialise a loop structure, must be zero-initialised */
|
|
1643
|
-
|
|
1644
|
-
|
|
2852
|
+
noinline ecb_cold
|
|
2853
|
+
static void
|
|
2854
|
+
loop_init (EV_P_ unsigned int flags) EV_THROW
|
|
1645
2855
|
{
|
|
1646
2856
|
if (!backend)
|
|
1647
2857
|
{
|
|
2858
|
+
origflags = flags;
|
|
2859
|
+
|
|
1648
2860
|
#if EV_USE_REALTIME
|
|
1649
2861
|
if (!have_realtime)
|
|
1650
2862
|
{
|
|
@@ -1676,30 +2888,34 @@ loop_init (EV_P_ unsigned int flags)
|
|
|
1676
2888
|
&& getenv ("LIBEV_FLAGS"))
|
|
1677
2889
|
flags = atoi (getenv ("LIBEV_FLAGS"));
|
|
1678
2890
|
|
|
1679
|
-
ev_rt_now
|
|
1680
|
-
mn_now
|
|
1681
|
-
now_floor
|
|
1682
|
-
rtmn_diff
|
|
2891
|
+
ev_rt_now = ev_time ();
|
|
2892
|
+
mn_now = get_clock ();
|
|
2893
|
+
now_floor = mn_now;
|
|
2894
|
+
rtmn_diff = ev_rt_now - mn_now;
|
|
1683
2895
|
#if EV_FEATURE_API
|
|
1684
|
-
invoke_cb
|
|
2896
|
+
invoke_cb = ev_invoke_pending;
|
|
1685
2897
|
#endif
|
|
1686
2898
|
|
|
1687
|
-
io_blocktime
|
|
1688
|
-
timeout_blocktime
|
|
1689
|
-
backend
|
|
1690
|
-
backend_fd
|
|
1691
|
-
sig_pending
|
|
2899
|
+
io_blocktime = 0.;
|
|
2900
|
+
timeout_blocktime = 0.;
|
|
2901
|
+
backend = 0;
|
|
2902
|
+
backend_fd = -1;
|
|
2903
|
+
sig_pending = 0;
|
|
1692
2904
|
#if EV_ASYNC_ENABLE
|
|
1693
|
-
async_pending
|
|
2905
|
+
async_pending = 0;
|
|
1694
2906
|
#endif
|
|
2907
|
+
pipe_write_skipped = 0;
|
|
2908
|
+
pipe_write_wanted = 0;
|
|
2909
|
+
evpipe [0] = -1;
|
|
2910
|
+
evpipe [1] = -1;
|
|
1695
2911
|
#if EV_USE_INOTIFY
|
|
1696
|
-
fs_fd
|
|
2912
|
+
fs_fd = flags & EVFLAG_NOINOTIFY ? -1 : -2;
|
|
1697
2913
|
#endif
|
|
1698
2914
|
#if EV_USE_SIGNALFD
|
|
1699
|
-
sigfd
|
|
2915
|
+
sigfd = flags & EVFLAG_SIGNALFD ? -2 : -1;
|
|
1700
2916
|
#endif
|
|
1701
2917
|
|
|
1702
|
-
if (!(flags &
|
|
2918
|
+
if (!(flags & EVBACKEND_MASK))
|
|
1703
2919
|
flags |= ev_recommended_backends ();
|
|
1704
2920
|
|
|
1705
2921
|
#if EV_USE_IOCP
|
|
@@ -1731,6 +2947,7 @@ loop_init (EV_P_ unsigned int flags)
|
|
|
1731
2947
|
}
|
|
1732
2948
|
|
|
1733
2949
|
/* free up a loop structure */
|
|
2950
|
+
ecb_cold
|
|
1734
2951
|
void
|
|
1735
2952
|
ev_loop_destroy (EV_P)
|
|
1736
2953
|
{
|
|
@@ -1752,7 +2969,7 @@ ev_loop_destroy (EV_P)
|
|
|
1752
2969
|
#endif
|
|
1753
2970
|
|
|
1754
2971
|
#if EV_CHILD_ENABLE
|
|
1755
|
-
if (ev_is_active (&childev))
|
|
2972
|
+
if (ev_is_default_loop (EV_A) && ev_is_active (&childev))
|
|
1756
2973
|
{
|
|
1757
2974
|
ev_ref (EV_A); /* child watcher */
|
|
1758
2975
|
ev_signal_stop (EV_A_ &childev);
|
|
@@ -1764,16 +2981,8 @@ ev_loop_destroy (EV_P)
|
|
|
1764
2981
|
/*ev_ref (EV_A);*/
|
|
1765
2982
|
/*ev_io_stop (EV_A_ &pipe_w);*/
|
|
1766
2983
|
|
|
1767
|
-
|
|
1768
|
-
if (
|
|
1769
|
-
close (evfd);
|
|
1770
|
-
#endif
|
|
1771
|
-
|
|
1772
|
-
if (evpipe [0] >= 0)
|
|
1773
|
-
{
|
|
1774
|
-
EV_WIN32_CLOSE_FD (evpipe [0]);
|
|
1775
|
-
EV_WIN32_CLOSE_FD (evpipe [1]);
|
|
1776
|
-
}
|
|
2984
|
+
if (evpipe [0] >= 0) EV_WIN32_CLOSE_FD (evpipe [0]);
|
|
2985
|
+
if (evpipe [1] >= 0) EV_WIN32_CLOSE_FD (evpipe [1]);
|
|
1777
2986
|
}
|
|
1778
2987
|
|
|
1779
2988
|
#if EV_USE_SIGNALFD
|
|
@@ -1869,43 +3078,31 @@ loop_fork (EV_P)
|
|
|
1869
3078
|
infy_fork (EV_A);
|
|
1870
3079
|
#endif
|
|
1871
3080
|
|
|
1872
|
-
|
|
3081
|
+
#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
|
|
3082
|
+
if (ev_is_active (&pipe_w) && postfork != 2)
|
|
1873
3083
|
{
|
|
1874
|
-
/*
|
|
1875
|
-
/* while we modify the fd vars */
|
|
1876
|
-
sig_pending = 1;
|
|
1877
|
-
#if EV_ASYNC_ENABLE
|
|
1878
|
-
async_pending = 1;
|
|
1879
|
-
#endif
|
|
3084
|
+
/* pipe_write_wanted must be false now, so modifying fd vars should be safe */
|
|
1880
3085
|
|
|
1881
3086
|
ev_ref (EV_A);
|
|
1882
3087
|
ev_io_stop (EV_A_ &pipe_w);
|
|
1883
3088
|
|
|
1884
|
-
#if EV_USE_EVENTFD
|
|
1885
|
-
if (evfd >= 0)
|
|
1886
|
-
close (evfd);
|
|
1887
|
-
#endif
|
|
1888
|
-
|
|
1889
3089
|
if (evpipe [0] >= 0)
|
|
1890
|
-
|
|
1891
|
-
EV_WIN32_CLOSE_FD (evpipe [0]);
|
|
1892
|
-
EV_WIN32_CLOSE_FD (evpipe [1]);
|
|
1893
|
-
}
|
|
3090
|
+
EV_WIN32_CLOSE_FD (evpipe [0]);
|
|
1894
3091
|
|
|
1895
|
-
#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
|
|
1896
3092
|
evpipe_init (EV_A);
|
|
1897
|
-
/*
|
|
1898
|
-
|
|
1899
|
-
#endif
|
|
3093
|
+
/* iterate over everything, in case we missed something before */
|
|
3094
|
+
ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);
|
|
1900
3095
|
}
|
|
3096
|
+
#endif
|
|
1901
3097
|
|
|
1902
3098
|
postfork = 0;
|
|
1903
3099
|
}
|
|
1904
3100
|
|
|
1905
3101
|
#if EV_MULTIPLICITY
|
|
1906
3102
|
|
|
3103
|
+
ecb_cold
|
|
1907
3104
|
struct ev_loop *
|
|
1908
|
-
ev_loop_new (unsigned int flags)
|
|
3105
|
+
ev_loop_new (unsigned int flags) EV_THROW
|
|
1909
3106
|
{
|
|
1910
3107
|
EV_P = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop));
|
|
1911
3108
|
|
|
@@ -1922,7 +3119,8 @@ ev_loop_new (unsigned int flags)
|
|
|
1922
3119
|
#endif /* multiplicity */
|
|
1923
3120
|
|
|
1924
3121
|
#if EV_VERIFY
|
|
1925
|
-
|
|
3122
|
+
noinline ecb_cold
|
|
3123
|
+
static void
|
|
1926
3124
|
verify_watcher (EV_P_ W w)
|
|
1927
3125
|
{
|
|
1928
3126
|
assert (("libev: watcher has invalid priority", ABSPRI (w) >= 0 && ABSPRI (w) < NUMPRI));
|
|
@@ -1931,7 +3129,8 @@ verify_watcher (EV_P_ W w)
|
|
|
1931
3129
|
assert (("libev: pending watcher not on pending queue", pendings [ABSPRI (w)][w->pending - 1].w == w));
|
|
1932
3130
|
}
|
|
1933
3131
|
|
|
1934
|
-
|
|
3132
|
+
noinline ecb_cold
|
|
3133
|
+
static void
|
|
1935
3134
|
verify_heap (EV_P_ ANHE *heap, int N)
|
|
1936
3135
|
{
|
|
1937
3136
|
int i;
|
|
@@ -1946,7 +3145,8 @@ verify_heap (EV_P_ ANHE *heap, int N)
|
|
|
1946
3145
|
}
|
|
1947
3146
|
}
|
|
1948
3147
|
|
|
1949
|
-
|
|
3148
|
+
noinline ecb_cold
|
|
3149
|
+
static void
|
|
1950
3150
|
array_verify (EV_P_ W *ws, int cnt)
|
|
1951
3151
|
{
|
|
1952
3152
|
while (cnt--)
|
|
@@ -1958,12 +3158,12 @@ array_verify (EV_P_ W *ws, int cnt)
|
|
|
1958
3158
|
#endif
|
|
1959
3159
|
|
|
1960
3160
|
#if EV_FEATURE_API
|
|
1961
|
-
void
|
|
1962
|
-
ev_verify (EV_P)
|
|
3161
|
+
void ecb_cold
|
|
3162
|
+
ev_verify (EV_P) EV_THROW
|
|
1963
3163
|
{
|
|
1964
3164
|
#if EV_VERIFY
|
|
1965
3165
|
int i;
|
|
1966
|
-
WL w;
|
|
3166
|
+
WL w, w2;
|
|
1967
3167
|
|
|
1968
3168
|
assert (activecnt >= -1);
|
|
1969
3169
|
|
|
@@ -1973,12 +3173,23 @@ ev_verify (EV_P)
|
|
|
1973
3173
|
|
|
1974
3174
|
assert (anfdmax >= 0);
|
|
1975
3175
|
for (i = 0; i < anfdmax; ++i)
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
3176
|
+
{
|
|
3177
|
+
int j = 0;
|
|
3178
|
+
|
|
3179
|
+
for (w = w2 = anfds [i].head; w; w = w->next)
|
|
3180
|
+
{
|
|
3181
|
+
verify_watcher (EV_A_ (W)w);
|
|
3182
|
+
|
|
3183
|
+
if (j++ & 1)
|
|
3184
|
+
{
|
|
3185
|
+
assert (("libev: io watcher list contains a loop", w != w2));
|
|
3186
|
+
w2 = w2->next;
|
|
3187
|
+
}
|
|
3188
|
+
|
|
3189
|
+
assert (("libev: inactive fd watcher on anfd list", ev_active (w) == 1));
|
|
3190
|
+
assert (("libev: fd mismatch between watcher and anfd", ((ev_io *)w)->fd == i));
|
|
3191
|
+
}
|
|
3192
|
+
}
|
|
1982
3193
|
|
|
1983
3194
|
assert (timermax >= timercnt);
|
|
1984
3195
|
verify_heap (EV_A_ timers, timercnt);
|
|
@@ -2034,11 +3245,12 @@ ev_verify (EV_P)
|
|
|
2034
3245
|
#endif
|
|
2035
3246
|
|
|
2036
3247
|
#if EV_MULTIPLICITY
|
|
3248
|
+
ecb_cold
|
|
2037
3249
|
struct ev_loop *
|
|
2038
3250
|
#else
|
|
2039
3251
|
int
|
|
2040
3252
|
#endif
|
|
2041
|
-
ev_default_loop (unsigned int flags)
|
|
3253
|
+
ev_default_loop (unsigned int flags) EV_THROW
|
|
2042
3254
|
{
|
|
2043
3255
|
if (!ev_default_loop_ptr)
|
|
2044
3256
|
{
|
|
@@ -2067,9 +3279,9 @@ ev_default_loop (unsigned int flags)
|
|
|
2067
3279
|
}
|
|
2068
3280
|
|
|
2069
3281
|
void
|
|
2070
|
-
ev_loop_fork (EV_P)
|
|
3282
|
+
ev_loop_fork (EV_P) EV_THROW
|
|
2071
3283
|
{
|
|
2072
|
-
postfork = 1;
|
|
3284
|
+
postfork = 1;
|
|
2073
3285
|
}
|
|
2074
3286
|
|
|
2075
3287
|
/*****************************************************************************/
|
|
@@ -2081,7 +3293,7 @@ ev_invoke (EV_P_ void *w, int revents)
|
|
|
2081
3293
|
}
|
|
2082
3294
|
|
|
2083
3295
|
unsigned int
|
|
2084
|
-
ev_pending_count (EV_P)
|
|
3296
|
+
ev_pending_count (EV_P) EV_THROW
|
|
2085
3297
|
{
|
|
2086
3298
|
int pri;
|
|
2087
3299
|
unsigned int count = 0;
|
|
@@ -2092,23 +3304,25 @@ ev_pending_count (EV_P)
|
|
|
2092
3304
|
return count;
|
|
2093
3305
|
}
|
|
2094
3306
|
|
|
2095
|
-
|
|
3307
|
+
noinline
|
|
3308
|
+
void
|
|
2096
3309
|
ev_invoke_pending (EV_P)
|
|
2097
3310
|
{
|
|
2098
|
-
|
|
3311
|
+
pendingpri = NUMPRI;
|
|
2099
3312
|
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
ANPENDING *p = pendings [pri] + --pendingcnt [pri];
|
|
3313
|
+
while (pendingpri) /* pendingpri possibly gets modified in the inner loop */
|
|
3314
|
+
{
|
|
3315
|
+
--pendingpri;
|
|
2104
3316
|
|
|
2105
|
-
|
|
2106
|
-
|
|
3317
|
+
while (pendingcnt [pendingpri])
|
|
3318
|
+
{
|
|
3319
|
+
ANPENDING *p = pendings [pendingpri] + --pendingcnt [pendingpri];
|
|
2107
3320
|
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
3321
|
+
p->w->pending = 0;
|
|
3322
|
+
EV_CB_INVOKE (p->w, p->events);
|
|
3323
|
+
EV_FREQUENT_CHECK;
|
|
3324
|
+
}
|
|
3325
|
+
}
|
|
2112
3326
|
}
|
|
2113
3327
|
|
|
2114
3328
|
#if EV_IDLE_ENABLE
|
|
@@ -2175,6 +3389,32 @@ timers_reify (EV_P)
|
|
|
2175
3389
|
}
|
|
2176
3390
|
|
|
2177
3391
|
#if EV_PERIODIC_ENABLE
|
|
3392
|
+
|
|
3393
|
+
noinline
|
|
3394
|
+
static void
|
|
3395
|
+
periodic_recalc (EV_P_ ev_periodic *w)
|
|
3396
|
+
{
|
|
3397
|
+
ev_tstamp interval = w->interval > MIN_INTERVAL ? w->interval : MIN_INTERVAL;
|
|
3398
|
+
ev_tstamp at = w->offset + interval * ev_floor ((ev_rt_now - w->offset) / interval);
|
|
3399
|
+
|
|
3400
|
+
/* the above almost always errs on the low side */
|
|
3401
|
+
while (at <= ev_rt_now)
|
|
3402
|
+
{
|
|
3403
|
+
ev_tstamp nat = at + w->interval;
|
|
3404
|
+
|
|
3405
|
+
/* when resolution fails us, we use ev_rt_now */
|
|
3406
|
+
if (expect_false (nat == at))
|
|
3407
|
+
{
|
|
3408
|
+
at = ev_rt_now;
|
|
3409
|
+
break;
|
|
3410
|
+
}
|
|
3411
|
+
|
|
3412
|
+
at = nat;
|
|
3413
|
+
}
|
|
3414
|
+
|
|
3415
|
+
ev_at (w) = at;
|
|
3416
|
+
}
|
|
3417
|
+
|
|
2178
3418
|
/* make periodics pending */
|
|
2179
3419
|
inline_size void
|
|
2180
3420
|
periodics_reify (EV_P)
|
|
@@ -2183,8 +3423,6 @@ periodics_reify (EV_P)
|
|
|
2183
3423
|
|
|
2184
3424
|
while (periodiccnt && ANHE_at (periodics [HEAP0]) < ev_rt_now)
|
|
2185
3425
|
{
|
|
2186
|
-
int feed_count = 0;
|
|
2187
|
-
|
|
2188
3426
|
do
|
|
2189
3427
|
{
|
|
2190
3428
|
ev_periodic *w = (ev_periodic *)ANHE_w (periodics [HEAP0]);
|
|
@@ -2203,20 +3441,7 @@ periodics_reify (EV_P)
|
|
|
2203
3441
|
}
|
|
2204
3442
|
else if (w->interval)
|
|
2205
3443
|
{
|
|
2206
|
-
|
|
2207
|
-
/* if next trigger time is not sufficiently in the future, put it there */
|
|
2208
|
-
/* this might happen because of floating point inexactness */
|
|
2209
|
-
if (ev_at (w) - ev_rt_now < TIME_EPSILON)
|
|
2210
|
-
{
|
|
2211
|
-
ev_at (w) += w->interval;
|
|
2212
|
-
|
|
2213
|
-
/* if interval is unreasonably low we might still have a time in the past */
|
|
2214
|
-
/* so correct this. this will make the periodic very inexact, but the user */
|
|
2215
|
-
/* has effectively asked to get triggered more often than possible */
|
|
2216
|
-
if (ev_at (w) < ev_rt_now)
|
|
2217
|
-
ev_at (w) = ev_rt_now;
|
|
2218
|
-
}
|
|
2219
|
-
|
|
3444
|
+
periodic_recalc (EV_A_ w);
|
|
2220
3445
|
ANHE_at_cache (periodics [HEAP0]);
|
|
2221
3446
|
downheap (periodics, periodiccnt, HEAP0);
|
|
2222
3447
|
}
|
|
@@ -2234,7 +3459,8 @@ periodics_reify (EV_P)
|
|
|
2234
3459
|
|
|
2235
3460
|
/* simply recalculate all periodics */
|
|
2236
3461
|
/* TODO: maybe ensure that at least one event happens when jumping forward? */
|
|
2237
|
-
|
|
3462
|
+
noinline ecb_cold
|
|
3463
|
+
static void
|
|
2238
3464
|
periodics_reschedule (EV_P)
|
|
2239
3465
|
{
|
|
2240
3466
|
int i;
|
|
@@ -2247,7 +3473,7 @@ periodics_reschedule (EV_P)
|
|
|
2247
3473
|
if (w->reschedule_cb)
|
|
2248
3474
|
ev_at (w) = w->reschedule_cb (w, ev_rt_now);
|
|
2249
3475
|
else if (w->interval)
|
|
2250
|
-
|
|
3476
|
+
periodic_recalc (EV_A_ w);
|
|
2251
3477
|
|
|
2252
3478
|
ANHE_at_cache (periodics [i]);
|
|
2253
3479
|
}
|
|
@@ -2257,7 +3483,8 @@ periodics_reschedule (EV_P)
|
|
|
2257
3483
|
#endif
|
|
2258
3484
|
|
|
2259
3485
|
/* adjust all timers by a given offset */
|
|
2260
|
-
|
|
3486
|
+
noinline ecb_cold
|
|
3487
|
+
static void
|
|
2261
3488
|
timers_reschedule (EV_P_ ev_tstamp adjust)
|
|
2262
3489
|
{
|
|
2263
3490
|
int i;
|
|
@@ -2304,9 +3531,12 @@ time_update (EV_P_ ev_tstamp max_block)
|
|
|
2304
3531
|
*/
|
|
2305
3532
|
for (i = 4; --i; )
|
|
2306
3533
|
{
|
|
3534
|
+
ev_tstamp diff;
|
|
2307
3535
|
rtmn_diff = ev_rt_now - mn_now;
|
|
2308
3536
|
|
|
2309
|
-
|
|
3537
|
+
diff = odiff - rtmn_diff;
|
|
3538
|
+
|
|
3539
|
+
if (expect_true ((diff < 0. ? -diff : diff) < MIN_TIMEJUMP))
|
|
2310
3540
|
return; /* all is well */
|
|
2311
3541
|
|
|
2312
3542
|
ev_rt_now = ev_time ();
|
|
@@ -2338,9 +3568,33 @@ time_update (EV_P_ ev_tstamp max_block)
|
|
|
2338
3568
|
}
|
|
2339
3569
|
}
|
|
2340
3570
|
|
|
2341
|
-
|
|
3571
|
+
/* ########## COOLIO PATCHERY HO! ########## */
|
|
3572
|
+
#if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
|
|
3573
|
+
struct ev_poll_args {
|
|
3574
|
+
struct ev_loop *loop;
|
|
3575
|
+
ev_tstamp waittime;
|
|
3576
|
+
};
|
|
3577
|
+
|
|
3578
|
+
static
|
|
3579
|
+
VALUE ev_backend_poll(void *ptr)
|
|
3580
|
+
{
|
|
3581
|
+
struct ev_poll_args *args = (struct ev_poll_args *)ptr;
|
|
3582
|
+
struct ev_loop *loop = args->loop;
|
|
3583
|
+
backend_poll (EV_A_ args->waittime);
|
|
3584
|
+
return Qnil;
|
|
3585
|
+
}
|
|
3586
|
+
#endif
|
|
3587
|
+
/* ######################################## */
|
|
3588
|
+
|
|
3589
|
+
int
|
|
2342
3590
|
ev_run (EV_P_ int flags)
|
|
2343
3591
|
{
|
|
3592
|
+
/* ########## COOLIO PATCHERY HO! ########## */
|
|
3593
|
+
#if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
|
|
3594
|
+
struct ev_poll_args poll_args;
|
|
3595
|
+
#endif
|
|
3596
|
+
/* ######################################## */
|
|
3597
|
+
|
|
2344
3598
|
#if EV_FEATURE_API
|
|
2345
3599
|
++loop_depth;
|
|
2346
3600
|
#endif
|
|
@@ -2406,20 +3660,25 @@ ev_run (EV_P_ int flags)
|
|
|
2406
3660
|
/* update time to cancel out callback processing overhead */
|
|
2407
3661
|
time_update (EV_A_ 1e100);
|
|
2408
3662
|
|
|
2409
|
-
|
|
3663
|
+
/* from now on, we want a pipe-wake-up */
|
|
3664
|
+
pipe_write_wanted = 1;
|
|
3665
|
+
|
|
3666
|
+
ECB_MEMORY_FENCE; /* make sure pipe_write_wanted is visible before we check for potential skips */
|
|
3667
|
+
|
|
3668
|
+
if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt || pipe_write_skipped)))
|
|
2410
3669
|
{
|
|
2411
3670
|
waittime = MAX_BLOCKTIME;
|
|
2412
3671
|
|
|
2413
3672
|
if (timercnt)
|
|
2414
3673
|
{
|
|
2415
|
-
ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now
|
|
3674
|
+
ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now;
|
|
2416
3675
|
if (waittime > to) waittime = to;
|
|
2417
3676
|
}
|
|
2418
3677
|
|
|
2419
3678
|
#if EV_PERIODIC_ENABLE
|
|
2420
3679
|
if (periodiccnt)
|
|
2421
3680
|
{
|
|
2422
|
-
ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now
|
|
3681
|
+
ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now;
|
|
2423
3682
|
if (waittime > to) waittime = to;
|
|
2424
3683
|
}
|
|
2425
3684
|
#endif
|
|
@@ -2428,13 +3687,18 @@ ev_run (EV_P_ int flags)
|
|
|
2428
3687
|
if (expect_false (waittime < timeout_blocktime))
|
|
2429
3688
|
waittime = timeout_blocktime;
|
|
2430
3689
|
|
|
3690
|
+
/* at this point, we NEED to wait, so we have to ensure */
|
|
3691
|
+
/* to pass a minimum nonzero value to the backend */
|
|
3692
|
+
if (expect_false (waittime < backend_mintime))
|
|
3693
|
+
waittime = backend_mintime;
|
|
3694
|
+
|
|
2431
3695
|
/* extra check because io_blocktime is commonly 0 */
|
|
2432
3696
|
if (expect_false (io_blocktime))
|
|
2433
3697
|
{
|
|
2434
3698
|
sleeptime = io_blocktime - (mn_now - prev_mn_now);
|
|
2435
3699
|
|
|
2436
|
-
if (sleeptime > waittime -
|
|
2437
|
-
sleeptime = waittime -
|
|
3700
|
+
if (sleeptime > waittime - backend_mintime)
|
|
3701
|
+
sleeptime = waittime - backend_mintime;
|
|
2438
3702
|
|
|
2439
3703
|
if (expect_true (sleeptime > 0.))
|
|
2440
3704
|
{
|
|
@@ -2448,9 +3712,82 @@ ev_run (EV_P_ int flags)
|
|
|
2448
3712
|
++loop_count;
|
|
2449
3713
|
#endif
|
|
2450
3714
|
assert ((loop_done = EVBREAK_RECURSE, 1)); /* assert for side effect */
|
|
2451
|
-
|
|
3715
|
+
|
|
3716
|
+
/*
|
|
3717
|
+
########################## COOLIO PATCHERY HO! ##########################
|
|
3718
|
+
|
|
3719
|
+
According to the grandwizards of Ruby, locking and unlocking of the global
|
|
3720
|
+
interpreter lock are apparently too powerful a concept for a mere mortal to
|
|
3721
|
+
wield (although redefining what + and - do to numbers is totally cool).
|
|
3722
|
+
And so it came to pass that the only acceptable way to release the global
|
|
3723
|
+
interpreter lock is through a convoluted callback system that thakes a
|
|
3724
|
+
function pointer. While the grandwizard of libev foresaw this sort of scenario,
|
|
3725
|
+
he too attempted to place an API with callbacks on it, one that runs before
|
|
3726
|
+
the system call, and one that runs immediately after.
|
|
3727
|
+
|
|
3728
|
+
And so it came to pass that trying to wrap everything up in callbacks created
|
|
3729
|
+
two incompatible APIs, Ruby's which releases the global interpreter lock and
|
|
3730
|
+
reacquires it when the callback returns, and libev's, which wants two
|
|
3731
|
+
callbacks, one which runs before the polling operation starts, and one which
|
|
3732
|
+
runs after it finishes.
|
|
3733
|
+
|
|
3734
|
+
These two systems are incompatible as they both want to use callbacks to
|
|
3735
|
+
solve the same problem, however libev wants to use before/after callbacks,
|
|
3736
|
+
and Ruby wants to use an "around" callback. This presents a significant
|
|
3737
|
+
problem as these two patterns of callbacks are diametrical opposites of each
|
|
3738
|
+
other and thus cannot be composed.
|
|
3739
|
+
|
|
3740
|
+
And thus we are left with no choice but to patch the internals of libev in
|
|
3741
|
+
order to release a mutex at just the precise moment.
|
|
3742
|
+
|
|
3743
|
+
This is a great example of a situation where granular locking and unlocking
|
|
3744
|
+
of the GVL is practically required. The goal is to get as close to the
|
|
3745
|
+
system call as possible, and to keep the GVL unlocked for the shortest
|
|
3746
|
+
amount of time possible.
|
|
3747
|
+
|
|
3748
|
+
Perhaps Ruby could benefit from such an API, e.g:
|
|
3749
|
+
|
|
3750
|
+
rb_thread_unsafe_dangerous_crazy_blocking_region_begin(...);
|
|
3751
|
+
rb_thread_unsafe_dangerous_crazy_blocking_region_end(...);
|
|
3752
|
+
|
|
3753
|
+
#######################################################################
|
|
3754
|
+
*/
|
|
3755
|
+
|
|
3756
|
+
/*
|
|
3757
|
+
simulate to rb_thread_call_without_gvl using rb_theread_blocking_region.
|
|
3758
|
+
https://github.com/brianmario/mysql2/blob/master/ext/mysql2/client.h#L8
|
|
3759
|
+
*/
|
|
3760
|
+
|
|
3761
|
+
#ifndef HAVE_RB_THREAD_CALL_WITHOUT_GVL
|
|
3762
|
+
#ifdef HAVE_RB_THREAD_BLOCKING_REGION
|
|
3763
|
+
#define rb_thread_call_without_gvl(func, data1, ubf, data2) \
|
|
3764
|
+
rb_thread_blocking_region((rb_blocking_function_t *)func, data1, ubf, data2)
|
|
3765
|
+
#endif
|
|
3766
|
+
#endif
|
|
3767
|
+
|
|
3768
|
+
#if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
|
|
3769
|
+
poll_args.loop = loop;
|
|
3770
|
+
poll_args.waittime = waittime;
|
|
3771
|
+
rb_thread_call_without_gvl((void *)ev_backend_poll, (void *)&poll_args, RUBY_UBF_IO, 0);
|
|
3772
|
+
#else
|
|
3773
|
+
backend_poll (EV_A_ waittime);
|
|
3774
|
+
#endif
|
|
3775
|
+
/*
|
|
3776
|
+
############################# END PATCHERY ############################
|
|
3777
|
+
*/
|
|
3778
|
+
|
|
2452
3779
|
assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */
|
|
2453
3780
|
|
|
3781
|
+
pipe_write_wanted = 0; /* just an optimisation, no fence needed */
|
|
3782
|
+
|
|
3783
|
+
ECB_MEMORY_FENCE_ACQUIRE;
|
|
3784
|
+
if (pipe_write_skipped)
|
|
3785
|
+
{
|
|
3786
|
+
assert (("libev: pipe_w not active, but pipe not written", ev_is_active (&pipe_w)));
|
|
3787
|
+
ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);
|
|
3788
|
+
}
|
|
3789
|
+
|
|
3790
|
+
|
|
2454
3791
|
/* update ev_rt_now, do magic */
|
|
2455
3792
|
time_update (EV_A_ waittime + sleeptime);
|
|
2456
3793
|
}
|
|
@@ -2486,40 +3823,42 @@ ev_run (EV_P_ int flags)
|
|
|
2486
3823
|
#if EV_FEATURE_API
|
|
2487
3824
|
--loop_depth;
|
|
2488
3825
|
#endif
|
|
3826
|
+
|
|
3827
|
+
return activecnt;
|
|
2489
3828
|
}
|
|
2490
3829
|
|
|
2491
3830
|
void
|
|
2492
|
-
ev_break (EV_P_ int how)
|
|
3831
|
+
ev_break (EV_P_ int how) EV_THROW
|
|
2493
3832
|
{
|
|
2494
3833
|
loop_done = how;
|
|
2495
3834
|
}
|
|
2496
3835
|
|
|
2497
3836
|
void
|
|
2498
|
-
ev_ref (EV_P)
|
|
3837
|
+
ev_ref (EV_P) EV_THROW
|
|
2499
3838
|
{
|
|
2500
3839
|
++activecnt;
|
|
2501
3840
|
}
|
|
2502
3841
|
|
|
2503
3842
|
void
|
|
2504
|
-
ev_unref (EV_P)
|
|
3843
|
+
ev_unref (EV_P) EV_THROW
|
|
2505
3844
|
{
|
|
2506
3845
|
--activecnt;
|
|
2507
3846
|
}
|
|
2508
3847
|
|
|
2509
3848
|
void
|
|
2510
|
-
ev_now_update (EV_P)
|
|
3849
|
+
ev_now_update (EV_P) EV_THROW
|
|
2511
3850
|
{
|
|
2512
3851
|
time_update (EV_A_ 1e100);
|
|
2513
3852
|
}
|
|
2514
3853
|
|
|
2515
3854
|
void
|
|
2516
|
-
ev_suspend (EV_P)
|
|
3855
|
+
ev_suspend (EV_P) EV_THROW
|
|
2517
3856
|
{
|
|
2518
3857
|
ev_now_update (EV_A);
|
|
2519
3858
|
}
|
|
2520
3859
|
|
|
2521
3860
|
void
|
|
2522
|
-
ev_resume (EV_P)
|
|
3861
|
+
ev_resume (EV_P) EV_THROW
|
|
2523
3862
|
{
|
|
2524
3863
|
ev_tstamp mn_prev = mn_now;
|
|
2525
3864
|
|
|
@@ -2568,7 +3907,7 @@ clear_pending (EV_P_ W w)
|
|
|
2568
3907
|
}
|
|
2569
3908
|
|
|
2570
3909
|
int
|
|
2571
|
-
ev_clear_pending (EV_P_ void *w)
|
|
3910
|
+
ev_clear_pending (EV_P_ void *w) EV_THROW
|
|
2572
3911
|
{
|
|
2573
3912
|
W w_ = (W)w;
|
|
2574
3913
|
int pending = w_->pending;
|
|
@@ -2610,8 +3949,9 @@ ev_stop (EV_P_ W w)
|
|
|
2610
3949
|
|
|
2611
3950
|
/*****************************************************************************/
|
|
2612
3951
|
|
|
2613
|
-
|
|
2614
|
-
|
|
3952
|
+
noinline
|
|
3953
|
+
void
|
|
3954
|
+
ev_io_start (EV_P_ ev_io *w) EV_THROW
|
|
2615
3955
|
{
|
|
2616
3956
|
int fd = w->fd;
|
|
2617
3957
|
|
|
@@ -2627,14 +3967,18 @@ ev_io_start (EV_P_ ev_io *w)
|
|
|
2627
3967
|
array_needsize (ANFD, anfds, anfdmax, fd + 1, array_init_zero);
|
|
2628
3968
|
wlist_add (&anfds[fd].head, (WL)w);
|
|
2629
3969
|
|
|
3970
|
+
/* common bug, apparently */
|
|
3971
|
+
assert (("libev: ev_io_start called with corrupted watcher", ((WL)w)->next != (WL)w));
|
|
3972
|
+
|
|
2630
3973
|
fd_change (EV_A_ fd, w->events & EV__IOFDSET | EV_ANFD_REIFY);
|
|
2631
3974
|
w->events &= ~EV__IOFDSET;
|
|
2632
3975
|
|
|
2633
3976
|
EV_FREQUENT_CHECK;
|
|
2634
3977
|
}
|
|
2635
3978
|
|
|
2636
|
-
|
|
2637
|
-
|
|
3979
|
+
noinline
|
|
3980
|
+
void
|
|
3981
|
+
ev_io_stop (EV_P_ ev_io *w) EV_THROW
|
|
2638
3982
|
{
|
|
2639
3983
|
clear_pending (EV_A_ (W)w);
|
|
2640
3984
|
if (expect_false (!ev_is_active (w)))
|
|
@@ -2652,8 +3996,9 @@ ev_io_stop (EV_P_ ev_io *w)
|
|
|
2652
3996
|
EV_FREQUENT_CHECK;
|
|
2653
3997
|
}
|
|
2654
3998
|
|
|
2655
|
-
|
|
2656
|
-
|
|
3999
|
+
noinline
|
|
4000
|
+
void
|
|
4001
|
+
ev_timer_start (EV_P_ ev_timer *w) EV_THROW
|
|
2657
4002
|
{
|
|
2658
4003
|
if (expect_false (ev_is_active (w)))
|
|
2659
4004
|
return;
|
|
@@ -2676,8 +4021,9 @@ ev_timer_start (EV_P_ ev_timer *w)
|
|
|
2676
4021
|
/*assert (("libev: internal timer heap corruption", timers [ev_active (w)] == (WT)w));*/
|
|
2677
4022
|
}
|
|
2678
4023
|
|
|
2679
|
-
|
|
2680
|
-
|
|
4024
|
+
noinline
|
|
4025
|
+
void
|
|
4026
|
+
ev_timer_stop (EV_P_ ev_timer *w) EV_THROW
|
|
2681
4027
|
{
|
|
2682
4028
|
clear_pending (EV_A_ (W)w);
|
|
2683
4029
|
if (expect_false (!ev_is_active (w)))
|
|
@@ -2706,11 +4052,14 @@ ev_timer_stop (EV_P_ ev_timer *w)
|
|
|
2706
4052
|
EV_FREQUENT_CHECK;
|
|
2707
4053
|
}
|
|
2708
4054
|
|
|
2709
|
-
|
|
2710
|
-
|
|
4055
|
+
noinline
|
|
4056
|
+
void
|
|
4057
|
+
ev_timer_again (EV_P_ ev_timer *w) EV_THROW
|
|
2711
4058
|
{
|
|
2712
4059
|
EV_FREQUENT_CHECK;
|
|
2713
4060
|
|
|
4061
|
+
clear_pending (EV_A_ (W)w);
|
|
4062
|
+
|
|
2714
4063
|
if (ev_is_active (w))
|
|
2715
4064
|
{
|
|
2716
4065
|
if (w->repeat)
|
|
@@ -2732,14 +4081,15 @@ ev_timer_again (EV_P_ ev_timer *w)
|
|
|
2732
4081
|
}
|
|
2733
4082
|
|
|
2734
4083
|
ev_tstamp
|
|
2735
|
-
ev_timer_remaining (EV_P_ ev_timer *w)
|
|
4084
|
+
ev_timer_remaining (EV_P_ ev_timer *w) EV_THROW
|
|
2736
4085
|
{
|
|
2737
4086
|
return ev_at (w) - (ev_is_active (w) ? mn_now : 0.);
|
|
2738
4087
|
}
|
|
2739
4088
|
|
|
2740
4089
|
#if EV_PERIODIC_ENABLE
|
|
2741
|
-
|
|
2742
|
-
|
|
4090
|
+
noinline
|
|
4091
|
+
void
|
|
4092
|
+
ev_periodic_start (EV_P_ ev_periodic *w) EV_THROW
|
|
2743
4093
|
{
|
|
2744
4094
|
if (expect_false (ev_is_active (w)))
|
|
2745
4095
|
return;
|
|
@@ -2749,8 +4099,7 @@ ev_periodic_start (EV_P_ ev_periodic *w)
|
|
|
2749
4099
|
else if (w->interval)
|
|
2750
4100
|
{
|
|
2751
4101
|
assert (("libev: ev_periodic_start called with negative interval value", w->interval >= 0.));
|
|
2752
|
-
|
|
2753
|
-
ev_at (w) = w->offset + ceil ((ev_rt_now - w->offset) / w->interval) * w->interval;
|
|
4102
|
+
periodic_recalc (EV_A_ w);
|
|
2754
4103
|
}
|
|
2755
4104
|
else
|
|
2756
4105
|
ev_at (w) = w->offset;
|
|
@@ -2769,8 +4118,9 @@ ev_periodic_start (EV_P_ ev_periodic *w)
|
|
|
2769
4118
|
/*assert (("libev: internal periodic heap corruption", ANHE_w (periodics [ev_active (w)]) == (WT)w));*/
|
|
2770
4119
|
}
|
|
2771
4120
|
|
|
2772
|
-
|
|
2773
|
-
|
|
4121
|
+
noinline
|
|
4122
|
+
void
|
|
4123
|
+
ev_periodic_stop (EV_P_ ev_periodic *w) EV_THROW
|
|
2774
4124
|
{
|
|
2775
4125
|
clear_pending (EV_A_ (W)w);
|
|
2776
4126
|
if (expect_false (!ev_is_active (w)))
|
|
@@ -2797,8 +4147,9 @@ ev_periodic_stop (EV_P_ ev_periodic *w)
|
|
|
2797
4147
|
EV_FREQUENT_CHECK;
|
|
2798
4148
|
}
|
|
2799
4149
|
|
|
2800
|
-
|
|
2801
|
-
|
|
4150
|
+
noinline
|
|
4151
|
+
void
|
|
4152
|
+
ev_periodic_again (EV_P_ ev_periodic *w) EV_THROW
|
|
2802
4153
|
{
|
|
2803
4154
|
/* TODO: use adjustheap and recalculation */
|
|
2804
4155
|
ev_periodic_stop (EV_A_ w);
|
|
@@ -2812,8 +4163,9 @@ ev_periodic_again (EV_P_ ev_periodic *w)
|
|
|
2812
4163
|
|
|
2813
4164
|
#if EV_SIGNAL_ENABLE
|
|
2814
4165
|
|
|
2815
|
-
|
|
2816
|
-
|
|
4166
|
+
noinline
|
|
4167
|
+
void
|
|
4168
|
+
ev_signal_start (EV_P_ ev_signal *w) EV_THROW
|
|
2817
4169
|
{
|
|
2818
4170
|
if (expect_false (ev_is_active (w)))
|
|
2819
4171
|
return;
|
|
@@ -2825,6 +4177,7 @@ ev_signal_start (EV_P_ ev_signal *w)
|
|
|
2825
4177
|
!signals [w->signum - 1].loop || signals [w->signum - 1].loop == loop));
|
|
2826
4178
|
|
|
2827
4179
|
signals [w->signum - 1].loop = EV_A;
|
|
4180
|
+
ECB_MEMORY_FENCE_RELEASE;
|
|
2828
4181
|
#endif
|
|
2829
4182
|
|
|
2830
4183
|
EV_FREQUENT_CHECK;
|
|
@@ -2881,17 +4234,21 @@ ev_signal_start (EV_P_ ev_signal *w)
|
|
|
2881
4234
|
sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */
|
|
2882
4235
|
sigaction (w->signum, &sa, 0);
|
|
2883
4236
|
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
4237
|
+
if (origflags & EVFLAG_NOSIGMASK)
|
|
4238
|
+
{
|
|
4239
|
+
sigemptyset (&sa.sa_mask);
|
|
4240
|
+
sigaddset (&sa.sa_mask, w->signum);
|
|
4241
|
+
sigprocmask (SIG_UNBLOCK, &sa.sa_mask, 0);
|
|
4242
|
+
}
|
|
2887
4243
|
#endif
|
|
2888
4244
|
}
|
|
2889
4245
|
|
|
2890
4246
|
EV_FREQUENT_CHECK;
|
|
2891
4247
|
}
|
|
2892
4248
|
|
|
2893
|
-
|
|
2894
|
-
|
|
4249
|
+
noinline
|
|
4250
|
+
void
|
|
4251
|
+
ev_signal_stop (EV_P_ ev_signal *w) EV_THROW
|
|
2895
4252
|
{
|
|
2896
4253
|
clear_pending (EV_A_ (W)w);
|
|
2897
4254
|
if (expect_false (!ev_is_active (w)))
|
|
@@ -2932,7 +4289,7 @@ ev_signal_stop (EV_P_ ev_signal *w)
|
|
|
2932
4289
|
#if EV_CHILD_ENABLE
|
|
2933
4290
|
|
|
2934
4291
|
void
|
|
2935
|
-
ev_child_start (EV_P_ ev_child *w)
|
|
4292
|
+
ev_child_start (EV_P_ ev_child *w) EV_THROW
|
|
2936
4293
|
{
|
|
2937
4294
|
#if EV_MULTIPLICITY
|
|
2938
4295
|
assert (("libev: child watchers are only supported in the default loop", loop == ev_default_loop_ptr));
|
|
@@ -2949,7 +4306,7 @@ ev_child_start (EV_P_ ev_child *w)
|
|
|
2949
4306
|
}
|
|
2950
4307
|
|
|
2951
4308
|
void
|
|
2952
|
-
ev_child_stop (EV_P_ ev_child *w)
|
|
4309
|
+
ev_child_stop (EV_P_ ev_child *w) EV_THROW
|
|
2953
4310
|
{
|
|
2954
4311
|
clear_pending (EV_A_ (W)w);
|
|
2955
4312
|
if (expect_false (!ev_is_active (w)))
|
|
@@ -2976,17 +4333,21 @@ ev_child_stop (EV_P_ ev_child *w)
|
|
|
2976
4333
|
#define NFS_STAT_INTERVAL 30.1074891 /* for filesystems potentially failing inotify */
|
|
2977
4334
|
#define MIN_STAT_INTERVAL 0.1074891
|
|
2978
4335
|
|
|
2979
|
-
static void
|
|
4336
|
+
noinline static void stat_timer_cb (EV_P_ ev_timer *w_, int revents);
|
|
2980
4337
|
|
|
2981
4338
|
#if EV_USE_INOTIFY
|
|
2982
4339
|
|
|
2983
4340
|
/* the * 2 is to allow for alignment padding, which for some reason is >> 8 */
|
|
2984
4341
|
# define EV_INOTIFY_BUFSIZE (sizeof (struct inotify_event) * 2 + NAME_MAX)
|
|
2985
4342
|
|
|
2986
|
-
|
|
4343
|
+
noinline
|
|
4344
|
+
static void
|
|
2987
4345
|
infy_add (EV_P_ ev_stat *w)
|
|
2988
4346
|
{
|
|
2989
|
-
w->wd = inotify_add_watch (fs_fd, w->path,
|
|
4347
|
+
w->wd = inotify_add_watch (fs_fd, w->path,
|
|
4348
|
+
IN_ATTRIB | IN_DELETE_SELF | IN_MOVE_SELF | IN_MODIFY
|
|
4349
|
+
| IN_CREATE | IN_DELETE | IN_MOVED_FROM | IN_MOVED_TO
|
|
4350
|
+
| IN_DONT_FOLLOW | IN_MASK_ADD);
|
|
2990
4351
|
|
|
2991
4352
|
if (w->wd >= 0)
|
|
2992
4353
|
{
|
|
@@ -3000,10 +4361,16 @@ infy_add (EV_P_ ev_stat *w)
|
|
|
3000
4361
|
w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL;
|
|
3001
4362
|
else if (!statfs (w->path, &sfs)
|
|
3002
4363
|
&& (sfs.f_type == 0x1373 /* devfs */
|
|
4364
|
+
|| sfs.f_type == 0x4006 /* fat */
|
|
4365
|
+
|| sfs.f_type == 0x4d44 /* msdos */
|
|
3003
4366
|
|| sfs.f_type == 0xEF53 /* ext2/3 */
|
|
4367
|
+
|| sfs.f_type == 0x72b6 /* jffs2 */
|
|
4368
|
+
|| sfs.f_type == 0x858458f6 /* ramfs */
|
|
4369
|
+
|| sfs.f_type == 0x5346544e /* ntfs */
|
|
3004
4370
|
|| sfs.f_type == 0x3153464a /* jfs */
|
|
4371
|
+
|| sfs.f_type == 0x9123683e /* btrfs */
|
|
3005
4372
|
|| sfs.f_type == 0x52654973 /* reiser3 */
|
|
3006
|
-
|| sfs.f_type == 0x01021994 /*
|
|
4373
|
+
|| sfs.f_type == 0x01021994 /* tmpfs */
|
|
3007
4374
|
|| sfs.f_type == 0x58465342 /* xfs */))
|
|
3008
4375
|
w->timer.repeat = 0.; /* filesystem is local, kernel new enough */
|
|
3009
4376
|
else
|
|
@@ -3034,7 +4401,7 @@ infy_add (EV_P_ ev_stat *w)
|
|
|
3034
4401
|
|
|
3035
4402
|
*pend = 0;
|
|
3036
4403
|
w->wd = inotify_add_watch (fs_fd, path, mask);
|
|
3037
|
-
}
|
|
4404
|
+
}
|
|
3038
4405
|
while (w->wd < 0 && (errno == ENOENT || errno == EACCES));
|
|
3039
4406
|
}
|
|
3040
4407
|
}
|
|
@@ -3048,7 +4415,8 @@ infy_add (EV_P_ ev_stat *w)
|
|
|
3048
4415
|
if (ev_is_active (&w->timer)) ev_unref (EV_A);
|
|
3049
4416
|
}
|
|
3050
4417
|
|
|
3051
|
-
|
|
4418
|
+
noinline
|
|
4419
|
+
static void
|
|
3052
4420
|
infy_del (EV_P_ ev_stat *w)
|
|
3053
4421
|
{
|
|
3054
4422
|
int slot;
|
|
@@ -3065,7 +4433,8 @@ infy_del (EV_P_ ev_stat *w)
|
|
|
3065
4433
|
inotify_rm_watch (fs_fd, wd);
|
|
3066
4434
|
}
|
|
3067
4435
|
|
|
3068
|
-
|
|
4436
|
+
noinline
|
|
4437
|
+
static void
|
|
3069
4438
|
infy_wd (EV_P_ int slot, int wd, struct inotify_event *ev)
|
|
3070
4439
|
{
|
|
3071
4440
|
if (slot < 0)
|
|
@@ -3111,7 +4480,8 @@ infy_cb (EV_P_ ev_io *w, int revents)
|
|
|
3111
4480
|
}
|
|
3112
4481
|
}
|
|
3113
4482
|
|
|
3114
|
-
inline_size
|
|
4483
|
+
inline_size ecb_cold
|
|
4484
|
+
void
|
|
3115
4485
|
ev_check_2625 (EV_P)
|
|
3116
4486
|
{
|
|
3117
4487
|
/* kernels < 2.6.25 are borked
|
|
@@ -3126,7 +4496,7 @@ ev_check_2625 (EV_P)
|
|
|
3126
4496
|
inline_size int
|
|
3127
4497
|
infy_newfd (void)
|
|
3128
4498
|
{
|
|
3129
|
-
#if defined
|
|
4499
|
+
#if defined IN_CLOEXEC && defined IN_NONBLOCK
|
|
3130
4500
|
int fd = inotify_init1 (IN_CLOEXEC | IN_NONBLOCK);
|
|
3131
4501
|
if (fd >= 0)
|
|
3132
4502
|
return fd;
|
|
@@ -3211,7 +4581,7 @@ infy_fork (EV_P)
|
|
|
3211
4581
|
#endif
|
|
3212
4582
|
|
|
3213
4583
|
void
|
|
3214
|
-
ev_stat_stat (EV_P_ ev_stat *w)
|
|
4584
|
+
ev_stat_stat (EV_P_ ev_stat *w) EV_THROW
|
|
3215
4585
|
{
|
|
3216
4586
|
if (lstat (w->path, &w->attr) < 0)
|
|
3217
4587
|
w->attr.st_nlink = 0;
|
|
@@ -3219,7 +4589,8 @@ ev_stat_stat (EV_P_ ev_stat *w)
|
|
|
3219
4589
|
w->attr.st_nlink = 1;
|
|
3220
4590
|
}
|
|
3221
4591
|
|
|
3222
|
-
|
|
4592
|
+
noinline
|
|
4593
|
+
static void
|
|
3223
4594
|
stat_timer_cb (EV_P_ ev_timer *w_, int revents)
|
|
3224
4595
|
{
|
|
3225
4596
|
ev_stat *w = (ev_stat *)(((char *)w_) - offsetof (ev_stat, timer));
|
|
@@ -3260,7 +4631,7 @@ stat_timer_cb (EV_P_ ev_timer *w_, int revents)
|
|
|
3260
4631
|
}
|
|
3261
4632
|
|
|
3262
4633
|
void
|
|
3263
|
-
ev_stat_start (EV_P_ ev_stat *w)
|
|
4634
|
+
ev_stat_start (EV_P_ ev_stat *w) EV_THROW
|
|
3264
4635
|
{
|
|
3265
4636
|
if (expect_false (ev_is_active (w)))
|
|
3266
4637
|
return;
|
|
@@ -3291,7 +4662,7 @@ ev_stat_start (EV_P_ ev_stat *w)
|
|
|
3291
4662
|
}
|
|
3292
4663
|
|
|
3293
4664
|
void
|
|
3294
|
-
ev_stat_stop (EV_P_ ev_stat *w)
|
|
4665
|
+
ev_stat_stop (EV_P_ ev_stat *w) EV_THROW
|
|
3295
4666
|
{
|
|
3296
4667
|
clear_pending (EV_A_ (W)w);
|
|
3297
4668
|
if (expect_false (!ev_is_active (w)))
|
|
@@ -3317,7 +4688,7 @@ ev_stat_stop (EV_P_ ev_stat *w)
|
|
|
3317
4688
|
|
|
3318
4689
|
#if EV_IDLE_ENABLE
|
|
3319
4690
|
void
|
|
3320
|
-
ev_idle_start (EV_P_ ev_idle *w)
|
|
4691
|
+
ev_idle_start (EV_P_ ev_idle *w) EV_THROW
|
|
3321
4692
|
{
|
|
3322
4693
|
if (expect_false (ev_is_active (w)))
|
|
3323
4694
|
return;
|
|
@@ -3340,7 +4711,7 @@ ev_idle_start (EV_P_ ev_idle *w)
|
|
|
3340
4711
|
}
|
|
3341
4712
|
|
|
3342
4713
|
void
|
|
3343
|
-
ev_idle_stop (EV_P_ ev_idle *w)
|
|
4714
|
+
ev_idle_stop (EV_P_ ev_idle *w) EV_THROW
|
|
3344
4715
|
{
|
|
3345
4716
|
clear_pending (EV_A_ (W)w);
|
|
3346
4717
|
if (expect_false (!ev_is_active (w)))
|
|
@@ -3364,7 +4735,7 @@ ev_idle_stop (EV_P_ ev_idle *w)
|
|
|
3364
4735
|
|
|
3365
4736
|
#if EV_PREPARE_ENABLE
|
|
3366
4737
|
void
|
|
3367
|
-
ev_prepare_start (EV_P_ ev_prepare *w)
|
|
4738
|
+
ev_prepare_start (EV_P_ ev_prepare *w) EV_THROW
|
|
3368
4739
|
{
|
|
3369
4740
|
if (expect_false (ev_is_active (w)))
|
|
3370
4741
|
return;
|
|
@@ -3379,7 +4750,7 @@ ev_prepare_start (EV_P_ ev_prepare *w)
|
|
|
3379
4750
|
}
|
|
3380
4751
|
|
|
3381
4752
|
void
|
|
3382
|
-
ev_prepare_stop (EV_P_ ev_prepare *w)
|
|
4753
|
+
ev_prepare_stop (EV_P_ ev_prepare *w) EV_THROW
|
|
3383
4754
|
{
|
|
3384
4755
|
clear_pending (EV_A_ (W)w);
|
|
3385
4756
|
if (expect_false (!ev_is_active (w)))
|
|
@@ -3402,7 +4773,7 @@ ev_prepare_stop (EV_P_ ev_prepare *w)
|
|
|
3402
4773
|
|
|
3403
4774
|
#if EV_CHECK_ENABLE
|
|
3404
4775
|
void
|
|
3405
|
-
ev_check_start (EV_P_ ev_check *w)
|
|
4776
|
+
ev_check_start (EV_P_ ev_check *w) EV_THROW
|
|
3406
4777
|
{
|
|
3407
4778
|
if (expect_false (ev_is_active (w)))
|
|
3408
4779
|
return;
|
|
@@ -3417,7 +4788,7 @@ ev_check_start (EV_P_ ev_check *w)
|
|
|
3417
4788
|
}
|
|
3418
4789
|
|
|
3419
4790
|
void
|
|
3420
|
-
ev_check_stop (EV_P_ ev_check *w)
|
|
4791
|
+
ev_check_stop (EV_P_ ev_check *w) EV_THROW
|
|
3421
4792
|
{
|
|
3422
4793
|
clear_pending (EV_A_ (W)w);
|
|
3423
4794
|
if (expect_false (!ev_is_active (w)))
|
|
@@ -3439,8 +4810,9 @@ ev_check_stop (EV_P_ ev_check *w)
|
|
|
3439
4810
|
#endif
|
|
3440
4811
|
|
|
3441
4812
|
#if EV_EMBED_ENABLE
|
|
3442
|
-
|
|
3443
|
-
|
|
4813
|
+
noinline
|
|
4814
|
+
void
|
|
4815
|
+
ev_embed_sweep (EV_P_ ev_embed *w) EV_THROW
|
|
3444
4816
|
{
|
|
3445
4817
|
ev_run (w->other, EVRUN_NOWAIT);
|
|
3446
4818
|
}
|
|
@@ -3498,7 +4870,7 @@ embed_idle_cb (EV_P_ ev_idle *idle, int revents)
|
|
|
3498
4870
|
#endif
|
|
3499
4871
|
|
|
3500
4872
|
void
|
|
3501
|
-
ev_embed_start (EV_P_ ev_embed *w)
|
|
4873
|
+
ev_embed_start (EV_P_ ev_embed *w) EV_THROW
|
|
3502
4874
|
{
|
|
3503
4875
|
if (expect_false (ev_is_active (w)))
|
|
3504
4876
|
return;
|
|
@@ -3529,7 +4901,7 @@ ev_embed_start (EV_P_ ev_embed *w)
|
|
|
3529
4901
|
}
|
|
3530
4902
|
|
|
3531
4903
|
void
|
|
3532
|
-
ev_embed_stop (EV_P_ ev_embed *w)
|
|
4904
|
+
ev_embed_stop (EV_P_ ev_embed *w) EV_THROW
|
|
3533
4905
|
{
|
|
3534
4906
|
clear_pending (EV_A_ (W)w);
|
|
3535
4907
|
if (expect_false (!ev_is_active (w)))
|
|
@@ -3549,7 +4921,7 @@ ev_embed_stop (EV_P_ ev_embed *w)
|
|
|
3549
4921
|
|
|
3550
4922
|
#if EV_FORK_ENABLE
|
|
3551
4923
|
void
|
|
3552
|
-
ev_fork_start (EV_P_ ev_fork *w)
|
|
4924
|
+
ev_fork_start (EV_P_ ev_fork *w) EV_THROW
|
|
3553
4925
|
{
|
|
3554
4926
|
if (expect_false (ev_is_active (w)))
|
|
3555
4927
|
return;
|
|
@@ -3564,7 +4936,7 @@ ev_fork_start (EV_P_ ev_fork *w)
|
|
|
3564
4936
|
}
|
|
3565
4937
|
|
|
3566
4938
|
void
|
|
3567
|
-
ev_fork_stop (EV_P_ ev_fork *w)
|
|
4939
|
+
ev_fork_stop (EV_P_ ev_fork *w) EV_THROW
|
|
3568
4940
|
{
|
|
3569
4941
|
clear_pending (EV_A_ (W)w);
|
|
3570
4942
|
if (expect_false (!ev_is_active (w)))
|
|
@@ -3587,7 +4959,7 @@ ev_fork_stop (EV_P_ ev_fork *w)
|
|
|
3587
4959
|
|
|
3588
4960
|
#if EV_CLEANUP_ENABLE
|
|
3589
4961
|
void
|
|
3590
|
-
ev_cleanup_start (EV_P_ ev_cleanup *w)
|
|
4962
|
+
ev_cleanup_start (EV_P_ ev_cleanup *w) EV_THROW
|
|
3591
4963
|
{
|
|
3592
4964
|
if (expect_false (ev_is_active (w)))
|
|
3593
4965
|
return;
|
|
@@ -3604,7 +4976,7 @@ ev_cleanup_start (EV_P_ ev_cleanup *w)
|
|
|
3604
4976
|
}
|
|
3605
4977
|
|
|
3606
4978
|
void
|
|
3607
|
-
ev_cleanup_stop (EV_P_ ev_cleanup *w)
|
|
4979
|
+
ev_cleanup_stop (EV_P_ ev_cleanup *w) EV_THROW
|
|
3608
4980
|
{
|
|
3609
4981
|
clear_pending (EV_A_ (W)w);
|
|
3610
4982
|
if (expect_false (!ev_is_active (w)))
|
|
@@ -3628,7 +5000,7 @@ ev_cleanup_stop (EV_P_ ev_cleanup *w)
|
|
|
3628
5000
|
|
|
3629
5001
|
#if EV_ASYNC_ENABLE
|
|
3630
5002
|
void
|
|
3631
|
-
ev_async_start (EV_P_ ev_async *w)
|
|
5003
|
+
ev_async_start (EV_P_ ev_async *w) EV_THROW
|
|
3632
5004
|
{
|
|
3633
5005
|
if (expect_false (ev_is_active (w)))
|
|
3634
5006
|
return;
|
|
@@ -3647,7 +5019,7 @@ ev_async_start (EV_P_ ev_async *w)
|
|
|
3647
5019
|
}
|
|
3648
5020
|
|
|
3649
5021
|
void
|
|
3650
|
-
ev_async_stop (EV_P_ ev_async *w)
|
|
5022
|
+
ev_async_stop (EV_P_ ev_async *w) EV_THROW
|
|
3651
5023
|
{
|
|
3652
5024
|
clear_pending (EV_A_ (W)w);
|
|
3653
5025
|
if (expect_false (!ev_is_active (w)))
|
|
@@ -3668,7 +5040,7 @@ ev_async_stop (EV_P_ ev_async *w)
|
|
|
3668
5040
|
}
|
|
3669
5041
|
|
|
3670
5042
|
void
|
|
3671
|
-
ev_async_send (EV_P_ ev_async *w)
|
|
5043
|
+
ev_async_send (EV_P_ ev_async *w) EV_THROW
|
|
3672
5044
|
{
|
|
3673
5045
|
w->sent = 1;
|
|
3674
5046
|
evpipe_write (EV_A_ &async_pending);
|
|
@@ -3715,7 +5087,7 @@ once_cb_to (EV_P_ ev_timer *w, int revents)
|
|
|
3715
5087
|
}
|
|
3716
5088
|
|
|
3717
5089
|
void
|
|
3718
|
-
ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg)
|
|
5090
|
+
ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) EV_THROW
|
|
3719
5091
|
{
|
|
3720
5092
|
struct ev_once *once = (struct ev_once *)ev_malloc (sizeof (struct ev_once));
|
|
3721
5093
|
|
|
@@ -3746,8 +5118,9 @@ ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, vo
|
|
|
3746
5118
|
/*****************************************************************************/
|
|
3747
5119
|
|
|
3748
5120
|
#if EV_WALK_ENABLE
|
|
5121
|
+
ecb_cold
|
|
3749
5122
|
void
|
|
3750
|
-
ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
|
|
5123
|
+
ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) EV_THROW
|
|
3751
5124
|
{
|
|
3752
5125
|
int i, j;
|
|
3753
5126
|
ev_watcher_list *wl, *wn;
|
|
@@ -3800,7 +5173,7 @@ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
|
|
|
3800
5173
|
|
|
3801
5174
|
#if EV_IDLE_ENABLE
|
|
3802
5175
|
if (types & EV_IDLE)
|
|
3803
|
-
for (j = NUMPRI;
|
|
5176
|
+
for (j = NUMPRI; j--; )
|
|
3804
5177
|
for (i = idlecnt [j]; i--; )
|
|
3805
5178
|
cb (EV_A_ EV_IDLE, idles [j][i]);
|
|
3806
5179
|
#endif
|
|
@@ -3863,5 +5236,3 @@ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
|
|
|
3863
5236
|
#include "ev_wrap.h"
|
|
3864
5237
|
#endif
|
|
3865
5238
|
|
|
3866
|
-
EV_CPP(})
|
|
3867
|
-
|