nio4r 0.2.0 → 2.7.5
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
- checksums.yaml.gz.sig +0 -0
- data/ext/libev/Changes +232 -3
- data/ext/libev/LICENSE +2 -1
- data/ext/libev/README +11 -10
- data/ext/libev/ev.c +2249 -473
- data/ext/libev/ev.h +165 -135
- data/ext/libev/ev_epoll.c +68 -36
- data/ext/libev/ev_iouring.c +694 -0
- data/ext/libev/ev_kqueue.c +44 -18
- data/ext/libev/ev_linuxaio.c +620 -0
- data/ext/libev/ev_poll.c +28 -20
- data/ext/libev/ev_port.c +23 -10
- data/ext/libev/ev_select.c +18 -12
- data/ext/libev/ev_vars.h +65 -19
- data/ext/libev/ev_win32.c +16 -7
- data/ext/libev/ev_wrap.h +236 -160
- data/ext/nio4r/.clang-format +16 -0
- data/ext/nio4r/bytebuffer.c +465 -0
- data/ext/nio4r/extconf.rb +44 -35
- data/ext/nio4r/libev.h +3 -4
- data/ext/nio4r/monitor.c +186 -54
- data/ext/nio4r/nio4r.h +17 -23
- data/ext/nio4r/nio4r_ext.c +11 -3
- data/ext/nio4r/org/nio4r/ByteBuffer.java +295 -0
- data/ext/nio4r/org/nio4r/Monitor.java +176 -0
- data/ext/nio4r/org/nio4r/Nio4r.java +104 -0
- data/ext/nio4r/org/nio4r/Selector.java +297 -0
- data/ext/nio4r/selector.c +350 -182
- data/lib/nio/bytebuffer.rb +235 -0
- data/lib/nio/monitor.rb +100 -8
- data/lib/nio/selector.rb +110 -44
- data/lib/nio/version.rb +8 -1
- data/lib/nio.rb +47 -16
- data/lib/nio4r.rb +7 -0
- data/license.md +80 -0
- data/readme.md +91 -0
- data/releases.md +343 -0
- data.tar.gz.sig +2 -0
- metadata +114 -79
- metadata.gz.sig +0 -0
- data/.gitignore +0 -20
- data/.rspec +0 -4
- data/.travis.yml +0 -7
- data/CHANGES.md +0 -10
- data/Gemfile +0 -4
- data/LICENSE.txt +0 -20
- data/README.md +0 -171
- data/Rakefile +0 -9
- data/examples/echo_server.rb +0 -38
- data/ext/libev/README.embed +0 -3
- data/ext/libev/test_libev_win32.c +0 -123
- data/lib/nio/jruby/monitor.rb +0 -42
- data/lib/nio/jruby/selector.rb +0 -135
- data/nio4r.gemspec +0 -22
- data/spec/nio/monitor_spec.rb +0 -46
- data/spec/nio/selector_spec.rb +0 -269
- data/spec/spec_helper.rb +0 -3
- data/tasks/extension.rake +0 -10
- data/tasks/rspec.rake +0 -7
data/ext/libev/ev.c
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* libev event processing core, watcher management
|
|
3
3
|
*
|
|
4
|
-
* Copyright (c) 2007
|
|
4
|
+
* Copyright (c) 2007-2019 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-
|
|
@@ -37,6 +37,15 @@
|
|
|
37
37
|
* either the BSD or the GPL.
|
|
38
38
|
*/
|
|
39
39
|
|
|
40
|
+
/* ########## NIO4R PATCHERY HO! ########## */
|
|
41
|
+
#include "ruby.h"
|
|
42
|
+
#include "ruby/thread.h"
|
|
43
|
+
|
|
44
|
+
#ifdef __APPLE__
|
|
45
|
+
#include <AvailabilityMacros.h>
|
|
46
|
+
#endif
|
|
47
|
+
/* ######################################## */
|
|
48
|
+
|
|
40
49
|
/* this big block deduces configuration from config.h */
|
|
41
50
|
#ifndef EV_STANDALONE
|
|
42
51
|
# ifdef EV_CONFIG_H
|
|
@@ -45,6 +54,12 @@
|
|
|
45
54
|
# include "config.h"
|
|
46
55
|
# endif
|
|
47
56
|
|
|
57
|
+
# if HAVE_FLOOR
|
|
58
|
+
# ifndef EV_USE_FLOOR
|
|
59
|
+
# define EV_USE_FLOOR 1
|
|
60
|
+
# endif
|
|
61
|
+
# endif
|
|
62
|
+
|
|
48
63
|
# if HAVE_CLOCK_SYSCALL
|
|
49
64
|
# ifndef EV_USE_CLOCK_SYSCALL
|
|
50
65
|
# define EV_USE_CLOCK_SYSCALL 1
|
|
@@ -55,7 +70,7 @@
|
|
|
55
70
|
# define EV_USE_MONOTONIC 1
|
|
56
71
|
# endif
|
|
57
72
|
# endif
|
|
58
|
-
# elif !defined
|
|
73
|
+
# elif !defined EV_USE_CLOCK_SYSCALL
|
|
59
74
|
# define EV_USE_CLOCK_SYSCALL 0
|
|
60
75
|
# endif
|
|
61
76
|
|
|
@@ -111,6 +126,24 @@
|
|
|
111
126
|
# define EV_USE_EPOLL 0
|
|
112
127
|
# endif
|
|
113
128
|
|
|
129
|
+
# if HAVE_LINUX_AIO_ABI_H
|
|
130
|
+
# ifndef EV_USE_LINUXAIO
|
|
131
|
+
# define EV_USE_LINUXAIO 0 /* was: EV_FEATURE_BACKENDS, always off by default */
|
|
132
|
+
# endif
|
|
133
|
+
# else
|
|
134
|
+
# undef EV_USE_LINUXAIO
|
|
135
|
+
# define EV_USE_LINUXAIO 0
|
|
136
|
+
# endif
|
|
137
|
+
|
|
138
|
+
# if HAVE_LINUX_FS_H && HAVE_SYS_TIMERFD_H && HAVE_KERNEL_RWF_T
|
|
139
|
+
# ifndef EV_USE_IOURING
|
|
140
|
+
# define EV_USE_IOURING EV_FEATURE_BACKENDS
|
|
141
|
+
# endif
|
|
142
|
+
# else
|
|
143
|
+
# undef EV_USE_IOURING
|
|
144
|
+
# define EV_USE_IOURING 0
|
|
145
|
+
# endif
|
|
146
|
+
|
|
114
147
|
# if HAVE_KQUEUE && HAVE_SYS_EVENT_H
|
|
115
148
|
# ifndef EV_USE_KQUEUE
|
|
116
149
|
# define EV_USE_KQUEUE EV_FEATURE_BACKENDS
|
|
@@ -156,9 +189,27 @@
|
|
|
156
189
|
# define EV_USE_EVENTFD 0
|
|
157
190
|
# endif
|
|
158
191
|
|
|
192
|
+
# if HAVE_SYS_TIMERFD_H
|
|
193
|
+
# ifndef EV_USE_TIMERFD
|
|
194
|
+
# define EV_USE_TIMERFD EV_FEATURE_OS
|
|
195
|
+
# endif
|
|
196
|
+
# else
|
|
197
|
+
# undef EV_USE_TIMERFD
|
|
198
|
+
# define EV_USE_TIMERFD 0
|
|
199
|
+
# endif
|
|
200
|
+
|
|
159
201
|
#endif
|
|
160
202
|
|
|
161
|
-
|
|
203
|
+
/* OS X, in its infinite idiocy, actually HARDCODES
|
|
204
|
+
* a limit of 1024 into their select. Where people have brains,
|
|
205
|
+
* OS X engineers apparently have a vacuum. Or maybe they were
|
|
206
|
+
* ordered to have a vacuum, or they do anything for money.
|
|
207
|
+
* This might help. Or not.
|
|
208
|
+
* Note that this must be defined early, as other include files
|
|
209
|
+
* will rely on this define as well.
|
|
210
|
+
*/
|
|
211
|
+
#define _DARWIN_UNLIMITED_SELECT 1
|
|
212
|
+
|
|
162
213
|
#include <stdlib.h>
|
|
163
214
|
#include <string.h>
|
|
164
215
|
#include <fcntl.h>
|
|
@@ -180,7 +231,16 @@
|
|
|
180
231
|
# include "ev.h"
|
|
181
232
|
#endif
|
|
182
233
|
|
|
183
|
-
|
|
234
|
+
#if EV_NO_THREADS
|
|
235
|
+
# undef EV_NO_SMP
|
|
236
|
+
# define EV_NO_SMP 1
|
|
237
|
+
# undef ECB_NO_THREADS
|
|
238
|
+
# define ECB_NO_THREADS 1
|
|
239
|
+
#endif
|
|
240
|
+
#if EV_NO_SMP
|
|
241
|
+
# undef EV_NO_SMP
|
|
242
|
+
# define ECB_NO_SMP 1
|
|
243
|
+
#endif
|
|
184
244
|
|
|
185
245
|
#ifndef _WIN32
|
|
186
246
|
# include <sys/time.h>
|
|
@@ -189,6 +249,7 @@ EV_CPP(extern "C" {)
|
|
|
189
249
|
#else
|
|
190
250
|
# include <io.h>
|
|
191
251
|
# define WIN32_LEAN_AND_MEAN
|
|
252
|
+
# include <winsock2.h>
|
|
192
253
|
# include <windows.h>
|
|
193
254
|
# ifndef EV_SELECT_IS_WINSOCKET
|
|
194
255
|
# define EV_SELECT_IS_WINSOCKET 1
|
|
@@ -196,54 +257,56 @@ EV_CPP(extern "C" {)
|
|
|
196
257
|
# undef EV_AVOID_STDIO
|
|
197
258
|
#endif
|
|
198
259
|
|
|
199
|
-
/* OS X, in its infinite idiocy, actually HARDCODES
|
|
200
|
-
* a limit of 1024 into their select. Where people have brains,
|
|
201
|
-
* OS X engineers apparently have a vacuum. Or maybe they were
|
|
202
|
-
* ordered to have a vacuum, or they do anything for money.
|
|
203
|
-
* This might help. Or not.
|
|
204
|
-
*/
|
|
205
|
-
#define _DARWIN_UNLIMITED_SELECT 1
|
|
206
|
-
|
|
207
260
|
/* this block tries to deduce configuration from header-defined symbols and defaults */
|
|
208
261
|
|
|
209
262
|
/* try to deduce the maximum number of signals on this platform */
|
|
210
|
-
#if defined
|
|
263
|
+
#if defined EV_NSIG
|
|
211
264
|
/* use what's provided */
|
|
212
|
-
#elif defined
|
|
265
|
+
#elif defined NSIG
|
|
213
266
|
# define EV_NSIG (NSIG)
|
|
214
|
-
#elif defined
|
|
267
|
+
#elif defined _NSIG
|
|
215
268
|
# define EV_NSIG (_NSIG)
|
|
216
|
-
#elif defined
|
|
269
|
+
#elif defined SIGMAX
|
|
217
270
|
# define EV_NSIG (SIGMAX+1)
|
|
218
|
-
#elif defined
|
|
271
|
+
#elif defined SIG_MAX
|
|
219
272
|
# define EV_NSIG (SIG_MAX+1)
|
|
220
|
-
#elif defined
|
|
273
|
+
#elif defined _SIG_MAX
|
|
221
274
|
# define EV_NSIG (_SIG_MAX+1)
|
|
222
|
-
#elif defined
|
|
275
|
+
#elif defined MAXSIG
|
|
223
276
|
# define EV_NSIG (MAXSIG+1)
|
|
224
|
-
#elif defined
|
|
277
|
+
#elif defined MAX_SIG
|
|
225
278
|
# define EV_NSIG (MAX_SIG+1)
|
|
226
|
-
#elif defined
|
|
279
|
+
#elif defined SIGARRAYSIZE
|
|
227
280
|
# define EV_NSIG (SIGARRAYSIZE) /* Assume ary[SIGARRAYSIZE] */
|
|
228
|
-
#elif defined
|
|
281
|
+
#elif defined _sys_nsig
|
|
229
282
|
# define EV_NSIG (_sys_nsig) /* Solaris 2.5 */
|
|
230
283
|
#else
|
|
231
|
-
#
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
#
|
|
284
|
+
# define EV_NSIG (8 * sizeof (sigset_t) + 1)
|
|
285
|
+
#endif
|
|
286
|
+
|
|
287
|
+
#ifndef EV_USE_FLOOR
|
|
288
|
+
# define EV_USE_FLOOR 0
|
|
235
289
|
#endif
|
|
236
290
|
|
|
237
291
|
#ifndef EV_USE_CLOCK_SYSCALL
|
|
238
|
-
# if __linux && __GLIBC__
|
|
292
|
+
# if __linux && __GLIBC__ == 2 && __GLIBC_MINOR__ < 17
|
|
239
293
|
# define EV_USE_CLOCK_SYSCALL EV_FEATURE_OS
|
|
240
294
|
# else
|
|
241
295
|
# define EV_USE_CLOCK_SYSCALL 0
|
|
242
296
|
# endif
|
|
243
297
|
#endif
|
|
244
298
|
|
|
299
|
+
#if !(_POSIX_TIMERS > 0)
|
|
300
|
+
# ifndef EV_USE_MONOTONIC
|
|
301
|
+
# define EV_USE_MONOTONIC 0
|
|
302
|
+
# endif
|
|
303
|
+
# ifndef EV_USE_REALTIME
|
|
304
|
+
# define EV_USE_REALTIME 0
|
|
305
|
+
# endif
|
|
306
|
+
#endif
|
|
307
|
+
|
|
245
308
|
#ifndef EV_USE_MONOTONIC
|
|
246
|
-
# if defined
|
|
309
|
+
# if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
|
|
247
310
|
# define EV_USE_MONOTONIC EV_FEATURE_OS
|
|
248
311
|
# else
|
|
249
312
|
# define EV_USE_MONOTONIC 0
|
|
@@ -290,6 +353,14 @@ EV_CPP(extern "C" {)
|
|
|
290
353
|
# define EV_USE_PORT 0
|
|
291
354
|
#endif
|
|
292
355
|
|
|
356
|
+
#ifndef EV_USE_LINUXAIO
|
|
357
|
+
# define EV_USE_LINUXAIO 0
|
|
358
|
+
#endif
|
|
359
|
+
|
|
360
|
+
#ifndef EV_USE_IOURING
|
|
361
|
+
# define EV_USE_IOURING 0
|
|
362
|
+
#endif
|
|
363
|
+
|
|
293
364
|
#ifndef EV_USE_INOTIFY
|
|
294
365
|
# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4))
|
|
295
366
|
# define EV_USE_INOTIFY EV_FEATURE_OS
|
|
@@ -322,6 +393,14 @@ EV_CPP(extern "C" {)
|
|
|
322
393
|
# endif
|
|
323
394
|
#endif
|
|
324
395
|
|
|
396
|
+
#ifndef EV_USE_TIMERFD
|
|
397
|
+
# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8))
|
|
398
|
+
# define EV_USE_TIMERFD EV_FEATURE_OS
|
|
399
|
+
# else
|
|
400
|
+
# define EV_USE_TIMERFD 0
|
|
401
|
+
# endif
|
|
402
|
+
#endif
|
|
403
|
+
|
|
325
404
|
#if 0 /* debugging */
|
|
326
405
|
# define EV_VERIFY 3
|
|
327
406
|
# define EV_USE_4HEAP 1
|
|
@@ -340,14 +419,31 @@ EV_CPP(extern "C" {)
|
|
|
340
419
|
# define EV_HEAP_CACHE_AT EV_FEATURE_DATA
|
|
341
420
|
#endif
|
|
342
421
|
|
|
422
|
+
#ifdef __ANDROID__
|
|
423
|
+
/* supposedly, android doesn't typedef fd_mask */
|
|
424
|
+
# undef EV_USE_SELECT
|
|
425
|
+
# define EV_USE_SELECT 0
|
|
426
|
+
/* supposedly, we need to include syscall.h, not sys/syscall.h, so just disable */
|
|
427
|
+
# undef EV_USE_CLOCK_SYSCALL
|
|
428
|
+
# define EV_USE_CLOCK_SYSCALL 0
|
|
429
|
+
#endif
|
|
430
|
+
|
|
431
|
+
/* aix's poll.h seems to cause lots of trouble */
|
|
432
|
+
#ifdef _AIX
|
|
433
|
+
/* AIX has a completely broken poll.h header */
|
|
434
|
+
# undef EV_USE_POLL
|
|
435
|
+
# define EV_USE_POLL 0
|
|
436
|
+
#endif
|
|
437
|
+
|
|
343
438
|
/* on linux, we can use a (slow) syscall to avoid a dependency on pthread, */
|
|
344
439
|
/* which makes programs even slower. might work on other unices, too. */
|
|
345
440
|
#if EV_USE_CLOCK_SYSCALL
|
|
346
|
-
# include <syscall.h>
|
|
441
|
+
# include <sys/syscall.h>
|
|
347
442
|
# ifdef SYS_clock_gettime
|
|
348
443
|
# define clock_gettime(id, ts) syscall (SYS_clock_gettime, (id), (ts))
|
|
349
444
|
# undef EV_USE_MONOTONIC
|
|
350
445
|
# define EV_USE_MONOTONIC 1
|
|
446
|
+
# define EV_NEED_SYSCALL 1
|
|
351
447
|
# else
|
|
352
448
|
# undef EV_USE_CLOCK_SYSCALL
|
|
353
449
|
# define EV_USE_CLOCK_SYSCALL 0
|
|
@@ -356,12 +452,6 @@ EV_CPP(extern "C" {)
|
|
|
356
452
|
|
|
357
453
|
/* this block fixes any misconfiguration where we know we run into trouble otherwise */
|
|
358
454
|
|
|
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
455
|
#ifndef CLOCK_MONOTONIC
|
|
366
456
|
# undef EV_USE_MONOTONIC
|
|
367
457
|
# define EV_USE_MONOTONIC 0
|
|
@@ -379,11 +469,36 @@ EV_CPP(extern "C" {)
|
|
|
379
469
|
|
|
380
470
|
#if !EV_USE_NANOSLEEP
|
|
381
471
|
/* hp-ux has it in sys/time.h, which we unconditionally include above */
|
|
382
|
-
# if !defined
|
|
472
|
+
# if !defined _WIN32 && !defined __hpux
|
|
383
473
|
# include <sys/select.h>
|
|
384
474
|
# endif
|
|
385
475
|
#endif
|
|
386
476
|
|
|
477
|
+
#if EV_USE_LINUXAIO
|
|
478
|
+
# include <sys/syscall.h>
|
|
479
|
+
# if SYS_io_getevents && EV_USE_EPOLL /* linuxaio backend requires epoll backend */
|
|
480
|
+
# define EV_NEED_SYSCALL 1
|
|
481
|
+
# else
|
|
482
|
+
# undef EV_USE_LINUXAIO
|
|
483
|
+
# define EV_USE_LINUXAIO 0
|
|
484
|
+
# endif
|
|
485
|
+
#endif
|
|
486
|
+
|
|
487
|
+
#if EV_USE_IOURING
|
|
488
|
+
# include <sys/syscall.h>
|
|
489
|
+
# if !SYS_io_uring_setup && __linux && !__alpha
|
|
490
|
+
# define SYS_io_uring_setup 425
|
|
491
|
+
# define SYS_io_uring_enter 426
|
|
492
|
+
# define SYS_io_uring_wregister 427
|
|
493
|
+
# endif
|
|
494
|
+
# if SYS_io_uring_setup && EV_USE_EPOLL /* iouring backend requires epoll backend */
|
|
495
|
+
# define EV_NEED_SYSCALL 1
|
|
496
|
+
# else
|
|
497
|
+
# undef EV_USE_IOURING
|
|
498
|
+
# define EV_USE_IOURING 0
|
|
499
|
+
# endif
|
|
500
|
+
#endif
|
|
501
|
+
|
|
387
502
|
#if EV_USE_INOTIFY
|
|
388
503
|
# include <sys/statfs.h>
|
|
389
504
|
# include <sys/inotify.h>
|
|
@@ -394,12 +509,8 @@ EV_CPP(extern "C" {)
|
|
|
394
509
|
# endif
|
|
395
510
|
#endif
|
|
396
511
|
|
|
397
|
-
#if EV_SELECT_IS_WINSOCKET
|
|
398
|
-
# include <winsock.h>
|
|
399
|
-
#endif
|
|
400
|
-
|
|
401
512
|
#if EV_USE_EVENTFD
|
|
402
|
-
/* our minimum requirement is glibc 2.7 which has the stub, but not the header */
|
|
513
|
+
/* our minimum requirement is glibc 2.7 which has the stub, but not the full header */
|
|
403
514
|
# include <stdint.h>
|
|
404
515
|
# ifndef EFD_NONBLOCK
|
|
405
516
|
# define EFD_NONBLOCK O_NONBLOCK
|
|
@@ -415,7 +526,7 @@ EV_CPP(extern "C") int (eventfd) (unsigned int initval, int flags);
|
|
|
415
526
|
#endif
|
|
416
527
|
|
|
417
528
|
#if EV_USE_SIGNALFD
|
|
418
|
-
/* our minimum requirement is glibc 2.7 which has the stub, but not the header */
|
|
529
|
+
/* our minimum requirement is glibc 2.7 which has the stub, but not the full header */
|
|
419
530
|
# include <stdint.h>
|
|
420
531
|
# ifndef SFD_NONBLOCK
|
|
421
532
|
# define SFD_NONBLOCK O_NONBLOCK
|
|
@@ -427,7 +538,7 @@ EV_CPP(extern "C") int (eventfd) (unsigned int initval, int flags);
|
|
|
427
538
|
# define SFD_CLOEXEC 02000000
|
|
428
539
|
# endif
|
|
429
540
|
# endif
|
|
430
|
-
EV_CPP (extern "C") int signalfd (int fd, const sigset_t *mask, int flags);
|
|
541
|
+
EV_CPP (extern "C") int (signalfd) (int fd, const sigset_t *mask, int flags);
|
|
431
542
|
|
|
432
543
|
struct signalfd_siginfo
|
|
433
544
|
{
|
|
@@ -436,7 +547,17 @@ struct signalfd_siginfo
|
|
|
436
547
|
};
|
|
437
548
|
#endif
|
|
438
549
|
|
|
439
|
-
|
|
550
|
+
/* for timerfd, libev core requires TFD_TIMER_CANCEL_ON_SET &c */
|
|
551
|
+
#if EV_USE_TIMERFD
|
|
552
|
+
# include <sys/timerfd.h>
|
|
553
|
+
/* timerfd is only used for periodics */
|
|
554
|
+
# if !(defined (TFD_TIMER_CANCEL_ON_SET) && defined (TFD_CLOEXEC) && defined (TFD_NONBLOCK)) || !EV_PERIODIC_ENABLE
|
|
555
|
+
# undef EV_USE_TIMERFD
|
|
556
|
+
# define EV_USE_TIMERFD 0
|
|
557
|
+
# endif
|
|
558
|
+
#endif
|
|
559
|
+
|
|
560
|
+
/*****************************************************************************/
|
|
440
561
|
|
|
441
562
|
#if EV_VERIFY >= 3
|
|
442
563
|
# define EV_FREQUENT_CHECK ev_verify (EV_A)
|
|
@@ -445,42 +566,1274 @@ struct signalfd_siginfo
|
|
|
445
566
|
#endif
|
|
446
567
|
|
|
447
568
|
/*
|
|
448
|
-
* This is used to
|
|
449
|
-
* It is added to ev_rt_now when scheduling periodics
|
|
450
|
-
* to ensure progress, time-wise, even when rounding
|
|
451
|
-
* errors are against us.
|
|
569
|
+
* This is used to work around floating point rounding problems.
|
|
452
570
|
* This value is good at least till the year 4000.
|
|
453
|
-
* Better solutions welcome.
|
|
454
571
|
*/
|
|
455
|
-
#define
|
|
572
|
+
#define MIN_INTERVAL 0.0001220703125 /* 1/2**13, good till 4000 */
|
|
573
|
+
/*#define MIN_INTERVAL 0.00000095367431640625 /* 1/2**20, good till 2200 */
|
|
574
|
+
|
|
575
|
+
#define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */
|
|
576
|
+
#define MAX_BLOCKTIME 59.743 /* never wait longer than this time (to detect time jumps) */
|
|
577
|
+
#define MAX_BLOCKTIME2 1500001.07 /* same, but when timerfd is used to detect jumps, also safe delay to not overflow */
|
|
578
|
+
|
|
579
|
+
/* find a portable timestamp that is "always" in the future but fits into time_t.
|
|
580
|
+
* this is quite hard, and we are mostly guessing - we handle 32 bit signed/unsigned time_t,
|
|
581
|
+
* and sizes larger than 32 bit, and maybe the unlikely floating point time_t */
|
|
582
|
+
#define EV_TSTAMP_HUGE \
|
|
583
|
+
(sizeof (time_t) >= 8 ? 10000000000000. \
|
|
584
|
+
: 0 < (time_t)4294967295 ? 4294967295. \
|
|
585
|
+
: 2147483647.) \
|
|
586
|
+
|
|
587
|
+
#ifndef EV_TS_CONST
|
|
588
|
+
# define EV_TS_CONST(nv) nv
|
|
589
|
+
# define EV_TS_TO_MSEC(a) a * 1e3 + 0.9999
|
|
590
|
+
# define EV_TS_FROM_USEC(us) us * 1e-6
|
|
591
|
+
# define EV_TV_SET(tv,t) do { tv.tv_sec = (long)t; tv.tv_usec = (long)((t - tv.tv_sec) * 1e6); } while (0)
|
|
592
|
+
# define EV_TS_SET(ts,t) do { ts.tv_sec = (long)t; ts.tv_nsec = (long)((t - ts.tv_sec) * 1e9); } while (0)
|
|
593
|
+
# define EV_TV_GET(tv) ((tv).tv_sec + (tv).tv_usec * 1e-6)
|
|
594
|
+
# define EV_TS_GET(ts) ((ts).tv_sec + (ts).tv_nsec * 1e-9)
|
|
595
|
+
#endif
|
|
596
|
+
|
|
597
|
+
/* the following is ecb.h embedded into libev - use update_ev_c to update from an external copy */
|
|
598
|
+
/* ECB.H BEGIN */
|
|
599
|
+
/*
|
|
600
|
+
* libecb - http://software.schmorp.de/pkg/libecb
|
|
601
|
+
*
|
|
602
|
+
* Copyright (©) 2009-2015,2018-2020 Marc Alexander Lehmann <libecb@schmorp.de>
|
|
603
|
+
* Copyright (©) 2011 Emanuele Giaquinta
|
|
604
|
+
* All rights reserved.
|
|
605
|
+
*
|
|
606
|
+
* Redistribution and use in source and binary forms, with or without modifica-
|
|
607
|
+
* tion, are permitted provided that the following conditions are met:
|
|
608
|
+
*
|
|
609
|
+
* 1. Redistributions of source code must retain the above copyright notice,
|
|
610
|
+
* this list of conditions and the following disclaimer.
|
|
611
|
+
*
|
|
612
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
|
613
|
+
* notice, this list of conditions and the following disclaimer in the
|
|
614
|
+
* documentation and/or other materials provided with the distribution.
|
|
615
|
+
*
|
|
616
|
+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
617
|
+
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
|
|
618
|
+
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
|
619
|
+
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
|
|
620
|
+
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
621
|
+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
622
|
+
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
623
|
+
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
|
|
624
|
+
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
625
|
+
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
626
|
+
*
|
|
627
|
+
* Alternatively, the contents of this file may be used under the terms of
|
|
628
|
+
* the GNU General Public License ("GPL") version 2 or any later version,
|
|
629
|
+
* in which case the provisions of the GPL are applicable instead of
|
|
630
|
+
* the above. If you wish to allow the use of your version of this file
|
|
631
|
+
* only under the terms of the GPL and not to allow others to use your
|
|
632
|
+
* version of this file under the BSD license, indicate your decision
|
|
633
|
+
* by deleting the provisions above and replace them with the notice
|
|
634
|
+
* and other provisions required by the GPL. If you do not delete the
|
|
635
|
+
* provisions above, a recipient may use your version of this file under
|
|
636
|
+
* either the BSD or the GPL.
|
|
637
|
+
*/
|
|
456
638
|
|
|
457
|
-
#
|
|
458
|
-
#define
|
|
639
|
+
#ifndef ECB_H
|
|
640
|
+
#define ECB_H
|
|
641
|
+
|
|
642
|
+
/* 16 bits major, 16 bits minor */
|
|
643
|
+
#define ECB_VERSION 0x00010008
|
|
644
|
+
|
|
645
|
+
#include <string.h> /* for memcpy */
|
|
646
|
+
|
|
647
|
+
#if defined (_WIN32) && !defined (__MINGW32__)
|
|
648
|
+
typedef signed char int8_t;
|
|
649
|
+
typedef unsigned char uint8_t;
|
|
650
|
+
typedef signed char int_fast8_t;
|
|
651
|
+
typedef unsigned char uint_fast8_t;
|
|
652
|
+
typedef signed short int16_t;
|
|
653
|
+
typedef unsigned short uint16_t;
|
|
654
|
+
typedef signed int int_fast16_t;
|
|
655
|
+
typedef unsigned int uint_fast16_t;
|
|
656
|
+
typedef signed int int32_t;
|
|
657
|
+
typedef unsigned int uint32_t;
|
|
658
|
+
typedef signed int int_fast32_t;
|
|
659
|
+
typedef unsigned int uint_fast32_t;
|
|
660
|
+
#if __GNUC__
|
|
661
|
+
typedef signed long long int64_t;
|
|
662
|
+
typedef unsigned long long uint64_t;
|
|
663
|
+
#else /* _MSC_VER || __BORLANDC__ */
|
|
664
|
+
typedef signed __int64 int64_t;
|
|
665
|
+
typedef unsigned __int64 uint64_t;
|
|
666
|
+
#endif
|
|
667
|
+
typedef int64_t int_fast64_t;
|
|
668
|
+
typedef uint64_t uint_fast64_t;
|
|
669
|
+
#ifdef _WIN64
|
|
670
|
+
#define ECB_PTRSIZE 8
|
|
671
|
+
typedef uint64_t uintptr_t;
|
|
672
|
+
typedef int64_t intptr_t;
|
|
673
|
+
#else
|
|
674
|
+
#define ECB_PTRSIZE 4
|
|
675
|
+
typedef uint32_t uintptr_t;
|
|
676
|
+
typedef int32_t intptr_t;
|
|
677
|
+
#endif
|
|
678
|
+
#else
|
|
679
|
+
#include <inttypes.h>
|
|
680
|
+
#if (defined INTPTR_MAX ? INTPTR_MAX : ULONG_MAX) > 0xffffffffU
|
|
681
|
+
#define ECB_PTRSIZE 8
|
|
682
|
+
#else
|
|
683
|
+
#define ECB_PTRSIZE 4
|
|
684
|
+
#endif
|
|
685
|
+
#endif
|
|
686
|
+
|
|
687
|
+
#define ECB_GCC_AMD64 (__amd64 || __amd64__ || __x86_64 || __x86_64__)
|
|
688
|
+
#define ECB_MSVC_AMD64 (_M_AMD64 || _M_X64)
|
|
689
|
+
|
|
690
|
+
#ifndef ECB_OPTIMIZE_SIZE
|
|
691
|
+
#if __OPTIMIZE_SIZE__
|
|
692
|
+
#define ECB_OPTIMIZE_SIZE 1
|
|
693
|
+
#else
|
|
694
|
+
#define ECB_OPTIMIZE_SIZE 0
|
|
695
|
+
#endif
|
|
696
|
+
#endif
|
|
697
|
+
|
|
698
|
+
/* work around x32 idiocy by defining proper macros */
|
|
699
|
+
#if ECB_GCC_AMD64 || ECB_MSVC_AMD64
|
|
700
|
+
#if _ILP32
|
|
701
|
+
#define ECB_AMD64_X32 1
|
|
702
|
+
#else
|
|
703
|
+
#define ECB_AMD64 1
|
|
704
|
+
#endif
|
|
705
|
+
#endif
|
|
706
|
+
|
|
707
|
+
/* many compilers define _GNUC_ to some versions but then only implement
|
|
708
|
+
* what their idiot authors think are the "more important" extensions,
|
|
709
|
+
* causing enormous grief in return for some better fake benchmark numbers.
|
|
710
|
+
* or so.
|
|
711
|
+
* we try to detect these and simply assume they are not gcc - if they have
|
|
712
|
+
* an issue with that they should have done it right in the first place.
|
|
713
|
+
*/
|
|
714
|
+
#if !defined __GNUC_MINOR__ || defined __INTEL_COMPILER || defined __SUNPRO_C || defined __SUNPRO_CC || defined __llvm__ || defined __clang__
|
|
715
|
+
#define ECB_GCC_VERSION(major,minor) 0
|
|
716
|
+
#else
|
|
717
|
+
#define ECB_GCC_VERSION(major,minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
|
|
718
|
+
#endif
|
|
459
719
|
|
|
460
|
-
#define
|
|
461
|
-
#define EV_TS_SET(ts,t) do { ts.tv_sec = (long)t; ts.tv_nsec = (long)((t - ts.tv_sec) * 1e9); } while (0)
|
|
720
|
+
#define ECB_CLANG_VERSION(major,minor) (__clang_major__ > (major) || (__clang_major__ == (major) && __clang_minor__ >= (minor)))
|
|
462
721
|
|
|
463
|
-
#if
|
|
464
|
-
#
|
|
465
|
-
# define noinline __attribute__ ((noinline))
|
|
722
|
+
#if __clang__ && defined __has_builtin
|
|
723
|
+
#define ECB_CLANG_BUILTIN(x) __has_builtin (x)
|
|
466
724
|
#else
|
|
467
|
-
#
|
|
468
|
-
#
|
|
469
|
-
|
|
470
|
-
#
|
|
471
|
-
#
|
|
725
|
+
#define ECB_CLANG_BUILTIN(x) 0
|
|
726
|
+
#endif
|
|
727
|
+
|
|
728
|
+
#if __clang__ && defined __has_extension
|
|
729
|
+
#define ECB_CLANG_EXTENSION(x) __has_extension (x)
|
|
730
|
+
#else
|
|
731
|
+
#define ECB_CLANG_EXTENSION(x) 0
|
|
732
|
+
#endif
|
|
733
|
+
|
|
734
|
+
#define ECB_CPP (__cplusplus+0)
|
|
735
|
+
#define ECB_CPP11 (__cplusplus >= 201103L)
|
|
736
|
+
#define ECB_CPP14 (__cplusplus >= 201402L)
|
|
737
|
+
#define ECB_CPP17 (__cplusplus >= 201703L)
|
|
738
|
+
|
|
739
|
+
#if ECB_CPP
|
|
740
|
+
#define ECB_C 0
|
|
741
|
+
#define ECB_STDC_VERSION 0
|
|
742
|
+
#else
|
|
743
|
+
#define ECB_C 1
|
|
744
|
+
#define ECB_STDC_VERSION __STDC_VERSION__
|
|
745
|
+
#endif
|
|
746
|
+
|
|
747
|
+
#define ECB_C99 (ECB_STDC_VERSION >= 199901L)
|
|
748
|
+
#define ECB_C11 (ECB_STDC_VERSION >= 201112L)
|
|
749
|
+
#define ECB_C17 (ECB_STDC_VERSION >= 201710L)
|
|
750
|
+
|
|
751
|
+
#if ECB_CPP
|
|
752
|
+
#define ECB_EXTERN_C extern "C"
|
|
753
|
+
#define ECB_EXTERN_C_BEG ECB_EXTERN_C {
|
|
754
|
+
#define ECB_EXTERN_C_END }
|
|
755
|
+
#else
|
|
756
|
+
#define ECB_EXTERN_C extern
|
|
757
|
+
#define ECB_EXTERN_C_BEG
|
|
758
|
+
#define ECB_EXTERN_C_END
|
|
759
|
+
#endif
|
|
760
|
+
|
|
761
|
+
/*****************************************************************************/
|
|
762
|
+
|
|
763
|
+
/* ECB_NO_THREADS - ecb is not used by multiple threads, ever */
|
|
764
|
+
/* ECB_NO_SMP - ecb might be used in multiple threads, but only on a single cpu */
|
|
765
|
+
|
|
766
|
+
#if ECB_NO_THREADS
|
|
767
|
+
#define ECB_NO_SMP 1
|
|
768
|
+
#endif
|
|
769
|
+
|
|
770
|
+
#if ECB_NO_SMP
|
|
771
|
+
#define ECB_MEMORY_FENCE do { } while (0)
|
|
772
|
+
#endif
|
|
773
|
+
|
|
774
|
+
/* http://www-01.ibm.com/support/knowledgecenter/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/compiler_ref/compiler_builtins.html */
|
|
775
|
+
#if __xlC__ && ECB_CPP
|
|
776
|
+
#include <builtins.h>
|
|
777
|
+
#endif
|
|
778
|
+
|
|
779
|
+
#if 1400 <= _MSC_VER
|
|
780
|
+
#include <intrin.h> /* fence functions _ReadBarrier, also bit search functions _BitScanReverse */
|
|
781
|
+
#endif
|
|
782
|
+
|
|
783
|
+
#ifndef ECB_MEMORY_FENCE
|
|
784
|
+
#if ECB_GCC_VERSION(2,5) || defined __INTEL_COMPILER || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
|
|
785
|
+
#define ECB_MEMORY_FENCE_RELAXED __asm__ __volatile__ ("" : : : "memory")
|
|
786
|
+
#if __i386 || __i386__
|
|
787
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory")
|
|
788
|
+
#define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory")
|
|
789
|
+
#define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("" : : : "memory")
|
|
790
|
+
#elif ECB_GCC_AMD64
|
|
791
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("mfence" : : : "memory")
|
|
792
|
+
#define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory")
|
|
793
|
+
#define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("" : : : "memory")
|
|
794
|
+
#elif __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__
|
|
795
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("sync" : : : "memory")
|
|
796
|
+
#elif defined __ARM_ARCH_2__ \
|
|
797
|
+
|| defined __ARM_ARCH_3__ || defined __ARM_ARCH_3M__ \
|
|
798
|
+
|| defined __ARM_ARCH_4__ || defined __ARM_ARCH_4T__ \
|
|
799
|
+
|| defined __ARM_ARCH_5__ || defined __ARM_ARCH_5E__ \
|
|
800
|
+
|| defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__ \
|
|
801
|
+
|| defined __ARM_ARCH_5TEJ__
|
|
802
|
+
/* should not need any, unless running old code on newer cpu - arm doesn't support that */
|
|
803
|
+
#elif defined __ARM_ARCH_6__ || defined __ARM_ARCH_6J__ \
|
|
804
|
+
|| defined __ARM_ARCH_6K__ || defined __ARM_ARCH_6ZK__ \
|
|
805
|
+
|| defined __ARM_ARCH_6T2__
|
|
806
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("mcr p15,0,%0,c7,c10,5" : : "r" (0) : "memory")
|
|
807
|
+
#elif defined __ARM_ARCH_7__ || defined __ARM_ARCH_7A__ \
|
|
808
|
+
|| defined __ARM_ARCH_7R__ || defined __ARM_ARCH_7M__
|
|
809
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("dmb" : : : "memory")
|
|
810
|
+
#elif __aarch64__
|
|
811
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("dmb ish" : : : "memory")
|
|
812
|
+
#elif (__sparc || __sparc__) && !(__sparc_v8__ || defined __sparcv8)
|
|
813
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad | #StoreStore | #StoreLoad" : : : "memory")
|
|
814
|
+
#define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad" : : : "memory")
|
|
815
|
+
#define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("membar #LoadStore | #StoreStore")
|
|
816
|
+
#elif defined __s390__ || defined __s390x__
|
|
817
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("bcr 15,0" : : : "memory")
|
|
818
|
+
#elif defined __mips__
|
|
819
|
+
/* GNU/Linux emulates sync on mips1 architectures, so we force its use */
|
|
820
|
+
/* anybody else who still uses mips1 is supposed to send in their version, with detection code. */
|
|
821
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ (".set mips2; sync; .set mips0" : : : "memory")
|
|
822
|
+
#elif defined __alpha__
|
|
823
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("mb" : : : "memory")
|
|
824
|
+
#elif defined __hppa__
|
|
825
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("" : : : "memory")
|
|
826
|
+
#define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
|
|
827
|
+
#elif defined __ia64__
|
|
828
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("mf" : : : "memory")
|
|
829
|
+
#elif defined __m68k__
|
|
830
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("" : : : "memory")
|
|
831
|
+
#elif defined __m88k__
|
|
832
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("tb1 0,%%r0,128" : : : "memory")
|
|
833
|
+
#elif defined __sh__
|
|
834
|
+
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("" : : : "memory")
|
|
835
|
+
#endif
|
|
836
|
+
#endif
|
|
837
|
+
#endif
|
|
838
|
+
|
|
839
|
+
#ifndef ECB_MEMORY_FENCE
|
|
840
|
+
#if ECB_GCC_VERSION(4,7)
|
|
841
|
+
/* see comment below (stdatomic.h) about the C11 memory model. */
|
|
842
|
+
#define ECB_MEMORY_FENCE __atomic_thread_fence (__ATOMIC_SEQ_CST)
|
|
843
|
+
#define ECB_MEMORY_FENCE_ACQUIRE __atomic_thread_fence (__ATOMIC_ACQUIRE)
|
|
844
|
+
#define ECB_MEMORY_FENCE_RELEASE __atomic_thread_fence (__ATOMIC_RELEASE)
|
|
845
|
+
#define ECB_MEMORY_FENCE_RELAXED __atomic_thread_fence (__ATOMIC_RELAXED)
|
|
846
|
+
|
|
847
|
+
#elif ECB_CLANG_EXTENSION(c_atomic)
|
|
848
|
+
/* see comment below (stdatomic.h) about the C11 memory model. */
|
|
849
|
+
#define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST)
|
|
850
|
+
#define ECB_MEMORY_FENCE_ACQUIRE __c11_atomic_thread_fence (__ATOMIC_ACQUIRE)
|
|
851
|
+
#define ECB_MEMORY_FENCE_RELEASE __c11_atomic_thread_fence (__ATOMIC_RELEASE)
|
|
852
|
+
#define ECB_MEMORY_FENCE_RELAXED __c11_atomic_thread_fence (__ATOMIC_RELAXED)
|
|
853
|
+
|
|
854
|
+
#elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__
|
|
855
|
+
#define ECB_MEMORY_FENCE __sync_synchronize ()
|
|
856
|
+
#elif _MSC_VER >= 1500 /* VC++ 2008 */
|
|
857
|
+
/* apparently, microsoft broke all the memory barrier stuff in Visual Studio 2008... */
|
|
858
|
+
#pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier)
|
|
859
|
+
#define ECB_MEMORY_FENCE _ReadWriteBarrier (); MemoryBarrier()
|
|
860
|
+
#define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier (); MemoryBarrier() /* according to msdn, _ReadBarrier is not a load fence */
|
|
861
|
+
#define ECB_MEMORY_FENCE_RELEASE _WriteBarrier (); MemoryBarrier()
|
|
862
|
+
#elif _MSC_VER >= 1400 /* VC++ 2005 */
|
|
863
|
+
#pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier)
|
|
864
|
+
#define ECB_MEMORY_FENCE _ReadWriteBarrier ()
|
|
865
|
+
#define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier () /* according to msdn, _ReadBarrier is not a load fence */
|
|
866
|
+
#define ECB_MEMORY_FENCE_RELEASE _WriteBarrier ()
|
|
867
|
+
#elif defined _WIN32
|
|
868
|
+
#include <WinNT.h>
|
|
869
|
+
#define ECB_MEMORY_FENCE MemoryBarrier () /* actually just xchg on x86... scary */
|
|
870
|
+
#elif __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
|
|
871
|
+
#include <mbarrier.h>
|
|
872
|
+
#define ECB_MEMORY_FENCE __machine_rw_barrier ()
|
|
873
|
+
#define ECB_MEMORY_FENCE_ACQUIRE __machine_acq_barrier ()
|
|
874
|
+
#define ECB_MEMORY_FENCE_RELEASE __machine_rel_barrier ()
|
|
875
|
+
#define ECB_MEMORY_FENCE_RELAXED __compiler_barrier ()
|
|
876
|
+
#elif __xlC__
|
|
877
|
+
#define ECB_MEMORY_FENCE __sync ()
|
|
878
|
+
#endif
|
|
879
|
+
#endif
|
|
880
|
+
|
|
881
|
+
#ifndef ECB_MEMORY_FENCE
|
|
882
|
+
#if ECB_C11 && !defined __STDC_NO_ATOMICS__
|
|
883
|
+
/* we assume that these memory fences work on all variables/all memory accesses, */
|
|
884
|
+
/* not just C11 atomics and atomic accesses */
|
|
885
|
+
#include <stdatomic.h>
|
|
886
|
+
#define ECB_MEMORY_FENCE atomic_thread_fence (memory_order_seq_cst)
|
|
887
|
+
#define ECB_MEMORY_FENCE_ACQUIRE atomic_thread_fence (memory_order_acquire)
|
|
888
|
+
#define ECB_MEMORY_FENCE_RELEASE atomic_thread_fence (memory_order_release)
|
|
889
|
+
#endif
|
|
890
|
+
#endif
|
|
891
|
+
|
|
892
|
+
#ifndef ECB_MEMORY_FENCE
|
|
893
|
+
#if !ECB_AVOID_PTHREADS
|
|
894
|
+
/*
|
|
895
|
+
* if you get undefined symbol references to pthread_mutex_lock,
|
|
896
|
+
* or failure to find pthread.h, then you should implement
|
|
897
|
+
* the ECB_MEMORY_FENCE operations for your cpu/compiler
|
|
898
|
+
* OR provide pthread.h and link against the posix thread library
|
|
899
|
+
* of your system.
|
|
900
|
+
*/
|
|
901
|
+
#include <pthread.h>
|
|
902
|
+
#define ECB_NEEDS_PTHREADS 1
|
|
903
|
+
#define ECB_MEMORY_FENCE_NEEDS_PTHREADS 1
|
|
904
|
+
|
|
905
|
+
static pthread_mutex_t ecb_mf_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
906
|
+
#define ECB_MEMORY_FENCE do { pthread_mutex_lock (&ecb_mf_lock); pthread_mutex_unlock (&ecb_mf_lock); } while (0)
|
|
907
|
+
#endif
|
|
908
|
+
#endif
|
|
909
|
+
|
|
910
|
+
#if !defined ECB_MEMORY_FENCE_ACQUIRE && defined ECB_MEMORY_FENCE
|
|
911
|
+
#define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE
|
|
912
|
+
#endif
|
|
913
|
+
|
|
914
|
+
#if !defined ECB_MEMORY_FENCE_RELEASE && defined ECB_MEMORY_FENCE
|
|
915
|
+
#define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE
|
|
916
|
+
#endif
|
|
917
|
+
|
|
918
|
+
#if !defined ECB_MEMORY_FENCE_RELAXED && defined ECB_MEMORY_FENCE
|
|
919
|
+
#define ECB_MEMORY_FENCE_RELAXED ECB_MEMORY_FENCE /* very heavy-handed */
|
|
920
|
+
#endif
|
|
921
|
+
|
|
922
|
+
/*****************************************************************************/
|
|
923
|
+
|
|
924
|
+
#if ECB_CPP
|
|
925
|
+
#define ecb_inline static inline
|
|
926
|
+
#elif ECB_GCC_VERSION(2,5)
|
|
927
|
+
#define ecb_inline static __inline__
|
|
928
|
+
#elif ECB_C99
|
|
929
|
+
#define ecb_inline static inline
|
|
930
|
+
#else
|
|
931
|
+
#define ecb_inline static
|
|
932
|
+
#endif
|
|
933
|
+
|
|
934
|
+
#if ECB_GCC_VERSION(3,3)
|
|
935
|
+
#define ecb_restrict __restrict__
|
|
936
|
+
#elif ECB_C99
|
|
937
|
+
#define ecb_restrict restrict
|
|
938
|
+
#else
|
|
939
|
+
#define ecb_restrict
|
|
940
|
+
#endif
|
|
941
|
+
|
|
942
|
+
typedef int ecb_bool;
|
|
943
|
+
|
|
944
|
+
#define ECB_CONCAT_(a, b) a ## b
|
|
945
|
+
#define ECB_CONCAT(a, b) ECB_CONCAT_(a, b)
|
|
946
|
+
#define ECB_STRINGIFY_(a) # a
|
|
947
|
+
#define ECB_STRINGIFY(a) ECB_STRINGIFY_(a)
|
|
948
|
+
#define ECB_STRINGIFY_EXPR(expr) ((expr), ECB_STRINGIFY_ (expr))
|
|
949
|
+
|
|
950
|
+
#define ecb_function_ ecb_inline
|
|
951
|
+
|
|
952
|
+
#if ECB_GCC_VERSION(3,1) || ECB_CLANG_VERSION(2,8)
|
|
953
|
+
#define ecb_attribute(attrlist) __attribute__ (attrlist)
|
|
954
|
+
#else
|
|
955
|
+
#define ecb_attribute(attrlist)
|
|
956
|
+
#endif
|
|
957
|
+
|
|
958
|
+
#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_constant_p)
|
|
959
|
+
#define ecb_is_constant(expr) __builtin_constant_p (expr)
|
|
960
|
+
#else
|
|
961
|
+
/* possible C11 impl for integral types
|
|
962
|
+
typedef struct ecb_is_constant_struct ecb_is_constant_struct;
|
|
963
|
+
#define ecb_is_constant(expr) _Generic ((1 ? (struct ecb_is_constant_struct *)0 : (void *)((expr) - (expr)), ecb_is_constant_struct *: 0, default: 1)) */
|
|
964
|
+
|
|
965
|
+
#define ecb_is_constant(expr) 0
|
|
966
|
+
#endif
|
|
967
|
+
|
|
968
|
+
#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_expect)
|
|
969
|
+
#define ecb_expect(expr,value) __builtin_expect ((expr),(value))
|
|
970
|
+
#else
|
|
971
|
+
#define ecb_expect(expr,value) (expr)
|
|
972
|
+
#endif
|
|
973
|
+
|
|
974
|
+
#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_prefetch)
|
|
975
|
+
#define ecb_prefetch(addr,rw,locality) __builtin_prefetch (addr, rw, locality)
|
|
976
|
+
#else
|
|
977
|
+
#define ecb_prefetch(addr,rw,locality)
|
|
978
|
+
#endif
|
|
979
|
+
|
|
980
|
+
/* no emulation for ecb_decltype */
|
|
981
|
+
#if ECB_CPP11
|
|
982
|
+
// older implementations might have problems with decltype(x)::type, work around it
|
|
983
|
+
template<class T> struct ecb_decltype_t { typedef T type; };
|
|
984
|
+
#define ecb_decltype(x) ecb_decltype_t<decltype (x)>::type
|
|
985
|
+
#elif ECB_GCC_VERSION(3,0) || ECB_CLANG_VERSION(2,8)
|
|
986
|
+
#define ecb_decltype(x) __typeof__ (x)
|
|
987
|
+
#endif
|
|
988
|
+
|
|
989
|
+
#if _MSC_VER >= 1300
|
|
990
|
+
#define ecb_deprecated __declspec (deprecated)
|
|
991
|
+
#else
|
|
992
|
+
#define ecb_deprecated ecb_attribute ((__deprecated__))
|
|
993
|
+
#endif
|
|
994
|
+
|
|
995
|
+
#if _MSC_VER >= 1500
|
|
996
|
+
#define ecb_deprecated_message(msg) __declspec (deprecated (msg))
|
|
997
|
+
#elif ECB_GCC_VERSION(4,5)
|
|
998
|
+
#define ecb_deprecated_message(msg) ecb_attribute ((__deprecated__ (msg))
|
|
999
|
+
#else
|
|
1000
|
+
#define ecb_deprecated_message(msg) ecb_deprecated
|
|
1001
|
+
#endif
|
|
1002
|
+
|
|
1003
|
+
#if _MSC_VER >= 1400
|
|
1004
|
+
#define ecb_noinline __declspec (noinline)
|
|
1005
|
+
#else
|
|
1006
|
+
#define ecb_noinline ecb_attribute ((__noinline__))
|
|
1007
|
+
#endif
|
|
1008
|
+
|
|
1009
|
+
#define ecb_unused ecb_attribute ((__unused__))
|
|
1010
|
+
#define ecb_const ecb_attribute ((__const__))
|
|
1011
|
+
#define ecb_pure ecb_attribute ((__pure__))
|
|
1012
|
+
|
|
1013
|
+
#if ECB_C11 || __IBMC_NORETURN
|
|
1014
|
+
/* http://www-01.ibm.com/support/knowledgecenter/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/language_ref/noreturn.html */
|
|
1015
|
+
#define ecb_noreturn _Noreturn
|
|
1016
|
+
#elif ECB_CPP11
|
|
1017
|
+
#define ecb_noreturn [[noreturn]]
|
|
1018
|
+
#elif _MSC_VER >= 1200
|
|
1019
|
+
/* http://msdn.microsoft.com/en-us/library/k6ktzx3s.aspx */
|
|
1020
|
+
#define ecb_noreturn __declspec (noreturn)
|
|
1021
|
+
#else
|
|
1022
|
+
#define ecb_noreturn ecb_attribute ((__noreturn__))
|
|
1023
|
+
#endif
|
|
1024
|
+
|
|
1025
|
+
#if ECB_GCC_VERSION(4,3)
|
|
1026
|
+
#define ecb_artificial ecb_attribute ((__artificial__))
|
|
1027
|
+
#define ecb_hot ecb_attribute ((__hot__))
|
|
1028
|
+
#define ecb_cold ecb_attribute ((__cold__))
|
|
1029
|
+
#else
|
|
1030
|
+
#define ecb_artificial
|
|
1031
|
+
#define ecb_hot
|
|
1032
|
+
#define ecb_cold
|
|
1033
|
+
#endif
|
|
1034
|
+
|
|
1035
|
+
/* put around conditional expressions if you are very sure that the */
|
|
1036
|
+
/* expression is mostly true or mostly false. note that these return */
|
|
1037
|
+
/* booleans, not the expression. */
|
|
1038
|
+
#define ecb_expect_false(expr) ecb_expect (!!(expr), 0)
|
|
1039
|
+
#define ecb_expect_true(expr) ecb_expect (!!(expr), 1)
|
|
1040
|
+
/* for compatibility to the rest of the world */
|
|
1041
|
+
#define ecb_likely(expr) ecb_expect_true (expr)
|
|
1042
|
+
#define ecb_unlikely(expr) ecb_expect_false (expr)
|
|
1043
|
+
|
|
1044
|
+
/* count trailing zero bits and count # of one bits */
|
|
1045
|
+
#if ECB_GCC_VERSION(3,4) \
|
|
1046
|
+
|| (ECB_CLANG_BUILTIN(__builtin_clz) && ECB_CLANG_BUILTIN(__builtin_clzll) \
|
|
1047
|
+
&& ECB_CLANG_BUILTIN(__builtin_ctz) && ECB_CLANG_BUILTIN(__builtin_ctzll) \
|
|
1048
|
+
&& ECB_CLANG_BUILTIN(__builtin_popcount))
|
|
1049
|
+
/* we assume int == 32 bit, long == 32 or 64 bit and long long == 64 bit */
|
|
1050
|
+
#define ecb_ld32(x) (__builtin_clz (x) ^ 31)
|
|
1051
|
+
#define ecb_ld64(x) (__builtin_clzll (x) ^ 63)
|
|
1052
|
+
#define ecb_ctz32(x) __builtin_ctz (x)
|
|
1053
|
+
#define ecb_ctz64(x) __builtin_ctzll (x)
|
|
1054
|
+
#define ecb_popcount32(x) __builtin_popcount (x)
|
|
1055
|
+
/* no popcountll */
|
|
1056
|
+
#else
|
|
1057
|
+
ecb_function_ ecb_const int ecb_ctz32 (uint32_t x);
|
|
1058
|
+
ecb_function_ ecb_const int
|
|
1059
|
+
ecb_ctz32 (uint32_t x)
|
|
1060
|
+
{
|
|
1061
|
+
#if 1400 <= _MSC_VER && (_M_IX86 || _M_X64 || _M_IA64 || _M_ARM)
|
|
1062
|
+
unsigned long r;
|
|
1063
|
+
_BitScanForward (&r, x);
|
|
1064
|
+
return (int)r;
|
|
1065
|
+
#else
|
|
1066
|
+
int r = 0;
|
|
1067
|
+
|
|
1068
|
+
x &= ~x + 1; /* this isolates the lowest bit */
|
|
1069
|
+
|
|
1070
|
+
#if ECB_branchless_on_i386
|
|
1071
|
+
r += !!(x & 0xaaaaaaaa) << 0;
|
|
1072
|
+
r += !!(x & 0xcccccccc) << 1;
|
|
1073
|
+
r += !!(x & 0xf0f0f0f0) << 2;
|
|
1074
|
+
r += !!(x & 0xff00ff00) << 3;
|
|
1075
|
+
r += !!(x & 0xffff0000) << 4;
|
|
1076
|
+
#else
|
|
1077
|
+
if (x & 0xaaaaaaaa) r += 1;
|
|
1078
|
+
if (x & 0xcccccccc) r += 2;
|
|
1079
|
+
if (x & 0xf0f0f0f0) r += 4;
|
|
1080
|
+
if (x & 0xff00ff00) r += 8;
|
|
1081
|
+
if (x & 0xffff0000) r += 16;
|
|
1082
|
+
#endif
|
|
1083
|
+
|
|
1084
|
+
return r;
|
|
1085
|
+
#endif
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
ecb_function_ ecb_const int ecb_ctz64 (uint64_t x);
|
|
1089
|
+
ecb_function_ ecb_const int
|
|
1090
|
+
ecb_ctz64 (uint64_t x)
|
|
1091
|
+
{
|
|
1092
|
+
#if 1400 <= _MSC_VER && (_M_X64 || _M_IA64 || _M_ARM)
|
|
1093
|
+
unsigned long r;
|
|
1094
|
+
_BitScanForward64 (&r, x);
|
|
1095
|
+
return (int)r;
|
|
1096
|
+
#else
|
|
1097
|
+
int shift = x & 0xffffffff ? 0 : 32;
|
|
1098
|
+
return ecb_ctz32 (x >> shift) + shift;
|
|
1099
|
+
#endif
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
ecb_function_ ecb_const int ecb_popcount32 (uint32_t x);
|
|
1103
|
+
ecb_function_ ecb_const int
|
|
1104
|
+
ecb_popcount32 (uint32_t x)
|
|
1105
|
+
{
|
|
1106
|
+
x -= (x >> 1) & 0x55555555;
|
|
1107
|
+
x = ((x >> 2) & 0x33333333) + (x & 0x33333333);
|
|
1108
|
+
x = ((x >> 4) + x) & 0x0f0f0f0f;
|
|
1109
|
+
x *= 0x01010101;
|
|
1110
|
+
|
|
1111
|
+
return x >> 24;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
ecb_function_ ecb_const int ecb_ld32 (uint32_t x);
|
|
1115
|
+
ecb_function_ ecb_const int ecb_ld32 (uint32_t x)
|
|
1116
|
+
{
|
|
1117
|
+
#if 1400 <= _MSC_VER && (_M_IX86 || _M_X64 || _M_IA64 || _M_ARM)
|
|
1118
|
+
unsigned long r;
|
|
1119
|
+
_BitScanReverse (&r, x);
|
|
1120
|
+
return (int)r;
|
|
1121
|
+
#else
|
|
1122
|
+
int r = 0;
|
|
1123
|
+
|
|
1124
|
+
if (x >> 16) { x >>= 16; r += 16; }
|
|
1125
|
+
if (x >> 8) { x >>= 8; r += 8; }
|
|
1126
|
+
if (x >> 4) { x >>= 4; r += 4; }
|
|
1127
|
+
if (x >> 2) { x >>= 2; r += 2; }
|
|
1128
|
+
if (x >> 1) { r += 1; }
|
|
1129
|
+
|
|
1130
|
+
return r;
|
|
1131
|
+
#endif
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
ecb_function_ ecb_const int ecb_ld64 (uint64_t x);
|
|
1135
|
+
ecb_function_ ecb_const int ecb_ld64 (uint64_t x)
|
|
1136
|
+
{
|
|
1137
|
+
#if 1400 <= _MSC_VER && (_M_X64 || _M_IA64 || _M_ARM)
|
|
1138
|
+
unsigned long r;
|
|
1139
|
+
_BitScanReverse64 (&r, x);
|
|
1140
|
+
return (int)r;
|
|
1141
|
+
#else
|
|
1142
|
+
int r = 0;
|
|
1143
|
+
|
|
1144
|
+
if (x >> 32) { x >>= 32; r += 32; }
|
|
1145
|
+
|
|
1146
|
+
return r + ecb_ld32 (x);
|
|
1147
|
+
#endif
|
|
1148
|
+
}
|
|
1149
|
+
#endif
|
|
1150
|
+
|
|
1151
|
+
ecb_function_ ecb_const ecb_bool ecb_is_pot32 (uint32_t x);
|
|
1152
|
+
ecb_function_ ecb_const ecb_bool ecb_is_pot32 (uint32_t x) { return !(x & (x - 1)); }
|
|
1153
|
+
ecb_function_ ecb_const ecb_bool ecb_is_pot64 (uint64_t x);
|
|
1154
|
+
ecb_function_ ecb_const ecb_bool ecb_is_pot64 (uint64_t x) { return !(x & (x - 1)); }
|
|
1155
|
+
|
|
1156
|
+
ecb_function_ ecb_const uint8_t ecb_bitrev8 (uint8_t x);
|
|
1157
|
+
ecb_function_ ecb_const uint8_t ecb_bitrev8 (uint8_t x)
|
|
1158
|
+
{
|
|
1159
|
+
return ( (x * 0x0802U & 0x22110U)
|
|
1160
|
+
| (x * 0x8020U & 0x88440U)) * 0x10101U >> 16;
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
ecb_function_ ecb_const uint16_t ecb_bitrev16 (uint16_t x);
|
|
1164
|
+
ecb_function_ ecb_const uint16_t ecb_bitrev16 (uint16_t x)
|
|
1165
|
+
{
|
|
1166
|
+
x = ((x >> 1) & 0x5555) | ((x & 0x5555) << 1);
|
|
1167
|
+
x = ((x >> 2) & 0x3333) | ((x & 0x3333) << 2);
|
|
1168
|
+
x = ((x >> 4) & 0x0f0f) | ((x & 0x0f0f) << 4);
|
|
1169
|
+
x = ( x >> 8 ) | ( x << 8);
|
|
1170
|
+
|
|
1171
|
+
return x;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
ecb_function_ ecb_const uint32_t ecb_bitrev32 (uint32_t x);
|
|
1175
|
+
ecb_function_ ecb_const uint32_t ecb_bitrev32 (uint32_t x)
|
|
1176
|
+
{
|
|
1177
|
+
x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1);
|
|
1178
|
+
x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2);
|
|
1179
|
+
x = ((x >> 4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) << 4);
|
|
1180
|
+
x = ((x >> 8) & 0x00ff00ff) | ((x & 0x00ff00ff) << 8);
|
|
1181
|
+
x = ( x >> 16 ) | ( x << 16);
|
|
1182
|
+
|
|
1183
|
+
return x;
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
/* popcount64 is only available on 64 bit cpus as gcc builtin */
|
|
1187
|
+
/* so for this version we are lazy */
|
|
1188
|
+
ecb_function_ ecb_const int ecb_popcount64 (uint64_t x);
|
|
1189
|
+
ecb_function_ ecb_const int
|
|
1190
|
+
ecb_popcount64 (uint64_t x)
|
|
1191
|
+
{
|
|
1192
|
+
return ecb_popcount32 (x) + ecb_popcount32 (x >> 32);
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
ecb_inline ecb_const uint8_t ecb_rotl8 (uint8_t x, unsigned int count);
|
|
1196
|
+
ecb_inline ecb_const uint8_t ecb_rotr8 (uint8_t x, unsigned int count);
|
|
1197
|
+
ecb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count);
|
|
1198
|
+
ecb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count);
|
|
1199
|
+
ecb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count);
|
|
1200
|
+
ecb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count);
|
|
1201
|
+
ecb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count);
|
|
1202
|
+
ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count);
|
|
1203
|
+
|
|
1204
|
+
ecb_inline ecb_const uint8_t ecb_rotl8 (uint8_t x, unsigned int count) { return (x >> ( 8 - count)) | (x << count); }
|
|
1205
|
+
ecb_inline ecb_const uint8_t ecb_rotr8 (uint8_t x, unsigned int count) { return (x << ( 8 - count)) | (x >> count); }
|
|
1206
|
+
ecb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count) { return (x >> (16 - count)) | (x << count); }
|
|
1207
|
+
ecb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count) { return (x << (16 - count)) | (x >> count); }
|
|
1208
|
+
ecb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count) { return (x >> (32 - count)) | (x << count); }
|
|
1209
|
+
ecb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count) { return (x << (32 - count)) | (x >> count); }
|
|
1210
|
+
ecb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count) { return (x >> (64 - count)) | (x << count); }
|
|
1211
|
+
ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (64 - count)) | (x >> count); }
|
|
1212
|
+
|
|
1213
|
+
#if ECB_CPP
|
|
1214
|
+
|
|
1215
|
+
inline uint8_t ecb_ctz (uint8_t v) { return ecb_ctz32 (v); }
|
|
1216
|
+
inline uint16_t ecb_ctz (uint16_t v) { return ecb_ctz32 (v); }
|
|
1217
|
+
inline uint32_t ecb_ctz (uint32_t v) { return ecb_ctz32 (v); }
|
|
1218
|
+
inline uint64_t ecb_ctz (uint64_t v) { return ecb_ctz64 (v); }
|
|
1219
|
+
|
|
1220
|
+
inline bool ecb_is_pot (uint8_t v) { return ecb_is_pot32 (v); }
|
|
1221
|
+
inline bool ecb_is_pot (uint16_t v) { return ecb_is_pot32 (v); }
|
|
1222
|
+
inline bool ecb_is_pot (uint32_t v) { return ecb_is_pot32 (v); }
|
|
1223
|
+
inline bool ecb_is_pot (uint64_t v) { return ecb_is_pot64 (v); }
|
|
1224
|
+
|
|
1225
|
+
inline int ecb_ld (uint8_t v) { return ecb_ld32 (v); }
|
|
1226
|
+
inline int ecb_ld (uint16_t v) { return ecb_ld32 (v); }
|
|
1227
|
+
inline int ecb_ld (uint32_t v) { return ecb_ld32 (v); }
|
|
1228
|
+
inline int ecb_ld (uint64_t v) { return ecb_ld64 (v); }
|
|
1229
|
+
|
|
1230
|
+
inline int ecb_popcount (uint8_t v) { return ecb_popcount32 (v); }
|
|
1231
|
+
inline int ecb_popcount (uint16_t v) { return ecb_popcount32 (v); }
|
|
1232
|
+
inline int ecb_popcount (uint32_t v) { return ecb_popcount32 (v); }
|
|
1233
|
+
inline int ecb_popcount (uint64_t v) { return ecb_popcount64 (v); }
|
|
1234
|
+
|
|
1235
|
+
inline uint8_t ecb_bitrev (uint8_t v) { return ecb_bitrev8 (v); }
|
|
1236
|
+
inline uint16_t ecb_bitrev (uint16_t v) { return ecb_bitrev16 (v); }
|
|
1237
|
+
inline uint32_t ecb_bitrev (uint32_t v) { return ecb_bitrev32 (v); }
|
|
1238
|
+
|
|
1239
|
+
inline uint8_t ecb_rotl (uint8_t v, unsigned int count) { return ecb_rotl8 (v, count); }
|
|
1240
|
+
inline uint16_t ecb_rotl (uint16_t v, unsigned int count) { return ecb_rotl16 (v, count); }
|
|
1241
|
+
inline uint32_t ecb_rotl (uint32_t v, unsigned int count) { return ecb_rotl32 (v, count); }
|
|
1242
|
+
inline uint64_t ecb_rotl (uint64_t v, unsigned int count) { return ecb_rotl64 (v, count); }
|
|
1243
|
+
|
|
1244
|
+
inline uint8_t ecb_rotr (uint8_t v, unsigned int count) { return ecb_rotr8 (v, count); }
|
|
1245
|
+
inline uint16_t ecb_rotr (uint16_t v, unsigned int count) { return ecb_rotr16 (v, count); }
|
|
1246
|
+
inline uint32_t ecb_rotr (uint32_t v, unsigned int count) { return ecb_rotr32 (v, count); }
|
|
1247
|
+
inline uint64_t ecb_rotr (uint64_t v, unsigned int count) { return ecb_rotr64 (v, count); }
|
|
1248
|
+
|
|
472
1249
|
#endif
|
|
473
1250
|
|
|
474
|
-
#
|
|
475
|
-
#
|
|
476
|
-
#define
|
|
1251
|
+
#if ECB_GCC_VERSION(4,3) || (ECB_CLANG_BUILTIN(__builtin_bswap32) && ECB_CLANG_BUILTIN(__builtin_bswap64))
|
|
1252
|
+
#if ECB_GCC_VERSION(4,8) || ECB_CLANG_BUILTIN(__builtin_bswap16)
|
|
1253
|
+
#define ecb_bswap16(x) __builtin_bswap16 (x)
|
|
1254
|
+
#else
|
|
1255
|
+
#define ecb_bswap16(x) (__builtin_bswap32 (x) >> 16)
|
|
1256
|
+
#endif
|
|
1257
|
+
#define ecb_bswap32(x) __builtin_bswap32 (x)
|
|
1258
|
+
#define ecb_bswap64(x) __builtin_bswap64 (x)
|
|
1259
|
+
#elif _MSC_VER
|
|
1260
|
+
#include <stdlib.h>
|
|
1261
|
+
#define ecb_bswap16(x) ((uint16_t)_byteswap_ushort ((uint16_t)(x)))
|
|
1262
|
+
#define ecb_bswap32(x) ((uint32_t)_byteswap_ulong ((uint32_t)(x)))
|
|
1263
|
+
#define ecb_bswap64(x) ((uint64_t)_byteswap_uint64 ((uint64_t)(x)))
|
|
1264
|
+
#else
|
|
1265
|
+
ecb_function_ ecb_const uint16_t ecb_bswap16 (uint16_t x);
|
|
1266
|
+
ecb_function_ ecb_const uint16_t
|
|
1267
|
+
ecb_bswap16 (uint16_t x)
|
|
1268
|
+
{
|
|
1269
|
+
return ecb_rotl16 (x, 8);
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
ecb_function_ ecb_const uint32_t ecb_bswap32 (uint32_t x);
|
|
1273
|
+
ecb_function_ ecb_const uint32_t
|
|
1274
|
+
ecb_bswap32 (uint32_t x)
|
|
1275
|
+
{
|
|
1276
|
+
return (((uint32_t)ecb_bswap16 (x)) << 16) | ecb_bswap16 (x >> 16);
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
ecb_function_ ecb_const uint64_t ecb_bswap64 (uint64_t x);
|
|
1280
|
+
ecb_function_ ecb_const uint64_t
|
|
1281
|
+
ecb_bswap64 (uint64_t x)
|
|
1282
|
+
{
|
|
1283
|
+
return (((uint64_t)ecb_bswap32 (x)) << 32) | ecb_bswap32 (x >> 32);
|
|
1284
|
+
}
|
|
1285
|
+
#endif
|
|
1286
|
+
|
|
1287
|
+
#if ECB_GCC_VERSION(4,5) || ECB_CLANG_BUILTIN(__builtin_unreachable)
|
|
1288
|
+
#define ecb_unreachable() __builtin_unreachable ()
|
|
1289
|
+
#else
|
|
1290
|
+
/* this seems to work fine, but gcc always emits a warning for it :/ */
|
|
1291
|
+
ecb_inline ecb_noreturn void ecb_unreachable (void);
|
|
1292
|
+
ecb_inline ecb_noreturn void ecb_unreachable (void) { }
|
|
1293
|
+
#endif
|
|
1294
|
+
|
|
1295
|
+
/* try to tell the compiler that some condition is definitely true */
|
|
1296
|
+
#define ecb_assume(cond) if (!(cond)) ecb_unreachable (); else 0
|
|
1297
|
+
|
|
1298
|
+
ecb_inline ecb_const uint32_t ecb_byteorder_helper (void);
|
|
1299
|
+
ecb_inline ecb_const uint32_t
|
|
1300
|
+
ecb_byteorder_helper (void)
|
|
1301
|
+
{
|
|
1302
|
+
/* the union code still generates code under pressure in gcc, */
|
|
1303
|
+
/* but less than using pointers, and always seems to */
|
|
1304
|
+
/* successfully return a constant. */
|
|
1305
|
+
/* the reason why we have this horrible preprocessor mess */
|
|
1306
|
+
/* is to avoid it in all cases, at least on common architectures */
|
|
1307
|
+
/* or when using a recent enough gcc version (>= 4.6) */
|
|
1308
|
+
#if (defined __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \
|
|
1309
|
+
|| ((__i386 || __i386__ || _M_IX86 || ECB_GCC_AMD64 || ECB_MSVC_AMD64) && !__VOS__)
|
|
1310
|
+
#define ECB_LITTLE_ENDIAN 1
|
|
1311
|
+
return 0x44332211;
|
|
1312
|
+
#elif (defined __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) \
|
|
1313
|
+
|| ((__AARCH64EB__ || __MIPSEB__ || __ARMEB__) && !__VOS__)
|
|
1314
|
+
#define ECB_BIG_ENDIAN 1
|
|
1315
|
+
return 0x11223344;
|
|
1316
|
+
#else
|
|
1317
|
+
union
|
|
1318
|
+
{
|
|
1319
|
+
uint8_t c[4];
|
|
1320
|
+
uint32_t u;
|
|
1321
|
+
} u = { 0x11, 0x22, 0x33, 0x44 };
|
|
1322
|
+
return u.u;
|
|
1323
|
+
#endif
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
ecb_inline ecb_const ecb_bool ecb_big_endian (void);
|
|
1327
|
+
ecb_inline ecb_const ecb_bool ecb_big_endian (void) { return ecb_byteorder_helper () == 0x11223344; }
|
|
1328
|
+
ecb_inline ecb_const ecb_bool ecb_little_endian (void);
|
|
1329
|
+
ecb_inline ecb_const ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44332211; }
|
|
1330
|
+
|
|
1331
|
+
/*****************************************************************************/
|
|
1332
|
+
/* unaligned load/store */
|
|
1333
|
+
|
|
1334
|
+
ecb_inline uint_fast16_t ecb_be_u16_to_host (uint_fast16_t v) { return ecb_little_endian () ? ecb_bswap16 (v) : v; }
|
|
1335
|
+
ecb_inline uint_fast32_t ecb_be_u32_to_host (uint_fast32_t v) { return ecb_little_endian () ? ecb_bswap32 (v) : v; }
|
|
1336
|
+
ecb_inline uint_fast64_t ecb_be_u64_to_host (uint_fast64_t v) { return ecb_little_endian () ? ecb_bswap64 (v) : v; }
|
|
1337
|
+
|
|
1338
|
+
ecb_inline uint_fast16_t ecb_le_u16_to_host (uint_fast16_t v) { return ecb_big_endian () ? ecb_bswap16 (v) : v; }
|
|
1339
|
+
ecb_inline uint_fast32_t ecb_le_u32_to_host (uint_fast32_t v) { return ecb_big_endian () ? ecb_bswap32 (v) : v; }
|
|
1340
|
+
ecb_inline uint_fast64_t ecb_le_u64_to_host (uint_fast64_t v) { return ecb_big_endian () ? ecb_bswap64 (v) : v; }
|
|
1341
|
+
|
|
1342
|
+
ecb_inline uint_fast16_t ecb_peek_u16_u (const void *ptr) { uint16_t v; memcpy (&v, ptr, sizeof (v)); return v; }
|
|
1343
|
+
ecb_inline uint_fast32_t ecb_peek_u32_u (const void *ptr) { uint32_t v; memcpy (&v, ptr, sizeof (v)); return v; }
|
|
1344
|
+
ecb_inline uint_fast64_t ecb_peek_u64_u (const void *ptr) { uint64_t v; memcpy (&v, ptr, sizeof (v)); return v; }
|
|
1345
|
+
|
|
1346
|
+
ecb_inline uint_fast16_t ecb_peek_be_u16_u (const void *ptr) { return ecb_be_u16_to_host (ecb_peek_u16_u (ptr)); }
|
|
1347
|
+
ecb_inline uint_fast32_t ecb_peek_be_u32_u (const void *ptr) { return ecb_be_u32_to_host (ecb_peek_u32_u (ptr)); }
|
|
1348
|
+
ecb_inline uint_fast64_t ecb_peek_be_u64_u (const void *ptr) { return ecb_be_u64_to_host (ecb_peek_u64_u (ptr)); }
|
|
1349
|
+
|
|
1350
|
+
ecb_inline uint_fast16_t ecb_peek_le_u16_u (const void *ptr) { return ecb_le_u16_to_host (ecb_peek_u16_u (ptr)); }
|
|
1351
|
+
ecb_inline uint_fast32_t ecb_peek_le_u32_u (const void *ptr) { return ecb_le_u32_to_host (ecb_peek_u32_u (ptr)); }
|
|
1352
|
+
ecb_inline uint_fast64_t ecb_peek_le_u64_u (const void *ptr) { return ecb_le_u64_to_host (ecb_peek_u64_u (ptr)); }
|
|
1353
|
+
|
|
1354
|
+
ecb_inline uint_fast16_t ecb_host_to_be_u16 (uint_fast16_t v) { return ecb_little_endian () ? ecb_bswap16 (v) : v; }
|
|
1355
|
+
ecb_inline uint_fast32_t ecb_host_to_be_u32 (uint_fast32_t v) { return ecb_little_endian () ? ecb_bswap32 (v) : v; }
|
|
1356
|
+
ecb_inline uint_fast64_t ecb_host_to_be_u64 (uint_fast64_t v) { return ecb_little_endian () ? ecb_bswap64 (v) : v; }
|
|
1357
|
+
|
|
1358
|
+
ecb_inline uint_fast16_t ecb_host_to_le_u16 (uint_fast16_t v) { return ecb_big_endian () ? ecb_bswap16 (v) : v; }
|
|
1359
|
+
ecb_inline uint_fast32_t ecb_host_to_le_u32 (uint_fast32_t v) { return ecb_big_endian () ? ecb_bswap32 (v) : v; }
|
|
1360
|
+
ecb_inline uint_fast64_t ecb_host_to_le_u64 (uint_fast64_t v) { return ecb_big_endian () ? ecb_bswap64 (v) : v; }
|
|
1361
|
+
|
|
1362
|
+
ecb_inline void ecb_poke_u16_u (void *ptr, uint16_t v) { memcpy (ptr, &v, sizeof (v)); }
|
|
1363
|
+
ecb_inline void ecb_poke_u32_u (void *ptr, uint32_t v) { memcpy (ptr, &v, sizeof (v)); }
|
|
1364
|
+
ecb_inline void ecb_poke_u64_u (void *ptr, uint64_t v) { memcpy (ptr, &v, sizeof (v)); }
|
|
1365
|
+
|
|
1366
|
+
ecb_inline void ecb_poke_be_u16_u (void *ptr, uint_fast16_t v) { ecb_poke_u16_u (ptr, ecb_host_to_be_u16 (v)); }
|
|
1367
|
+
ecb_inline void ecb_poke_be_u32_u (void *ptr, uint_fast32_t v) { ecb_poke_u32_u (ptr, ecb_host_to_be_u32 (v)); }
|
|
1368
|
+
ecb_inline void ecb_poke_be_u64_u (void *ptr, uint_fast64_t v) { ecb_poke_u64_u (ptr, ecb_host_to_be_u64 (v)); }
|
|
1369
|
+
|
|
1370
|
+
ecb_inline void ecb_poke_le_u16_u (void *ptr, uint_fast16_t v) { ecb_poke_u16_u (ptr, ecb_host_to_le_u16 (v)); }
|
|
1371
|
+
ecb_inline void ecb_poke_le_u32_u (void *ptr, uint_fast32_t v) { ecb_poke_u32_u (ptr, ecb_host_to_le_u32 (v)); }
|
|
1372
|
+
ecb_inline void ecb_poke_le_u64_u (void *ptr, uint_fast64_t v) { ecb_poke_u64_u (ptr, ecb_host_to_le_u64 (v)); }
|
|
1373
|
+
|
|
1374
|
+
#if ECB_CPP
|
|
1375
|
+
|
|
1376
|
+
inline uint8_t ecb_bswap (uint8_t v) { return v; }
|
|
1377
|
+
inline uint16_t ecb_bswap (uint16_t v) { return ecb_bswap16 (v); }
|
|
1378
|
+
inline uint32_t ecb_bswap (uint32_t v) { return ecb_bswap32 (v); }
|
|
1379
|
+
inline uint64_t ecb_bswap (uint64_t v) { return ecb_bswap64 (v); }
|
|
1380
|
+
|
|
1381
|
+
template<typename T> inline T ecb_be_to_host (T v) { return ecb_little_endian () ? ecb_bswap (v) : v; }
|
|
1382
|
+
template<typename T> inline T ecb_le_to_host (T v) { return ecb_big_endian () ? ecb_bswap (v) : v; }
|
|
1383
|
+
template<typename T> inline T ecb_peek (const void *ptr) { return *(const T *)ptr; }
|
|
1384
|
+
template<typename T> inline T ecb_peek_be (const void *ptr) { return ecb_be_to_host (ecb_peek <T> (ptr)); }
|
|
1385
|
+
template<typename T> inline T ecb_peek_le (const void *ptr) { return ecb_le_to_host (ecb_peek <T> (ptr)); }
|
|
1386
|
+
template<typename T> inline T ecb_peek_u (const void *ptr) { T v; memcpy (&v, ptr, sizeof (v)); return v; }
|
|
1387
|
+
template<typename T> inline T ecb_peek_be_u (const void *ptr) { return ecb_be_to_host (ecb_peek_u<T> (ptr)); }
|
|
1388
|
+
template<typename T> inline T ecb_peek_le_u (const void *ptr) { return ecb_le_to_host (ecb_peek_u<T> (ptr)); }
|
|
1389
|
+
|
|
1390
|
+
template<typename T> inline T ecb_host_to_be (T v) { return ecb_little_endian () ? ecb_bswap (v) : v; }
|
|
1391
|
+
template<typename T> inline T ecb_host_to_le (T v) { return ecb_big_endian () ? ecb_bswap (v) : v; }
|
|
1392
|
+
template<typename T> inline void ecb_poke (void *ptr, T v) { *(T *)ptr = v; }
|
|
1393
|
+
template<typename T> inline void ecb_poke_be (void *ptr, T v) { return ecb_poke <T> (ptr, ecb_host_to_be (v)); }
|
|
1394
|
+
template<typename T> inline void ecb_poke_le (void *ptr, T v) { return ecb_poke <T> (ptr, ecb_host_to_le (v)); }
|
|
1395
|
+
template<typename T> inline void ecb_poke_u (void *ptr, T v) { memcpy (ptr, &v, sizeof (v)); }
|
|
1396
|
+
template<typename T> inline void ecb_poke_be_u (void *ptr, T v) { return ecb_poke_u<T> (ptr, ecb_host_to_be (v)); }
|
|
1397
|
+
template<typename T> inline void ecb_poke_le_u (void *ptr, T v) { return ecb_poke_u<T> (ptr, ecb_host_to_le (v)); }
|
|
1398
|
+
|
|
1399
|
+
#endif
|
|
1400
|
+
|
|
1401
|
+
/*****************************************************************************/
|
|
1402
|
+
|
|
1403
|
+
#if ECB_GCC_VERSION(3,0) || ECB_C99
|
|
1404
|
+
#define ecb_mod(m,n) ((m) % (n) + ((m) % (n) < 0 ? (n) : 0))
|
|
1405
|
+
#else
|
|
1406
|
+
#define ecb_mod(m,n) ((m) < 0 ? ((n) - 1 - ((-1 - (m)) % (n))) : ((m) % (n)))
|
|
1407
|
+
#endif
|
|
1408
|
+
|
|
1409
|
+
#if ECB_CPP
|
|
1410
|
+
template<typename T>
|
|
1411
|
+
static inline T ecb_div_rd (T val, T div)
|
|
1412
|
+
{
|
|
1413
|
+
return val < 0 ? - ((-val + div - 1) / div) : (val ) / div;
|
|
1414
|
+
}
|
|
1415
|
+
template<typename T>
|
|
1416
|
+
static inline T ecb_div_ru (T val, T div)
|
|
1417
|
+
{
|
|
1418
|
+
return val < 0 ? - ((-val ) / div) : (val + div - 1) / div;
|
|
1419
|
+
}
|
|
1420
|
+
#else
|
|
1421
|
+
#define ecb_div_rd(val,div) ((val) < 0 ? - ((-(val) + (div) - 1) / (div)) : ((val) ) / (div))
|
|
1422
|
+
#define ecb_div_ru(val,div) ((val) < 0 ? - ((-(val) ) / (div)) : ((val) + (div) - 1) / (div))
|
|
1423
|
+
#endif
|
|
1424
|
+
|
|
1425
|
+
#if ecb_cplusplus_does_not_suck
|
|
1426
|
+
/* does not work for local types (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm) */
|
|
1427
|
+
template<typename T, int N>
|
|
1428
|
+
static inline int ecb_array_length (const T (&arr)[N])
|
|
1429
|
+
{
|
|
1430
|
+
return N;
|
|
1431
|
+
}
|
|
1432
|
+
#else
|
|
1433
|
+
#define ecb_array_length(name) (sizeof (name) / sizeof (name [0]))
|
|
1434
|
+
#endif
|
|
1435
|
+
|
|
1436
|
+
/*****************************************************************************/
|
|
1437
|
+
|
|
1438
|
+
ecb_function_ ecb_const uint32_t ecb_binary16_to_binary32 (uint32_t x);
|
|
1439
|
+
ecb_function_ ecb_const uint32_t
|
|
1440
|
+
ecb_binary16_to_binary32 (uint32_t x)
|
|
1441
|
+
{
|
|
1442
|
+
unsigned int s = (x & 0x8000) << (31 - 15);
|
|
1443
|
+
int e = (x >> 10) & 0x001f;
|
|
1444
|
+
unsigned int m = x & 0x03ff;
|
|
1445
|
+
|
|
1446
|
+
if (ecb_expect_false (e == 31))
|
|
1447
|
+
/* infinity or NaN */
|
|
1448
|
+
e = 255 - (127 - 15);
|
|
1449
|
+
else if (ecb_expect_false (!e))
|
|
1450
|
+
{
|
|
1451
|
+
if (ecb_expect_true (!m))
|
|
1452
|
+
/* zero, handled by code below by forcing e to 0 */
|
|
1453
|
+
e = 0 - (127 - 15);
|
|
1454
|
+
else
|
|
1455
|
+
{
|
|
1456
|
+
/* subnormal, renormalise */
|
|
1457
|
+
unsigned int s = 10 - ecb_ld32 (m);
|
|
1458
|
+
|
|
1459
|
+
m = (m << s) & 0x3ff; /* mask implicit bit */
|
|
1460
|
+
e -= s - 1;
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
/* e and m now are normalised, or zero, (or inf or nan) */
|
|
1465
|
+
e += 127 - 15;
|
|
1466
|
+
|
|
1467
|
+
return s | (e << 23) | (m << (23 - 10));
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
ecb_function_ ecb_const uint16_t ecb_binary32_to_binary16 (uint32_t x);
|
|
1471
|
+
ecb_function_ ecb_const uint16_t
|
|
1472
|
+
ecb_binary32_to_binary16 (uint32_t x)
|
|
1473
|
+
{
|
|
1474
|
+
unsigned int s = (x >> 16) & 0x00008000; /* sign bit, the easy part */
|
|
1475
|
+
unsigned int e = ((x >> 23) & 0x000000ff) - (127 - 15); /* the desired exponent */
|
|
1476
|
+
unsigned int m = x & 0x007fffff;
|
|
1477
|
+
|
|
1478
|
+
x &= 0x7fffffff;
|
|
1479
|
+
|
|
1480
|
+
/* if it's within range of binary16 normals, use fast path */
|
|
1481
|
+
if (ecb_expect_true (0x38800000 <= x && x <= 0x477fefff))
|
|
1482
|
+
{
|
|
1483
|
+
/* mantissa round-to-even */
|
|
1484
|
+
m += 0x00000fff + ((m >> (23 - 10)) & 1);
|
|
1485
|
+
|
|
1486
|
+
/* handle overflow */
|
|
1487
|
+
if (ecb_expect_false (m >= 0x00800000))
|
|
1488
|
+
{
|
|
1489
|
+
m >>= 1;
|
|
1490
|
+
e += 1;
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
return s | (e << 10) | (m >> (23 - 10));
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
/* handle large numbers and infinity */
|
|
1497
|
+
if (ecb_expect_true (0x477fefff < x && x <= 0x7f800000))
|
|
1498
|
+
return s | 0x7c00;
|
|
1499
|
+
|
|
1500
|
+
/* handle zero, subnormals and small numbers */
|
|
1501
|
+
if (ecb_expect_true (x < 0x38800000))
|
|
1502
|
+
{
|
|
1503
|
+
/* zero */
|
|
1504
|
+
if (ecb_expect_true (!x))
|
|
1505
|
+
return s;
|
|
1506
|
+
|
|
1507
|
+
/* handle subnormals */
|
|
1508
|
+
|
|
1509
|
+
/* too small, will be zero */
|
|
1510
|
+
if (e < (14 - 24)) /* might not be sharp, but is good enough */
|
|
1511
|
+
return s;
|
|
1512
|
+
|
|
1513
|
+
m |= 0x00800000; /* make implicit bit explicit */
|
|
1514
|
+
|
|
1515
|
+
/* very tricky - we need to round to the nearest e (+10) bit value */
|
|
1516
|
+
{
|
|
1517
|
+
unsigned int bits = 14 - e;
|
|
1518
|
+
unsigned int half = (1 << (bits - 1)) - 1;
|
|
1519
|
+
unsigned int even = (m >> bits) & 1;
|
|
1520
|
+
|
|
1521
|
+
/* if this overflows, we will end up with a normalised number */
|
|
1522
|
+
m = (m + half + even) >> bits;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
return s | m;
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
/* handle NaNs, preserve leftmost nan bits, but make sure we don't turn them into infinities */
|
|
1529
|
+
m >>= 13;
|
|
1530
|
+
|
|
1531
|
+
return s | 0x7c00 | m | !m;
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
/*******************************************************************************/
|
|
1535
|
+
/* floating point stuff, can be disabled by defining ECB_NO_LIBM */
|
|
1536
|
+
|
|
1537
|
+
/* basically, everything uses "ieee pure-endian" floating point numbers */
|
|
1538
|
+
/* the only noteworthy exception is ancient armle, which uses order 43218765 */
|
|
1539
|
+
#if 0 \
|
|
1540
|
+
|| __i386 || __i386__ \
|
|
1541
|
+
|| ECB_GCC_AMD64 \
|
|
1542
|
+
|| __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__ \
|
|
1543
|
+
|| defined __s390__ || defined __s390x__ \
|
|
1544
|
+
|| defined __mips__ \
|
|
1545
|
+
|| defined __alpha__ \
|
|
1546
|
+
|| defined __hppa__ \
|
|
1547
|
+
|| defined __ia64__ \
|
|
1548
|
+
|| defined __m68k__ \
|
|
1549
|
+
|| defined __m88k__ \
|
|
1550
|
+
|| defined __sh__ \
|
|
1551
|
+
|| defined _M_IX86 || defined ECB_MSVC_AMD64 || defined _M_IA64 \
|
|
1552
|
+
|| (defined __arm__ && (defined __ARM_EABI__ || defined __EABI__ || defined __VFP_FP__ || defined _WIN32_WCE || defined __ANDROID__)) \
|
|
1553
|
+
|| defined __aarch64__
|
|
1554
|
+
#define ECB_STDFP 1
|
|
1555
|
+
#else
|
|
1556
|
+
#define ECB_STDFP 0
|
|
1557
|
+
#endif
|
|
1558
|
+
|
|
1559
|
+
#ifndef ECB_NO_LIBM
|
|
1560
|
+
|
|
1561
|
+
#include <math.h> /* for frexp*, ldexp*, INFINITY, NAN */
|
|
1562
|
+
|
|
1563
|
+
/* only the oldest of old doesn't have this one. solaris. */
|
|
1564
|
+
#ifdef INFINITY
|
|
1565
|
+
#define ECB_INFINITY INFINITY
|
|
1566
|
+
#else
|
|
1567
|
+
#define ECB_INFINITY HUGE_VAL
|
|
1568
|
+
#endif
|
|
1569
|
+
|
|
1570
|
+
#ifdef NAN
|
|
1571
|
+
#define ECB_NAN NAN
|
|
1572
|
+
#else
|
|
1573
|
+
#define ECB_NAN ECB_INFINITY
|
|
1574
|
+
#endif
|
|
1575
|
+
|
|
1576
|
+
#if ECB_C99 || _XOPEN_VERSION >= 600 || _POSIX_VERSION >= 200112L
|
|
1577
|
+
#define ecb_ldexpf(x,e) ldexpf ((x), (e))
|
|
1578
|
+
#define ecb_frexpf(x,e) frexpf ((x), (e))
|
|
1579
|
+
#else
|
|
1580
|
+
#define ecb_ldexpf(x,e) (float) ldexp ((double) (x), (e))
|
|
1581
|
+
#define ecb_frexpf(x,e) (float) frexp ((double) (x), (e))
|
|
1582
|
+
#endif
|
|
1583
|
+
|
|
1584
|
+
/* convert a float to ieee single/binary32 */
|
|
1585
|
+
ecb_function_ ecb_const uint32_t ecb_float_to_binary32 (float x);
|
|
1586
|
+
ecb_function_ ecb_const uint32_t
|
|
1587
|
+
ecb_float_to_binary32 (float x)
|
|
1588
|
+
{
|
|
1589
|
+
uint32_t r;
|
|
1590
|
+
|
|
1591
|
+
#if ECB_STDFP
|
|
1592
|
+
memcpy (&r, &x, 4);
|
|
1593
|
+
#else
|
|
1594
|
+
/* slow emulation, works for anything but -0 */
|
|
1595
|
+
uint32_t m;
|
|
1596
|
+
int e;
|
|
1597
|
+
|
|
1598
|
+
if (x == 0e0f ) return 0x00000000U;
|
|
1599
|
+
if (x > +3.40282346638528860e+38f) return 0x7f800000U;
|
|
1600
|
+
if (x < -3.40282346638528860e+38f) return 0xff800000U;
|
|
1601
|
+
if (x != x ) return 0x7fbfffffU;
|
|
1602
|
+
|
|
1603
|
+
m = ecb_frexpf (x, &e) * 0x1000000U;
|
|
1604
|
+
|
|
1605
|
+
r = m & 0x80000000U;
|
|
1606
|
+
|
|
1607
|
+
if (r)
|
|
1608
|
+
m = -m;
|
|
1609
|
+
|
|
1610
|
+
if (e <= -126)
|
|
1611
|
+
{
|
|
1612
|
+
m &= 0xffffffU;
|
|
1613
|
+
m >>= (-125 - e);
|
|
1614
|
+
e = -126;
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
r |= (e + 126) << 23;
|
|
1618
|
+
r |= m & 0x7fffffU;
|
|
1619
|
+
#endif
|
|
1620
|
+
|
|
1621
|
+
return r;
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
/* converts an ieee single/binary32 to a float */
|
|
1625
|
+
ecb_function_ ecb_const float ecb_binary32_to_float (uint32_t x);
|
|
1626
|
+
ecb_function_ ecb_const float
|
|
1627
|
+
ecb_binary32_to_float (uint32_t x)
|
|
1628
|
+
{
|
|
1629
|
+
float r;
|
|
1630
|
+
|
|
1631
|
+
#if ECB_STDFP
|
|
1632
|
+
memcpy (&r, &x, 4);
|
|
1633
|
+
#else
|
|
1634
|
+
/* emulation, only works for normals and subnormals and +0 */
|
|
1635
|
+
int neg = x >> 31;
|
|
1636
|
+
int e = (x >> 23) & 0xffU;
|
|
1637
|
+
|
|
1638
|
+
x &= 0x7fffffU;
|
|
1639
|
+
|
|
1640
|
+
if (e)
|
|
1641
|
+
x |= 0x800000U;
|
|
1642
|
+
else
|
|
1643
|
+
e = 1;
|
|
1644
|
+
|
|
1645
|
+
/* we distrust ldexpf a bit and do the 2**-24 scaling by an extra multiply */
|
|
1646
|
+
r = ecb_ldexpf (x * (0.5f / 0x800000U), e - 126);
|
|
1647
|
+
|
|
1648
|
+
r = neg ? -r : r;
|
|
1649
|
+
#endif
|
|
1650
|
+
|
|
1651
|
+
return r;
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
/* convert a double to ieee double/binary64 */
|
|
1655
|
+
ecb_function_ ecb_const uint64_t ecb_double_to_binary64 (double x);
|
|
1656
|
+
ecb_function_ ecb_const uint64_t
|
|
1657
|
+
ecb_double_to_binary64 (double x)
|
|
1658
|
+
{
|
|
1659
|
+
uint64_t r;
|
|
1660
|
+
|
|
1661
|
+
#if ECB_STDFP
|
|
1662
|
+
memcpy (&r, &x, 8);
|
|
1663
|
+
#else
|
|
1664
|
+
/* slow emulation, works for anything but -0 */
|
|
1665
|
+
uint64_t m;
|
|
1666
|
+
int e;
|
|
1667
|
+
|
|
1668
|
+
if (x == 0e0 ) return 0x0000000000000000U;
|
|
1669
|
+
if (x > +1.79769313486231470e+308) return 0x7ff0000000000000U;
|
|
1670
|
+
if (x < -1.79769313486231470e+308) return 0xfff0000000000000U;
|
|
1671
|
+
if (x != x ) return 0X7ff7ffffffffffffU;
|
|
1672
|
+
|
|
1673
|
+
m = frexp (x, &e) * 0x20000000000000U;
|
|
1674
|
+
|
|
1675
|
+
r = m & 0x8000000000000000;;
|
|
1676
|
+
|
|
1677
|
+
if (r)
|
|
1678
|
+
m = -m;
|
|
1679
|
+
|
|
1680
|
+
if (e <= -1022)
|
|
1681
|
+
{
|
|
1682
|
+
m &= 0x1fffffffffffffU;
|
|
1683
|
+
m >>= (-1021 - e);
|
|
1684
|
+
e = -1022;
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
r |= ((uint64_t)(e + 1022)) << 52;
|
|
1688
|
+
r |= m & 0xfffffffffffffU;
|
|
1689
|
+
#endif
|
|
1690
|
+
|
|
1691
|
+
return r;
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
/* converts an ieee double/binary64 to a double */
|
|
1695
|
+
ecb_function_ ecb_const double ecb_binary64_to_double (uint64_t x);
|
|
1696
|
+
ecb_function_ ecb_const double
|
|
1697
|
+
ecb_binary64_to_double (uint64_t x)
|
|
1698
|
+
{
|
|
1699
|
+
double r;
|
|
1700
|
+
|
|
1701
|
+
#if ECB_STDFP
|
|
1702
|
+
memcpy (&r, &x, 8);
|
|
1703
|
+
#else
|
|
1704
|
+
/* emulation, only works for normals and subnormals and +0 */
|
|
1705
|
+
int neg = x >> 63;
|
|
1706
|
+
int e = (x >> 52) & 0x7ffU;
|
|
1707
|
+
|
|
1708
|
+
x &= 0xfffffffffffffU;
|
|
1709
|
+
|
|
1710
|
+
if (e)
|
|
1711
|
+
x |= 0x10000000000000U;
|
|
1712
|
+
else
|
|
1713
|
+
e = 1;
|
|
1714
|
+
|
|
1715
|
+
/* we distrust ldexp a bit and do the 2**-53 scaling by an extra multiply */
|
|
1716
|
+
r = ldexp (x * (0.5 / 0x10000000000000U), e - 1022);
|
|
1717
|
+
|
|
1718
|
+
r = neg ? -r : r;
|
|
1719
|
+
#endif
|
|
1720
|
+
|
|
1721
|
+
return r;
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1724
|
+
/* convert a float to ieee half/binary16 */
|
|
1725
|
+
ecb_function_ ecb_const uint16_t ecb_float_to_binary16 (float x);
|
|
1726
|
+
ecb_function_ ecb_const uint16_t
|
|
1727
|
+
ecb_float_to_binary16 (float x)
|
|
1728
|
+
{
|
|
1729
|
+
return ecb_binary32_to_binary16 (ecb_float_to_binary32 (x));
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
/* convert an ieee half/binary16 to float */
|
|
1733
|
+
ecb_function_ ecb_const float ecb_binary16_to_float (uint16_t x);
|
|
1734
|
+
ecb_function_ ecb_const float
|
|
1735
|
+
ecb_binary16_to_float (uint16_t x)
|
|
1736
|
+
{
|
|
1737
|
+
return ecb_binary32_to_float (ecb_binary16_to_binary32 (x));
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
#endif
|
|
1741
|
+
|
|
1742
|
+
#endif
|
|
1743
|
+
|
|
1744
|
+
/* ECB.H END */
|
|
1745
|
+
|
|
1746
|
+
#if ECB_MEMORY_FENCE_NEEDS_PTHREADS
|
|
1747
|
+
/* if your architecture doesn't need memory fences, e.g. because it is
|
|
1748
|
+
* single-cpu/core, or if you use libev in a project that doesn't use libev
|
|
1749
|
+
* from multiple threads, then you can define ECB_NO_THREADS when compiling
|
|
1750
|
+
* libev, in which cases the memory fences become nops.
|
|
1751
|
+
* alternatively, you can remove this #error and link against libpthread,
|
|
1752
|
+
* which will then provide the memory fences.
|
|
1753
|
+
*/
|
|
1754
|
+
# error "memory fences not defined for your architecture, please report"
|
|
1755
|
+
#endif
|
|
1756
|
+
|
|
1757
|
+
#ifndef ECB_MEMORY_FENCE
|
|
1758
|
+
# define ECB_MEMORY_FENCE do { } while (0)
|
|
1759
|
+
# define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE
|
|
1760
|
+
# define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE
|
|
1761
|
+
#endif
|
|
1762
|
+
|
|
1763
|
+
#define inline_size ecb_inline
|
|
477
1764
|
|
|
478
1765
|
#if EV_FEATURE_CODE
|
|
479
|
-
# define inline_speed
|
|
1766
|
+
# define inline_speed ecb_inline
|
|
480
1767
|
#else
|
|
481
|
-
# define inline_speed static
|
|
1768
|
+
# define inline_speed ecb_noinline static
|
|
482
1769
|
#endif
|
|
483
1770
|
|
|
1771
|
+
/*****************************************************************************/
|
|
1772
|
+
/* raw syscall wrappers */
|
|
1773
|
+
|
|
1774
|
+
#if EV_NEED_SYSCALL
|
|
1775
|
+
|
|
1776
|
+
#include <sys/syscall.h>
|
|
1777
|
+
|
|
1778
|
+
/*
|
|
1779
|
+
* define some syscall wrappers for common architectures
|
|
1780
|
+
* this is mostly for nice looks during debugging, not performance.
|
|
1781
|
+
* our syscalls return < 0, not == -1, on error. which is good
|
|
1782
|
+
* enough for linux aio.
|
|
1783
|
+
* TODO: arm is also common nowadays, maybe even mips and x86
|
|
1784
|
+
* TODO: after implementing this, it suddenly looks like overkill, but its hard to remove...
|
|
1785
|
+
*/
|
|
1786
|
+
#if __GNUC__ && __linux && ECB_AMD64 && !EV_FEATURE_CODE
|
|
1787
|
+
/* the costly errno access probably kills this for size optimisation */
|
|
1788
|
+
|
|
1789
|
+
#define ev_syscall(nr,narg,arg1,arg2,arg3,arg4,arg5,arg6) \
|
|
1790
|
+
({ \
|
|
1791
|
+
long res; \
|
|
1792
|
+
register unsigned long r6 __asm__ ("r9" ); \
|
|
1793
|
+
register unsigned long r5 __asm__ ("r8" ); \
|
|
1794
|
+
register unsigned long r4 __asm__ ("r10"); \
|
|
1795
|
+
register unsigned long r3 __asm__ ("rdx"); \
|
|
1796
|
+
register unsigned long r2 __asm__ ("rsi"); \
|
|
1797
|
+
register unsigned long r1 __asm__ ("rdi"); \
|
|
1798
|
+
if (narg >= 6) r6 = (unsigned long)(arg6); \
|
|
1799
|
+
if (narg >= 5) r5 = (unsigned long)(arg5); \
|
|
1800
|
+
if (narg >= 4) r4 = (unsigned long)(arg4); \
|
|
1801
|
+
if (narg >= 3) r3 = (unsigned long)(arg3); \
|
|
1802
|
+
if (narg >= 2) r2 = (unsigned long)(arg2); \
|
|
1803
|
+
if (narg >= 1) r1 = (unsigned long)(arg1); \
|
|
1804
|
+
__asm__ __volatile__ ( \
|
|
1805
|
+
"syscall\n\t" \
|
|
1806
|
+
: "=a" (res) \
|
|
1807
|
+
: "0" (nr), "r" (r1), "r" (r2), "r" (r3), "r" (r4), "r" (r5) \
|
|
1808
|
+
: "cc", "r11", "cx", "memory"); \
|
|
1809
|
+
errno = -res; \
|
|
1810
|
+
res; \
|
|
1811
|
+
})
|
|
1812
|
+
|
|
1813
|
+
#endif
|
|
1814
|
+
|
|
1815
|
+
#ifdef ev_syscall
|
|
1816
|
+
#define ev_syscall0(nr) ev_syscall (nr, 0, 0, 0, 0, 0, 0, 0)
|
|
1817
|
+
#define ev_syscall1(nr,arg1) ev_syscall (nr, 1, arg1, 0, 0, 0, 0, 0)
|
|
1818
|
+
#define ev_syscall2(nr,arg1,arg2) ev_syscall (nr, 2, arg1, arg2, 0, 0, 0, 0)
|
|
1819
|
+
#define ev_syscall3(nr,arg1,arg2,arg3) ev_syscall (nr, 3, arg1, arg2, arg3, 0, 0, 0)
|
|
1820
|
+
#define ev_syscall4(nr,arg1,arg2,arg3,arg4) ev_syscall (nr, 3, arg1, arg2, arg3, arg4, 0, 0)
|
|
1821
|
+
#define ev_syscall5(nr,arg1,arg2,arg3,arg4,arg5) ev_syscall (nr, 5, arg1, arg2, arg3, arg4, arg5, 0)
|
|
1822
|
+
#define ev_syscall6(nr,arg1,arg2,arg3,arg4,arg5,arg6) ev_syscall (nr, 6, arg1, arg2, arg3, arg4, arg5,arg6)
|
|
1823
|
+
#else
|
|
1824
|
+
#define ev_syscall0(nr) syscall (nr)
|
|
1825
|
+
#define ev_syscall1(nr,arg1) syscall (nr, arg1)
|
|
1826
|
+
#define ev_syscall2(nr,arg1,arg2) syscall (nr, arg1, arg2)
|
|
1827
|
+
#define ev_syscall3(nr,arg1,arg2,arg3) syscall (nr, arg1, arg2, arg3)
|
|
1828
|
+
#define ev_syscall4(nr,arg1,arg2,arg3,arg4) syscall (nr, arg1, arg2, arg3, arg4)
|
|
1829
|
+
#define ev_syscall5(nr,arg1,arg2,arg3,arg4,arg5) syscall (nr, arg1, arg2, arg3, arg4, arg5)
|
|
1830
|
+
#define ev_syscall6(nr,arg1,arg2,arg3,arg4,arg5,arg6) syscall (nr, arg1, arg2, arg3, arg4, arg5,arg6)
|
|
1831
|
+
#endif
|
|
1832
|
+
|
|
1833
|
+
#endif
|
|
1834
|
+
|
|
1835
|
+
/*****************************************************************************/
|
|
1836
|
+
|
|
484
1837
|
#define NUMPRI (EV_MAXPRI - EV_MINPRI + 1)
|
|
485
1838
|
|
|
486
1839
|
#if EV_MINPRI == EV_MAXPRI
|
|
@@ -489,8 +1842,7 @@ struct signalfd_siginfo
|
|
|
489
1842
|
# define ABSPRI(w) (((W)w)->priority - EV_MINPRI)
|
|
490
1843
|
#endif
|
|
491
1844
|
|
|
492
|
-
#define EMPTY
|
|
493
|
-
#define EMPTY2(a,b) /* used to suppress some warnings */
|
|
1845
|
+
#define EMPTY /* required for microsofts broken pseudo-c compiler */
|
|
494
1846
|
|
|
495
1847
|
typedef ev_watcher *W;
|
|
496
1848
|
typedef ev_watcher_list *WL;
|
|
@@ -525,11 +1877,65 @@ static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work?
|
|
|
525
1877
|
|
|
526
1878
|
/*****************************************************************************/
|
|
527
1879
|
|
|
1880
|
+
#if EV_USE_LINUXAIO
|
|
1881
|
+
# include <linux/aio_abi.h> /* probably only needed for aio_context_t */
|
|
1882
|
+
#endif
|
|
1883
|
+
|
|
1884
|
+
/* define a suitable floor function (only used by periodics atm) */
|
|
1885
|
+
|
|
1886
|
+
#if EV_USE_FLOOR
|
|
1887
|
+
# include <math.h>
|
|
1888
|
+
# define ev_floor(v) floor (v)
|
|
1889
|
+
#else
|
|
1890
|
+
|
|
1891
|
+
#include <float.h>
|
|
1892
|
+
|
|
1893
|
+
/* a floor() replacement function, should be independent of ev_tstamp type */
|
|
1894
|
+
ecb_noinline
|
|
1895
|
+
static ev_tstamp
|
|
1896
|
+
ev_floor (ev_tstamp v)
|
|
1897
|
+
{
|
|
1898
|
+
/* the choice of shift factor is not terribly important */
|
|
1899
|
+
#if FLT_RADIX != 2 /* assume FLT_RADIX == 10 */
|
|
1900
|
+
const ev_tstamp shift = sizeof (unsigned long) >= 8 ? 10000000000000000000. : 1000000000.;
|
|
1901
|
+
#else
|
|
1902
|
+
const ev_tstamp shift = sizeof (unsigned long) >= 8 ? 18446744073709551616. : 4294967296.;
|
|
1903
|
+
#endif
|
|
1904
|
+
|
|
1905
|
+
/* special treatment for negative arguments */
|
|
1906
|
+
if (ecb_expect_false (v < 0.))
|
|
1907
|
+
{
|
|
1908
|
+
ev_tstamp f = -ev_floor (-v);
|
|
1909
|
+
|
|
1910
|
+
return f - (f == v ? 0 : 1);
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
/* argument too large for an unsigned long? then reduce it */
|
|
1914
|
+
if (ecb_expect_false (v >= shift))
|
|
1915
|
+
{
|
|
1916
|
+
ev_tstamp f;
|
|
1917
|
+
|
|
1918
|
+
if (v == v - 1.)
|
|
1919
|
+
return v; /* very large numbers are assumed to be integer */
|
|
1920
|
+
|
|
1921
|
+
f = shift * ev_floor (v * (1. / shift));
|
|
1922
|
+
return f + ev_floor (v - f);
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
/* fits into an unsigned long */
|
|
1926
|
+
return (unsigned long)v;
|
|
1927
|
+
}
|
|
1928
|
+
|
|
1929
|
+
#endif
|
|
1930
|
+
|
|
1931
|
+
/*****************************************************************************/
|
|
1932
|
+
|
|
528
1933
|
#ifdef __linux
|
|
529
1934
|
# include <sys/utsname.h>
|
|
530
1935
|
#endif
|
|
531
1936
|
|
|
532
|
-
|
|
1937
|
+
ecb_noinline ecb_cold
|
|
1938
|
+
static unsigned int
|
|
533
1939
|
ev_linux_version (void)
|
|
534
1940
|
{
|
|
535
1941
|
#ifdef __linux
|
|
@@ -568,22 +1974,25 @@ ev_linux_version (void)
|
|
|
568
1974
|
/*****************************************************************************/
|
|
569
1975
|
|
|
570
1976
|
#if EV_AVOID_STDIO
|
|
571
|
-
|
|
1977
|
+
ecb_noinline ecb_cold
|
|
1978
|
+
static void
|
|
572
1979
|
ev_printerr (const char *msg)
|
|
573
1980
|
{
|
|
574
1981
|
write (STDERR_FILENO, msg, strlen (msg));
|
|
575
1982
|
}
|
|
576
1983
|
#endif
|
|
577
1984
|
|
|
578
|
-
static void (*syserr_cb)(const char *msg);
|
|
1985
|
+
static void (*syserr_cb)(const char *msg) EV_NOEXCEPT;
|
|
579
1986
|
|
|
1987
|
+
ecb_cold
|
|
580
1988
|
void
|
|
581
|
-
ev_set_syserr_cb (void (*cb)(const char *msg))
|
|
1989
|
+
ev_set_syserr_cb (void (*cb)(const char *msg) EV_NOEXCEPT) EV_NOEXCEPT
|
|
582
1990
|
{
|
|
583
1991
|
syserr_cb = cb;
|
|
584
1992
|
}
|
|
585
1993
|
|
|
586
|
-
|
|
1994
|
+
ecb_noinline ecb_cold
|
|
1995
|
+
static void
|
|
587
1996
|
ev_syserr (const char *msg)
|
|
588
1997
|
{
|
|
589
1998
|
if (!msg)
|
|
@@ -606,14 +2015,13 @@ ev_syserr (const char *msg)
|
|
|
606
2015
|
}
|
|
607
2016
|
|
|
608
2017
|
static void *
|
|
609
|
-
ev_realloc_emul (void *ptr,
|
|
2018
|
+
ev_realloc_emul (void *ptr, size_t size) EV_NOEXCEPT
|
|
610
2019
|
{
|
|
611
|
-
#if __GLIBC__
|
|
612
|
-
return realloc (ptr, size);
|
|
613
|
-
#else
|
|
614
2020
|
/* some systems, notably openbsd and darwin, fail to properly
|
|
615
2021
|
* implement realloc (x, 0) (as required by both ansi c-89 and
|
|
616
2022
|
* the single unix specification, so work around them here.
|
|
2023
|
+
* recently, also (at least) fedora and debian started breaking it,
|
|
2024
|
+
* despite documenting it otherwise.
|
|
617
2025
|
*/
|
|
618
2026
|
|
|
619
2027
|
if (size)
|
|
@@ -621,19 +2029,19 @@ ev_realloc_emul (void *ptr, long size)
|
|
|
621
2029
|
|
|
622
2030
|
free (ptr);
|
|
623
2031
|
return 0;
|
|
624
|
-
#endif
|
|
625
2032
|
}
|
|
626
2033
|
|
|
627
|
-
static void *(*alloc)(void *ptr,
|
|
2034
|
+
static void *(*alloc)(void *ptr, size_t size) EV_NOEXCEPT = ev_realloc_emul;
|
|
628
2035
|
|
|
2036
|
+
ecb_cold
|
|
629
2037
|
void
|
|
630
|
-
ev_set_allocator (void *(*cb)(void *ptr,
|
|
2038
|
+
ev_set_allocator (void *(*cb)(void *ptr, size_t size) EV_NOEXCEPT) EV_NOEXCEPT
|
|
631
2039
|
{
|
|
632
2040
|
alloc = cb;
|
|
633
2041
|
}
|
|
634
2042
|
|
|
635
2043
|
inline_speed void *
|
|
636
|
-
ev_realloc (void *ptr,
|
|
2044
|
+
ev_realloc (void *ptr, size_t size)
|
|
637
2045
|
{
|
|
638
2046
|
ptr = alloc (ptr, size);
|
|
639
2047
|
|
|
@@ -664,8 +2072,8 @@ typedef struct
|
|
|
664
2072
|
WL head;
|
|
665
2073
|
unsigned char events; /* the events watched for */
|
|
666
2074
|
unsigned char reify; /* flag set when this ANFD needs reification (EV_ANFD_REIFY, EV__IOFDSET) */
|
|
667
|
-
unsigned char emask; /*
|
|
668
|
-
unsigned char
|
|
2075
|
+
unsigned char emask; /* some backends store the actual kernel mask in here */
|
|
2076
|
+
unsigned char eflags; /* flags field for use by backends */
|
|
669
2077
|
#if EV_USE_EPOLL
|
|
670
2078
|
unsigned int egen; /* generation counter to counter epoll bugs */
|
|
671
2079
|
#endif
|
|
@@ -725,11 +2133,11 @@ typedef struct
|
|
|
725
2133
|
#include "ev_wrap.h"
|
|
726
2134
|
|
|
727
2135
|
static struct ev_loop default_loop_struct;
|
|
728
|
-
struct ev_loop *ev_default_loop_ptr;
|
|
2136
|
+
EV_API_DECL struct ev_loop *ev_default_loop_ptr = 0; /* needs to be initialised to make it a definition despite extern */
|
|
729
2137
|
|
|
730
2138
|
#else
|
|
731
2139
|
|
|
732
|
-
ev_tstamp ev_rt_now;
|
|
2140
|
+
EV_API_DECL ev_tstamp ev_rt_now = EV_TS_CONST (0.); /* needs to be initialised to make it a definition despite extern */
|
|
733
2141
|
#define VAR(name,decl) static decl;
|
|
734
2142
|
#include "ev_vars.h"
|
|
735
2143
|
#undef VAR
|
|
@@ -739,8 +2147,8 @@ typedef struct
|
|
|
739
2147
|
#endif
|
|
740
2148
|
|
|
741
2149
|
#if EV_FEATURE_API
|
|
742
|
-
# define EV_RELEASE_CB if (
|
|
743
|
-
# define EV_ACQUIRE_CB if (
|
|
2150
|
+
# define EV_RELEASE_CB if (ecb_expect_false (release_cb)) release_cb (EV_A)
|
|
2151
|
+
# define EV_ACQUIRE_CB if (ecb_expect_false (acquire_cb)) acquire_cb (EV_A)
|
|
744
2152
|
# define EV_INVOKE_PENDING invoke_cb (EV_A)
|
|
745
2153
|
#else
|
|
746
2154
|
# define EV_RELEASE_CB (void)0
|
|
@@ -754,20 +2162,22 @@ typedef struct
|
|
|
754
2162
|
|
|
755
2163
|
#ifndef EV_HAVE_EV_TIME
|
|
756
2164
|
ev_tstamp
|
|
757
|
-
ev_time (void)
|
|
2165
|
+
ev_time (void) EV_NOEXCEPT
|
|
758
2166
|
{
|
|
759
2167
|
#if EV_USE_REALTIME
|
|
760
|
-
if (
|
|
2168
|
+
if (ecb_expect_true (have_realtime))
|
|
761
2169
|
{
|
|
762
2170
|
struct timespec ts;
|
|
763
2171
|
clock_gettime (CLOCK_REALTIME, &ts);
|
|
764
|
-
return
|
|
2172
|
+
return EV_TS_GET (ts);
|
|
765
2173
|
}
|
|
766
2174
|
#endif
|
|
767
2175
|
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
2176
|
+
{
|
|
2177
|
+
struct timeval tv;
|
|
2178
|
+
gettimeofday (&tv, 0);
|
|
2179
|
+
return EV_TV_GET (tv);
|
|
2180
|
+
}
|
|
771
2181
|
}
|
|
772
2182
|
#endif
|
|
773
2183
|
|
|
@@ -775,11 +2185,11 @@ inline_size ev_tstamp
|
|
|
775
2185
|
get_clock (void)
|
|
776
2186
|
{
|
|
777
2187
|
#if EV_USE_MONOTONIC
|
|
778
|
-
if (
|
|
2188
|
+
if (ecb_expect_true (have_monotonic))
|
|
779
2189
|
{
|
|
780
2190
|
struct timespec ts;
|
|
781
2191
|
clock_gettime (CLOCK_MONOTONIC, &ts);
|
|
782
|
-
return
|
|
2192
|
+
return EV_TS_GET (ts);
|
|
783
2193
|
}
|
|
784
2194
|
#endif
|
|
785
2195
|
|
|
@@ -788,24 +2198,26 @@ get_clock (void)
|
|
|
788
2198
|
|
|
789
2199
|
#if EV_MULTIPLICITY
|
|
790
2200
|
ev_tstamp
|
|
791
|
-
ev_now (EV_P)
|
|
2201
|
+
ev_now (EV_P) EV_NOEXCEPT
|
|
792
2202
|
{
|
|
793
2203
|
return ev_rt_now;
|
|
794
2204
|
}
|
|
795
2205
|
#endif
|
|
796
2206
|
|
|
797
2207
|
void
|
|
798
|
-
ev_sleep (ev_tstamp delay)
|
|
2208
|
+
ev_sleep (ev_tstamp delay) EV_NOEXCEPT
|
|
799
2209
|
{
|
|
800
|
-
if (delay > 0.)
|
|
2210
|
+
if (delay > EV_TS_CONST (0.))
|
|
801
2211
|
{
|
|
802
2212
|
#if EV_USE_NANOSLEEP
|
|
803
2213
|
struct timespec ts;
|
|
804
2214
|
|
|
805
2215
|
EV_TS_SET (ts, delay);
|
|
806
2216
|
nanosleep (&ts, 0);
|
|
807
|
-
#elif defined
|
|
808
|
-
|
|
2217
|
+
#elif defined _WIN32
|
|
2218
|
+
/* maybe this should round up, as ms is very low resolution */
|
|
2219
|
+
/* compared to select (µs) or nanosleep (ns) */
|
|
2220
|
+
Sleep ((unsigned long)(EV_TS_TO_MSEC (delay)));
|
|
809
2221
|
#else
|
|
810
2222
|
struct timeval tv;
|
|
811
2223
|
|
|
@@ -818,14 +2230,6 @@ ev_sleep (ev_tstamp delay)
|
|
|
818
2230
|
}
|
|
819
2231
|
}
|
|
820
2232
|
|
|
821
|
-
inline_speed int
|
|
822
|
-
ev_timeout_to_ms (ev_tstamp timeout)
|
|
823
|
-
{
|
|
824
|
-
int ms = timeout * 1000. + .999999;
|
|
825
|
-
|
|
826
|
-
return expect_true (ms) ? ms : timeout < 1e-6 ? 0 : 1;
|
|
827
|
-
}
|
|
828
|
-
|
|
829
2233
|
/*****************************************************************************/
|
|
830
2234
|
|
|
831
2235
|
#define MALLOC_ROUND 4096 /* prefer to allocate in chunks of this size, must be 2**n and >> 4 longs */
|
|
@@ -841,7 +2245,7 @@ array_nextsize (int elem, int cur, int cnt)
|
|
|
841
2245
|
ncur <<= 1;
|
|
842
2246
|
while (cnt > ncur);
|
|
843
2247
|
|
|
844
|
-
/* if size is large, round to MALLOC_ROUND - 4 * longs to
|
|
2248
|
+
/* if size is large, round to MALLOC_ROUND - 4 * longs to accommodate malloc overhead */
|
|
845
2249
|
if (elem * ncur > MALLOC_ROUND - sizeof (void *) * 4)
|
|
846
2250
|
{
|
|
847
2251
|
ncur *= elem;
|
|
@@ -853,23 +2257,26 @@ array_nextsize (int elem, int cur, int cnt)
|
|
|
853
2257
|
return ncur;
|
|
854
2258
|
}
|
|
855
2259
|
|
|
856
|
-
|
|
2260
|
+
ecb_noinline ecb_cold
|
|
2261
|
+
static void *
|
|
857
2262
|
array_realloc (int elem, void *base, int *cur, int cnt)
|
|
858
2263
|
{
|
|
859
2264
|
*cur = array_nextsize (elem, *cur, cnt);
|
|
860
2265
|
return ev_realloc (base, elem * *cur);
|
|
861
2266
|
}
|
|
862
2267
|
|
|
863
|
-
#define
|
|
864
|
-
|
|
2268
|
+
#define array_needsize_noinit(base,offset,count)
|
|
2269
|
+
|
|
2270
|
+
#define array_needsize_zerofill(base,offset,count) \
|
|
2271
|
+
memset ((void *)(base + offset), 0, sizeof (*(base)) * (count))
|
|
865
2272
|
|
|
866
2273
|
#define array_needsize(type,base,cur,cnt,init) \
|
|
867
|
-
if (
|
|
2274
|
+
if (ecb_expect_false ((cnt) > (cur))) \
|
|
868
2275
|
{ \
|
|
869
|
-
int ocur_ = (cur);
|
|
2276
|
+
ecb_unused int ocur_ = (cur); \
|
|
870
2277
|
(base) = (type *)array_realloc \
|
|
871
2278
|
(sizeof (type), (base), &(cur), (cnt)); \
|
|
872
|
-
init ((base)
|
|
2279
|
+
init ((base), ocur_, ((cur) - ocur_)); \
|
|
873
2280
|
}
|
|
874
2281
|
|
|
875
2282
|
#if 0
|
|
@@ -888,32 +2295,36 @@ array_realloc (int elem, void *base, int *cur, int cnt)
|
|
|
888
2295
|
/*****************************************************************************/
|
|
889
2296
|
|
|
890
2297
|
/* dummy callback for pending events */
|
|
891
|
-
|
|
2298
|
+
ecb_noinline
|
|
2299
|
+
static void
|
|
892
2300
|
pendingcb (EV_P_ ev_prepare *w, int revents)
|
|
893
2301
|
{
|
|
894
2302
|
}
|
|
895
2303
|
|
|
896
|
-
|
|
897
|
-
|
|
2304
|
+
ecb_noinline
|
|
2305
|
+
void
|
|
2306
|
+
ev_feed_event (EV_P_ void *w, int revents) EV_NOEXCEPT
|
|
898
2307
|
{
|
|
899
2308
|
W w_ = (W)w;
|
|
900
2309
|
int pri = ABSPRI (w_);
|
|
901
2310
|
|
|
902
|
-
if (
|
|
2311
|
+
if (ecb_expect_false (w_->pending))
|
|
903
2312
|
pendings [pri][w_->pending - 1].events |= revents;
|
|
904
2313
|
else
|
|
905
2314
|
{
|
|
906
2315
|
w_->pending = ++pendingcnt [pri];
|
|
907
|
-
array_needsize (ANPENDING, pendings [pri], pendingmax [pri], w_->pending,
|
|
2316
|
+
array_needsize (ANPENDING, pendings [pri], pendingmax [pri], w_->pending, array_needsize_noinit);
|
|
908
2317
|
pendings [pri][w_->pending - 1].w = w_;
|
|
909
2318
|
pendings [pri][w_->pending - 1].events = revents;
|
|
910
2319
|
}
|
|
2320
|
+
|
|
2321
|
+
pendingpri = NUMPRI - 1;
|
|
911
2322
|
}
|
|
912
2323
|
|
|
913
2324
|
inline_speed void
|
|
914
2325
|
feed_reverse (EV_P_ W w)
|
|
915
2326
|
{
|
|
916
|
-
array_needsize (W, rfeeds, rfeedmax, rfeedcnt + 1,
|
|
2327
|
+
array_needsize (W, rfeeds, rfeedmax, rfeedcnt + 1, array_needsize_noinit);
|
|
917
2328
|
rfeeds [rfeedcnt++] = w;
|
|
918
2329
|
}
|
|
919
2330
|
|
|
@@ -958,12 +2369,12 @@ fd_event (EV_P_ int fd, int revents)
|
|
|
958
2369
|
{
|
|
959
2370
|
ANFD *anfd = anfds + fd;
|
|
960
2371
|
|
|
961
|
-
if (
|
|
2372
|
+
if (ecb_expect_true (!anfd->reify))
|
|
962
2373
|
fd_event_nocheck (EV_A_ fd, revents);
|
|
963
2374
|
}
|
|
964
2375
|
|
|
965
2376
|
void
|
|
966
|
-
ev_feed_fd_event (EV_P_ int fd, int revents)
|
|
2377
|
+
ev_feed_fd_event (EV_P_ int fd, int revents) EV_NOEXCEPT
|
|
967
2378
|
{
|
|
968
2379
|
if (fd >= 0 && fd < anfdmax)
|
|
969
2380
|
fd_event_nocheck (EV_A_ fd, revents);
|
|
@@ -976,13 +2387,25 @@ fd_reify (EV_P)
|
|
|
976
2387
|
{
|
|
977
2388
|
int i;
|
|
978
2389
|
|
|
2390
|
+
/* most backends do not modify the fdchanges list in backend_modfiy.
|
|
2391
|
+
* except io_uring, which has fixed-size buffers which might force us
|
|
2392
|
+
* to handle events in backend_modify, causing fdchanges to be amended,
|
|
2393
|
+
* which could result in an endless loop.
|
|
2394
|
+
* to avoid this, we do not dynamically handle fds that were added
|
|
2395
|
+
* during fd_reify. that means that for those backends, fdchangecnt
|
|
2396
|
+
* might be non-zero during poll, which must cause them to not block.
|
|
2397
|
+
* to not put too much of a burden on other backends, this detail
|
|
2398
|
+
* needs to be handled in the backend.
|
|
2399
|
+
*/
|
|
2400
|
+
int changecnt = fdchangecnt;
|
|
2401
|
+
|
|
979
2402
|
#if EV_SELECT_IS_WINSOCKET || EV_USE_IOCP
|
|
980
|
-
for (i = 0; i <
|
|
2403
|
+
for (i = 0; i < changecnt; ++i)
|
|
981
2404
|
{
|
|
982
2405
|
int fd = fdchanges [i];
|
|
983
2406
|
ANFD *anfd = anfds + fd;
|
|
984
2407
|
|
|
985
|
-
if (anfd->reify & EV__IOFDSET)
|
|
2408
|
+
if (anfd->reify & EV__IOFDSET && anfd->head)
|
|
986
2409
|
{
|
|
987
2410
|
SOCKET handle = EV_FD_TO_WIN32_HANDLE (fd);
|
|
988
2411
|
|
|
@@ -1001,7 +2424,7 @@ fd_reify (EV_P)
|
|
|
1001
2424
|
}
|
|
1002
2425
|
#endif
|
|
1003
2426
|
|
|
1004
|
-
for (i = 0; i <
|
|
2427
|
+
for (i = 0; i < changecnt; ++i)
|
|
1005
2428
|
{
|
|
1006
2429
|
int fd = fdchanges [i];
|
|
1007
2430
|
ANFD *anfd = anfds + fd;
|
|
@@ -1010,9 +2433,9 @@ fd_reify (EV_P)
|
|
|
1010
2433
|
unsigned char o_events = anfd->events;
|
|
1011
2434
|
unsigned char o_reify = anfd->reify;
|
|
1012
2435
|
|
|
1013
|
-
anfd->reify
|
|
2436
|
+
anfd->reify = 0;
|
|
1014
2437
|
|
|
1015
|
-
/*if (
|
|
2438
|
+
/*if (ecb_expect_true (o_reify & EV_ANFD_REIFY)) probably a deoptimisation */
|
|
1016
2439
|
{
|
|
1017
2440
|
anfd->events = 0;
|
|
1018
2441
|
|
|
@@ -1027,26 +2450,34 @@ fd_reify (EV_P)
|
|
|
1027
2450
|
backend_modify (EV_A_ fd, o_events, anfd->events);
|
|
1028
2451
|
}
|
|
1029
2452
|
|
|
1030
|
-
fdchangecnt
|
|
2453
|
+
/* normally, fdchangecnt hasn't changed. if it has, then new fds have been added.
|
|
2454
|
+
* this is a rare case (see beginning comment in this function), so we copy them to the
|
|
2455
|
+
* front and hope the backend handles this case.
|
|
2456
|
+
*/
|
|
2457
|
+
if (ecb_expect_false (fdchangecnt != changecnt))
|
|
2458
|
+
memmove (fdchanges, fdchanges + changecnt, (fdchangecnt - changecnt) * sizeof (*fdchanges));
|
|
2459
|
+
|
|
2460
|
+
fdchangecnt -= changecnt;
|
|
1031
2461
|
}
|
|
1032
2462
|
|
|
1033
2463
|
/* something about the given fd changed */
|
|
1034
|
-
inline_size
|
|
2464
|
+
inline_size
|
|
2465
|
+
void
|
|
1035
2466
|
fd_change (EV_P_ int fd, int flags)
|
|
1036
2467
|
{
|
|
1037
2468
|
unsigned char reify = anfds [fd].reify;
|
|
1038
|
-
anfds [fd].reify
|
|
2469
|
+
anfds [fd].reify = reify | flags;
|
|
1039
2470
|
|
|
1040
|
-
if (
|
|
2471
|
+
if (ecb_expect_true (!reify))
|
|
1041
2472
|
{
|
|
1042
2473
|
++fdchangecnt;
|
|
1043
|
-
array_needsize (int, fdchanges, fdchangemax, fdchangecnt,
|
|
2474
|
+
array_needsize (int, fdchanges, fdchangemax, fdchangecnt, array_needsize_noinit);
|
|
1044
2475
|
fdchanges [fdchangecnt - 1] = fd;
|
|
1045
2476
|
}
|
|
1046
2477
|
}
|
|
1047
2478
|
|
|
1048
2479
|
/* the given fd is invalid/unusable, so make sure it doesn't hurt us anymore */
|
|
1049
|
-
inline_speed void
|
|
2480
|
+
inline_speed ecb_cold void
|
|
1050
2481
|
fd_kill (EV_P_ int fd)
|
|
1051
2482
|
{
|
|
1052
2483
|
ev_io *w;
|
|
@@ -1059,7 +2490,7 @@ fd_kill (EV_P_ int fd)
|
|
|
1059
2490
|
}
|
|
1060
2491
|
|
|
1061
2492
|
/* check whether the given fd is actually valid, for error recovery */
|
|
1062
|
-
inline_size int
|
|
2493
|
+
inline_size ecb_cold int
|
|
1063
2494
|
fd_valid (int fd)
|
|
1064
2495
|
{
|
|
1065
2496
|
#ifdef _WIN32
|
|
@@ -1070,7 +2501,8 @@ fd_valid (int fd)
|
|
|
1070
2501
|
}
|
|
1071
2502
|
|
|
1072
2503
|
/* called on EBADF to verify fds */
|
|
1073
|
-
|
|
2504
|
+
ecb_noinline ecb_cold
|
|
2505
|
+
static void
|
|
1074
2506
|
fd_ebadf (EV_P)
|
|
1075
2507
|
{
|
|
1076
2508
|
int fd;
|
|
@@ -1082,7 +2514,8 @@ fd_ebadf (EV_P)
|
|
|
1082
2514
|
}
|
|
1083
2515
|
|
|
1084
2516
|
/* called on ENOMEM in select/poll to kill some fds and retry */
|
|
1085
|
-
|
|
2517
|
+
ecb_noinline ecb_cold
|
|
2518
|
+
static void
|
|
1086
2519
|
fd_enomem (EV_P)
|
|
1087
2520
|
{
|
|
1088
2521
|
int fd;
|
|
@@ -1096,7 +2529,8 @@ fd_enomem (EV_P)
|
|
|
1096
2529
|
}
|
|
1097
2530
|
|
|
1098
2531
|
/* usually called after fork if backend needs to re-arm all fds from scratch */
|
|
1099
|
-
|
|
2532
|
+
ecb_noinline
|
|
2533
|
+
static void
|
|
1100
2534
|
fd_rearm_all (EV_P)
|
|
1101
2535
|
{
|
|
1102
2536
|
int fd;
|
|
@@ -1159,19 +2593,19 @@ downheap (ANHE *heap, int N, int k)
|
|
|
1159
2593
|
ANHE *pos = heap + DHEAP * (k - HEAP0) + HEAP0 + 1;
|
|
1160
2594
|
|
|
1161
2595
|
/* find minimum child */
|
|
1162
|
-
if (
|
|
2596
|
+
if (ecb_expect_true (pos + DHEAP - 1 < E))
|
|
1163
2597
|
{
|
|
1164
2598
|
/* fast path */ (minpos = pos + 0), (minat = ANHE_at (*minpos));
|
|
1165
|
-
if ( ANHE_at (pos [1])
|
|
1166
|
-
if ( ANHE_at (pos [2])
|
|
1167
|
-
if ( ANHE_at (pos [3])
|
|
2599
|
+
if ( minat > ANHE_at (pos [1])) (minpos = pos + 1), (minat = ANHE_at (*minpos));
|
|
2600
|
+
if ( minat > ANHE_at (pos [2])) (minpos = pos + 2), (minat = ANHE_at (*minpos));
|
|
2601
|
+
if ( minat > ANHE_at (pos [3])) (minpos = pos + 3), (minat = ANHE_at (*minpos));
|
|
1168
2602
|
}
|
|
1169
2603
|
else if (pos < E)
|
|
1170
2604
|
{
|
|
1171
2605
|
/* slow path */ (minpos = pos + 0), (minat = ANHE_at (*minpos));
|
|
1172
|
-
if (pos + 1 < E && ANHE_at (pos [1])
|
|
1173
|
-
if (pos + 2 < E && ANHE_at (pos [2])
|
|
1174
|
-
if (pos + 3 < E && ANHE_at (pos [3])
|
|
2606
|
+
if (pos + 1 < E && minat > ANHE_at (pos [1])) (minpos = pos + 1), (minat = ANHE_at (*minpos));
|
|
2607
|
+
if (pos + 2 < E && minat > ANHE_at (pos [2])) (minpos = pos + 2), (minat = ANHE_at (*minpos));
|
|
2608
|
+
if (pos + 3 < E && minat > ANHE_at (pos [3])) (minpos = pos + 3), (minat = ANHE_at (*minpos));
|
|
1175
2609
|
}
|
|
1176
2610
|
else
|
|
1177
2611
|
break;
|
|
@@ -1189,7 +2623,7 @@ downheap (ANHE *heap, int N, int k)
|
|
|
1189
2623
|
ev_active (ANHE_w (he)) = k;
|
|
1190
2624
|
}
|
|
1191
2625
|
|
|
1192
|
-
#else /* 4HEAP */
|
|
2626
|
+
#else /* not 4HEAP */
|
|
1193
2627
|
|
|
1194
2628
|
#define HEAP0 1
|
|
1195
2629
|
#define HPARENT(k) ((k) >> 1)
|
|
@@ -1271,7 +2705,7 @@ reheap (ANHE *heap, int N)
|
|
|
1271
2705
|
|
|
1272
2706
|
/*****************************************************************************/
|
|
1273
2707
|
|
|
1274
|
-
/* associate signal watchers to a signal
|
|
2708
|
+
/* associate signal watchers to a signal */
|
|
1275
2709
|
typedef struct
|
|
1276
2710
|
{
|
|
1277
2711
|
EV_ATOMIC_T pending;
|
|
@@ -1287,62 +2721,95 @@ static ANSIG signals [EV_NSIG - 1];
|
|
|
1287
2721
|
|
|
1288
2722
|
#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
|
|
1289
2723
|
|
|
1290
|
-
|
|
2724
|
+
ecb_noinline ecb_cold
|
|
2725
|
+
static void
|
|
1291
2726
|
evpipe_init (EV_P)
|
|
1292
2727
|
{
|
|
1293
2728
|
if (!ev_is_active (&pipe_w))
|
|
1294
2729
|
{
|
|
2730
|
+
int fds [2];
|
|
2731
|
+
|
|
1295
2732
|
# if EV_USE_EVENTFD
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
2733
|
+
fds [0] = -1;
|
|
2734
|
+
fds [1] = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
|
|
2735
|
+
if (fds [1] < 0 && errno == EINVAL)
|
|
2736
|
+
fds [1] = eventfd (0, 0);
|
|
1299
2737
|
|
|
1300
|
-
if (
|
|
2738
|
+
if (fds [1] < 0)
|
|
2739
|
+
# endif
|
|
1301
2740
|
{
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
2741
|
+
while (pipe (fds))
|
|
2742
|
+
ev_syserr ("(libev) error creating signal/async pipe");
|
|
2743
|
+
|
|
2744
|
+
fd_intern (fds [0]);
|
|
1305
2745
|
}
|
|
2746
|
+
|
|
2747
|
+
evpipe [0] = fds [0];
|
|
2748
|
+
|
|
2749
|
+
if (evpipe [1] < 0)
|
|
2750
|
+
evpipe [1] = fds [1]; /* first call, set write fd */
|
|
1306
2751
|
else
|
|
1307
|
-
# endif
|
|
1308
2752
|
{
|
|
1309
|
-
|
|
1310
|
-
|
|
2753
|
+
/* on subsequent calls, do not change evpipe [1] */
|
|
2754
|
+
/* so that evpipe_write can always rely on its value. */
|
|
2755
|
+
/* this branch does not do anything sensible on windows, */
|
|
2756
|
+
/* so must not be executed on windows */
|
|
1311
2757
|
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
ev_io_set (&pipe_w, evpipe [0], EV_READ);
|
|
2758
|
+
dup2 (fds [1], evpipe [1]);
|
|
2759
|
+
close (fds [1]);
|
|
1315
2760
|
}
|
|
1316
2761
|
|
|
2762
|
+
fd_intern (evpipe [1]);
|
|
2763
|
+
|
|
2764
|
+
ev_io_set (&pipe_w, evpipe [0] < 0 ? evpipe [1] : evpipe [0], EV_READ);
|
|
1317
2765
|
ev_io_start (EV_A_ &pipe_w);
|
|
1318
2766
|
ev_unref (EV_A); /* watcher should not keep loop alive */
|
|
1319
2767
|
}
|
|
1320
2768
|
}
|
|
1321
2769
|
|
|
1322
|
-
|
|
2770
|
+
inline_speed void
|
|
1323
2771
|
evpipe_write (EV_P_ EV_ATOMIC_T *flag)
|
|
1324
2772
|
{
|
|
1325
|
-
|
|
2773
|
+
ECB_MEMORY_FENCE; /* push out the write before this function was called, acquire flag */
|
|
2774
|
+
|
|
2775
|
+
if (ecb_expect_true (*flag))
|
|
2776
|
+
return;
|
|
2777
|
+
|
|
2778
|
+
*flag = 1;
|
|
2779
|
+
ECB_MEMORY_FENCE_RELEASE; /* make sure flag is visible before the wakeup */
|
|
2780
|
+
|
|
2781
|
+
pipe_write_skipped = 1;
|
|
2782
|
+
|
|
2783
|
+
ECB_MEMORY_FENCE; /* make sure pipe_write_skipped is visible before we check pipe_write_wanted */
|
|
2784
|
+
|
|
2785
|
+
if (pipe_write_wanted)
|
|
1326
2786
|
{
|
|
1327
|
-
int old_errno
|
|
1328
|
-
|
|
2787
|
+
int old_errno;
|
|
2788
|
+
|
|
2789
|
+
pipe_write_skipped = 0;
|
|
2790
|
+
ECB_MEMORY_FENCE_RELEASE;
|
|
1329
2791
|
|
|
1330
|
-
|
|
2792
|
+
old_errno = errno; /* save errno because write will clobber it */
|
|
1331
2793
|
|
|
1332
2794
|
#if EV_USE_EVENTFD
|
|
1333
|
-
if (
|
|
2795
|
+
if (evpipe [0] < 0)
|
|
1334
2796
|
{
|
|
1335
2797
|
uint64_t counter = 1;
|
|
1336
|
-
write (
|
|
2798
|
+
write (evpipe [1], &counter, sizeof (uint64_t));
|
|
1337
2799
|
}
|
|
1338
2800
|
else
|
|
1339
2801
|
#endif
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
2802
|
+
{
|
|
2803
|
+
#ifdef _WIN32
|
|
2804
|
+
WSABUF buf;
|
|
2805
|
+
DWORD sent;
|
|
2806
|
+
buf.buf = (char *)&buf;
|
|
2807
|
+
buf.len = 1;
|
|
2808
|
+
WSASend (EV_FD_TO_WIN32_HANDLE (evpipe [1]), &buf, 1, &sent, 0, 0, 0);
|
|
2809
|
+
#else
|
|
2810
|
+
write (evpipe [1], &(evpipe [1]), 1);
|
|
2811
|
+
#endif
|
|
2812
|
+
}
|
|
1346
2813
|
|
|
1347
2814
|
errno = old_errno;
|
|
1348
2815
|
}
|
|
@@ -1355,27 +2822,44 @@ pipecb (EV_P_ ev_io *iow, int revents)
|
|
|
1355
2822
|
{
|
|
1356
2823
|
int i;
|
|
1357
2824
|
|
|
1358
|
-
|
|
1359
|
-
if (evfd >= 0)
|
|
2825
|
+
if (revents & EV_READ)
|
|
1360
2826
|
{
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
2827
|
+
#if EV_USE_EVENTFD
|
|
2828
|
+
if (evpipe [0] < 0)
|
|
2829
|
+
{
|
|
2830
|
+
uint64_t counter;
|
|
2831
|
+
read (evpipe [1], &counter, sizeof (uint64_t));
|
|
2832
|
+
}
|
|
2833
|
+
else
|
|
1365
2834
|
#endif
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
2835
|
+
{
|
|
2836
|
+
char dummy[4];
|
|
2837
|
+
#ifdef _WIN32
|
|
2838
|
+
WSABUF buf;
|
|
2839
|
+
DWORD recvd;
|
|
2840
|
+
DWORD flags = 0;
|
|
2841
|
+
buf.buf = dummy;
|
|
2842
|
+
buf.len = sizeof (dummy);
|
|
2843
|
+
WSARecv (EV_FD_TO_WIN32_HANDLE (evpipe [0]), &buf, 1, &recvd, &flags, 0, 0);
|
|
2844
|
+
#else
|
|
2845
|
+
read (evpipe [0], &dummy, sizeof (dummy));
|
|
2846
|
+
#endif
|
|
2847
|
+
}
|
|
1370
2848
|
}
|
|
1371
2849
|
|
|
2850
|
+
pipe_write_skipped = 0;
|
|
2851
|
+
|
|
2852
|
+
ECB_MEMORY_FENCE; /* push out skipped, acquire flags */
|
|
2853
|
+
|
|
1372
2854
|
#if EV_SIGNAL_ENABLE
|
|
1373
2855
|
if (sig_pending)
|
|
1374
2856
|
{
|
|
1375
2857
|
sig_pending = 0;
|
|
1376
2858
|
|
|
2859
|
+
ECB_MEMORY_FENCE;
|
|
2860
|
+
|
|
1377
2861
|
for (i = EV_NSIG - 1; i--; )
|
|
1378
|
-
if (
|
|
2862
|
+
if (ecb_expect_false (signals [i].pending))
|
|
1379
2863
|
ev_feed_signal_event (EV_A_ i + 1);
|
|
1380
2864
|
}
|
|
1381
2865
|
#endif
|
|
@@ -1385,10 +2869,13 @@ pipecb (EV_P_ ev_io *iow, int revents)
|
|
|
1385
2869
|
{
|
|
1386
2870
|
async_pending = 0;
|
|
1387
2871
|
|
|
2872
|
+
ECB_MEMORY_FENCE;
|
|
2873
|
+
|
|
1388
2874
|
for (i = asynccnt; i--; )
|
|
1389
2875
|
if (asyncs [i]->sent)
|
|
1390
2876
|
{
|
|
1391
2877
|
asyncs [i]->sent = 0;
|
|
2878
|
+
ECB_MEMORY_FENCE_RELEASE;
|
|
1392
2879
|
ev_feed_event (EV_A_ asyncs [i], EV_ASYNC);
|
|
1393
2880
|
}
|
|
1394
2881
|
}
|
|
@@ -1398,10 +2885,12 @@ pipecb (EV_P_ ev_io *iow, int revents)
|
|
|
1398
2885
|
/*****************************************************************************/
|
|
1399
2886
|
|
|
1400
2887
|
void
|
|
1401
|
-
ev_feed_signal (int signum)
|
|
2888
|
+
ev_feed_signal (int signum) EV_NOEXCEPT
|
|
1402
2889
|
{
|
|
1403
2890
|
#if EV_MULTIPLICITY
|
|
1404
|
-
EV_P
|
|
2891
|
+
EV_P;
|
|
2892
|
+
ECB_MEMORY_FENCE_ACQUIRE;
|
|
2893
|
+
EV_A = signals [signum - 1].loop;
|
|
1405
2894
|
|
|
1406
2895
|
if (!EV_A)
|
|
1407
2896
|
return;
|
|
@@ -1421,12 +2910,13 @@ ev_sighandler (int signum)
|
|
|
1421
2910
|
ev_feed_signal (signum);
|
|
1422
2911
|
}
|
|
1423
2912
|
|
|
1424
|
-
|
|
1425
|
-
|
|
2913
|
+
ecb_noinline
|
|
2914
|
+
void
|
|
2915
|
+
ev_feed_signal_event (EV_P_ int signum) EV_NOEXCEPT
|
|
1426
2916
|
{
|
|
1427
2917
|
WL w;
|
|
1428
2918
|
|
|
1429
|
-
if (
|
|
2919
|
+
if (ecb_expect_false (signum <= 0 || signum >= EV_NSIG))
|
|
1430
2920
|
return;
|
|
1431
2921
|
|
|
1432
2922
|
--signum;
|
|
@@ -1435,11 +2925,12 @@ ev_feed_signal_event (EV_P_ int signum)
|
|
|
1435
2925
|
/* it is permissible to try to feed a signal to the wrong loop */
|
|
1436
2926
|
/* or, likely more useful, feeding a signal nobody is waiting for */
|
|
1437
2927
|
|
|
1438
|
-
if (
|
|
2928
|
+
if (ecb_expect_false (signals [signum].loop != EV_A))
|
|
1439
2929
|
return;
|
|
1440
2930
|
#endif
|
|
1441
2931
|
|
|
1442
2932
|
signals [signum].pending = 0;
|
|
2933
|
+
ECB_MEMORY_FENCE_RELEASE;
|
|
1443
2934
|
|
|
1444
2935
|
for (w = signals [signum].head; w; w = w->next)
|
|
1445
2936
|
ev_feed_event (EV_A_ (W)w, EV_SIGNAL);
|
|
@@ -1528,6 +3019,57 @@ childcb (EV_P_ ev_signal *sw, int revents)
|
|
|
1528
3019
|
|
|
1529
3020
|
/*****************************************************************************/
|
|
1530
3021
|
|
|
3022
|
+
#if EV_USE_TIMERFD
|
|
3023
|
+
|
|
3024
|
+
static void periodics_reschedule (EV_P);
|
|
3025
|
+
|
|
3026
|
+
static void
|
|
3027
|
+
timerfdcb (EV_P_ ev_io *iow, int revents)
|
|
3028
|
+
{
|
|
3029
|
+
struct itimerspec its = { 0 };
|
|
3030
|
+
|
|
3031
|
+
its.it_value.tv_sec = ev_rt_now + (int)MAX_BLOCKTIME2;
|
|
3032
|
+
timerfd_settime (timerfd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &its, 0);
|
|
3033
|
+
|
|
3034
|
+
ev_rt_now = ev_time ();
|
|
3035
|
+
/* periodics_reschedule only needs ev_rt_now */
|
|
3036
|
+
/* but maybe in the future we want the full treatment. */
|
|
3037
|
+
/*
|
|
3038
|
+
now_floor = EV_TS_CONST (0.);
|
|
3039
|
+
time_update (EV_A_ EV_TSTAMP_HUGE);
|
|
3040
|
+
*/
|
|
3041
|
+
#if EV_PERIODIC_ENABLE
|
|
3042
|
+
periodics_reschedule (EV_A);
|
|
3043
|
+
#endif
|
|
3044
|
+
}
|
|
3045
|
+
|
|
3046
|
+
ecb_noinline ecb_cold
|
|
3047
|
+
static void
|
|
3048
|
+
evtimerfd_init (EV_P)
|
|
3049
|
+
{
|
|
3050
|
+
if (!ev_is_active (&timerfd_w))
|
|
3051
|
+
{
|
|
3052
|
+
timerfd = timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC);
|
|
3053
|
+
|
|
3054
|
+
if (timerfd >= 0)
|
|
3055
|
+
{
|
|
3056
|
+
fd_intern (timerfd); /* just to be sure */
|
|
3057
|
+
|
|
3058
|
+
ev_io_init (&timerfd_w, timerfdcb, timerfd, EV_READ);
|
|
3059
|
+
ev_set_priority (&timerfd_w, EV_MINPRI);
|
|
3060
|
+
ev_io_start (EV_A_ &timerfd_w);
|
|
3061
|
+
ev_unref (EV_A); /* watcher should not keep loop alive */
|
|
3062
|
+
|
|
3063
|
+
/* (re-) arm timer */
|
|
3064
|
+
timerfdcb (EV_A_ 0, 0);
|
|
3065
|
+
}
|
|
3066
|
+
}
|
|
3067
|
+
}
|
|
3068
|
+
|
|
3069
|
+
#endif
|
|
3070
|
+
|
|
3071
|
+
/*****************************************************************************/
|
|
3072
|
+
|
|
1531
3073
|
#if EV_USE_IOCP
|
|
1532
3074
|
# include "ev_iocp.c"
|
|
1533
3075
|
#endif
|
|
@@ -1540,6 +3082,12 @@ childcb (EV_P_ ev_signal *sw, int revents)
|
|
|
1540
3082
|
#if EV_USE_EPOLL
|
|
1541
3083
|
# include "ev_epoll.c"
|
|
1542
3084
|
#endif
|
|
3085
|
+
#if EV_USE_LINUXAIO
|
|
3086
|
+
# include "ev_linuxaio.c"
|
|
3087
|
+
#endif
|
|
3088
|
+
#if EV_USE_IOURING
|
|
3089
|
+
# include "ev_iouring.c"
|
|
3090
|
+
#endif
|
|
1543
3091
|
#if EV_USE_POLL
|
|
1544
3092
|
# include "ev_poll.c"
|
|
1545
3093
|
#endif
|
|
@@ -1547,20 +3095,20 @@ childcb (EV_P_ ev_signal *sw, int revents)
|
|
|
1547
3095
|
# include "ev_select.c"
|
|
1548
3096
|
#endif
|
|
1549
3097
|
|
|
1550
|
-
int
|
|
1551
|
-
ev_version_major (void)
|
|
3098
|
+
ecb_cold int
|
|
3099
|
+
ev_version_major (void) EV_NOEXCEPT
|
|
1552
3100
|
{
|
|
1553
3101
|
return EV_VERSION_MAJOR;
|
|
1554
3102
|
}
|
|
1555
3103
|
|
|
1556
|
-
int
|
|
1557
|
-
ev_version_minor (void)
|
|
3104
|
+
ecb_cold int
|
|
3105
|
+
ev_version_minor (void) EV_NOEXCEPT
|
|
1558
3106
|
{
|
|
1559
3107
|
return EV_VERSION_MINOR;
|
|
1560
3108
|
}
|
|
1561
3109
|
|
|
1562
3110
|
/* return true if we are running with elevated privileges and should ignore env variables */
|
|
1563
|
-
int
|
|
3111
|
+
inline_size ecb_cold int
|
|
1564
3112
|
enable_secure (void)
|
|
1565
3113
|
{
|
|
1566
3114
|
#ifdef _WIN32
|
|
@@ -1571,103 +3119,123 @@ enable_secure (void)
|
|
|
1571
3119
|
#endif
|
|
1572
3120
|
}
|
|
1573
3121
|
|
|
3122
|
+
ecb_cold
|
|
1574
3123
|
unsigned int
|
|
1575
|
-
ev_supported_backends (void)
|
|
3124
|
+
ev_supported_backends (void) EV_NOEXCEPT
|
|
1576
3125
|
{
|
|
1577
3126
|
unsigned int flags = 0;
|
|
1578
3127
|
|
|
1579
|
-
if (EV_USE_PORT
|
|
1580
|
-
if (EV_USE_KQUEUE) flags |= EVBACKEND_KQUEUE;
|
|
1581
|
-
if (EV_USE_EPOLL
|
|
1582
|
-
if (
|
|
1583
|
-
if (
|
|
3128
|
+
if (EV_USE_PORT ) flags |= EVBACKEND_PORT;
|
|
3129
|
+
if (EV_USE_KQUEUE ) flags |= EVBACKEND_KQUEUE;
|
|
3130
|
+
if (EV_USE_EPOLL ) flags |= EVBACKEND_EPOLL;
|
|
3131
|
+
if (EV_USE_LINUXAIO && ev_linux_version () >= 0x041300) flags |= EVBACKEND_LINUXAIO; /* 4.19+ */
|
|
3132
|
+
if (EV_USE_IOURING && ev_linux_version () >= 0x050601 ) flags |= EVBACKEND_IOURING; /* 5.6.1+ */
|
|
3133
|
+
if (EV_USE_POLL ) flags |= EVBACKEND_POLL;
|
|
3134
|
+
if (EV_USE_SELECT ) flags |= EVBACKEND_SELECT;
|
|
1584
3135
|
|
|
1585
3136
|
return flags;
|
|
1586
3137
|
}
|
|
1587
3138
|
|
|
3139
|
+
ecb_cold
|
|
1588
3140
|
unsigned int
|
|
1589
|
-
ev_recommended_backends (void)
|
|
3141
|
+
ev_recommended_backends (void) EV_NOEXCEPT
|
|
1590
3142
|
{
|
|
1591
3143
|
unsigned int flags = ev_supported_backends ();
|
|
1592
3144
|
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
/* it usually doesn't work correctly on anything but sockets and pipes */
|
|
1596
|
-
flags &= ~EVBACKEND_KQUEUE;
|
|
1597
|
-
#endif
|
|
1598
|
-
#ifdef __APPLE__
|
|
3145
|
+
/* apple has a poor track record but post 10.12.2 it seems to work sufficiently well */
|
|
3146
|
+
#if defined(__APPLE__) && (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_14)
|
|
1599
3147
|
/* only select works correctly on that "unix-certified" platform */
|
|
1600
3148
|
flags &= ~EVBACKEND_KQUEUE; /* horribly broken, even for sockets */
|
|
1601
3149
|
flags &= ~EVBACKEND_POLL; /* poll is based on kqueue from 10.5 onwards */
|
|
1602
3150
|
#endif
|
|
3151
|
+
|
|
3152
|
+
#if !defined(__NetBSD__) && !defined(__APPLE__)
|
|
3153
|
+
/* kqueue is borked on everything but netbsd and osx >= 10.12.2 apparently */
|
|
3154
|
+
/* it usually doesn't work correctly on anything but sockets and pipes */
|
|
3155
|
+
flags &= ~EVBACKEND_KQUEUE;
|
|
3156
|
+
#endif
|
|
3157
|
+
|
|
1603
3158
|
#ifdef __FreeBSD__
|
|
1604
3159
|
flags &= ~EVBACKEND_POLL; /* poll return value is unusable (http://forums.freebsd.org/archive/index.php/t-10270.html) */
|
|
1605
3160
|
#endif
|
|
1606
3161
|
|
|
3162
|
+
#ifdef __linux__
|
|
3163
|
+
/* NOTE: linuxaio is very experimental, never recommend */
|
|
3164
|
+
flags &= ~EVBACKEND_LINUXAIO;
|
|
3165
|
+
|
|
3166
|
+
/* NOTE: io_uring is super experimental, never recommend */
|
|
3167
|
+
flags &= ~EVBACKEND_IOURING;
|
|
3168
|
+
#endif
|
|
3169
|
+
|
|
1607
3170
|
return flags;
|
|
1608
3171
|
}
|
|
1609
3172
|
|
|
3173
|
+
ecb_cold
|
|
1610
3174
|
unsigned int
|
|
1611
|
-
ev_embeddable_backends (void)
|
|
3175
|
+
ev_embeddable_backends (void) EV_NOEXCEPT
|
|
1612
3176
|
{
|
|
1613
|
-
int flags = EVBACKEND_EPOLL | EVBACKEND_KQUEUE | EVBACKEND_PORT;
|
|
3177
|
+
int flags = EVBACKEND_EPOLL | EVBACKEND_KQUEUE | EVBACKEND_PORT | EVBACKEND_IOURING;
|
|
1614
3178
|
|
|
1615
3179
|
/* epoll embeddability broken on all linux versions up to at least 2.6.23 */
|
|
1616
3180
|
if (ev_linux_version () < 0x020620) /* disable it on linux < 2.6.32 */
|
|
1617
3181
|
flags &= ~EVBACKEND_EPOLL;
|
|
1618
3182
|
|
|
3183
|
+
/* EVBACKEND_LINUXAIO is theoretically embeddable, but suffers from a performance overhead */
|
|
3184
|
+
|
|
1619
3185
|
return flags;
|
|
1620
3186
|
}
|
|
1621
3187
|
|
|
1622
3188
|
unsigned int
|
|
1623
|
-
ev_backend (EV_P)
|
|
3189
|
+
ev_backend (EV_P) EV_NOEXCEPT
|
|
1624
3190
|
{
|
|
1625
3191
|
return backend;
|
|
1626
3192
|
}
|
|
1627
3193
|
|
|
1628
3194
|
#if EV_FEATURE_API
|
|
1629
3195
|
unsigned int
|
|
1630
|
-
ev_iteration (EV_P)
|
|
3196
|
+
ev_iteration (EV_P) EV_NOEXCEPT
|
|
1631
3197
|
{
|
|
1632
3198
|
return loop_count;
|
|
1633
3199
|
}
|
|
1634
3200
|
|
|
1635
3201
|
unsigned int
|
|
1636
|
-
ev_depth (EV_P)
|
|
3202
|
+
ev_depth (EV_P) EV_NOEXCEPT
|
|
1637
3203
|
{
|
|
1638
3204
|
return loop_depth;
|
|
1639
3205
|
}
|
|
1640
3206
|
|
|
1641
3207
|
void
|
|
1642
|
-
ev_set_io_collect_interval (EV_P_ ev_tstamp interval)
|
|
3208
|
+
ev_set_io_collect_interval (EV_P_ ev_tstamp interval) EV_NOEXCEPT
|
|
1643
3209
|
{
|
|
1644
3210
|
io_blocktime = interval;
|
|
1645
3211
|
}
|
|
1646
3212
|
|
|
1647
3213
|
void
|
|
1648
|
-
ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval)
|
|
3214
|
+
ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval) EV_NOEXCEPT
|
|
1649
3215
|
{
|
|
1650
3216
|
timeout_blocktime = interval;
|
|
1651
3217
|
}
|
|
1652
3218
|
|
|
1653
3219
|
void
|
|
1654
|
-
ev_set_userdata (EV_P_ void *data)
|
|
3220
|
+
ev_set_userdata (EV_P_ void *data) EV_NOEXCEPT
|
|
1655
3221
|
{
|
|
1656
3222
|
userdata = data;
|
|
1657
3223
|
}
|
|
1658
3224
|
|
|
1659
3225
|
void *
|
|
1660
|
-
ev_userdata (EV_P)
|
|
3226
|
+
ev_userdata (EV_P) EV_NOEXCEPT
|
|
1661
3227
|
{
|
|
1662
3228
|
return userdata;
|
|
1663
3229
|
}
|
|
1664
3230
|
|
|
1665
|
-
void
|
|
3231
|
+
void
|
|
3232
|
+
ev_set_invoke_pending_cb (EV_P_ ev_loop_callback invoke_pending_cb) EV_NOEXCEPT
|
|
1666
3233
|
{
|
|
1667
3234
|
invoke_cb = invoke_pending_cb;
|
|
1668
3235
|
}
|
|
1669
3236
|
|
|
1670
|
-
void
|
|
3237
|
+
void
|
|
3238
|
+
ev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_NOEXCEPT, void (*acquire)(EV_P) EV_NOEXCEPT) EV_NOEXCEPT
|
|
1671
3239
|
{
|
|
1672
3240
|
release_cb = release;
|
|
1673
3241
|
acquire_cb = acquire;
|
|
@@ -1675,8 +3243,9 @@ void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P), void (*acquire)(EV_P))
|
|
|
1675
3243
|
#endif
|
|
1676
3244
|
|
|
1677
3245
|
/* initialise a loop structure, must be zero-initialised */
|
|
1678
|
-
|
|
1679
|
-
|
|
3246
|
+
ecb_noinline ecb_cold
|
|
3247
|
+
static void
|
|
3248
|
+
loop_init (EV_P_ unsigned int flags) EV_NOEXCEPT
|
|
1680
3249
|
{
|
|
1681
3250
|
if (!backend)
|
|
1682
3251
|
{
|
|
@@ -1713,49 +3282,62 @@ loop_init (EV_P_ unsigned int flags)
|
|
|
1713
3282
|
&& getenv ("LIBEV_FLAGS"))
|
|
1714
3283
|
flags = atoi (getenv ("LIBEV_FLAGS"));
|
|
1715
3284
|
|
|
1716
|
-
ev_rt_now
|
|
1717
|
-
mn_now
|
|
1718
|
-
now_floor
|
|
1719
|
-
rtmn_diff
|
|
3285
|
+
ev_rt_now = ev_time ();
|
|
3286
|
+
mn_now = get_clock ();
|
|
3287
|
+
now_floor = mn_now;
|
|
3288
|
+
rtmn_diff = ev_rt_now - mn_now;
|
|
1720
3289
|
#if EV_FEATURE_API
|
|
1721
|
-
invoke_cb
|
|
3290
|
+
invoke_cb = ev_invoke_pending;
|
|
1722
3291
|
#endif
|
|
1723
3292
|
|
|
1724
|
-
io_blocktime
|
|
1725
|
-
timeout_blocktime
|
|
1726
|
-
backend
|
|
1727
|
-
backend_fd
|
|
1728
|
-
sig_pending
|
|
3293
|
+
io_blocktime = 0.;
|
|
3294
|
+
timeout_blocktime = 0.;
|
|
3295
|
+
backend = 0;
|
|
3296
|
+
backend_fd = -1;
|
|
3297
|
+
sig_pending = 0;
|
|
1729
3298
|
#if EV_ASYNC_ENABLE
|
|
1730
|
-
async_pending
|
|
3299
|
+
async_pending = 0;
|
|
1731
3300
|
#endif
|
|
3301
|
+
pipe_write_skipped = 0;
|
|
3302
|
+
pipe_write_wanted = 0;
|
|
3303
|
+
evpipe [0] = -1;
|
|
3304
|
+
evpipe [1] = -1;
|
|
1732
3305
|
#if EV_USE_INOTIFY
|
|
1733
|
-
fs_fd
|
|
3306
|
+
fs_fd = flags & EVFLAG_NOINOTIFY ? -1 : -2;
|
|
1734
3307
|
#endif
|
|
1735
3308
|
#if EV_USE_SIGNALFD
|
|
1736
|
-
sigfd
|
|
3309
|
+
sigfd = flags & EVFLAG_SIGNALFD ? -2 : -1;
|
|
3310
|
+
#endif
|
|
3311
|
+
#if EV_USE_TIMERFD
|
|
3312
|
+
timerfd = flags & EVFLAG_NOTIMERFD ? -1 : -2;
|
|
1737
3313
|
#endif
|
|
1738
3314
|
|
|
1739
3315
|
if (!(flags & EVBACKEND_MASK))
|
|
1740
3316
|
flags |= ev_recommended_backends ();
|
|
1741
3317
|
|
|
1742
3318
|
#if EV_USE_IOCP
|
|
1743
|
-
if (!backend && (flags & EVBACKEND_IOCP
|
|
3319
|
+
if (!backend && (flags & EVBACKEND_IOCP )) backend = iocp_init (EV_A_ flags);
|
|
1744
3320
|
#endif
|
|
1745
3321
|
#if EV_USE_PORT
|
|
1746
|
-
if (!backend && (flags & EVBACKEND_PORT
|
|
3322
|
+
if (!backend && (flags & EVBACKEND_PORT )) backend = port_init (EV_A_ flags);
|
|
1747
3323
|
#endif
|
|
1748
3324
|
#if EV_USE_KQUEUE
|
|
1749
|
-
if (!backend && (flags & EVBACKEND_KQUEUE)) backend = kqueue_init
|
|
3325
|
+
if (!backend && (flags & EVBACKEND_KQUEUE )) backend = kqueue_init (EV_A_ flags);
|
|
3326
|
+
#endif
|
|
3327
|
+
#if EV_USE_IOURING
|
|
3328
|
+
if (!backend && (flags & EVBACKEND_IOURING )) backend = iouring_init (EV_A_ flags);
|
|
3329
|
+
#endif
|
|
3330
|
+
#if EV_USE_LINUXAIO
|
|
3331
|
+
if (!backend && (flags & EVBACKEND_LINUXAIO)) backend = linuxaio_init (EV_A_ flags);
|
|
1750
3332
|
#endif
|
|
1751
3333
|
#if EV_USE_EPOLL
|
|
1752
|
-
if (!backend && (flags & EVBACKEND_EPOLL
|
|
3334
|
+
if (!backend && (flags & EVBACKEND_EPOLL )) backend = epoll_init (EV_A_ flags);
|
|
1753
3335
|
#endif
|
|
1754
3336
|
#if EV_USE_POLL
|
|
1755
|
-
if (!backend && (flags & EVBACKEND_POLL
|
|
3337
|
+
if (!backend && (flags & EVBACKEND_POLL )) backend = poll_init (EV_A_ flags);
|
|
1756
3338
|
#endif
|
|
1757
3339
|
#if EV_USE_SELECT
|
|
1758
|
-
if (!backend && (flags & EVBACKEND_SELECT)) backend = select_init
|
|
3340
|
+
if (!backend && (flags & EVBACKEND_SELECT )) backend = select_init (EV_A_ flags);
|
|
1759
3341
|
#endif
|
|
1760
3342
|
|
|
1761
3343
|
ev_prepare_init (&pending_w, pendingcb);
|
|
@@ -1768,6 +3350,7 @@ loop_init (EV_P_ unsigned int flags)
|
|
|
1768
3350
|
}
|
|
1769
3351
|
|
|
1770
3352
|
/* free up a loop structure */
|
|
3353
|
+
ecb_cold
|
|
1771
3354
|
void
|
|
1772
3355
|
ev_loop_destroy (EV_P)
|
|
1773
3356
|
{
|
|
@@ -1781,7 +3364,7 @@ ev_loop_destroy (EV_P)
|
|
|
1781
3364
|
|
|
1782
3365
|
#if EV_CLEANUP_ENABLE
|
|
1783
3366
|
/* queue cleanup watchers (and execute them) */
|
|
1784
|
-
if (
|
|
3367
|
+
if (ecb_expect_false (cleanupcnt))
|
|
1785
3368
|
{
|
|
1786
3369
|
queue_events (EV_A_ (W *)cleanups, cleanupcnt, EV_CLEANUP);
|
|
1787
3370
|
EV_INVOKE_PENDING;
|
|
@@ -1789,7 +3372,7 @@ ev_loop_destroy (EV_P)
|
|
|
1789
3372
|
#endif
|
|
1790
3373
|
|
|
1791
3374
|
#if EV_CHILD_ENABLE
|
|
1792
|
-
if (ev_is_active (&childev))
|
|
3375
|
+
if (ev_is_default_loop (EV_A) && ev_is_active (&childev))
|
|
1793
3376
|
{
|
|
1794
3377
|
ev_ref (EV_A); /* child watcher */
|
|
1795
3378
|
ev_signal_stop (EV_A_ &childev);
|
|
@@ -1801,16 +3384,8 @@ ev_loop_destroy (EV_P)
|
|
|
1801
3384
|
/*ev_ref (EV_A);*/
|
|
1802
3385
|
/*ev_io_stop (EV_A_ &pipe_w);*/
|
|
1803
3386
|
|
|
1804
|
-
|
|
1805
|
-
if (
|
|
1806
|
-
close (evfd);
|
|
1807
|
-
#endif
|
|
1808
|
-
|
|
1809
|
-
if (evpipe [0] >= 0)
|
|
1810
|
-
{
|
|
1811
|
-
EV_WIN32_CLOSE_FD (evpipe [0]);
|
|
1812
|
-
EV_WIN32_CLOSE_FD (evpipe [1]);
|
|
1813
|
-
}
|
|
3387
|
+
if (evpipe [0] >= 0) EV_WIN32_CLOSE_FD (evpipe [0]);
|
|
3388
|
+
if (evpipe [1] >= 0) EV_WIN32_CLOSE_FD (evpipe [1]);
|
|
1814
3389
|
}
|
|
1815
3390
|
|
|
1816
3391
|
#if EV_USE_SIGNALFD
|
|
@@ -1818,6 +3393,11 @@ ev_loop_destroy (EV_P)
|
|
|
1818
3393
|
close (sigfd);
|
|
1819
3394
|
#endif
|
|
1820
3395
|
|
|
3396
|
+
#if EV_USE_TIMERFD
|
|
3397
|
+
if (ev_is_active (&timerfd_w))
|
|
3398
|
+
close (timerfd);
|
|
3399
|
+
#endif
|
|
3400
|
+
|
|
1821
3401
|
#if EV_USE_INOTIFY
|
|
1822
3402
|
if (fs_fd >= 0)
|
|
1823
3403
|
close (fs_fd);
|
|
@@ -1827,22 +3407,28 @@ ev_loop_destroy (EV_P)
|
|
|
1827
3407
|
close (backend_fd);
|
|
1828
3408
|
|
|
1829
3409
|
#if EV_USE_IOCP
|
|
1830
|
-
if (backend == EVBACKEND_IOCP
|
|
3410
|
+
if (backend == EVBACKEND_IOCP ) iocp_destroy (EV_A);
|
|
1831
3411
|
#endif
|
|
1832
3412
|
#if EV_USE_PORT
|
|
1833
|
-
if (backend == EVBACKEND_PORT
|
|
3413
|
+
if (backend == EVBACKEND_PORT ) port_destroy (EV_A);
|
|
1834
3414
|
#endif
|
|
1835
3415
|
#if EV_USE_KQUEUE
|
|
1836
|
-
if (backend == EVBACKEND_KQUEUE) kqueue_destroy
|
|
3416
|
+
if (backend == EVBACKEND_KQUEUE ) kqueue_destroy (EV_A);
|
|
3417
|
+
#endif
|
|
3418
|
+
#if EV_USE_IOURING
|
|
3419
|
+
if (backend == EVBACKEND_IOURING ) iouring_destroy (EV_A);
|
|
3420
|
+
#endif
|
|
3421
|
+
#if EV_USE_LINUXAIO
|
|
3422
|
+
if (backend == EVBACKEND_LINUXAIO) linuxaio_destroy (EV_A);
|
|
1837
3423
|
#endif
|
|
1838
3424
|
#if EV_USE_EPOLL
|
|
1839
|
-
if (backend == EVBACKEND_EPOLL
|
|
3425
|
+
if (backend == EVBACKEND_EPOLL ) epoll_destroy (EV_A);
|
|
1840
3426
|
#endif
|
|
1841
3427
|
#if EV_USE_POLL
|
|
1842
|
-
if (backend == EVBACKEND_POLL
|
|
3428
|
+
if (backend == EVBACKEND_POLL ) poll_destroy (EV_A);
|
|
1843
3429
|
#endif
|
|
1844
3430
|
#if EV_USE_SELECT
|
|
1845
|
-
if (backend == EVBACKEND_SELECT) select_destroy
|
|
3431
|
+
if (backend == EVBACKEND_SELECT ) select_destroy (EV_A);
|
|
1846
3432
|
#endif
|
|
1847
3433
|
|
|
1848
3434
|
for (i = NUMPRI; i--; )
|
|
@@ -1894,46 +3480,61 @@ inline_size void
|
|
|
1894
3480
|
loop_fork (EV_P)
|
|
1895
3481
|
{
|
|
1896
3482
|
#if EV_USE_PORT
|
|
1897
|
-
if (backend == EVBACKEND_PORT
|
|
3483
|
+
if (backend == EVBACKEND_PORT ) port_fork (EV_A);
|
|
1898
3484
|
#endif
|
|
1899
3485
|
#if EV_USE_KQUEUE
|
|
1900
|
-
if (backend == EVBACKEND_KQUEUE) kqueue_fork
|
|
3486
|
+
if (backend == EVBACKEND_KQUEUE ) kqueue_fork (EV_A);
|
|
3487
|
+
#endif
|
|
3488
|
+
#if EV_USE_IOURING
|
|
3489
|
+
if (backend == EVBACKEND_IOURING ) iouring_fork (EV_A);
|
|
3490
|
+
#endif
|
|
3491
|
+
#if EV_USE_LINUXAIO
|
|
3492
|
+
if (backend == EVBACKEND_LINUXAIO) linuxaio_fork (EV_A);
|
|
1901
3493
|
#endif
|
|
1902
3494
|
#if EV_USE_EPOLL
|
|
1903
|
-
if (backend == EVBACKEND_EPOLL
|
|
3495
|
+
if (backend == EVBACKEND_EPOLL ) epoll_fork (EV_A);
|
|
1904
3496
|
#endif
|
|
1905
3497
|
#if EV_USE_INOTIFY
|
|
1906
3498
|
infy_fork (EV_A);
|
|
1907
3499
|
#endif
|
|
1908
3500
|
|
|
1909
|
-
if (
|
|
3501
|
+
if (postfork != 2)
|
|
1910
3502
|
{
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
#if EV_ASYNC_ENABLE
|
|
1915
|
-
async_pending = 1;
|
|
1916
|
-
#endif
|
|
3503
|
+
#if EV_USE_SIGNALFD
|
|
3504
|
+
/* surprisingly, nothing needs to be done for signalfd, accoridng to docs, it does the right thing on fork */
|
|
3505
|
+
#endif
|
|
1917
3506
|
|
|
1918
|
-
|
|
1919
|
-
|
|
3507
|
+
#if EV_USE_TIMERFD
|
|
3508
|
+
if (ev_is_active (&timerfd_w))
|
|
3509
|
+
{
|
|
3510
|
+
ev_ref (EV_A);
|
|
3511
|
+
ev_io_stop (EV_A_ &timerfd_w);
|
|
1920
3512
|
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
close (evfd);
|
|
1924
|
-
#endif
|
|
3513
|
+
close (timerfd);
|
|
3514
|
+
timerfd = -2;
|
|
1925
3515
|
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
3516
|
+
evtimerfd_init (EV_A);
|
|
3517
|
+
/* reschedule periodics, in case we missed something */
|
|
3518
|
+
ev_feed_event (EV_A_ &timerfd_w, EV_CUSTOM);
|
|
3519
|
+
}
|
|
3520
|
+
#endif
|
|
1931
3521
|
|
|
1932
|
-
#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
3522
|
+
#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
|
|
3523
|
+
if (ev_is_active (&pipe_w))
|
|
3524
|
+
{
|
|
3525
|
+
/* pipe_write_wanted must be false now, so modifying fd vars should be safe */
|
|
3526
|
+
|
|
3527
|
+
ev_ref (EV_A);
|
|
3528
|
+
ev_io_stop (EV_A_ &pipe_w);
|
|
3529
|
+
|
|
3530
|
+
if (evpipe [0] >= 0)
|
|
3531
|
+
EV_WIN32_CLOSE_FD (evpipe [0]);
|
|
3532
|
+
|
|
3533
|
+
evpipe_init (EV_A);
|
|
3534
|
+
/* iterate over everything, in case we missed something before */
|
|
3535
|
+
ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);
|
|
3536
|
+
}
|
|
3537
|
+
#endif
|
|
1937
3538
|
}
|
|
1938
3539
|
|
|
1939
3540
|
postfork = 0;
|
|
@@ -1941,8 +3542,9 @@ loop_fork (EV_P)
|
|
|
1941
3542
|
|
|
1942
3543
|
#if EV_MULTIPLICITY
|
|
1943
3544
|
|
|
3545
|
+
ecb_cold
|
|
1944
3546
|
struct ev_loop *
|
|
1945
|
-
ev_loop_new (unsigned int flags)
|
|
3547
|
+
ev_loop_new (unsigned int flags) EV_NOEXCEPT
|
|
1946
3548
|
{
|
|
1947
3549
|
EV_P = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop));
|
|
1948
3550
|
|
|
@@ -1959,7 +3561,8 @@ ev_loop_new (unsigned int flags)
|
|
|
1959
3561
|
#endif /* multiplicity */
|
|
1960
3562
|
|
|
1961
3563
|
#if EV_VERIFY
|
|
1962
|
-
|
|
3564
|
+
ecb_noinline ecb_cold
|
|
3565
|
+
static void
|
|
1963
3566
|
verify_watcher (EV_P_ W w)
|
|
1964
3567
|
{
|
|
1965
3568
|
assert (("libev: watcher has invalid priority", ABSPRI (w) >= 0 && ABSPRI (w) < NUMPRI));
|
|
@@ -1968,7 +3571,8 @@ verify_watcher (EV_P_ W w)
|
|
|
1968
3571
|
assert (("libev: pending watcher not on pending queue", pendings [ABSPRI (w)][w->pending - 1].w == w));
|
|
1969
3572
|
}
|
|
1970
3573
|
|
|
1971
|
-
|
|
3574
|
+
ecb_noinline ecb_cold
|
|
3575
|
+
static void
|
|
1972
3576
|
verify_heap (EV_P_ ANHE *heap, int N)
|
|
1973
3577
|
{
|
|
1974
3578
|
int i;
|
|
@@ -1983,7 +3587,8 @@ verify_heap (EV_P_ ANHE *heap, int N)
|
|
|
1983
3587
|
}
|
|
1984
3588
|
}
|
|
1985
3589
|
|
|
1986
|
-
|
|
3590
|
+
ecb_noinline ecb_cold
|
|
3591
|
+
static void
|
|
1987
3592
|
array_verify (EV_P_ W *ws, int cnt)
|
|
1988
3593
|
{
|
|
1989
3594
|
while (cnt--)
|
|
@@ -1995,12 +3600,12 @@ array_verify (EV_P_ W *ws, int cnt)
|
|
|
1995
3600
|
#endif
|
|
1996
3601
|
|
|
1997
3602
|
#if EV_FEATURE_API
|
|
1998
|
-
void
|
|
1999
|
-
ev_verify (EV_P)
|
|
3603
|
+
void ecb_cold
|
|
3604
|
+
ev_verify (EV_P) EV_NOEXCEPT
|
|
2000
3605
|
{
|
|
2001
3606
|
#if EV_VERIFY
|
|
2002
3607
|
int i;
|
|
2003
|
-
WL w;
|
|
3608
|
+
WL w, w2;
|
|
2004
3609
|
|
|
2005
3610
|
assert (activecnt >= -1);
|
|
2006
3611
|
|
|
@@ -2010,12 +3615,23 @@ ev_verify (EV_P)
|
|
|
2010
3615
|
|
|
2011
3616
|
assert (anfdmax >= 0);
|
|
2012
3617
|
for (i = 0; i < anfdmax; ++i)
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
3618
|
+
{
|
|
3619
|
+
int j = 0;
|
|
3620
|
+
|
|
3621
|
+
for (w = w2 = anfds [i].head; w; w = w->next)
|
|
3622
|
+
{
|
|
3623
|
+
verify_watcher (EV_A_ (W)w);
|
|
3624
|
+
|
|
3625
|
+
if (j++ & 1)
|
|
3626
|
+
{
|
|
3627
|
+
assert (("libev: io watcher list contains a loop", w != w2));
|
|
3628
|
+
w2 = w2->next;
|
|
3629
|
+
}
|
|
3630
|
+
|
|
3631
|
+
assert (("libev: inactive fd watcher on anfd list", ev_active (w) == 1));
|
|
3632
|
+
assert (("libev: fd mismatch between watcher and anfd", ((ev_io *)w)->fd == i));
|
|
3633
|
+
}
|
|
3634
|
+
}
|
|
2019
3635
|
|
|
2020
3636
|
assert (timermax >= timercnt);
|
|
2021
3637
|
verify_heap (EV_A_ timers, timercnt);
|
|
@@ -2071,11 +3687,12 @@ ev_verify (EV_P)
|
|
|
2071
3687
|
#endif
|
|
2072
3688
|
|
|
2073
3689
|
#if EV_MULTIPLICITY
|
|
3690
|
+
ecb_cold
|
|
2074
3691
|
struct ev_loop *
|
|
2075
3692
|
#else
|
|
2076
3693
|
int
|
|
2077
3694
|
#endif
|
|
2078
|
-
ev_default_loop (unsigned int flags)
|
|
3695
|
+
ev_default_loop (unsigned int flags) EV_NOEXCEPT
|
|
2079
3696
|
{
|
|
2080
3697
|
if (!ev_default_loop_ptr)
|
|
2081
3698
|
{
|
|
@@ -2104,9 +3721,9 @@ ev_default_loop (unsigned int flags)
|
|
|
2104
3721
|
}
|
|
2105
3722
|
|
|
2106
3723
|
void
|
|
2107
|
-
ev_loop_fork (EV_P)
|
|
3724
|
+
ev_loop_fork (EV_P) EV_NOEXCEPT
|
|
2108
3725
|
{
|
|
2109
|
-
postfork = 1;
|
|
3726
|
+
postfork = 1;
|
|
2110
3727
|
}
|
|
2111
3728
|
|
|
2112
3729
|
/*****************************************************************************/
|
|
@@ -2118,7 +3735,7 @@ ev_invoke (EV_P_ void *w, int revents)
|
|
|
2118
3735
|
}
|
|
2119
3736
|
|
|
2120
3737
|
unsigned int
|
|
2121
|
-
ev_pending_count (EV_P)
|
|
3738
|
+
ev_pending_count (EV_P) EV_NOEXCEPT
|
|
2122
3739
|
{
|
|
2123
3740
|
int pri;
|
|
2124
3741
|
unsigned int count = 0;
|
|
@@ -2129,20 +3746,27 @@ ev_pending_count (EV_P)
|
|
|
2129
3746
|
return count;
|
|
2130
3747
|
}
|
|
2131
3748
|
|
|
2132
|
-
|
|
3749
|
+
ecb_noinline
|
|
3750
|
+
void
|
|
2133
3751
|
ev_invoke_pending (EV_P)
|
|
2134
3752
|
{
|
|
2135
|
-
|
|
3753
|
+
pendingpri = NUMPRI;
|
|
2136
3754
|
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
ANPENDING *p = pendings [pri] + --pendingcnt [pri];
|
|
3755
|
+
do
|
|
3756
|
+
{
|
|
3757
|
+
--pendingpri;
|
|
2141
3758
|
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
3759
|
+
/* pendingpri possibly gets modified in the inner loop */
|
|
3760
|
+
while (pendingcnt [pendingpri])
|
|
3761
|
+
{
|
|
3762
|
+
ANPENDING *p = pendings [pendingpri] + --pendingcnt [pendingpri];
|
|
3763
|
+
|
|
3764
|
+
p->w->pending = 0;
|
|
3765
|
+
EV_CB_INVOKE (p->w, p->events);
|
|
3766
|
+
EV_FREQUENT_CHECK;
|
|
3767
|
+
}
|
|
3768
|
+
}
|
|
3769
|
+
while (pendingpri);
|
|
2146
3770
|
}
|
|
2147
3771
|
|
|
2148
3772
|
#if EV_IDLE_ENABLE
|
|
@@ -2151,7 +3775,7 @@ ev_invoke_pending (EV_P)
|
|
|
2151
3775
|
inline_size void
|
|
2152
3776
|
idle_reify (EV_P)
|
|
2153
3777
|
{
|
|
2154
|
-
if (
|
|
3778
|
+
if (ecb_expect_false (idleall))
|
|
2155
3779
|
{
|
|
2156
3780
|
int pri;
|
|
2157
3781
|
|
|
@@ -2191,7 +3815,7 @@ timers_reify (EV_P)
|
|
|
2191
3815
|
if (ev_at (w) < mn_now)
|
|
2192
3816
|
ev_at (w) = mn_now;
|
|
2193
3817
|
|
|
2194
|
-
assert (("libev: negative ev_timer repeat value found while processing timers", w->repeat > 0.));
|
|
3818
|
+
assert (("libev: negative ev_timer repeat value found while processing timers", w->repeat > EV_TS_CONST (0.)));
|
|
2195
3819
|
|
|
2196
3820
|
ANHE_at_cache (timers [HEAP0]);
|
|
2197
3821
|
downheap (timers, timercnt, HEAP0);
|
|
@@ -2210,12 +3834,29 @@ timers_reify (EV_P)
|
|
|
2210
3834
|
|
|
2211
3835
|
#if EV_PERIODIC_ENABLE
|
|
2212
3836
|
|
|
2213
|
-
|
|
3837
|
+
ecb_noinline
|
|
3838
|
+
static void
|
|
2214
3839
|
periodic_recalc (EV_P_ ev_periodic *w)
|
|
2215
3840
|
{
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
3841
|
+
ev_tstamp interval = w->interval > MIN_INTERVAL ? w->interval : MIN_INTERVAL;
|
|
3842
|
+
ev_tstamp at = w->offset + interval * ev_floor ((ev_rt_now - w->offset) / interval);
|
|
3843
|
+
|
|
3844
|
+
/* the above almost always errs on the low side */
|
|
3845
|
+
while (at <= ev_rt_now)
|
|
3846
|
+
{
|
|
3847
|
+
ev_tstamp nat = at + w->interval;
|
|
3848
|
+
|
|
3849
|
+
/* when resolution fails us, we use ev_rt_now */
|
|
3850
|
+
if (ecb_expect_false (nat == at))
|
|
3851
|
+
{
|
|
3852
|
+
at = ev_rt_now;
|
|
3853
|
+
break;
|
|
3854
|
+
}
|
|
3855
|
+
|
|
3856
|
+
at = nat;
|
|
3857
|
+
}
|
|
3858
|
+
|
|
3859
|
+
ev_at (w) = at;
|
|
2219
3860
|
}
|
|
2220
3861
|
|
|
2221
3862
|
/* make periodics pending */
|
|
@@ -2226,8 +3867,6 @@ periodics_reify (EV_P)
|
|
|
2226
3867
|
|
|
2227
3868
|
while (periodiccnt && ANHE_at (periodics [HEAP0]) < ev_rt_now)
|
|
2228
3869
|
{
|
|
2229
|
-
int feed_count = 0;
|
|
2230
|
-
|
|
2231
3870
|
do
|
|
2232
3871
|
{
|
|
2233
3872
|
ev_periodic *w = (ev_periodic *)ANHE_w (periodics [HEAP0]);
|
|
@@ -2247,20 +3886,6 @@ periodics_reify (EV_P)
|
|
|
2247
3886
|
else if (w->interval)
|
|
2248
3887
|
{
|
|
2249
3888
|
periodic_recalc (EV_A_ w);
|
|
2250
|
-
|
|
2251
|
-
/* if next trigger time is not sufficiently in the future, put it there */
|
|
2252
|
-
/* this might happen because of floating point inexactness */
|
|
2253
|
-
if (ev_at (w) - ev_rt_now < TIME_EPSILON)
|
|
2254
|
-
{
|
|
2255
|
-
ev_at (w) += w->interval;
|
|
2256
|
-
|
|
2257
|
-
/* if interval is unreasonably low we might still have a time in the past */
|
|
2258
|
-
/* so correct this. this will make the periodic very inexact, but the user */
|
|
2259
|
-
/* has effectively asked to get triggered more often than possible */
|
|
2260
|
-
if (ev_at (w) < ev_rt_now)
|
|
2261
|
-
ev_at (w) = ev_rt_now;
|
|
2262
|
-
}
|
|
2263
|
-
|
|
2264
3889
|
ANHE_at_cache (periodics [HEAP0]);
|
|
2265
3890
|
downheap (periodics, periodiccnt, HEAP0);
|
|
2266
3891
|
}
|
|
@@ -2278,7 +3903,8 @@ periodics_reify (EV_P)
|
|
|
2278
3903
|
|
|
2279
3904
|
/* simply recalculate all periodics */
|
|
2280
3905
|
/* TODO: maybe ensure that at least one event happens when jumping forward? */
|
|
2281
|
-
|
|
3906
|
+
ecb_noinline ecb_cold
|
|
3907
|
+
static void
|
|
2282
3908
|
periodics_reschedule (EV_P)
|
|
2283
3909
|
{
|
|
2284
3910
|
int i;
|
|
@@ -2301,7 +3927,8 @@ periodics_reschedule (EV_P)
|
|
|
2301
3927
|
#endif
|
|
2302
3928
|
|
|
2303
3929
|
/* adjust all timers by a given offset */
|
|
2304
|
-
|
|
3930
|
+
ecb_noinline ecb_cold
|
|
3931
|
+
static void
|
|
2305
3932
|
timers_reschedule (EV_P_ ev_tstamp adjust)
|
|
2306
3933
|
{
|
|
2307
3934
|
int i;
|
|
@@ -2320,7 +3947,7 @@ inline_speed void
|
|
|
2320
3947
|
time_update (EV_P_ ev_tstamp max_block)
|
|
2321
3948
|
{
|
|
2322
3949
|
#if EV_USE_MONOTONIC
|
|
2323
|
-
if (
|
|
3950
|
+
if (ecb_expect_true (have_monotonic))
|
|
2324
3951
|
{
|
|
2325
3952
|
int i;
|
|
2326
3953
|
ev_tstamp odiff = rtmn_diff;
|
|
@@ -2329,7 +3956,7 @@ time_update (EV_P_ ev_tstamp max_block)
|
|
|
2329
3956
|
|
|
2330
3957
|
/* only fetch the realtime clock every 0.5*MIN_TIMEJUMP seconds */
|
|
2331
3958
|
/* interpolate in the meantime */
|
|
2332
|
-
if (
|
|
3959
|
+
if (ecb_expect_true (mn_now - now_floor < EV_TS_CONST (MIN_TIMEJUMP * .5)))
|
|
2333
3960
|
{
|
|
2334
3961
|
ev_rt_now = rtmn_diff + mn_now;
|
|
2335
3962
|
return;
|
|
@@ -2348,9 +3975,12 @@ time_update (EV_P_ ev_tstamp max_block)
|
|
|
2348
3975
|
*/
|
|
2349
3976
|
for (i = 4; --i; )
|
|
2350
3977
|
{
|
|
3978
|
+
ev_tstamp diff;
|
|
2351
3979
|
rtmn_diff = ev_rt_now - mn_now;
|
|
2352
3980
|
|
|
2353
|
-
|
|
3981
|
+
diff = odiff - rtmn_diff;
|
|
3982
|
+
|
|
3983
|
+
if (ecb_expect_true ((diff < EV_TS_CONST (0.) ? -diff : diff) < EV_TS_CONST (MIN_TIMEJUMP)))
|
|
2354
3984
|
return; /* all is well */
|
|
2355
3985
|
|
|
2356
3986
|
ev_rt_now = ev_time ();
|
|
@@ -2369,7 +3999,7 @@ time_update (EV_P_ ev_tstamp max_block)
|
|
|
2369
3999
|
{
|
|
2370
4000
|
ev_rt_now = ev_time ();
|
|
2371
4001
|
|
|
2372
|
-
if (
|
|
4002
|
+
if (ecb_expect_false (mn_now > ev_rt_now || ev_rt_now > mn_now + max_block + EV_TS_CONST (MIN_TIMEJUMP)))
|
|
2373
4003
|
{
|
|
2374
4004
|
/* adjust timers. this is easy, as the offset is the same for all of them */
|
|
2375
4005
|
timers_reschedule (EV_A_ ev_rt_now - mn_now);
|
|
@@ -2382,9 +4012,30 @@ time_update (EV_P_ ev_tstamp max_block)
|
|
|
2382
4012
|
}
|
|
2383
4013
|
}
|
|
2384
4014
|
|
|
2385
|
-
|
|
4015
|
+
/* ########## NIO4R PATCHERY HO! ########## */
|
|
4016
|
+
struct ev_poll_args {
|
|
4017
|
+
struct ev_loop *loop;
|
|
4018
|
+
ev_tstamp waittime;
|
|
4019
|
+
};
|
|
4020
|
+
|
|
4021
|
+
static
|
|
4022
|
+
void * ev_backend_poll(void *ptr)
|
|
4023
|
+
{
|
|
4024
|
+
struct ev_poll_args *args = (struct ev_poll_args *)ptr;
|
|
4025
|
+
struct ev_loop *loop = args->loop;
|
|
4026
|
+
backend_poll (EV_A_ args->waittime);
|
|
4027
|
+
|
|
4028
|
+
return NULL;
|
|
4029
|
+
}
|
|
4030
|
+
/* ######################################## */
|
|
4031
|
+
|
|
4032
|
+
int
|
|
2386
4033
|
ev_run (EV_P_ int flags)
|
|
2387
4034
|
{
|
|
4035
|
+
/* ########## NIO4R PATCHERY HO! ########## */
|
|
4036
|
+
struct ev_poll_args poll_args;
|
|
4037
|
+
/* ######################################## */
|
|
4038
|
+
|
|
2388
4039
|
#if EV_FEATURE_API
|
|
2389
4040
|
++loop_depth;
|
|
2390
4041
|
#endif
|
|
@@ -2402,8 +4053,8 @@ ev_run (EV_P_ int flags)
|
|
|
2402
4053
|
#endif
|
|
2403
4054
|
|
|
2404
4055
|
#ifndef _WIN32
|
|
2405
|
-
if (
|
|
2406
|
-
if (
|
|
4056
|
+
if (ecb_expect_false (curpid)) /* penalise the forking check even more */
|
|
4057
|
+
if (ecb_expect_false (getpid () != curpid))
|
|
2407
4058
|
{
|
|
2408
4059
|
curpid = getpid ();
|
|
2409
4060
|
postfork = 1;
|
|
@@ -2412,7 +4063,7 @@ ev_run (EV_P_ int flags)
|
|
|
2412
4063
|
|
|
2413
4064
|
#if EV_FORK_ENABLE
|
|
2414
4065
|
/* we might have forked, so queue fork handlers */
|
|
2415
|
-
if (
|
|
4066
|
+
if (ecb_expect_false (postfork))
|
|
2416
4067
|
if (forkcnt)
|
|
2417
4068
|
{
|
|
2418
4069
|
queue_events (EV_A_ (W *)forks, forkcnt, EV_FORK);
|
|
@@ -2422,18 +4073,18 @@ ev_run (EV_P_ int flags)
|
|
|
2422
4073
|
|
|
2423
4074
|
#if EV_PREPARE_ENABLE
|
|
2424
4075
|
/* queue prepare watchers (and execute them) */
|
|
2425
|
-
if (
|
|
4076
|
+
if (ecb_expect_false (preparecnt))
|
|
2426
4077
|
{
|
|
2427
4078
|
queue_events (EV_A_ (W *)prepares, preparecnt, EV_PREPARE);
|
|
2428
4079
|
EV_INVOKE_PENDING;
|
|
2429
4080
|
}
|
|
2430
4081
|
#endif
|
|
2431
4082
|
|
|
2432
|
-
if (
|
|
4083
|
+
if (ecb_expect_false (loop_done))
|
|
2433
4084
|
break;
|
|
2434
4085
|
|
|
2435
4086
|
/* we might have forked, so reify kernel state if necessary */
|
|
2436
|
-
if (
|
|
4087
|
+
if (ecb_expect_false (postfork))
|
|
2437
4088
|
loop_fork (EV_A);
|
|
2438
4089
|
|
|
2439
4090
|
/* update fd-related kernel structures */
|
|
@@ -2448,39 +4099,66 @@ ev_run (EV_P_ int flags)
|
|
|
2448
4099
|
ev_tstamp prev_mn_now = mn_now;
|
|
2449
4100
|
|
|
2450
4101
|
/* update time to cancel out callback processing overhead */
|
|
2451
|
-
time_update (EV_A_
|
|
4102
|
+
time_update (EV_A_ EV_TS_CONST (EV_TSTAMP_HUGE));
|
|
4103
|
+
|
|
4104
|
+
/* from now on, we want a pipe-wake-up */
|
|
4105
|
+
pipe_write_wanted = 1;
|
|
2452
4106
|
|
|
2453
|
-
|
|
4107
|
+
ECB_MEMORY_FENCE; /* make sure pipe_write_wanted is visible before we check for potential skips */
|
|
4108
|
+
|
|
4109
|
+
if (ecb_expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt || pipe_write_skipped)))
|
|
2454
4110
|
{
|
|
2455
|
-
waittime = MAX_BLOCKTIME;
|
|
4111
|
+
waittime = EV_TS_CONST (MAX_BLOCKTIME);
|
|
4112
|
+
|
|
4113
|
+
#if EV_USE_TIMERFD
|
|
4114
|
+
/* sleep a lot longer when we can reliably detect timejumps */
|
|
4115
|
+
if (ecb_expect_true (timerfd >= 0))
|
|
4116
|
+
waittime = EV_TS_CONST (MAX_BLOCKTIME2);
|
|
4117
|
+
#endif
|
|
4118
|
+
#if !EV_PERIODIC_ENABLE
|
|
4119
|
+
/* without periodics but with monotonic clock there is no need */
|
|
4120
|
+
/* for any time jump detection, so sleep longer */
|
|
4121
|
+
if (ecb_expect_true (have_monotonic))
|
|
4122
|
+
waittime = EV_TS_CONST (MAX_BLOCKTIME2);
|
|
4123
|
+
#endif
|
|
2456
4124
|
|
|
2457
4125
|
if (timercnt)
|
|
2458
4126
|
{
|
|
2459
|
-
ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now
|
|
4127
|
+
ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now;
|
|
2460
4128
|
if (waittime > to) waittime = to;
|
|
2461
4129
|
}
|
|
2462
4130
|
|
|
2463
4131
|
#if EV_PERIODIC_ENABLE
|
|
2464
4132
|
if (periodiccnt)
|
|
2465
4133
|
{
|
|
2466
|
-
ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now
|
|
4134
|
+
ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now;
|
|
2467
4135
|
if (waittime > to) waittime = to;
|
|
2468
4136
|
}
|
|
2469
4137
|
#endif
|
|
2470
4138
|
|
|
2471
4139
|
/* don't let timeouts decrease the waittime below timeout_blocktime */
|
|
2472
|
-
if (
|
|
4140
|
+
if (ecb_expect_false (waittime < timeout_blocktime))
|
|
2473
4141
|
waittime = timeout_blocktime;
|
|
2474
4142
|
|
|
4143
|
+
/* now there are two more special cases left, either we have
|
|
4144
|
+
* already-expired timers, so we should not sleep, or we have timers
|
|
4145
|
+
* that expire very soon, in which case we need to wait for a minimum
|
|
4146
|
+
* amount of time for some event loop backends.
|
|
4147
|
+
*/
|
|
4148
|
+
if (ecb_expect_false (waittime < backend_mintime))
|
|
4149
|
+
waittime = waittime <= EV_TS_CONST (0.)
|
|
4150
|
+
? EV_TS_CONST (0.)
|
|
4151
|
+
: backend_mintime;
|
|
4152
|
+
|
|
2475
4153
|
/* extra check because io_blocktime is commonly 0 */
|
|
2476
|
-
if (
|
|
4154
|
+
if (ecb_expect_false (io_blocktime))
|
|
2477
4155
|
{
|
|
2478
4156
|
sleeptime = io_blocktime - (mn_now - prev_mn_now);
|
|
2479
4157
|
|
|
2480
|
-
if (sleeptime > waittime -
|
|
2481
|
-
sleeptime = waittime -
|
|
4158
|
+
if (sleeptime > waittime - backend_mintime)
|
|
4159
|
+
sleeptime = waittime - backend_mintime;
|
|
2482
4160
|
|
|
2483
|
-
if (
|
|
4161
|
+
if (ecb_expect_true (sleeptime > EV_TS_CONST (0.)))
|
|
2484
4162
|
{
|
|
2485
4163
|
ev_sleep (sleeptime);
|
|
2486
4164
|
waittime -= sleeptime;
|
|
@@ -2492,9 +4170,65 @@ ev_run (EV_P_ int flags)
|
|
|
2492
4170
|
++loop_count;
|
|
2493
4171
|
#endif
|
|
2494
4172
|
assert ((loop_done = EVBREAK_RECURSE, 1)); /* assert for side effect */
|
|
2495
|
-
|
|
4173
|
+
|
|
4174
|
+
/*
|
|
4175
|
+
########################## NIO4R PATCHERY HO! ##########################
|
|
4176
|
+
|
|
4177
|
+
According to the grandwizards of Ruby, locking and unlocking of the global
|
|
4178
|
+
interpreter lock are apparently too powerful a concept for a mere mortal to
|
|
4179
|
+
wield (although redefining what + and - do to numbers is totally cool).
|
|
4180
|
+
And so it came to pass that the only acceptable way to release the global
|
|
4181
|
+
interpreter lock is through a convoluted callback system that thakes a
|
|
4182
|
+
function pointer. While the grandwizard of libev foresaw this sort of scenario,
|
|
4183
|
+
he too attempted to place an API with callbacks on it, one that runs before
|
|
4184
|
+
the system call, and one that runs immediately after.
|
|
4185
|
+
|
|
4186
|
+
And so it came to pass that trying to wrap everything up in callbacks created
|
|
4187
|
+
two incompatible APIs, Ruby's which releases the global interpreter lock and
|
|
4188
|
+
reacquires it when the callback returns, and libev's, which wants two
|
|
4189
|
+
callbacks, one which runs before the polling operation starts, and one which
|
|
4190
|
+
runs after it finishes.
|
|
4191
|
+
|
|
4192
|
+
These two systems are incompatible as they both want to use callbacks to
|
|
4193
|
+
solve the same problem, however libev wants to use before/after callbacks,
|
|
4194
|
+
and Ruby wants to use an "around" callback. This presents a significant
|
|
4195
|
+
problem as these two patterns of callbacks are diametrical opposites of each
|
|
4196
|
+
other and thus cannot be composed.
|
|
4197
|
+
|
|
4198
|
+
And thus we are left with no choice but to patch the internals of libev in
|
|
4199
|
+
order to release a mutex at just the precise moment.
|
|
4200
|
+
|
|
4201
|
+
This is a great example of a situation where granular locking and unlocking
|
|
4202
|
+
of the GVL is practically required. The goal is to get as close to the
|
|
4203
|
+
system call as possible, and to keep the GVL unlocked for the shortest
|
|
4204
|
+
amount of time possible.
|
|
4205
|
+
|
|
4206
|
+
Perhaps Ruby could benefit from such an API, e.g:
|
|
4207
|
+
|
|
4208
|
+
rb_thread_unsafe_dangerous_crazy_blocking_region_begin(...);
|
|
4209
|
+
rb_thread_unsafe_dangerous_crazy_blocking_region_end(...);
|
|
4210
|
+
|
|
4211
|
+
#######################################################################
|
|
4212
|
+
*/
|
|
4213
|
+
|
|
4214
|
+
poll_args.loop = loop;
|
|
4215
|
+
poll_args.waittime = waittime;
|
|
4216
|
+
rb_thread_call_without_gvl(ev_backend_poll, (void *)&poll_args, RUBY_UBF_IO, 0);
|
|
4217
|
+
/*
|
|
4218
|
+
############################# END PATCHERY ############################
|
|
4219
|
+
*/
|
|
4220
|
+
|
|
2496
4221
|
assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */
|
|
2497
4222
|
|
|
4223
|
+
pipe_write_wanted = 0; /* just an optimisation, no fence needed */
|
|
4224
|
+
|
|
4225
|
+
ECB_MEMORY_FENCE_ACQUIRE;
|
|
4226
|
+
if (pipe_write_skipped)
|
|
4227
|
+
{
|
|
4228
|
+
assert (("libev: pipe_w not active, but pipe not written", ev_is_active (&pipe_w)));
|
|
4229
|
+
ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);
|
|
4230
|
+
}
|
|
4231
|
+
|
|
2498
4232
|
/* update ev_rt_now, do magic */
|
|
2499
4233
|
time_update (EV_A_ waittime + sleeptime);
|
|
2500
4234
|
}
|
|
@@ -2512,13 +4246,13 @@ ev_run (EV_P_ int flags)
|
|
|
2512
4246
|
|
|
2513
4247
|
#if EV_CHECK_ENABLE
|
|
2514
4248
|
/* queue check watchers, to be executed first */
|
|
2515
|
-
if (
|
|
4249
|
+
if (ecb_expect_false (checkcnt))
|
|
2516
4250
|
queue_events (EV_A_ (W *)checks, checkcnt, EV_CHECK);
|
|
2517
4251
|
#endif
|
|
2518
4252
|
|
|
2519
4253
|
EV_INVOKE_PENDING;
|
|
2520
4254
|
}
|
|
2521
|
-
while (
|
|
4255
|
+
while (ecb_expect_true (
|
|
2522
4256
|
activecnt
|
|
2523
4257
|
&& !loop_done
|
|
2524
4258
|
&& !(flags & (EVRUN_ONCE | EVRUN_NOWAIT))
|
|
@@ -2530,40 +4264,42 @@ ev_run (EV_P_ int flags)
|
|
|
2530
4264
|
#if EV_FEATURE_API
|
|
2531
4265
|
--loop_depth;
|
|
2532
4266
|
#endif
|
|
4267
|
+
|
|
4268
|
+
return activecnt;
|
|
2533
4269
|
}
|
|
2534
4270
|
|
|
2535
4271
|
void
|
|
2536
|
-
ev_break (EV_P_ int how)
|
|
4272
|
+
ev_break (EV_P_ int how) EV_NOEXCEPT
|
|
2537
4273
|
{
|
|
2538
4274
|
loop_done = how;
|
|
2539
4275
|
}
|
|
2540
4276
|
|
|
2541
4277
|
void
|
|
2542
|
-
ev_ref (EV_P)
|
|
4278
|
+
ev_ref (EV_P) EV_NOEXCEPT
|
|
2543
4279
|
{
|
|
2544
4280
|
++activecnt;
|
|
2545
4281
|
}
|
|
2546
4282
|
|
|
2547
4283
|
void
|
|
2548
|
-
ev_unref (EV_P)
|
|
4284
|
+
ev_unref (EV_P) EV_NOEXCEPT
|
|
2549
4285
|
{
|
|
2550
4286
|
--activecnt;
|
|
2551
4287
|
}
|
|
2552
4288
|
|
|
2553
4289
|
void
|
|
2554
|
-
ev_now_update (EV_P)
|
|
4290
|
+
ev_now_update (EV_P) EV_NOEXCEPT
|
|
2555
4291
|
{
|
|
2556
|
-
time_update (EV_A_
|
|
4292
|
+
time_update (EV_A_ EV_TSTAMP_HUGE);
|
|
2557
4293
|
}
|
|
2558
4294
|
|
|
2559
4295
|
void
|
|
2560
|
-
ev_suspend (EV_P)
|
|
4296
|
+
ev_suspend (EV_P) EV_NOEXCEPT
|
|
2561
4297
|
{
|
|
2562
4298
|
ev_now_update (EV_A);
|
|
2563
4299
|
}
|
|
2564
4300
|
|
|
2565
4301
|
void
|
|
2566
|
-
ev_resume (EV_P)
|
|
4302
|
+
ev_resume (EV_P) EV_NOEXCEPT
|
|
2567
4303
|
{
|
|
2568
4304
|
ev_tstamp mn_prev = mn_now;
|
|
2569
4305
|
|
|
@@ -2590,7 +4326,7 @@ wlist_del (WL *head, WL elem)
|
|
|
2590
4326
|
{
|
|
2591
4327
|
while (*head)
|
|
2592
4328
|
{
|
|
2593
|
-
if (
|
|
4329
|
+
if (ecb_expect_true (*head == elem))
|
|
2594
4330
|
{
|
|
2595
4331
|
*head = elem->next;
|
|
2596
4332
|
break;
|
|
@@ -2612,12 +4348,12 @@ clear_pending (EV_P_ W w)
|
|
|
2612
4348
|
}
|
|
2613
4349
|
|
|
2614
4350
|
int
|
|
2615
|
-
ev_clear_pending (EV_P_ void *w)
|
|
4351
|
+
ev_clear_pending (EV_P_ void *w) EV_NOEXCEPT
|
|
2616
4352
|
{
|
|
2617
4353
|
W w_ = (W)w;
|
|
2618
4354
|
int pending = w_->pending;
|
|
2619
4355
|
|
|
2620
|
-
if (
|
|
4356
|
+
if (ecb_expect_true (pending))
|
|
2621
4357
|
{
|
|
2622
4358
|
ANPENDING *p = pendings [ABSPRI (w_)] + pending - 1;
|
|
2623
4359
|
p->w = (W)&pending_w;
|
|
@@ -2654,38 +4390,49 @@ ev_stop (EV_P_ W w)
|
|
|
2654
4390
|
|
|
2655
4391
|
/*****************************************************************************/
|
|
2656
4392
|
|
|
2657
|
-
|
|
2658
|
-
|
|
4393
|
+
ecb_noinline
|
|
4394
|
+
void
|
|
4395
|
+
ev_io_start (EV_P_ ev_io *w) EV_NOEXCEPT
|
|
2659
4396
|
{
|
|
2660
4397
|
int fd = w->fd;
|
|
2661
4398
|
|
|
2662
|
-
if (
|
|
4399
|
+
if (ecb_expect_false (ev_is_active (w)))
|
|
2663
4400
|
return;
|
|
2664
4401
|
|
|
2665
4402
|
assert (("libev: ev_io_start called with negative fd", fd >= 0));
|
|
2666
4403
|
assert (("libev: ev_io_start called with illegal event mask", !(w->events & ~(EV__IOFDSET | EV_READ | EV_WRITE))));
|
|
2667
4404
|
|
|
4405
|
+
#if EV_VERIFY >= 2
|
|
4406
|
+
assert (("libev: ev_io_start called on watcher with invalid fd", fd_valid (fd)));
|
|
4407
|
+
#endif
|
|
2668
4408
|
EV_FREQUENT_CHECK;
|
|
2669
4409
|
|
|
2670
4410
|
ev_start (EV_A_ (W)w, 1);
|
|
2671
|
-
array_needsize (ANFD, anfds, anfdmax, fd + 1,
|
|
4411
|
+
array_needsize (ANFD, anfds, anfdmax, fd + 1, array_needsize_zerofill);
|
|
2672
4412
|
wlist_add (&anfds[fd].head, (WL)w);
|
|
2673
4413
|
|
|
4414
|
+
/* common bug, apparently */
|
|
4415
|
+
assert (("libev: ev_io_start called with corrupted watcher", ((WL)w)->next != (WL)w));
|
|
4416
|
+
|
|
2674
4417
|
fd_change (EV_A_ fd, w->events & EV__IOFDSET | EV_ANFD_REIFY);
|
|
2675
4418
|
w->events &= ~EV__IOFDSET;
|
|
2676
4419
|
|
|
2677
4420
|
EV_FREQUENT_CHECK;
|
|
2678
4421
|
}
|
|
2679
4422
|
|
|
2680
|
-
|
|
2681
|
-
|
|
4423
|
+
ecb_noinline
|
|
4424
|
+
void
|
|
4425
|
+
ev_io_stop (EV_P_ ev_io *w) EV_NOEXCEPT
|
|
2682
4426
|
{
|
|
2683
4427
|
clear_pending (EV_A_ (W)w);
|
|
2684
|
-
if (
|
|
4428
|
+
if (ecb_expect_false (!ev_is_active (w)))
|
|
2685
4429
|
return;
|
|
2686
4430
|
|
|
2687
4431
|
assert (("libev: ev_io_stop called with illegal fd (must stay constant after start!)", w->fd >= 0 && w->fd < anfdmax));
|
|
2688
4432
|
|
|
4433
|
+
#if EV_VERIFY >= 2
|
|
4434
|
+
assert (("libev: ev_io_stop called on watcher with invalid fd", fd_valid (w->fd)));
|
|
4435
|
+
#endif
|
|
2689
4436
|
EV_FREQUENT_CHECK;
|
|
2690
4437
|
|
|
2691
4438
|
wlist_del (&anfds[w->fd].head, (WL)w);
|
|
@@ -2696,10 +4443,11 @@ ev_io_stop (EV_P_ ev_io *w)
|
|
|
2696
4443
|
EV_FREQUENT_CHECK;
|
|
2697
4444
|
}
|
|
2698
4445
|
|
|
2699
|
-
|
|
2700
|
-
|
|
4446
|
+
ecb_noinline
|
|
4447
|
+
void
|
|
4448
|
+
ev_timer_start (EV_P_ ev_timer *w) EV_NOEXCEPT
|
|
2701
4449
|
{
|
|
2702
|
-
if (
|
|
4450
|
+
if (ecb_expect_false (ev_is_active (w)))
|
|
2703
4451
|
return;
|
|
2704
4452
|
|
|
2705
4453
|
ev_at (w) += mn_now;
|
|
@@ -2710,7 +4458,7 @@ ev_timer_start (EV_P_ ev_timer *w)
|
|
|
2710
4458
|
|
|
2711
4459
|
++timercnt;
|
|
2712
4460
|
ev_start (EV_A_ (W)w, timercnt + HEAP0 - 1);
|
|
2713
|
-
array_needsize (ANHE, timers, timermax, ev_active (w) + 1,
|
|
4461
|
+
array_needsize (ANHE, timers, timermax, ev_active (w) + 1, array_needsize_noinit);
|
|
2714
4462
|
ANHE_w (timers [ev_active (w)]) = (WT)w;
|
|
2715
4463
|
ANHE_at_cache (timers [ev_active (w)]);
|
|
2716
4464
|
upheap (timers, ev_active (w));
|
|
@@ -2720,11 +4468,12 @@ ev_timer_start (EV_P_ ev_timer *w)
|
|
|
2720
4468
|
/*assert (("libev: internal timer heap corruption", timers [ev_active (w)] == (WT)w));*/
|
|
2721
4469
|
}
|
|
2722
4470
|
|
|
2723
|
-
|
|
2724
|
-
|
|
4471
|
+
ecb_noinline
|
|
4472
|
+
void
|
|
4473
|
+
ev_timer_stop (EV_P_ ev_timer *w) EV_NOEXCEPT
|
|
2725
4474
|
{
|
|
2726
4475
|
clear_pending (EV_A_ (W)w);
|
|
2727
|
-
if (
|
|
4476
|
+
if (ecb_expect_false (!ev_is_active (w)))
|
|
2728
4477
|
return;
|
|
2729
4478
|
|
|
2730
4479
|
EV_FREQUENT_CHECK;
|
|
@@ -2736,7 +4485,7 @@ ev_timer_stop (EV_P_ ev_timer *w)
|
|
|
2736
4485
|
|
|
2737
4486
|
--timercnt;
|
|
2738
4487
|
|
|
2739
|
-
if (
|
|
4488
|
+
if (ecb_expect_true (active < timercnt + HEAP0))
|
|
2740
4489
|
{
|
|
2741
4490
|
timers [active] = timers [timercnt + HEAP0];
|
|
2742
4491
|
adjustheap (timers, timercnt, active);
|
|
@@ -2750,11 +4499,14 @@ ev_timer_stop (EV_P_ ev_timer *w)
|
|
|
2750
4499
|
EV_FREQUENT_CHECK;
|
|
2751
4500
|
}
|
|
2752
4501
|
|
|
2753
|
-
|
|
2754
|
-
|
|
4502
|
+
ecb_noinline
|
|
4503
|
+
void
|
|
4504
|
+
ev_timer_again (EV_P_ ev_timer *w) EV_NOEXCEPT
|
|
2755
4505
|
{
|
|
2756
4506
|
EV_FREQUENT_CHECK;
|
|
2757
4507
|
|
|
4508
|
+
clear_pending (EV_A_ (W)w);
|
|
4509
|
+
|
|
2758
4510
|
if (ev_is_active (w))
|
|
2759
4511
|
{
|
|
2760
4512
|
if (w->repeat)
|
|
@@ -2776,18 +4528,24 @@ ev_timer_again (EV_P_ ev_timer *w)
|
|
|
2776
4528
|
}
|
|
2777
4529
|
|
|
2778
4530
|
ev_tstamp
|
|
2779
|
-
ev_timer_remaining (EV_P_ ev_timer *w)
|
|
4531
|
+
ev_timer_remaining (EV_P_ ev_timer *w) EV_NOEXCEPT
|
|
2780
4532
|
{
|
|
2781
|
-
return ev_at (w) - (ev_is_active (w) ? mn_now : 0.);
|
|
4533
|
+
return ev_at (w) - (ev_is_active (w) ? mn_now : EV_TS_CONST (0.));
|
|
2782
4534
|
}
|
|
2783
4535
|
|
|
2784
4536
|
#if EV_PERIODIC_ENABLE
|
|
2785
|
-
|
|
2786
|
-
|
|
4537
|
+
ecb_noinline
|
|
4538
|
+
void
|
|
4539
|
+
ev_periodic_start (EV_P_ ev_periodic *w) EV_NOEXCEPT
|
|
2787
4540
|
{
|
|
2788
|
-
if (
|
|
4541
|
+
if (ecb_expect_false (ev_is_active (w)))
|
|
2789
4542
|
return;
|
|
2790
4543
|
|
|
4544
|
+
#if EV_USE_TIMERFD
|
|
4545
|
+
if (timerfd == -2)
|
|
4546
|
+
evtimerfd_init (EV_A);
|
|
4547
|
+
#endif
|
|
4548
|
+
|
|
2791
4549
|
if (w->reschedule_cb)
|
|
2792
4550
|
ev_at (w) = w->reschedule_cb (w, ev_rt_now);
|
|
2793
4551
|
else if (w->interval)
|
|
@@ -2802,7 +4560,7 @@ ev_periodic_start (EV_P_ ev_periodic *w)
|
|
|
2802
4560
|
|
|
2803
4561
|
++periodiccnt;
|
|
2804
4562
|
ev_start (EV_A_ (W)w, periodiccnt + HEAP0 - 1);
|
|
2805
|
-
array_needsize (ANHE, periodics, periodicmax, ev_active (w) + 1,
|
|
4563
|
+
array_needsize (ANHE, periodics, periodicmax, ev_active (w) + 1, array_needsize_noinit);
|
|
2806
4564
|
ANHE_w (periodics [ev_active (w)]) = (WT)w;
|
|
2807
4565
|
ANHE_at_cache (periodics [ev_active (w)]);
|
|
2808
4566
|
upheap (periodics, ev_active (w));
|
|
@@ -2812,11 +4570,12 @@ ev_periodic_start (EV_P_ ev_periodic *w)
|
|
|
2812
4570
|
/*assert (("libev: internal periodic heap corruption", ANHE_w (periodics [ev_active (w)]) == (WT)w));*/
|
|
2813
4571
|
}
|
|
2814
4572
|
|
|
2815
|
-
|
|
2816
|
-
|
|
4573
|
+
ecb_noinline
|
|
4574
|
+
void
|
|
4575
|
+
ev_periodic_stop (EV_P_ ev_periodic *w) EV_NOEXCEPT
|
|
2817
4576
|
{
|
|
2818
4577
|
clear_pending (EV_A_ (W)w);
|
|
2819
|
-
if (
|
|
4578
|
+
if (ecb_expect_false (!ev_is_active (w)))
|
|
2820
4579
|
return;
|
|
2821
4580
|
|
|
2822
4581
|
EV_FREQUENT_CHECK;
|
|
@@ -2828,7 +4587,7 @@ ev_periodic_stop (EV_P_ ev_periodic *w)
|
|
|
2828
4587
|
|
|
2829
4588
|
--periodiccnt;
|
|
2830
4589
|
|
|
2831
|
-
if (
|
|
4590
|
+
if (ecb_expect_true (active < periodiccnt + HEAP0))
|
|
2832
4591
|
{
|
|
2833
4592
|
periodics [active] = periodics [periodiccnt + HEAP0];
|
|
2834
4593
|
adjustheap (periodics, periodiccnt, active);
|
|
@@ -2840,8 +4599,9 @@ ev_periodic_stop (EV_P_ ev_periodic *w)
|
|
|
2840
4599
|
EV_FREQUENT_CHECK;
|
|
2841
4600
|
}
|
|
2842
4601
|
|
|
2843
|
-
|
|
2844
|
-
|
|
4602
|
+
ecb_noinline
|
|
4603
|
+
void
|
|
4604
|
+
ev_periodic_again (EV_P_ ev_periodic *w) EV_NOEXCEPT
|
|
2845
4605
|
{
|
|
2846
4606
|
/* TODO: use adjustheap and recalculation */
|
|
2847
4607
|
ev_periodic_stop (EV_A_ w);
|
|
@@ -2855,10 +4615,11 @@ ev_periodic_again (EV_P_ ev_periodic *w)
|
|
|
2855
4615
|
|
|
2856
4616
|
#if EV_SIGNAL_ENABLE
|
|
2857
4617
|
|
|
2858
|
-
|
|
2859
|
-
|
|
4618
|
+
ecb_noinline
|
|
4619
|
+
void
|
|
4620
|
+
ev_signal_start (EV_P_ ev_signal *w) EV_NOEXCEPT
|
|
2860
4621
|
{
|
|
2861
|
-
if (
|
|
4622
|
+
if (ecb_expect_false (ev_is_active (w)))
|
|
2862
4623
|
return;
|
|
2863
4624
|
|
|
2864
4625
|
assert (("libev: ev_signal_start called with illegal signal number", w->signum > 0 && w->signum < EV_NSIG));
|
|
@@ -2868,6 +4629,7 @@ ev_signal_start (EV_P_ ev_signal *w)
|
|
|
2868
4629
|
!signals [w->signum - 1].loop || signals [w->signum - 1].loop == loop));
|
|
2869
4630
|
|
|
2870
4631
|
signals [w->signum - 1].loop = EV_A;
|
|
4632
|
+
ECB_MEMORY_FENCE_RELEASE;
|
|
2871
4633
|
#endif
|
|
2872
4634
|
|
|
2873
4635
|
EV_FREQUENT_CHECK;
|
|
@@ -2936,11 +4698,12 @@ ev_signal_start (EV_P_ ev_signal *w)
|
|
|
2936
4698
|
EV_FREQUENT_CHECK;
|
|
2937
4699
|
}
|
|
2938
4700
|
|
|
2939
|
-
|
|
2940
|
-
|
|
4701
|
+
ecb_noinline
|
|
4702
|
+
void
|
|
4703
|
+
ev_signal_stop (EV_P_ ev_signal *w) EV_NOEXCEPT
|
|
2941
4704
|
{
|
|
2942
4705
|
clear_pending (EV_A_ (W)w);
|
|
2943
|
-
if (
|
|
4706
|
+
if (ecb_expect_false (!ev_is_active (w)))
|
|
2944
4707
|
return;
|
|
2945
4708
|
|
|
2946
4709
|
EV_FREQUENT_CHECK;
|
|
@@ -2978,12 +4741,12 @@ ev_signal_stop (EV_P_ ev_signal *w)
|
|
|
2978
4741
|
#if EV_CHILD_ENABLE
|
|
2979
4742
|
|
|
2980
4743
|
void
|
|
2981
|
-
ev_child_start (EV_P_ ev_child *w)
|
|
4744
|
+
ev_child_start (EV_P_ ev_child *w) EV_NOEXCEPT
|
|
2982
4745
|
{
|
|
2983
4746
|
#if EV_MULTIPLICITY
|
|
2984
4747
|
assert (("libev: child watchers are only supported in the default loop", loop == ev_default_loop_ptr));
|
|
2985
4748
|
#endif
|
|
2986
|
-
if (
|
|
4749
|
+
if (ecb_expect_false (ev_is_active (w)))
|
|
2987
4750
|
return;
|
|
2988
4751
|
|
|
2989
4752
|
EV_FREQUENT_CHECK;
|
|
@@ -2995,10 +4758,10 @@ ev_child_start (EV_P_ ev_child *w)
|
|
|
2995
4758
|
}
|
|
2996
4759
|
|
|
2997
4760
|
void
|
|
2998
|
-
ev_child_stop (EV_P_ ev_child *w)
|
|
4761
|
+
ev_child_stop (EV_P_ ev_child *w) EV_NOEXCEPT
|
|
2999
4762
|
{
|
|
3000
4763
|
clear_pending (EV_A_ (W)w);
|
|
3001
|
-
if (
|
|
4764
|
+
if (ecb_expect_false (!ev_is_active (w)))
|
|
3002
4765
|
return;
|
|
3003
4766
|
|
|
3004
4767
|
EV_FREQUENT_CHECK;
|
|
@@ -3022,17 +4785,21 @@ ev_child_stop (EV_P_ ev_child *w)
|
|
|
3022
4785
|
#define NFS_STAT_INTERVAL 30.1074891 /* for filesystems potentially failing inotify */
|
|
3023
4786
|
#define MIN_STAT_INTERVAL 0.1074891
|
|
3024
4787
|
|
|
3025
|
-
static void
|
|
4788
|
+
ecb_noinline static void stat_timer_cb (EV_P_ ev_timer *w_, int revents);
|
|
3026
4789
|
|
|
3027
4790
|
#if EV_USE_INOTIFY
|
|
3028
4791
|
|
|
3029
4792
|
/* the * 2 is to allow for alignment padding, which for some reason is >> 8 */
|
|
3030
4793
|
# define EV_INOTIFY_BUFSIZE (sizeof (struct inotify_event) * 2 + NAME_MAX)
|
|
3031
4794
|
|
|
3032
|
-
|
|
4795
|
+
ecb_noinline
|
|
4796
|
+
static void
|
|
3033
4797
|
infy_add (EV_P_ ev_stat *w)
|
|
3034
4798
|
{
|
|
3035
|
-
w->wd = inotify_add_watch (fs_fd, w->path,
|
|
4799
|
+
w->wd = inotify_add_watch (fs_fd, w->path,
|
|
4800
|
+
IN_ATTRIB | IN_DELETE_SELF | IN_MOVE_SELF | IN_MODIFY
|
|
4801
|
+
| IN_CREATE | IN_DELETE | IN_MOVED_FROM | IN_MOVED_TO
|
|
4802
|
+
| IN_DONT_FOLLOW | IN_MASK_ADD);
|
|
3036
4803
|
|
|
3037
4804
|
if (w->wd >= 0)
|
|
3038
4805
|
{
|
|
@@ -3046,10 +4813,16 @@ infy_add (EV_P_ ev_stat *w)
|
|
|
3046
4813
|
w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL;
|
|
3047
4814
|
else if (!statfs (w->path, &sfs)
|
|
3048
4815
|
&& (sfs.f_type == 0x1373 /* devfs */
|
|
4816
|
+
|| sfs.f_type == 0x4006 /* fat */
|
|
4817
|
+
|| sfs.f_type == 0x4d44 /* msdos */
|
|
3049
4818
|
|| sfs.f_type == 0xEF53 /* ext2/3 */
|
|
4819
|
+
|| sfs.f_type == 0x72b6 /* jffs2 */
|
|
4820
|
+
|| sfs.f_type == 0x858458f6 /* ramfs */
|
|
4821
|
+
|| sfs.f_type == 0x5346544e /* ntfs */
|
|
3050
4822
|
|| sfs.f_type == 0x3153464a /* jfs */
|
|
4823
|
+
|| sfs.f_type == 0x9123683e /* btrfs */
|
|
3051
4824
|
|| sfs.f_type == 0x52654973 /* reiser3 */
|
|
3052
|
-
|| sfs.f_type == 0x01021994 /*
|
|
4825
|
+
|| sfs.f_type == 0x01021994 /* tmpfs */
|
|
3053
4826
|
|| sfs.f_type == 0x58465342 /* xfs */))
|
|
3054
4827
|
w->timer.repeat = 0.; /* filesystem is local, kernel new enough */
|
|
3055
4828
|
else
|
|
@@ -3094,7 +4867,8 @@ infy_add (EV_P_ ev_stat *w)
|
|
|
3094
4867
|
if (ev_is_active (&w->timer)) ev_unref (EV_A);
|
|
3095
4868
|
}
|
|
3096
4869
|
|
|
3097
|
-
|
|
4870
|
+
ecb_noinline
|
|
4871
|
+
static void
|
|
3098
4872
|
infy_del (EV_P_ ev_stat *w)
|
|
3099
4873
|
{
|
|
3100
4874
|
int slot;
|
|
@@ -3111,7 +4885,8 @@ infy_del (EV_P_ ev_stat *w)
|
|
|
3111
4885
|
inotify_rm_watch (fs_fd, wd);
|
|
3112
4886
|
}
|
|
3113
4887
|
|
|
3114
|
-
|
|
4888
|
+
ecb_noinline
|
|
4889
|
+
static void
|
|
3115
4890
|
infy_wd (EV_P_ int slot, int wd, struct inotify_event *ev)
|
|
3116
4891
|
{
|
|
3117
4892
|
if (slot < 0)
|
|
@@ -3157,7 +4932,8 @@ infy_cb (EV_P_ ev_io *w, int revents)
|
|
|
3157
4932
|
}
|
|
3158
4933
|
}
|
|
3159
4934
|
|
|
3160
|
-
inline_size
|
|
4935
|
+
inline_size ecb_cold
|
|
4936
|
+
void
|
|
3161
4937
|
ev_check_2625 (EV_P)
|
|
3162
4938
|
{
|
|
3163
4939
|
/* kernels < 2.6.25 are borked
|
|
@@ -3172,7 +4948,7 @@ ev_check_2625 (EV_P)
|
|
|
3172
4948
|
inline_size int
|
|
3173
4949
|
infy_newfd (void)
|
|
3174
4950
|
{
|
|
3175
|
-
#if defined
|
|
4951
|
+
#if defined IN_CLOEXEC && defined IN_NONBLOCK
|
|
3176
4952
|
int fd = inotify_init1 (IN_CLOEXEC | IN_NONBLOCK);
|
|
3177
4953
|
if (fd >= 0)
|
|
3178
4954
|
return fd;
|
|
@@ -3257,7 +5033,7 @@ infy_fork (EV_P)
|
|
|
3257
5033
|
#endif
|
|
3258
5034
|
|
|
3259
5035
|
void
|
|
3260
|
-
ev_stat_stat (EV_P_ ev_stat *w)
|
|
5036
|
+
ev_stat_stat (EV_P_ ev_stat *w) EV_NOEXCEPT
|
|
3261
5037
|
{
|
|
3262
5038
|
if (lstat (w->path, &w->attr) < 0)
|
|
3263
5039
|
w->attr.st_nlink = 0;
|
|
@@ -3265,7 +5041,8 @@ ev_stat_stat (EV_P_ ev_stat *w)
|
|
|
3265
5041
|
w->attr.st_nlink = 1;
|
|
3266
5042
|
}
|
|
3267
5043
|
|
|
3268
|
-
|
|
5044
|
+
ecb_noinline
|
|
5045
|
+
static void
|
|
3269
5046
|
stat_timer_cb (EV_P_ ev_timer *w_, int revents)
|
|
3270
5047
|
{
|
|
3271
5048
|
ev_stat *w = (ev_stat *)(((char *)w_) - offsetof (ev_stat, timer));
|
|
@@ -3306,9 +5083,9 @@ stat_timer_cb (EV_P_ ev_timer *w_, int revents)
|
|
|
3306
5083
|
}
|
|
3307
5084
|
|
|
3308
5085
|
void
|
|
3309
|
-
ev_stat_start (EV_P_ ev_stat *w)
|
|
5086
|
+
ev_stat_start (EV_P_ ev_stat *w) EV_NOEXCEPT
|
|
3310
5087
|
{
|
|
3311
|
-
if (
|
|
5088
|
+
if (ecb_expect_false (ev_is_active (w)))
|
|
3312
5089
|
return;
|
|
3313
5090
|
|
|
3314
5091
|
ev_stat_stat (EV_A_ w);
|
|
@@ -3337,10 +5114,10 @@ ev_stat_start (EV_P_ ev_stat *w)
|
|
|
3337
5114
|
}
|
|
3338
5115
|
|
|
3339
5116
|
void
|
|
3340
|
-
ev_stat_stop (EV_P_ ev_stat *w)
|
|
5117
|
+
ev_stat_stop (EV_P_ ev_stat *w) EV_NOEXCEPT
|
|
3341
5118
|
{
|
|
3342
5119
|
clear_pending (EV_A_ (W)w);
|
|
3343
|
-
if (
|
|
5120
|
+
if (ecb_expect_false (!ev_is_active (w)))
|
|
3344
5121
|
return;
|
|
3345
5122
|
|
|
3346
5123
|
EV_FREQUENT_CHECK;
|
|
@@ -3363,9 +5140,9 @@ ev_stat_stop (EV_P_ ev_stat *w)
|
|
|
3363
5140
|
|
|
3364
5141
|
#if EV_IDLE_ENABLE
|
|
3365
5142
|
void
|
|
3366
|
-
ev_idle_start (EV_P_ ev_idle *w)
|
|
5143
|
+
ev_idle_start (EV_P_ ev_idle *w) EV_NOEXCEPT
|
|
3367
5144
|
{
|
|
3368
|
-
if (
|
|
5145
|
+
if (ecb_expect_false (ev_is_active (w)))
|
|
3369
5146
|
return;
|
|
3370
5147
|
|
|
3371
5148
|
pri_adjust (EV_A_ (W)w);
|
|
@@ -3378,7 +5155,7 @@ ev_idle_start (EV_P_ ev_idle *w)
|
|
|
3378
5155
|
++idleall;
|
|
3379
5156
|
ev_start (EV_A_ (W)w, active);
|
|
3380
5157
|
|
|
3381
|
-
array_needsize (ev_idle *, idles [ABSPRI (w)], idlemax [ABSPRI (w)], active,
|
|
5158
|
+
array_needsize (ev_idle *, idles [ABSPRI (w)], idlemax [ABSPRI (w)], active, array_needsize_noinit);
|
|
3382
5159
|
idles [ABSPRI (w)][active - 1] = w;
|
|
3383
5160
|
}
|
|
3384
5161
|
|
|
@@ -3386,10 +5163,10 @@ ev_idle_start (EV_P_ ev_idle *w)
|
|
|
3386
5163
|
}
|
|
3387
5164
|
|
|
3388
5165
|
void
|
|
3389
|
-
ev_idle_stop (EV_P_ ev_idle *w)
|
|
5166
|
+
ev_idle_stop (EV_P_ ev_idle *w) EV_NOEXCEPT
|
|
3390
5167
|
{
|
|
3391
5168
|
clear_pending (EV_A_ (W)w);
|
|
3392
|
-
if (
|
|
5169
|
+
if (ecb_expect_false (!ev_is_active (w)))
|
|
3393
5170
|
return;
|
|
3394
5171
|
|
|
3395
5172
|
EV_FREQUENT_CHECK;
|
|
@@ -3410,25 +5187,25 @@ ev_idle_stop (EV_P_ ev_idle *w)
|
|
|
3410
5187
|
|
|
3411
5188
|
#if EV_PREPARE_ENABLE
|
|
3412
5189
|
void
|
|
3413
|
-
ev_prepare_start (EV_P_ ev_prepare *w)
|
|
5190
|
+
ev_prepare_start (EV_P_ ev_prepare *w) EV_NOEXCEPT
|
|
3414
5191
|
{
|
|
3415
|
-
if (
|
|
5192
|
+
if (ecb_expect_false (ev_is_active (w)))
|
|
3416
5193
|
return;
|
|
3417
5194
|
|
|
3418
5195
|
EV_FREQUENT_CHECK;
|
|
3419
5196
|
|
|
3420
5197
|
ev_start (EV_A_ (W)w, ++preparecnt);
|
|
3421
|
-
array_needsize (ev_prepare *, prepares, preparemax, preparecnt,
|
|
5198
|
+
array_needsize (ev_prepare *, prepares, preparemax, preparecnt, array_needsize_noinit);
|
|
3422
5199
|
prepares [preparecnt - 1] = w;
|
|
3423
5200
|
|
|
3424
5201
|
EV_FREQUENT_CHECK;
|
|
3425
5202
|
}
|
|
3426
5203
|
|
|
3427
5204
|
void
|
|
3428
|
-
ev_prepare_stop (EV_P_ ev_prepare *w)
|
|
5205
|
+
ev_prepare_stop (EV_P_ ev_prepare *w) EV_NOEXCEPT
|
|
3429
5206
|
{
|
|
3430
5207
|
clear_pending (EV_A_ (W)w);
|
|
3431
|
-
if (
|
|
5208
|
+
if (ecb_expect_false (!ev_is_active (w)))
|
|
3432
5209
|
return;
|
|
3433
5210
|
|
|
3434
5211
|
EV_FREQUENT_CHECK;
|
|
@@ -3448,25 +5225,25 @@ ev_prepare_stop (EV_P_ ev_prepare *w)
|
|
|
3448
5225
|
|
|
3449
5226
|
#if EV_CHECK_ENABLE
|
|
3450
5227
|
void
|
|
3451
|
-
ev_check_start (EV_P_ ev_check *w)
|
|
5228
|
+
ev_check_start (EV_P_ ev_check *w) EV_NOEXCEPT
|
|
3452
5229
|
{
|
|
3453
|
-
if (
|
|
5230
|
+
if (ecb_expect_false (ev_is_active (w)))
|
|
3454
5231
|
return;
|
|
3455
5232
|
|
|
3456
5233
|
EV_FREQUENT_CHECK;
|
|
3457
5234
|
|
|
3458
5235
|
ev_start (EV_A_ (W)w, ++checkcnt);
|
|
3459
|
-
array_needsize (ev_check *, checks, checkmax, checkcnt,
|
|
5236
|
+
array_needsize (ev_check *, checks, checkmax, checkcnt, array_needsize_noinit);
|
|
3460
5237
|
checks [checkcnt - 1] = w;
|
|
3461
5238
|
|
|
3462
5239
|
EV_FREQUENT_CHECK;
|
|
3463
5240
|
}
|
|
3464
5241
|
|
|
3465
5242
|
void
|
|
3466
|
-
ev_check_stop (EV_P_ ev_check *w)
|
|
5243
|
+
ev_check_stop (EV_P_ ev_check *w) EV_NOEXCEPT
|
|
3467
5244
|
{
|
|
3468
5245
|
clear_pending (EV_A_ (W)w);
|
|
3469
|
-
if (
|
|
5246
|
+
if (ecb_expect_false (!ev_is_active (w)))
|
|
3470
5247
|
return;
|
|
3471
5248
|
|
|
3472
5249
|
EV_FREQUENT_CHECK;
|
|
@@ -3485,8 +5262,9 @@ ev_check_stop (EV_P_ ev_check *w)
|
|
|
3485
5262
|
#endif
|
|
3486
5263
|
|
|
3487
5264
|
#if EV_EMBED_ENABLE
|
|
3488
|
-
|
|
3489
|
-
|
|
5265
|
+
ecb_noinline
|
|
5266
|
+
void
|
|
5267
|
+
ev_embed_sweep (EV_P_ ev_embed *w) EV_NOEXCEPT
|
|
3490
5268
|
{
|
|
3491
5269
|
ev_run (w->other, EVRUN_NOWAIT);
|
|
3492
5270
|
}
|
|
@@ -3518,6 +5296,7 @@ embed_prepare_cb (EV_P_ ev_prepare *prepare, int revents)
|
|
|
3518
5296
|
}
|
|
3519
5297
|
}
|
|
3520
5298
|
|
|
5299
|
+
#if EV_FORK_ENABLE
|
|
3521
5300
|
static void
|
|
3522
5301
|
embed_fork_cb (EV_P_ ev_fork *fork_w, int revents)
|
|
3523
5302
|
{
|
|
@@ -3534,6 +5313,7 @@ embed_fork_cb (EV_P_ ev_fork *fork_w, int revents)
|
|
|
3534
5313
|
|
|
3535
5314
|
ev_embed_start (EV_A_ w);
|
|
3536
5315
|
}
|
|
5316
|
+
#endif
|
|
3537
5317
|
|
|
3538
5318
|
#if 0
|
|
3539
5319
|
static void
|
|
@@ -3544,9 +5324,9 @@ embed_idle_cb (EV_P_ ev_idle *idle, int revents)
|
|
|
3544
5324
|
#endif
|
|
3545
5325
|
|
|
3546
5326
|
void
|
|
3547
|
-
ev_embed_start (EV_P_ ev_embed *w)
|
|
5327
|
+
ev_embed_start (EV_P_ ev_embed *w) EV_NOEXCEPT
|
|
3548
5328
|
{
|
|
3549
|
-
if (
|
|
5329
|
+
if (ecb_expect_false (ev_is_active (w)))
|
|
3550
5330
|
return;
|
|
3551
5331
|
|
|
3552
5332
|
{
|
|
@@ -3564,8 +5344,10 @@ ev_embed_start (EV_P_ ev_embed *w)
|
|
|
3564
5344
|
ev_set_priority (&w->prepare, EV_MINPRI);
|
|
3565
5345
|
ev_prepare_start (EV_A_ &w->prepare);
|
|
3566
5346
|
|
|
5347
|
+
#if EV_FORK_ENABLE
|
|
3567
5348
|
ev_fork_init (&w->fork, embed_fork_cb);
|
|
3568
5349
|
ev_fork_start (EV_A_ &w->fork);
|
|
5350
|
+
#endif
|
|
3569
5351
|
|
|
3570
5352
|
/*ev_idle_init (&w->idle, e,bed_idle_cb);*/
|
|
3571
5353
|
|
|
@@ -3575,17 +5357,19 @@ ev_embed_start (EV_P_ ev_embed *w)
|
|
|
3575
5357
|
}
|
|
3576
5358
|
|
|
3577
5359
|
void
|
|
3578
|
-
ev_embed_stop (EV_P_ ev_embed *w)
|
|
5360
|
+
ev_embed_stop (EV_P_ ev_embed *w) EV_NOEXCEPT
|
|
3579
5361
|
{
|
|
3580
5362
|
clear_pending (EV_A_ (W)w);
|
|
3581
|
-
if (
|
|
5363
|
+
if (ecb_expect_false (!ev_is_active (w)))
|
|
3582
5364
|
return;
|
|
3583
5365
|
|
|
3584
5366
|
EV_FREQUENT_CHECK;
|
|
3585
5367
|
|
|
3586
5368
|
ev_io_stop (EV_A_ &w->io);
|
|
3587
5369
|
ev_prepare_stop (EV_A_ &w->prepare);
|
|
5370
|
+
#if EV_FORK_ENABLE
|
|
3588
5371
|
ev_fork_stop (EV_A_ &w->fork);
|
|
5372
|
+
#endif
|
|
3589
5373
|
|
|
3590
5374
|
ev_stop (EV_A_ (W)w);
|
|
3591
5375
|
|
|
@@ -3595,25 +5379,25 @@ ev_embed_stop (EV_P_ ev_embed *w)
|
|
|
3595
5379
|
|
|
3596
5380
|
#if EV_FORK_ENABLE
|
|
3597
5381
|
void
|
|
3598
|
-
ev_fork_start (EV_P_ ev_fork *w)
|
|
5382
|
+
ev_fork_start (EV_P_ ev_fork *w) EV_NOEXCEPT
|
|
3599
5383
|
{
|
|
3600
|
-
if (
|
|
5384
|
+
if (ecb_expect_false (ev_is_active (w)))
|
|
3601
5385
|
return;
|
|
3602
5386
|
|
|
3603
5387
|
EV_FREQUENT_CHECK;
|
|
3604
5388
|
|
|
3605
5389
|
ev_start (EV_A_ (W)w, ++forkcnt);
|
|
3606
|
-
array_needsize (ev_fork *, forks, forkmax, forkcnt,
|
|
5390
|
+
array_needsize (ev_fork *, forks, forkmax, forkcnt, array_needsize_noinit);
|
|
3607
5391
|
forks [forkcnt - 1] = w;
|
|
3608
5392
|
|
|
3609
5393
|
EV_FREQUENT_CHECK;
|
|
3610
5394
|
}
|
|
3611
5395
|
|
|
3612
5396
|
void
|
|
3613
|
-
ev_fork_stop (EV_P_ ev_fork *w)
|
|
5397
|
+
ev_fork_stop (EV_P_ ev_fork *w) EV_NOEXCEPT
|
|
3614
5398
|
{
|
|
3615
5399
|
clear_pending (EV_A_ (W)w);
|
|
3616
|
-
if (
|
|
5400
|
+
if (ecb_expect_false (!ev_is_active (w)))
|
|
3617
5401
|
return;
|
|
3618
5402
|
|
|
3619
5403
|
EV_FREQUENT_CHECK;
|
|
@@ -3633,15 +5417,15 @@ ev_fork_stop (EV_P_ ev_fork *w)
|
|
|
3633
5417
|
|
|
3634
5418
|
#if EV_CLEANUP_ENABLE
|
|
3635
5419
|
void
|
|
3636
|
-
ev_cleanup_start (EV_P_ ev_cleanup *w)
|
|
5420
|
+
ev_cleanup_start (EV_P_ ev_cleanup *w) EV_NOEXCEPT
|
|
3637
5421
|
{
|
|
3638
|
-
if (
|
|
5422
|
+
if (ecb_expect_false (ev_is_active (w)))
|
|
3639
5423
|
return;
|
|
3640
5424
|
|
|
3641
5425
|
EV_FREQUENT_CHECK;
|
|
3642
5426
|
|
|
3643
5427
|
ev_start (EV_A_ (W)w, ++cleanupcnt);
|
|
3644
|
-
array_needsize (ev_cleanup *, cleanups, cleanupmax, cleanupcnt,
|
|
5428
|
+
array_needsize (ev_cleanup *, cleanups, cleanupmax, cleanupcnt, array_needsize_noinit);
|
|
3645
5429
|
cleanups [cleanupcnt - 1] = w;
|
|
3646
5430
|
|
|
3647
5431
|
/* cleanup watchers should never keep a refcount on the loop */
|
|
@@ -3650,10 +5434,10 @@ ev_cleanup_start (EV_P_ ev_cleanup *w)
|
|
|
3650
5434
|
}
|
|
3651
5435
|
|
|
3652
5436
|
void
|
|
3653
|
-
ev_cleanup_stop (EV_P_ ev_cleanup *w)
|
|
5437
|
+
ev_cleanup_stop (EV_P_ ev_cleanup *w) EV_NOEXCEPT
|
|
3654
5438
|
{
|
|
3655
5439
|
clear_pending (EV_A_ (W)w);
|
|
3656
|
-
if (
|
|
5440
|
+
if (ecb_expect_false (!ev_is_active (w)))
|
|
3657
5441
|
return;
|
|
3658
5442
|
|
|
3659
5443
|
EV_FREQUENT_CHECK;
|
|
@@ -3674,9 +5458,9 @@ ev_cleanup_stop (EV_P_ ev_cleanup *w)
|
|
|
3674
5458
|
|
|
3675
5459
|
#if EV_ASYNC_ENABLE
|
|
3676
5460
|
void
|
|
3677
|
-
ev_async_start (EV_P_ ev_async *w)
|
|
5461
|
+
ev_async_start (EV_P_ ev_async *w) EV_NOEXCEPT
|
|
3678
5462
|
{
|
|
3679
|
-
if (
|
|
5463
|
+
if (ecb_expect_false (ev_is_active (w)))
|
|
3680
5464
|
return;
|
|
3681
5465
|
|
|
3682
5466
|
w->sent = 0;
|
|
@@ -3686,17 +5470,17 @@ ev_async_start (EV_P_ ev_async *w)
|
|
|
3686
5470
|
EV_FREQUENT_CHECK;
|
|
3687
5471
|
|
|
3688
5472
|
ev_start (EV_A_ (W)w, ++asynccnt);
|
|
3689
|
-
array_needsize (ev_async *, asyncs, asyncmax, asynccnt,
|
|
5473
|
+
array_needsize (ev_async *, asyncs, asyncmax, asynccnt, array_needsize_noinit);
|
|
3690
5474
|
asyncs [asynccnt - 1] = w;
|
|
3691
5475
|
|
|
3692
5476
|
EV_FREQUENT_CHECK;
|
|
3693
5477
|
}
|
|
3694
5478
|
|
|
3695
5479
|
void
|
|
3696
|
-
ev_async_stop (EV_P_ ev_async *w)
|
|
5480
|
+
ev_async_stop (EV_P_ ev_async *w) EV_NOEXCEPT
|
|
3697
5481
|
{
|
|
3698
5482
|
clear_pending (EV_A_ (W)w);
|
|
3699
|
-
if (
|
|
5483
|
+
if (ecb_expect_false (!ev_is_active (w)))
|
|
3700
5484
|
return;
|
|
3701
5485
|
|
|
3702
5486
|
EV_FREQUENT_CHECK;
|
|
@@ -3714,7 +5498,7 @@ ev_async_stop (EV_P_ ev_async *w)
|
|
|
3714
5498
|
}
|
|
3715
5499
|
|
|
3716
5500
|
void
|
|
3717
|
-
ev_async_send (EV_P_ ev_async *w)
|
|
5501
|
+
ev_async_send (EV_P_ ev_async *w) EV_NOEXCEPT
|
|
3718
5502
|
{
|
|
3719
5503
|
w->sent = 1;
|
|
3720
5504
|
evpipe_write (EV_A_ &async_pending);
|
|
@@ -3761,16 +5545,10 @@ once_cb_to (EV_P_ ev_timer *w, int revents)
|
|
|
3761
5545
|
}
|
|
3762
5546
|
|
|
3763
5547
|
void
|
|
3764
|
-
ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg)
|
|
5548
|
+
ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) EV_NOEXCEPT
|
|
3765
5549
|
{
|
|
3766
5550
|
struct ev_once *once = (struct ev_once *)ev_malloc (sizeof (struct ev_once));
|
|
3767
5551
|
|
|
3768
|
-
if (expect_false (!once))
|
|
3769
|
-
{
|
|
3770
|
-
cb (EV_ERROR | EV_READ | EV_WRITE | EV_TIMER, arg);
|
|
3771
|
-
return;
|
|
3772
|
-
}
|
|
3773
|
-
|
|
3774
5552
|
once->cb = cb;
|
|
3775
5553
|
once->arg = arg;
|
|
3776
5554
|
|
|
@@ -3792,8 +5570,9 @@ ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, vo
|
|
|
3792
5570
|
/*****************************************************************************/
|
|
3793
5571
|
|
|
3794
5572
|
#if EV_WALK_ENABLE
|
|
5573
|
+
ecb_cold
|
|
3795
5574
|
void
|
|
3796
|
-
ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
|
|
5575
|
+
ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) EV_NOEXCEPT
|
|
3797
5576
|
{
|
|
3798
5577
|
int i, j;
|
|
3799
5578
|
ev_watcher_list *wl, *wn;
|
|
@@ -3846,7 +5625,7 @@ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
|
|
|
3846
5625
|
|
|
3847
5626
|
#if EV_IDLE_ENABLE
|
|
3848
5627
|
if (types & EV_IDLE)
|
|
3849
|
-
for (j = NUMPRI;
|
|
5628
|
+
for (j = NUMPRI; j--; )
|
|
3850
5629
|
for (i = idlecnt [j]; i--; )
|
|
3851
5630
|
cb (EV_A_ EV_IDLE, idles [j][i]);
|
|
3852
5631
|
#endif
|
|
@@ -3908,6 +5687,3 @@ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
|
|
|
3908
5687
|
#if EV_MULTIPLICITY
|
|
3909
5688
|
#include "ev_wrap.h"
|
|
3910
5689
|
#endif
|
|
3911
|
-
|
|
3912
|
-
EV_CPP(})
|
|
3913
|
-
|