nio4r 2.4.0 → 2.5.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/workflow.yml +47 -0
  3. data/.rubocop.yml +30 -11
  4. data/CHANGES.md +63 -0
  5. data/Gemfile +1 -1
  6. data/README.md +57 -30
  7. data/examples/echo_server.rb +2 -2
  8. data/ext/libev/Changes +90 -2
  9. data/ext/libev/README +2 -1
  10. data/ext/libev/ev.c +708 -247
  11. data/ext/libev/ev.h +33 -29
  12. data/ext/libev/ev_epoll.c +41 -28
  13. data/ext/libev/ev_iouring.c +694 -0
  14. data/ext/libev/ev_kqueue.c +15 -9
  15. data/ext/libev/ev_linuxaio.c +620 -0
  16. data/ext/libev/ev_poll.c +19 -14
  17. data/ext/libev/ev_port.c +8 -5
  18. data/ext/libev/ev_select.c +6 -6
  19. data/ext/libev/ev_vars.h +46 -1
  20. data/ext/libev/ev_win32.c +2 -2
  21. data/ext/libev/ev_wrap.h +72 -0
  22. data/ext/nio4r/.clang-format +16 -0
  23. data/ext/nio4r/bytebuffer.c +27 -28
  24. data/ext/nio4r/extconf.rb +9 -0
  25. data/ext/nio4r/libev.h +1 -3
  26. data/ext/nio4r/monitor.c +34 -31
  27. data/ext/nio4r/nio4r.h +7 -12
  28. data/ext/nio4r/org/nio4r/ByteBuffer.java +2 -0
  29. data/ext/nio4r/org/nio4r/Monitor.java +1 -0
  30. data/ext/nio4r/org/nio4r/Selector.java +13 -11
  31. data/ext/nio4r/selector.c +66 -51
  32. data/lib/nio.rb +20 -1
  33. data/lib/nio/bytebuffer.rb +4 -0
  34. data/lib/nio/monitor.rb +1 -1
  35. data/lib/nio/selector.rb +12 -10
  36. data/lib/nio/version.rb +1 -1
  37. data/nio4r.gemspec +10 -2
  38. data/spec/nio/bytebuffer_spec.rb +0 -1
  39. data/spec/nio/selectables/ssl_socket_spec.rb +3 -1
  40. data/spec/nio/selectables/udp_socket_spec.rb +2 -2
  41. data/spec/nio/selector_spec.rb +27 -5
  42. data/spec/spec_helper.rb +2 -0
  43. metadata +17 -12
  44. data/.travis.yml +0 -29
  45. data/Guardfile +0 -10
  46. data/LICENSE.txt +0 -20
  47. data/appveyor.yml +0 -40
data/ext/libev/README CHANGED
@@ -18,7 +18,8 @@ ABOUT
18
18
  - extensive and detailed, readable documentation (not doxygen garbage).
19
19
  - fully supports fork, can detect fork in various ways and automatically
20
20
  re-arms kernel mechanisms that do not support fork.
21
- - highly optimised select, poll, epoll, kqueue and event ports backends.
21
+ - highly optimised select, poll, linux epoll, linux aio, bsd kqueue
22
+ and solaris event ports backends.
22
23
  - filesystem object (path) watching (with optional linux inotify support).
23
24
  - wallclock-based times (using absolute time, cron-like).
24
25
  - relative timers/timeouts (handle time jumps).
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-2018 Marc Alexander Lehmann <libev@schmorp.de>
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-
@@ -116,7 +116,7 @@
116
116
  # undef EV_USE_POLL
117
117
  # define EV_USE_POLL 0
118
118
  # endif
119
-
119
+
120
120
  # if HAVE_EPOLL_CTL && HAVE_SYS_EPOLL_H
121
121
  # ifndef EV_USE_EPOLL
122
122
  # define EV_USE_EPOLL EV_FEATURE_BACKENDS
@@ -125,7 +125,25 @@
125
125
  # undef EV_USE_EPOLL
126
126
  # define EV_USE_EPOLL 0
127
127
  # endif
128
-
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
+
129
147
  # if HAVE_KQUEUE && HAVE_SYS_EVENT_H
130
148
  # ifndef EV_USE_KQUEUE
131
149
  # define EV_USE_KQUEUE EV_FEATURE_BACKENDS
@@ -134,7 +152,7 @@
134
152
  # undef EV_USE_KQUEUE
135
153
  # define EV_USE_KQUEUE 0
136
154
  # endif
137
-
155
+
138
156
  # if HAVE_PORT_H && HAVE_PORT_CREATE
139
157
  # ifndef EV_USE_PORT
140
158
  # define EV_USE_PORT EV_FEATURE_BACKENDS
@@ -170,7 +188,16 @@
170
188
  # undef EV_USE_EVENTFD
171
189
  # define EV_USE_EVENTFD 0
172
190
  # endif
173
-
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
+
174
201
  #endif
175
202
 
176
203
  /* OS X, in its infinite idiocy, actually HARDCODES
@@ -326,6 +353,14 @@
326
353
  # define EV_USE_PORT 0
327
354
  #endif
328
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
+
329
364
  #ifndef EV_USE_INOTIFY
330
365
  # if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4))
331
366
  # define EV_USE_INOTIFY EV_FEATURE_OS
@@ -358,6 +393,14 @@
358
393
  # endif
359
394
  #endif
360
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
+
361
404
  #if 0 /* debugging */
362
405
  # define EV_VERIFY 3
363
406
  # define EV_USE_4HEAP 1
@@ -400,6 +443,7 @@
400
443
  # define clock_gettime(id, ts) syscall (SYS_clock_gettime, (id), (ts))
401
444
  # undef EV_USE_MONOTONIC
402
445
  # define EV_USE_MONOTONIC 1
446
+ # define EV_NEED_SYSCALL 1
403
447
  # else
404
448
  # undef EV_USE_CLOCK_SYSCALL
405
449
  # define EV_USE_CLOCK_SYSCALL 0
@@ -430,6 +474,31 @@
430
474
  # endif
431
475
  #endif
432
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
+
433
502
  #if EV_USE_INOTIFY
434
503
  # include <sys/statfs.h>
435
504
  # include <sys/inotify.h>
@@ -441,7 +510,7 @@
441
510
  #endif
442
511
 
443
512
  #if EV_USE_EVENTFD
444
- /* 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 */
445
514
  # include <stdint.h>
446
515
  # ifndef EFD_NONBLOCK
447
516
  # define EFD_NONBLOCK O_NONBLOCK
@@ -457,7 +526,7 @@ EV_CPP(extern "C") int (eventfd) (unsigned int initval, int flags);
457
526
  #endif
458
527
 
459
528
  #if EV_USE_SIGNALFD
460
- /* 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 */
461
530
  # include <stdint.h>
462
531
  # ifndef SFD_NONBLOCK
463
532
  # define SFD_NONBLOCK O_NONBLOCK
@@ -469,7 +538,7 @@ EV_CPP(extern "C") int (eventfd) (unsigned int initval, int flags);
469
538
  # define SFD_CLOEXEC 02000000
470
539
  # endif
471
540
  # endif
472
- 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);
473
542
 
474
543
  struct signalfd_siginfo
475
544
  {
@@ -478,7 +547,17 @@ struct signalfd_siginfo
478
547
  };
479
548
  #endif
480
549
 
481
- /**/
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
+ /*****************************************************************************/
482
561
 
483
562
  #if EV_VERIFY >= 3
484
563
  # define EV_FREQUENT_CHECK ev_verify (EV_A)
@@ -493,18 +572,34 @@ struct signalfd_siginfo
493
572
  #define MIN_INTERVAL 0.0001220703125 /* 1/2**13, good till 4000 */
494
573
  /*#define MIN_INTERVAL 0.00000095367431640625 /* 1/2**20, good till 2200 */
495
574
 
496
- #define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */
497
- #define MAX_BLOCKTIME 59.743 /* never wait longer than this time (to detect time jumps) */
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 */
498
578
 
499
- #define EV_TV_SET(tv,t) do { tv.tv_sec = (long)t; tv.tv_usec = (long)((t - tv.tv_sec) * 1e6); } while (0)
500
- #define EV_TS_SET(ts,t) do { ts.tv_sec = (long)t; ts.tv_nsec = (long)((t - ts.tv_sec) * 1e9); } while (0)
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
501
596
 
502
597
  /* the following is ecb.h embedded into libev - use update_ev_c to update from an external copy */
503
598
  /* ECB.H BEGIN */
504
599
  /*
505
600
  * libecb - http://software.schmorp.de/pkg/libecb
506
601
  *
507
- * Copyright (©) 2009-2015 Marc Alexander Lehmann <libecb@schmorp.de>
602
+ * Copyright (©) 2009-2015,2018-2020 Marc Alexander Lehmann <libecb@schmorp.de>
508
603
  * Copyright (©) 2011 Emanuele Giaquinta
509
604
  * All rights reserved.
510
605
  *
@@ -545,15 +640,23 @@ struct signalfd_siginfo
545
640
  #define ECB_H
546
641
 
547
642
  /* 16 bits major, 16 bits minor */
548
- #define ECB_VERSION 0x00010005
643
+ #define ECB_VERSION 0x00010008
549
644
 
550
- #ifdef _WIN32
645
+ #include <string.h> /* for memcpy */
646
+
647
+ #if defined (_WIN32) && !defined (__MINGW32__)
551
648
  typedef signed char int8_t;
552
649
  typedef unsigned char uint8_t;
650
+ typedef signed char int_fast8_t;
651
+ typedef unsigned char uint_fast8_t;
553
652
  typedef signed short int16_t;
554
653
  typedef unsigned short uint16_t;
654
+ typedef signed int int_fast16_t;
655
+ typedef unsigned int uint_fast16_t;
555
656
  typedef signed int int32_t;
556
657
  typedef unsigned int uint32_t;
658
+ typedef signed int int_fast32_t;
659
+ typedef unsigned int uint_fast32_t;
557
660
  #if __GNUC__
558
661
  typedef signed long long int64_t;
559
662
  typedef unsigned long long uint64_t;
@@ -561,6 +664,8 @@ struct signalfd_siginfo
561
664
  typedef signed __int64 int64_t;
562
665
  typedef unsigned __int64 uint64_t;
563
666
  #endif
667
+ typedef int64_t int_fast64_t;
668
+ typedef uint64_t uint_fast64_t;
564
669
  #ifdef _WIN64
565
670
  #define ECB_PTRSIZE 8
566
671
  typedef uint64_t uintptr_t;
@@ -582,6 +687,14 @@ struct signalfd_siginfo
582
687
  #define ECB_GCC_AMD64 (__amd64 || __amd64__ || __x86_64 || __x86_64__)
583
688
  #define ECB_MSVC_AMD64 (_M_AMD64 || _M_X64)
584
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
+
585
698
  /* work around x32 idiocy by defining proper macros */
586
699
  #if ECB_GCC_AMD64 || ECB_MSVC_AMD64
587
700
  #if _ILP32
@@ -669,6 +782,7 @@ struct signalfd_siginfo
669
782
 
670
783
  #ifndef ECB_MEMORY_FENCE
671
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")
672
786
  #if __i386 || __i386__
673
787
  #define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory")
674
788
  #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory")
@@ -728,12 +842,14 @@ struct signalfd_siginfo
728
842
  #define ECB_MEMORY_FENCE __atomic_thread_fence (__ATOMIC_SEQ_CST)
729
843
  #define ECB_MEMORY_FENCE_ACQUIRE __atomic_thread_fence (__ATOMIC_ACQUIRE)
730
844
  #define ECB_MEMORY_FENCE_RELEASE __atomic_thread_fence (__ATOMIC_RELEASE)
845
+ #define ECB_MEMORY_FENCE_RELAXED __atomic_thread_fence (__ATOMIC_RELAXED)
731
846
 
732
847
  #elif ECB_CLANG_EXTENSION(c_atomic)
733
848
  /* see comment below (stdatomic.h) about the C11 memory model. */
734
849
  #define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST)
735
850
  #define ECB_MEMORY_FENCE_ACQUIRE __c11_atomic_thread_fence (__ATOMIC_ACQUIRE)
736
851
  #define ECB_MEMORY_FENCE_RELEASE __c11_atomic_thread_fence (__ATOMIC_RELEASE)
852
+ #define ECB_MEMORY_FENCE_RELAXED __c11_atomic_thread_fence (__ATOMIC_RELAXED)
737
853
 
738
854
  #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__
739
855
  #define ECB_MEMORY_FENCE __sync_synchronize ()
@@ -753,9 +869,10 @@ struct signalfd_siginfo
753
869
  #define ECB_MEMORY_FENCE MemoryBarrier () /* actually just xchg on x86... scary */
754
870
  #elif __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
755
871
  #include <mbarrier.h>
756
- #define ECB_MEMORY_FENCE __machine_rw_barrier ()
757
- #define ECB_MEMORY_FENCE_ACQUIRE __machine_r_barrier ()
758
- #define ECB_MEMORY_FENCE_RELEASE __machine_w_barrier ()
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 ()
759
876
  #elif __xlC__
760
877
  #define ECB_MEMORY_FENCE __sync ()
761
878
  #endif
@@ -766,15 +883,9 @@ struct signalfd_siginfo
766
883
  /* we assume that these memory fences work on all variables/all memory accesses, */
767
884
  /* not just C11 atomics and atomic accesses */
768
885
  #include <stdatomic.h>
769
- /* Unfortunately, neither gcc 4.7 nor clang 3.1 generate any instructions for */
770
- /* any fence other than seq_cst, which isn't very efficient for us. */
771
- /* Why that is, we don't know - either the C11 memory model is quite useless */
772
- /* for most usages, or gcc and clang have a bug */
773
- /* I *currently* lean towards the latter, and inefficiently implement */
774
- /* all three of ecb's fences as a seq_cst fence */
775
- /* Update, gcc-4.8 generates mfence for all c++ fences, but nothing */
776
- /* for all __atomic_thread_fence's except seq_cst */
777
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)
778
889
  #endif
779
890
  #endif
780
891
 
@@ -804,6 +915,10 @@ struct signalfd_siginfo
804
915
  #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE
805
916
  #endif
806
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
+
807
922
  /*****************************************************************************/
808
923
 
809
924
  #if ECB_CPP
@@ -1095,6 +1210,44 @@ ecb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count) { retu
1095
1210
  ecb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count) { return (x >> (64 - count)) | (x << count); }
1096
1211
  ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (64 - count)) | (x >> count); }
1097
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
+
1249
+ #endif
1250
+
1098
1251
  #if ECB_GCC_VERSION(4,3) || (ECB_CLANG_BUILTIN(__builtin_bswap32) && ECB_CLANG_BUILTIN(__builtin_bswap64))
1099
1252
  #if ECB_GCC_VERSION(4,8) || ECB_CLANG_BUILTIN(__builtin_bswap16)
1100
1253
  #define ecb_bswap16(x) __builtin_bswap16 (x)
@@ -1175,6 +1328,78 @@ ecb_inline ecb_const ecb_bool ecb_big_endian (void) { return ecb_byteorder_he
1175
1328
  ecb_inline ecb_const ecb_bool ecb_little_endian (void);
1176
1329
  ecb_inline ecb_const ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44332211; }
1177
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
+
1178
1403
  #if ECB_GCC_VERSION(3,0) || ECB_C99
1179
1404
  #define ecb_mod(m,n) ((m) % (n) + ((m) % (n) < 0 ? (n) : 0))
1180
1405
  #else
@@ -1208,6 +1433,8 @@ ecb_inline ecb_const ecb_bool ecb_little_endian (void) { return ecb_byteorder_he
1208
1433
  #define ecb_array_length(name) (sizeof (name) / sizeof (name [0]))
1209
1434
  #endif
1210
1435
 
1436
+ /*****************************************************************************/
1437
+
1211
1438
  ecb_function_ ecb_const uint32_t ecb_binary16_to_binary32 (uint32_t x);
1212
1439
  ecb_function_ ecb_const uint32_t
1213
1440
  ecb_binary16_to_binary32 (uint32_t x)
@@ -1325,7 +1552,6 @@ ecb_binary32_to_binary16 (uint32_t x)
1325
1552
  || (defined __arm__ && (defined __ARM_EABI__ || defined __EABI__ || defined __VFP_FP__ || defined _WIN32_WCE || defined __ANDROID__)) \
1326
1553
  || defined __aarch64__
1327
1554
  #define ECB_STDFP 1
1328
- #include <string.h> /* for memcpy */
1329
1555
  #else
1330
1556
  #define ECB_STDFP 0
1331
1557
  #endif
@@ -1520,7 +1746,7 @@ ecb_binary32_to_binary16 (uint32_t x)
1520
1746
  #if ECB_MEMORY_FENCE_NEEDS_PTHREADS
1521
1747
  /* if your architecture doesn't need memory fences, e.g. because it is
1522
1748
  * single-cpu/core, or if you use libev in a project that doesn't use libev
1523
- * from multiple threads, then you can define ECB_AVOID_PTHREADS when compiling
1749
+ * from multiple threads, then you can define ECB_NO_THREADS when compiling
1524
1750
  * libev, in which cases the memory fences become nops.
1525
1751
  * alternatively, you can remove this #error and link against libpthread,
1526
1752
  * which will then provide the memory fences.
@@ -1534,18 +1760,80 @@ ecb_binary32_to_binary16 (uint32_t x)
1534
1760
  # define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE
1535
1761
  #endif
1536
1762
 
1537
- #define expect_false(cond) ecb_expect_false (cond)
1538
- #define expect_true(cond) ecb_expect_true (cond)
1539
- #define noinline ecb_noinline
1540
-
1541
1763
  #define inline_size ecb_inline
1542
1764
 
1543
1765
  #if EV_FEATURE_CODE
1544
1766
  # define inline_speed ecb_inline
1545
1767
  #else
1546
- # define inline_speed noinline static
1768
+ # define inline_speed ecb_noinline static
1547
1769
  #endif
1548
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
+
1549
1837
  #define NUMPRI (EV_MAXPRI - EV_MINPRI + 1)
1550
1838
 
1551
1839
  #if EV_MINPRI == EV_MAXPRI
@@ -1554,8 +1842,7 @@ ecb_binary32_to_binary16 (uint32_t x)
1554
1842
  # define ABSPRI(w) (((W)w)->priority - EV_MINPRI)
1555
1843
  #endif
1556
1844
 
1557
- #define EMPTY /* required for microsofts broken pseudo-c compiler */
1558
- #define EMPTY2(a,b) /* used to suppress some warnings */
1845
+ #define EMPTY /* required for microsofts broken pseudo-c compiler */
1559
1846
 
1560
1847
  typedef ev_watcher *W;
1561
1848
  typedef ev_watcher_list *WL;
@@ -1590,6 +1877,10 @@ static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work?
1590
1877
 
1591
1878
  /*****************************************************************************/
1592
1879
 
1880
+ #if EV_USE_LINUXAIO
1881
+ # include <linux/aio_abi.h> /* probably only needed for aio_context_t */
1882
+ #endif
1883
+
1593
1884
  /* define a suitable floor function (only used by periodics atm) */
1594
1885
 
1595
1886
  #if EV_USE_FLOOR
@@ -1600,7 +1891,7 @@ static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work?
1600
1891
  #include <float.h>
1601
1892
 
1602
1893
  /* a floor() replacement function, should be independent of ev_tstamp type */
1603
- noinline
1894
+ ecb_noinline
1604
1895
  static ev_tstamp
1605
1896
  ev_floor (ev_tstamp v)
1606
1897
  {
@@ -1611,26 +1902,26 @@ ev_floor (ev_tstamp v)
1611
1902
  const ev_tstamp shift = sizeof (unsigned long) >= 8 ? 18446744073709551616. : 4294967296.;
1612
1903
  #endif
1613
1904
 
1614
- /* argument too large for an unsigned long? */
1615
- if (expect_false (v >= shift))
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))
1616
1915
  {
1617
1916
  ev_tstamp f;
1618
1917
 
1619
1918
  if (v == v - 1.)
1620
- return v; /* very large number */
1919
+ return v; /* very large numbers are assumed to be integer */
1621
1920
 
1622
1921
  f = shift * ev_floor (v * (1. / shift));
1623
1922
  return f + ev_floor (v - f);
1624
1923
  }
1625
1924
 
1626
- /* special treatment for negative args? */
1627
- if (expect_false (v < 0.))
1628
- {
1629
- ev_tstamp f = -ev_floor (-v);
1630
-
1631
- return f - (f == v ? 0 : 1);
1632
- }
1633
-
1634
1925
  /* fits into an unsigned long */
1635
1926
  return (unsigned long)v;
1636
1927
  }
@@ -1643,7 +1934,7 @@ ev_floor (ev_tstamp v)
1643
1934
  # include <sys/utsname.h>
1644
1935
  #endif
1645
1936
 
1646
- noinline ecb_cold
1937
+ ecb_noinline ecb_cold
1647
1938
  static unsigned int
1648
1939
  ev_linux_version (void)
1649
1940
  {
@@ -1683,7 +1974,7 @@ ev_linux_version (void)
1683
1974
  /*****************************************************************************/
1684
1975
 
1685
1976
  #if EV_AVOID_STDIO
1686
- noinline ecb_cold
1977
+ ecb_noinline ecb_cold
1687
1978
  static void
1688
1979
  ev_printerr (const char *msg)
1689
1980
  {
@@ -1700,7 +1991,7 @@ ev_set_syserr_cb (void (*cb)(const char *msg) EV_NOEXCEPT) EV_NOEXCEPT
1700
1991
  syserr_cb = cb;
1701
1992
  }
1702
1993
 
1703
- noinline ecb_cold
1994
+ ecb_noinline ecb_cold
1704
1995
  static void
1705
1996
  ev_syserr (const char *msg)
1706
1997
  {
@@ -1724,7 +2015,7 @@ ev_syserr (const char *msg)
1724
2015
  }
1725
2016
 
1726
2017
  static void *
1727
- ev_realloc_emul (void *ptr, long size) EV_NOEXCEPT
2018
+ ev_realloc_emul (void *ptr, size_t size) EV_NOEXCEPT
1728
2019
  {
1729
2020
  /* some systems, notably openbsd and darwin, fail to properly
1730
2021
  * implement realloc (x, 0) (as required by both ansi c-89 and
@@ -1740,17 +2031,17 @@ ev_realloc_emul (void *ptr, long size) EV_NOEXCEPT
1740
2031
  return 0;
1741
2032
  }
1742
2033
 
1743
- static void *(*alloc)(void *ptr, long size) EV_NOEXCEPT = ev_realloc_emul;
2034
+ static void *(*alloc)(void *ptr, size_t size) EV_NOEXCEPT = ev_realloc_emul;
1744
2035
 
1745
2036
  ecb_cold
1746
2037
  void
1747
- ev_set_allocator (void *(*cb)(void *ptr, long size) EV_NOEXCEPT) EV_NOEXCEPT
2038
+ ev_set_allocator (void *(*cb)(void *ptr, size_t size) EV_NOEXCEPT) EV_NOEXCEPT
1748
2039
  {
1749
2040
  alloc = cb;
1750
2041
  }
1751
2042
 
1752
2043
  inline_speed void *
1753
- ev_realloc (void *ptr, long size)
2044
+ ev_realloc (void *ptr, size_t size)
1754
2045
  {
1755
2046
  ptr = alloc (ptr, size);
1756
2047
 
@@ -1781,8 +2072,8 @@ typedef struct
1781
2072
  WL head;
1782
2073
  unsigned char events; /* the events watched for */
1783
2074
  unsigned char reify; /* flag set when this ANFD needs reification (EV_ANFD_REIFY, EV__IOFDSET) */
1784
- unsigned char emask; /* the epoll backend stores the actual kernel mask in here */
1785
- unsigned char unused;
2075
+ unsigned char emask; /* some backends store the actual kernel mask in here */
2076
+ unsigned char eflags; /* flags field for use by backends */
1786
2077
  #if EV_USE_EPOLL
1787
2078
  unsigned int egen; /* generation counter to counter epoll bugs */
1788
2079
  #endif
@@ -1846,7 +2137,7 @@ typedef struct
1846
2137
 
1847
2138
  #else
1848
2139
 
1849
- EV_API_DECL ev_tstamp ev_rt_now = 0; /* needs to be initialised to make it a definition despite extern */
2140
+ EV_API_DECL ev_tstamp ev_rt_now = EV_TS_CONST (0.); /* needs to be initialised to make it a definition despite extern */
1850
2141
  #define VAR(name,decl) static decl;
1851
2142
  #include "ev_vars.h"
1852
2143
  #undef VAR
@@ -1856,8 +2147,8 @@ typedef struct
1856
2147
  #endif
1857
2148
 
1858
2149
  #if EV_FEATURE_API
1859
- # define EV_RELEASE_CB if (expect_false (release_cb)) release_cb (EV_A)
1860
- # define EV_ACQUIRE_CB if (expect_false (acquire_cb)) acquire_cb (EV_A)
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)
1861
2152
  # define EV_INVOKE_PENDING invoke_cb (EV_A)
1862
2153
  #else
1863
2154
  # define EV_RELEASE_CB (void)0
@@ -1874,17 +2165,19 @@ ev_tstamp
1874
2165
  ev_time (void) EV_NOEXCEPT
1875
2166
  {
1876
2167
  #if EV_USE_REALTIME
1877
- if (expect_true (have_realtime))
2168
+ if (ecb_expect_true (have_realtime))
1878
2169
  {
1879
2170
  struct timespec ts;
1880
2171
  clock_gettime (CLOCK_REALTIME, &ts);
1881
- return ts.tv_sec + ts.tv_nsec * 1e-9;
2172
+ return EV_TS_GET (ts);
1882
2173
  }
1883
2174
  #endif
1884
2175
 
1885
- struct timeval tv;
1886
- gettimeofday (&tv, 0);
1887
- return tv.tv_sec + tv.tv_usec * 1e-6;
2176
+ {
2177
+ struct timeval tv;
2178
+ gettimeofday (&tv, 0);
2179
+ return EV_TV_GET (tv);
2180
+ }
1888
2181
  }
1889
2182
  #endif
1890
2183
 
@@ -1892,11 +2185,11 @@ inline_size ev_tstamp
1892
2185
  get_clock (void)
1893
2186
  {
1894
2187
  #if EV_USE_MONOTONIC
1895
- if (expect_true (have_monotonic))
2188
+ if (ecb_expect_true (have_monotonic))
1896
2189
  {
1897
2190
  struct timespec ts;
1898
2191
  clock_gettime (CLOCK_MONOTONIC, &ts);
1899
- return ts.tv_sec + ts.tv_nsec * 1e-9;
2192
+ return EV_TS_GET (ts);
1900
2193
  }
1901
2194
  #endif
1902
2195
 
@@ -1914,7 +2207,7 @@ ev_now (EV_P) EV_NOEXCEPT
1914
2207
  void
1915
2208
  ev_sleep (ev_tstamp delay) EV_NOEXCEPT
1916
2209
  {
1917
- if (delay > 0.)
2210
+ if (delay > EV_TS_CONST (0.))
1918
2211
  {
1919
2212
  #if EV_USE_NANOSLEEP
1920
2213
  struct timespec ts;
@@ -1924,7 +2217,7 @@ ev_sleep (ev_tstamp delay) EV_NOEXCEPT
1924
2217
  #elif defined _WIN32
1925
2218
  /* maybe this should round up, as ms is very low resolution */
1926
2219
  /* compared to select (µs) or nanosleep (ns) */
1927
- Sleep ((unsigned long)(delay * 1e3));
2220
+ Sleep ((unsigned long)(EV_TS_TO_MSEC (delay)));
1928
2221
  #else
1929
2222
  struct timeval tv;
1930
2223
 
@@ -1964,7 +2257,7 @@ array_nextsize (int elem, int cur, int cnt)
1964
2257
  return ncur;
1965
2258
  }
1966
2259
 
1967
- noinline ecb_cold
2260
+ ecb_noinline ecb_cold
1968
2261
  static void *
1969
2262
  array_realloc (int elem, void *base, int *cur, int cnt)
1970
2263
  {
@@ -1972,16 +2265,18 @@ array_realloc (int elem, void *base, int *cur, int cnt)
1972
2265
  return ev_realloc (base, elem * *cur);
1973
2266
  }
1974
2267
 
1975
- #define array_init_zero(base,count) \
1976
- memset ((void *)(base), 0, sizeof (*(base)) * (count))
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))
1977
2272
 
1978
2273
  #define array_needsize(type,base,cur,cnt,init) \
1979
- if (expect_false ((cnt) > (cur))) \
2274
+ if (ecb_expect_false ((cnt) > (cur))) \
1980
2275
  { \
1981
2276
  ecb_unused int ocur_ = (cur); \
1982
2277
  (base) = (type *)array_realloc \
1983
2278
  (sizeof (type), (base), &(cur), (cnt)); \
1984
- init ((base) + (ocur_), (cur) - ocur_); \
2279
+ init ((base), ocur_, ((cur) - ocur_)); \
1985
2280
  }
1986
2281
 
1987
2282
  #if 0
@@ -2000,25 +2295,25 @@ array_realloc (int elem, void *base, int *cur, int cnt)
2000
2295
  /*****************************************************************************/
2001
2296
 
2002
2297
  /* dummy callback for pending events */
2003
- noinline
2298
+ ecb_noinline
2004
2299
  static void
2005
2300
  pendingcb (EV_P_ ev_prepare *w, int revents)
2006
2301
  {
2007
2302
  }
2008
2303
 
2009
- noinline
2304
+ ecb_noinline
2010
2305
  void
2011
2306
  ev_feed_event (EV_P_ void *w, int revents) EV_NOEXCEPT
2012
2307
  {
2013
2308
  W w_ = (W)w;
2014
2309
  int pri = ABSPRI (w_);
2015
2310
 
2016
- if (expect_false (w_->pending))
2311
+ if (ecb_expect_false (w_->pending))
2017
2312
  pendings [pri][w_->pending - 1].events |= revents;
2018
2313
  else
2019
2314
  {
2020
2315
  w_->pending = ++pendingcnt [pri];
2021
- array_needsize (ANPENDING, pendings [pri], pendingmax [pri], w_->pending, EMPTY2);
2316
+ array_needsize (ANPENDING, pendings [pri], pendingmax [pri], w_->pending, array_needsize_noinit);
2022
2317
  pendings [pri][w_->pending - 1].w = w_;
2023
2318
  pendings [pri][w_->pending - 1].events = revents;
2024
2319
  }
@@ -2029,7 +2324,7 @@ ev_feed_event (EV_P_ void *w, int revents) EV_NOEXCEPT
2029
2324
  inline_speed void
2030
2325
  feed_reverse (EV_P_ W w)
2031
2326
  {
2032
- array_needsize (W, rfeeds, rfeedmax, rfeedcnt + 1, EMPTY2);
2327
+ array_needsize (W, rfeeds, rfeedmax, rfeedcnt + 1, array_needsize_noinit);
2033
2328
  rfeeds [rfeedcnt++] = w;
2034
2329
  }
2035
2330
 
@@ -2074,7 +2369,7 @@ fd_event (EV_P_ int fd, int revents)
2074
2369
  {
2075
2370
  ANFD *anfd = anfds + fd;
2076
2371
 
2077
- if (expect_true (!anfd->reify))
2372
+ if (ecb_expect_true (!anfd->reify))
2078
2373
  fd_event_nocheck (EV_A_ fd, revents);
2079
2374
  }
2080
2375
 
@@ -2092,8 +2387,20 @@ fd_reify (EV_P)
2092
2387
  {
2093
2388
  int i;
2094
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
+
2095
2402
  #if EV_SELECT_IS_WINSOCKET || EV_USE_IOCP
2096
- for (i = 0; i < fdchangecnt; ++i)
2403
+ for (i = 0; i < changecnt; ++i)
2097
2404
  {
2098
2405
  int fd = fdchanges [i];
2099
2406
  ANFD *anfd = anfds + fd;
@@ -2117,7 +2424,7 @@ fd_reify (EV_P)
2117
2424
  }
2118
2425
  #endif
2119
2426
 
2120
- for (i = 0; i < fdchangecnt; ++i)
2427
+ for (i = 0; i < changecnt; ++i)
2121
2428
  {
2122
2429
  int fd = fdchanges [i];
2123
2430
  ANFD *anfd = anfds + fd;
@@ -2126,9 +2433,9 @@ fd_reify (EV_P)
2126
2433
  unsigned char o_events = anfd->events;
2127
2434
  unsigned char o_reify = anfd->reify;
2128
2435
 
2129
- anfd->reify = 0;
2436
+ anfd->reify = 0;
2130
2437
 
2131
- /*if (expect_true (o_reify & EV_ANFD_REIFY)) probably a deoptimisation */
2438
+ /*if (ecb_expect_true (o_reify & EV_ANFD_REIFY)) probably a deoptimisation */
2132
2439
  {
2133
2440
  anfd->events = 0;
2134
2441
 
@@ -2143,7 +2450,14 @@ fd_reify (EV_P)
2143
2450
  backend_modify (EV_A_ fd, o_events, anfd->events);
2144
2451
  }
2145
2452
 
2146
- fdchangecnt = 0;
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;
2147
2461
  }
2148
2462
 
2149
2463
  /* something about the given fd changed */
@@ -2152,12 +2466,12 @@ void
2152
2466
  fd_change (EV_P_ int fd, int flags)
2153
2467
  {
2154
2468
  unsigned char reify = anfds [fd].reify;
2155
- anfds [fd].reify |= flags;
2469
+ anfds [fd].reify = reify | flags;
2156
2470
 
2157
- if (expect_true (!reify))
2471
+ if (ecb_expect_true (!reify))
2158
2472
  {
2159
2473
  ++fdchangecnt;
2160
- array_needsize (int, fdchanges, fdchangemax, fdchangecnt, EMPTY2);
2474
+ array_needsize (int, fdchanges, fdchangemax, fdchangecnt, array_needsize_noinit);
2161
2475
  fdchanges [fdchangecnt - 1] = fd;
2162
2476
  }
2163
2477
  }
@@ -2187,7 +2501,7 @@ fd_valid (int fd)
2187
2501
  }
2188
2502
 
2189
2503
  /* called on EBADF to verify fds */
2190
- noinline ecb_cold
2504
+ ecb_noinline ecb_cold
2191
2505
  static void
2192
2506
  fd_ebadf (EV_P)
2193
2507
  {
@@ -2200,7 +2514,7 @@ fd_ebadf (EV_P)
2200
2514
  }
2201
2515
 
2202
2516
  /* called on ENOMEM in select/poll to kill some fds and retry */
2203
- noinline ecb_cold
2517
+ ecb_noinline ecb_cold
2204
2518
  static void
2205
2519
  fd_enomem (EV_P)
2206
2520
  {
@@ -2215,7 +2529,7 @@ fd_enomem (EV_P)
2215
2529
  }
2216
2530
 
2217
2531
  /* usually called after fork if backend needs to re-arm all fds from scratch */
2218
- noinline
2532
+ ecb_noinline
2219
2533
  static void
2220
2534
  fd_rearm_all (EV_P)
2221
2535
  {
@@ -2279,19 +2593,19 @@ downheap (ANHE *heap, int N, int k)
2279
2593
  ANHE *pos = heap + DHEAP * (k - HEAP0) + HEAP0 + 1;
2280
2594
 
2281
2595
  /* find minimum child */
2282
- if (expect_true (pos + DHEAP - 1 < E))
2596
+ if (ecb_expect_true (pos + DHEAP - 1 < E))
2283
2597
  {
2284
2598
  /* fast path */ (minpos = pos + 0), (minat = ANHE_at (*minpos));
2285
- if ( ANHE_at (pos [1]) < minat) (minpos = pos + 1), (minat = ANHE_at (*minpos));
2286
- if ( ANHE_at (pos [2]) < minat) (minpos = pos + 2), (minat = ANHE_at (*minpos));
2287
- if ( ANHE_at (pos [3]) < minat) (minpos = pos + 3), (minat = ANHE_at (*minpos));
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));
2288
2602
  }
2289
2603
  else if (pos < E)
2290
2604
  {
2291
2605
  /* slow path */ (minpos = pos + 0), (minat = ANHE_at (*minpos));
2292
- if (pos + 1 < E && ANHE_at (pos [1]) < minat) (minpos = pos + 1), (minat = ANHE_at (*minpos));
2293
- if (pos + 2 < E && ANHE_at (pos [2]) < minat) (minpos = pos + 2), (minat = ANHE_at (*minpos));
2294
- if (pos + 3 < E && ANHE_at (pos [3]) < minat) (minpos = pos + 3), (minat = ANHE_at (*minpos));
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));
2295
2609
  }
2296
2610
  else
2297
2611
  break;
@@ -2309,7 +2623,7 @@ downheap (ANHE *heap, int N, int k)
2309
2623
  ev_active (ANHE_w (he)) = k;
2310
2624
  }
2311
2625
 
2312
- #else /* 4HEAP */
2626
+ #else /* not 4HEAP */
2313
2627
 
2314
2628
  #define HEAP0 1
2315
2629
  #define HPARENT(k) ((k) >> 1)
@@ -2336,7 +2650,7 @@ downheap (ANHE *heap, int N, int k)
2336
2650
 
2337
2651
  heap [k] = heap [c];
2338
2652
  ev_active (ANHE_w (heap [k])) = k;
2339
-
2653
+
2340
2654
  k = c;
2341
2655
  }
2342
2656
 
@@ -2391,7 +2705,7 @@ reheap (ANHE *heap, int N)
2391
2705
 
2392
2706
  /*****************************************************************************/
2393
2707
 
2394
- /* associate signal watchers to a signal signal */
2708
+ /* associate signal watchers to a signal */
2395
2709
  typedef struct
2396
2710
  {
2397
2711
  EV_ATOMIC_T pending;
@@ -2407,7 +2721,7 @@ static ANSIG signals [EV_NSIG - 1];
2407
2721
 
2408
2722
  #if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
2409
2723
 
2410
- noinline ecb_cold
2724
+ ecb_noinline ecb_cold
2411
2725
  static void
2412
2726
  evpipe_init (EV_P)
2413
2727
  {
@@ -2458,7 +2772,7 @@ evpipe_write (EV_P_ EV_ATOMIC_T *flag)
2458
2772
  {
2459
2773
  ECB_MEMORY_FENCE; /* push out the write before this function was called, acquire flag */
2460
2774
 
2461
- if (expect_true (*flag))
2775
+ if (ecb_expect_true (*flag))
2462
2776
  return;
2463
2777
 
2464
2778
  *flag = 1;
@@ -2545,7 +2859,7 @@ pipecb (EV_P_ ev_io *iow, int revents)
2545
2859
  ECB_MEMORY_FENCE;
2546
2860
 
2547
2861
  for (i = EV_NSIG - 1; i--; )
2548
- if (expect_false (signals [i].pending))
2862
+ if (ecb_expect_false (signals [i].pending))
2549
2863
  ev_feed_signal_event (EV_A_ i + 1);
2550
2864
  }
2551
2865
  #endif
@@ -2596,13 +2910,13 @@ ev_sighandler (int signum)
2596
2910
  ev_feed_signal (signum);
2597
2911
  }
2598
2912
 
2599
- noinline
2913
+ ecb_noinline
2600
2914
  void
2601
2915
  ev_feed_signal_event (EV_P_ int signum) EV_NOEXCEPT
2602
2916
  {
2603
2917
  WL w;
2604
2918
 
2605
- if (expect_false (signum <= 0 || signum >= EV_NSIG))
2919
+ if (ecb_expect_false (signum <= 0 || signum >= EV_NSIG))
2606
2920
  return;
2607
2921
 
2608
2922
  --signum;
@@ -2611,7 +2925,7 @@ ev_feed_signal_event (EV_P_ int signum) EV_NOEXCEPT
2611
2925
  /* it is permissible to try to feed a signal to the wrong loop */
2612
2926
  /* or, likely more useful, feeding a signal nobody is waiting for */
2613
2927
 
2614
- if (expect_false (signals [signum].loop != EV_A))
2928
+ if (ecb_expect_false (signals [signum].loop != EV_A))
2615
2929
  return;
2616
2930
  #endif
2617
2931
 
@@ -2705,6 +3019,57 @@ childcb (EV_P_ ev_signal *sw, int revents)
2705
3019
 
2706
3020
  /*****************************************************************************/
2707
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
+
2708
3073
  #if EV_USE_IOCP
2709
3074
  # include "ev_iocp.c"
2710
3075
  #endif
@@ -2717,6 +3082,12 @@ childcb (EV_P_ ev_signal *sw, int revents)
2717
3082
  #if EV_USE_EPOLL
2718
3083
  # include "ev_epoll.c"
2719
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
2720
3091
  #if EV_USE_POLL
2721
3092
  # include "ev_poll.c"
2722
3093
  #endif
@@ -2754,12 +3125,14 @@ ev_supported_backends (void) EV_NOEXCEPT
2754
3125
  {
2755
3126
  unsigned int flags = 0;
2756
3127
 
2757
- if (EV_USE_PORT ) flags |= EVBACKEND_PORT;
2758
- if (EV_USE_KQUEUE) flags |= EVBACKEND_KQUEUE;
2759
- if (EV_USE_EPOLL ) flags |= EVBACKEND_EPOLL;
2760
- if (EV_USE_POLL ) flags |= EVBACKEND_POLL;
2761
- if (EV_USE_SELECT) flags |= EVBACKEND_SELECT;
2762
-
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;
3135
+
2763
3136
  return flags;
2764
3137
  }
2765
3138
 
@@ -2769,21 +3142,31 @@ ev_recommended_backends (void) EV_NOEXCEPT
2769
3142
  {
2770
3143
  unsigned int flags = ev_supported_backends ();
2771
3144
 
2772
- #if defined(__APPLE__) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_14)
2773
- /* apple has a poor track record but post 10.12.2 it seems to work sufficiently well */
2774
- #elif defined(__NetBSD__)
2775
- /* kqueue is borked on everything but netbsd apparently */
2776
- /* it usually doesn't work correctly on anything but sockets and pipes */
2777
- #else
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)
2778
3147
  /* only select works correctly on that "unix-certified" platform */
2779
3148
  flags &= ~EVBACKEND_KQUEUE; /* horribly broken, even for sockets */
2780
3149
  flags &= ~EVBACKEND_POLL; /* poll is based on kqueue from 10.5 onwards */
2781
3150
  #endif
2782
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
+
2783
3158
  #ifdef __FreeBSD__
2784
3159
  flags &= ~EVBACKEND_POLL; /* poll return value is unusable (http://forums.freebsd.org/archive/index.php/t-10270.html) */
2785
3160
  #endif
2786
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
+
2787
3170
  return flags;
2788
3171
  }
2789
3172
 
@@ -2791,12 +3174,14 @@ ecb_cold
2791
3174
  unsigned int
2792
3175
  ev_embeddable_backends (void) EV_NOEXCEPT
2793
3176
  {
2794
- int flags = EVBACKEND_EPOLL | EVBACKEND_KQUEUE | EVBACKEND_PORT;
3177
+ int flags = EVBACKEND_EPOLL | EVBACKEND_KQUEUE | EVBACKEND_PORT | EVBACKEND_IOURING;
2795
3178
 
2796
3179
  /* epoll embeddability broken on all linux versions up to at least 2.6.23 */
2797
3180
  if (ev_linux_version () < 0x020620) /* disable it on linux < 2.6.32 */
2798
3181
  flags &= ~EVBACKEND_EPOLL;
2799
3182
 
3183
+ /* EVBACKEND_LINUXAIO is theoretically embeddable, but suffers from a performance overhead */
3184
+
2800
3185
  return flags;
2801
3186
  }
2802
3187
 
@@ -2858,7 +3243,7 @@ ev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_NOEXCEPT, void (*acquire)
2858
3243
  #endif
2859
3244
 
2860
3245
  /* initialise a loop structure, must be zero-initialised */
2861
- noinline ecb_cold
3246
+ ecb_noinline ecb_cold
2862
3247
  static void
2863
3248
  loop_init (EV_P_ unsigned int flags) EV_NOEXCEPT
2864
3249
  {
@@ -2923,27 +3308,36 @@ loop_init (EV_P_ unsigned int flags) EV_NOEXCEPT
2923
3308
  #if EV_USE_SIGNALFD
2924
3309
  sigfd = flags & EVFLAG_SIGNALFD ? -2 : -1;
2925
3310
  #endif
3311
+ #if EV_USE_TIMERFD
3312
+ timerfd = flags & EVFLAG_NOTIMERFD ? -1 : -2;
3313
+ #endif
2926
3314
 
2927
3315
  if (!(flags & EVBACKEND_MASK))
2928
3316
  flags |= ev_recommended_backends ();
2929
3317
 
2930
3318
  #if EV_USE_IOCP
2931
- if (!backend && (flags & EVBACKEND_IOCP )) backend = iocp_init (EV_A_ flags);
3319
+ if (!backend && (flags & EVBACKEND_IOCP )) backend = iocp_init (EV_A_ flags);
2932
3320
  #endif
2933
3321
  #if EV_USE_PORT
2934
- if (!backend && (flags & EVBACKEND_PORT )) backend = port_init (EV_A_ flags);
3322
+ if (!backend && (flags & EVBACKEND_PORT )) backend = port_init (EV_A_ flags);
2935
3323
  #endif
2936
3324
  #if EV_USE_KQUEUE
2937
- if (!backend && (flags & EVBACKEND_KQUEUE)) backend = kqueue_init (EV_A_ flags);
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);
2938
3332
  #endif
2939
3333
  #if EV_USE_EPOLL
2940
- if (!backend && (flags & EVBACKEND_EPOLL )) backend = epoll_init (EV_A_ flags);
3334
+ if (!backend && (flags & EVBACKEND_EPOLL )) backend = epoll_init (EV_A_ flags);
2941
3335
  #endif
2942
3336
  #if EV_USE_POLL
2943
- if (!backend && (flags & EVBACKEND_POLL )) backend = poll_init (EV_A_ flags);
3337
+ if (!backend && (flags & EVBACKEND_POLL )) backend = poll_init (EV_A_ flags);
2944
3338
  #endif
2945
3339
  #if EV_USE_SELECT
2946
- if (!backend && (flags & EVBACKEND_SELECT)) backend = select_init (EV_A_ flags);
3340
+ if (!backend && (flags & EVBACKEND_SELECT )) backend = select_init (EV_A_ flags);
2947
3341
  #endif
2948
3342
 
2949
3343
  ev_prepare_init (&pending_w, pendingcb);
@@ -2970,7 +3364,7 @@ ev_loop_destroy (EV_P)
2970
3364
 
2971
3365
  #if EV_CLEANUP_ENABLE
2972
3366
  /* queue cleanup watchers (and execute them) */
2973
- if (expect_false (cleanupcnt))
3367
+ if (ecb_expect_false (cleanupcnt))
2974
3368
  {
2975
3369
  queue_events (EV_A_ (W *)cleanups, cleanupcnt, EV_CLEANUP);
2976
3370
  EV_INVOKE_PENDING;
@@ -2999,6 +3393,11 @@ ev_loop_destroy (EV_P)
2999
3393
  close (sigfd);
3000
3394
  #endif
3001
3395
 
3396
+ #if EV_USE_TIMERFD
3397
+ if (ev_is_active (&timerfd_w))
3398
+ close (timerfd);
3399
+ #endif
3400
+
3002
3401
  #if EV_USE_INOTIFY
3003
3402
  if (fs_fd >= 0)
3004
3403
  close (fs_fd);
@@ -3008,22 +3407,28 @@ ev_loop_destroy (EV_P)
3008
3407
  close (backend_fd);
3009
3408
 
3010
3409
  #if EV_USE_IOCP
3011
- if (backend == EVBACKEND_IOCP ) iocp_destroy (EV_A);
3410
+ if (backend == EVBACKEND_IOCP ) iocp_destroy (EV_A);
3012
3411
  #endif
3013
3412
  #if EV_USE_PORT
3014
- if (backend == EVBACKEND_PORT ) port_destroy (EV_A);
3413
+ if (backend == EVBACKEND_PORT ) port_destroy (EV_A);
3015
3414
  #endif
3016
3415
  #if EV_USE_KQUEUE
3017
- if (backend == EVBACKEND_KQUEUE) kqueue_destroy (EV_A);
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);
3018
3423
  #endif
3019
3424
  #if EV_USE_EPOLL
3020
- if (backend == EVBACKEND_EPOLL ) epoll_destroy (EV_A);
3425
+ if (backend == EVBACKEND_EPOLL ) epoll_destroy (EV_A);
3021
3426
  #endif
3022
3427
  #if EV_USE_POLL
3023
- if (backend == EVBACKEND_POLL ) poll_destroy (EV_A);
3428
+ if (backend == EVBACKEND_POLL ) poll_destroy (EV_A);
3024
3429
  #endif
3025
3430
  #if EV_USE_SELECT
3026
- if (backend == EVBACKEND_SELECT) select_destroy (EV_A);
3431
+ if (backend == EVBACKEND_SELECT ) select_destroy (EV_A);
3027
3432
  #endif
3028
3433
 
3029
3434
  for (i = NUMPRI; i--; )
@@ -3075,34 +3480,62 @@ inline_size void
3075
3480
  loop_fork (EV_P)
3076
3481
  {
3077
3482
  #if EV_USE_PORT
3078
- if (backend == EVBACKEND_PORT ) port_fork (EV_A);
3483
+ if (backend == EVBACKEND_PORT ) port_fork (EV_A);
3079
3484
  #endif
3080
3485
  #if EV_USE_KQUEUE
3081
- if (backend == EVBACKEND_KQUEUE) kqueue_fork (EV_A);
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);
3082
3493
  #endif
3083
3494
  #if EV_USE_EPOLL
3084
- if (backend == EVBACKEND_EPOLL ) epoll_fork (EV_A);
3495
+ if (backend == EVBACKEND_EPOLL ) epoll_fork (EV_A);
3085
3496
  #endif
3086
3497
  #if EV_USE_INOTIFY
3087
3498
  infy_fork (EV_A);
3088
3499
  #endif
3089
3500
 
3090
- #if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
3091
- if (ev_is_active (&pipe_w) && postfork != 2)
3501
+ if (postfork != 2)
3092
3502
  {
3093
- /* pipe_write_wanted must be false now, so modifying fd vars should be safe */
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
3094
3506
 
3095
- ev_ref (EV_A);
3096
- ev_io_stop (EV_A_ &pipe_w);
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);
3097
3512
 
3098
- if (evpipe [0] >= 0)
3099
- EV_WIN32_CLOSE_FD (evpipe [0]);
3513
+ close (timerfd);
3514
+ timerfd = -2;
3100
3515
 
3101
- evpipe_init (EV_A);
3102
- /* iterate over everything, in case we missed something before */
3103
- ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);
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
3521
+
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
3104
3538
  }
3105
- #endif
3106
3539
 
3107
3540
  postfork = 0;
3108
3541
  }
@@ -3128,7 +3561,7 @@ ev_loop_new (unsigned int flags) EV_NOEXCEPT
3128
3561
  #endif /* multiplicity */
3129
3562
 
3130
3563
  #if EV_VERIFY
3131
- noinline ecb_cold
3564
+ ecb_noinline ecb_cold
3132
3565
  static void
3133
3566
  verify_watcher (EV_P_ W w)
3134
3567
  {
@@ -3138,7 +3571,7 @@ verify_watcher (EV_P_ W w)
3138
3571
  assert (("libev: pending watcher not on pending queue", pendings [ABSPRI (w)][w->pending - 1].w == w));
3139
3572
  }
3140
3573
 
3141
- noinline ecb_cold
3574
+ ecb_noinline ecb_cold
3142
3575
  static void
3143
3576
  verify_heap (EV_P_ ANHE *heap, int N)
3144
3577
  {
@@ -3154,7 +3587,7 @@ verify_heap (EV_P_ ANHE *heap, int N)
3154
3587
  }
3155
3588
  }
3156
3589
 
3157
- noinline ecb_cold
3590
+ ecb_noinline ecb_cold
3158
3591
  static void
3159
3592
  array_verify (EV_P_ W *ws, int cnt)
3160
3593
  {
@@ -3313,7 +3746,7 @@ ev_pending_count (EV_P) EV_NOEXCEPT
3313
3746
  return count;
3314
3747
  }
3315
3748
 
3316
- noinline
3749
+ ecb_noinline
3317
3750
  void
3318
3751
  ev_invoke_pending (EV_P)
3319
3752
  {
@@ -3342,7 +3775,7 @@ ev_invoke_pending (EV_P)
3342
3775
  inline_size void
3343
3776
  idle_reify (EV_P)
3344
3777
  {
3345
- if (expect_false (idleall))
3778
+ if (ecb_expect_false (idleall))
3346
3779
  {
3347
3780
  int pri;
3348
3781
 
@@ -3382,7 +3815,7 @@ timers_reify (EV_P)
3382
3815
  if (ev_at (w) < mn_now)
3383
3816
  ev_at (w) = mn_now;
3384
3817
 
3385
- 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.)));
3386
3819
 
3387
3820
  ANHE_at_cache (timers [HEAP0]);
3388
3821
  downheap (timers, timercnt, HEAP0);
@@ -3401,7 +3834,7 @@ timers_reify (EV_P)
3401
3834
 
3402
3835
  #if EV_PERIODIC_ENABLE
3403
3836
 
3404
- noinline
3837
+ ecb_noinline
3405
3838
  static void
3406
3839
  periodic_recalc (EV_P_ ev_periodic *w)
3407
3840
  {
@@ -3414,7 +3847,7 @@ periodic_recalc (EV_P_ ev_periodic *w)
3414
3847
  ev_tstamp nat = at + w->interval;
3415
3848
 
3416
3849
  /* when resolution fails us, we use ev_rt_now */
3417
- if (expect_false (nat == at))
3850
+ if (ecb_expect_false (nat == at))
3418
3851
  {
3419
3852
  at = ev_rt_now;
3420
3853
  break;
@@ -3470,7 +3903,7 @@ periodics_reify (EV_P)
3470
3903
 
3471
3904
  /* simply recalculate all periodics */
3472
3905
  /* TODO: maybe ensure that at least one event happens when jumping forward? */
3473
- noinline ecb_cold
3906
+ ecb_noinline ecb_cold
3474
3907
  static void
3475
3908
  periodics_reschedule (EV_P)
3476
3909
  {
@@ -3494,7 +3927,7 @@ periodics_reschedule (EV_P)
3494
3927
  #endif
3495
3928
 
3496
3929
  /* adjust all timers by a given offset */
3497
- noinline ecb_cold
3930
+ ecb_noinline ecb_cold
3498
3931
  static void
3499
3932
  timers_reschedule (EV_P_ ev_tstamp adjust)
3500
3933
  {
@@ -3514,7 +3947,7 @@ inline_speed void
3514
3947
  time_update (EV_P_ ev_tstamp max_block)
3515
3948
  {
3516
3949
  #if EV_USE_MONOTONIC
3517
- if (expect_true (have_monotonic))
3950
+ if (ecb_expect_true (have_monotonic))
3518
3951
  {
3519
3952
  int i;
3520
3953
  ev_tstamp odiff = rtmn_diff;
@@ -3523,7 +3956,7 @@ time_update (EV_P_ ev_tstamp max_block)
3523
3956
 
3524
3957
  /* only fetch the realtime clock every 0.5*MIN_TIMEJUMP seconds */
3525
3958
  /* interpolate in the meantime */
3526
- if (expect_true (mn_now - now_floor < MIN_TIMEJUMP * .5))
3959
+ if (ecb_expect_true (mn_now - now_floor < EV_TS_CONST (MIN_TIMEJUMP * .5)))
3527
3960
  {
3528
3961
  ev_rt_now = rtmn_diff + mn_now;
3529
3962
  return;
@@ -3547,7 +3980,7 @@ time_update (EV_P_ ev_tstamp max_block)
3547
3980
 
3548
3981
  diff = odiff - rtmn_diff;
3549
3982
 
3550
- if (expect_true ((diff < 0. ? -diff : diff) < MIN_TIMEJUMP))
3983
+ if (ecb_expect_true ((diff < EV_TS_CONST (0.) ? -diff : diff) < EV_TS_CONST (MIN_TIMEJUMP)))
3551
3984
  return; /* all is well */
3552
3985
 
3553
3986
  ev_rt_now = ev_time ();
@@ -3566,7 +3999,7 @@ time_update (EV_P_ ev_tstamp max_block)
3566
3999
  {
3567
4000
  ev_rt_now = ev_time ();
3568
4001
 
3569
- if (expect_false (mn_now > ev_rt_now || ev_rt_now > mn_now + max_block + MIN_TIMEJUMP))
4002
+ if (ecb_expect_false (mn_now > ev_rt_now || ev_rt_now > mn_now + max_block + EV_TS_CONST (MIN_TIMEJUMP)))
3570
4003
  {
3571
4004
  /* adjust timers. this is easy, as the offset is the same for all of them */
3572
4005
  timers_reschedule (EV_A_ ev_rt_now - mn_now);
@@ -3586,11 +4019,13 @@ struct ev_poll_args {
3586
4019
  };
3587
4020
 
3588
4021
  static
3589
- VALUE ev_backend_poll(void *ptr)
4022
+ void * ev_backend_poll(void *ptr)
3590
4023
  {
3591
4024
  struct ev_poll_args *args = (struct ev_poll_args *)ptr;
3592
4025
  struct ev_loop *loop = args->loop;
3593
4026
  backend_poll (EV_A_ args->waittime);
4027
+
4028
+ return NULL;
3594
4029
  }
3595
4030
  /* ######################################## */
3596
4031
 
@@ -3598,7 +4033,7 @@ int
3598
4033
  ev_run (EV_P_ int flags)
3599
4034
  {
3600
4035
  /* ########## NIO4R PATCHERY HO! ########## */
3601
- struct ev_poll_args poll_args;
4036
+ struct ev_poll_args poll_args;
3602
4037
  /* ######################################## */
3603
4038
 
3604
4039
  #if EV_FEATURE_API
@@ -3618,8 +4053,8 @@ ev_run (EV_P_ int flags)
3618
4053
  #endif
3619
4054
 
3620
4055
  #ifndef _WIN32
3621
- if (expect_false (curpid)) /* penalise the forking check even more */
3622
- if (expect_false (getpid () != curpid))
4056
+ if (ecb_expect_false (curpid)) /* penalise the forking check even more */
4057
+ if (ecb_expect_false (getpid () != curpid))
3623
4058
  {
3624
4059
  curpid = getpid ();
3625
4060
  postfork = 1;
@@ -3628,7 +4063,7 @@ ev_run (EV_P_ int flags)
3628
4063
 
3629
4064
  #if EV_FORK_ENABLE
3630
4065
  /* we might have forked, so queue fork handlers */
3631
- if (expect_false (postfork))
4066
+ if (ecb_expect_false (postfork))
3632
4067
  if (forkcnt)
3633
4068
  {
3634
4069
  queue_events (EV_A_ (W *)forks, forkcnt, EV_FORK);
@@ -3638,18 +4073,18 @@ ev_run (EV_P_ int flags)
3638
4073
 
3639
4074
  #if EV_PREPARE_ENABLE
3640
4075
  /* queue prepare watchers (and execute them) */
3641
- if (expect_false (preparecnt))
4076
+ if (ecb_expect_false (preparecnt))
3642
4077
  {
3643
4078
  queue_events (EV_A_ (W *)prepares, preparecnt, EV_PREPARE);
3644
4079
  EV_INVOKE_PENDING;
3645
4080
  }
3646
4081
  #endif
3647
4082
 
3648
- if (expect_false (loop_done))
4083
+ if (ecb_expect_false (loop_done))
3649
4084
  break;
3650
4085
 
3651
4086
  /* we might have forked, so reify kernel state if necessary */
3652
- if (expect_false (postfork))
4087
+ if (ecb_expect_false (postfork))
3653
4088
  loop_fork (EV_A);
3654
4089
 
3655
4090
  /* update fd-related kernel structures */
@@ -3664,16 +4099,28 @@ ev_run (EV_P_ int flags)
3664
4099
  ev_tstamp prev_mn_now = mn_now;
3665
4100
 
3666
4101
  /* update time to cancel out callback processing overhead */
3667
- time_update (EV_A_ 1e100);
4102
+ time_update (EV_A_ EV_TS_CONST (EV_TSTAMP_HUGE));
3668
4103
 
3669
4104
  /* from now on, we want a pipe-wake-up */
3670
4105
  pipe_write_wanted = 1;
3671
4106
 
3672
4107
  ECB_MEMORY_FENCE; /* make sure pipe_write_wanted is visible before we check for potential skips */
3673
4108
 
3674
- if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt || pipe_write_skipped)))
4109
+ if (ecb_expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt || pipe_write_skipped)))
3675
4110
  {
3676
- 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
3677
4124
 
3678
4125
  if (timercnt)
3679
4126
  {
@@ -3690,23 +4137,28 @@ ev_run (EV_P_ int flags)
3690
4137
  #endif
3691
4138
 
3692
4139
  /* don't let timeouts decrease the waittime below timeout_blocktime */
3693
- if (expect_false (waittime < timeout_blocktime))
4140
+ if (ecb_expect_false (waittime < timeout_blocktime))
3694
4141
  waittime = timeout_blocktime;
3695
4142
 
3696
- /* at this point, we NEED to wait, so we have to ensure */
3697
- /* to pass a minimum nonzero value to the backend */
3698
- if (expect_false (waittime < backend_mintime))
3699
- waittime = backend_mintime;
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;
3700
4152
 
3701
4153
  /* extra check because io_blocktime is commonly 0 */
3702
- if (expect_false (io_blocktime))
4154
+ if (ecb_expect_false (io_blocktime))
3703
4155
  {
3704
4156
  sleeptime = io_blocktime - (mn_now - prev_mn_now);
3705
4157
 
3706
4158
  if (sleeptime > waittime - backend_mintime)
3707
4159
  sleeptime = waittime - backend_mintime;
3708
4160
 
3709
- if (expect_true (sleeptime > 0.))
4161
+ if (ecb_expect_true (sleeptime > EV_TS_CONST (0.)))
3710
4162
  {
3711
4163
  ev_sleep (sleeptime);
3712
4164
  waittime -= sleeptime;
@@ -3777,7 +4229,6 @@ rb_thread_unsafe_dangerous_crazy_blocking_region_end(...);
3777
4229
  ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);
3778
4230
  }
3779
4231
 
3780
-
3781
4232
  /* update ev_rt_now, do magic */
3782
4233
  time_update (EV_A_ waittime + sleeptime);
3783
4234
  }
@@ -3795,13 +4246,13 @@ rb_thread_unsafe_dangerous_crazy_blocking_region_end(...);
3795
4246
 
3796
4247
  #if EV_CHECK_ENABLE
3797
4248
  /* queue check watchers, to be executed first */
3798
- if (expect_false (checkcnt))
4249
+ if (ecb_expect_false (checkcnt))
3799
4250
  queue_events (EV_A_ (W *)checks, checkcnt, EV_CHECK);
3800
4251
  #endif
3801
4252
 
3802
4253
  EV_INVOKE_PENDING;
3803
4254
  }
3804
- while (expect_true (
4255
+ while (ecb_expect_true (
3805
4256
  activecnt
3806
4257
  && !loop_done
3807
4258
  && !(flags & (EVRUN_ONCE | EVRUN_NOWAIT))
@@ -3838,7 +4289,7 @@ ev_unref (EV_P) EV_NOEXCEPT
3838
4289
  void
3839
4290
  ev_now_update (EV_P) EV_NOEXCEPT
3840
4291
  {
3841
- time_update (EV_A_ 1e100);
4292
+ time_update (EV_A_ EV_TSTAMP_HUGE);
3842
4293
  }
3843
4294
 
3844
4295
  void
@@ -3875,7 +4326,7 @@ wlist_del (WL *head, WL elem)
3875
4326
  {
3876
4327
  while (*head)
3877
4328
  {
3878
- if (expect_true (*head == elem))
4329
+ if (ecb_expect_true (*head == elem))
3879
4330
  {
3880
4331
  *head = elem->next;
3881
4332
  break;
@@ -3902,7 +4353,7 @@ ev_clear_pending (EV_P_ void *w) EV_NOEXCEPT
3902
4353
  W w_ = (W)w;
3903
4354
  int pending = w_->pending;
3904
4355
 
3905
- if (expect_true (pending))
4356
+ if (ecb_expect_true (pending))
3906
4357
  {
3907
4358
  ANPENDING *p = pendings [ABSPRI (w_)] + pending - 1;
3908
4359
  p->w = (W)&pending_w;
@@ -3939,22 +4390,25 @@ ev_stop (EV_P_ W w)
3939
4390
 
3940
4391
  /*****************************************************************************/
3941
4392
 
3942
- noinline
4393
+ ecb_noinline
3943
4394
  void
3944
4395
  ev_io_start (EV_P_ ev_io *w) EV_NOEXCEPT
3945
4396
  {
3946
4397
  int fd = w->fd;
3947
4398
 
3948
- if (expect_false (ev_is_active (w)))
4399
+ if (ecb_expect_false (ev_is_active (w)))
3949
4400
  return;
3950
4401
 
3951
4402
  assert (("libev: ev_io_start called with negative fd", fd >= 0));
3952
4403
  assert (("libev: ev_io_start called with illegal event mask", !(w->events & ~(EV__IOFDSET | EV_READ | EV_WRITE))));
3953
4404
 
4405
+ #if EV_VERIFY >= 2
4406
+ assert (("libev: ev_io_start called on watcher with invalid fd", fd_valid (fd)));
4407
+ #endif
3954
4408
  EV_FREQUENT_CHECK;
3955
4409
 
3956
4410
  ev_start (EV_A_ (W)w, 1);
3957
- array_needsize (ANFD, anfds, anfdmax, fd + 1, array_init_zero);
4411
+ array_needsize (ANFD, anfds, anfdmax, fd + 1, array_needsize_zerofill);
3958
4412
  wlist_add (&anfds[fd].head, (WL)w);
3959
4413
 
3960
4414
  /* common bug, apparently */
@@ -3966,16 +4420,19 @@ ev_io_start (EV_P_ ev_io *w) EV_NOEXCEPT
3966
4420
  EV_FREQUENT_CHECK;
3967
4421
  }
3968
4422
 
3969
- noinline
4423
+ ecb_noinline
3970
4424
  void
3971
4425
  ev_io_stop (EV_P_ ev_io *w) EV_NOEXCEPT
3972
4426
  {
3973
4427
  clear_pending (EV_A_ (W)w);
3974
- if (expect_false (!ev_is_active (w)))
4428
+ if (ecb_expect_false (!ev_is_active (w)))
3975
4429
  return;
3976
4430
 
3977
4431
  assert (("libev: ev_io_stop called with illegal fd (must stay constant after start!)", w->fd >= 0 && w->fd < anfdmax));
3978
4432
 
4433
+ #if EV_VERIFY >= 2
4434
+ assert (("libev: ev_io_stop called on watcher with invalid fd", fd_valid (w->fd)));
4435
+ #endif
3979
4436
  EV_FREQUENT_CHECK;
3980
4437
 
3981
4438
  wlist_del (&anfds[w->fd].head, (WL)w);
@@ -3986,11 +4443,11 @@ ev_io_stop (EV_P_ ev_io *w) EV_NOEXCEPT
3986
4443
  EV_FREQUENT_CHECK;
3987
4444
  }
3988
4445
 
3989
- noinline
4446
+ ecb_noinline
3990
4447
  void
3991
4448
  ev_timer_start (EV_P_ ev_timer *w) EV_NOEXCEPT
3992
4449
  {
3993
- if (expect_false (ev_is_active (w)))
4450
+ if (ecb_expect_false (ev_is_active (w)))
3994
4451
  return;
3995
4452
 
3996
4453
  ev_at (w) += mn_now;
@@ -4001,7 +4458,7 @@ ev_timer_start (EV_P_ ev_timer *w) EV_NOEXCEPT
4001
4458
 
4002
4459
  ++timercnt;
4003
4460
  ev_start (EV_A_ (W)w, timercnt + HEAP0 - 1);
4004
- array_needsize (ANHE, timers, timermax, ev_active (w) + 1, EMPTY2);
4461
+ array_needsize (ANHE, timers, timermax, ev_active (w) + 1, array_needsize_noinit);
4005
4462
  ANHE_w (timers [ev_active (w)]) = (WT)w;
4006
4463
  ANHE_at_cache (timers [ev_active (w)]);
4007
4464
  upheap (timers, ev_active (w));
@@ -4011,12 +4468,12 @@ ev_timer_start (EV_P_ ev_timer *w) EV_NOEXCEPT
4011
4468
  /*assert (("libev: internal timer heap corruption", timers [ev_active (w)] == (WT)w));*/
4012
4469
  }
4013
4470
 
4014
- noinline
4471
+ ecb_noinline
4015
4472
  void
4016
4473
  ev_timer_stop (EV_P_ ev_timer *w) EV_NOEXCEPT
4017
4474
  {
4018
4475
  clear_pending (EV_A_ (W)w);
4019
- if (expect_false (!ev_is_active (w)))
4476
+ if (ecb_expect_false (!ev_is_active (w)))
4020
4477
  return;
4021
4478
 
4022
4479
  EV_FREQUENT_CHECK;
@@ -4028,7 +4485,7 @@ ev_timer_stop (EV_P_ ev_timer *w) EV_NOEXCEPT
4028
4485
 
4029
4486
  --timercnt;
4030
4487
 
4031
- if (expect_true (active < timercnt + HEAP0))
4488
+ if (ecb_expect_true (active < timercnt + HEAP0))
4032
4489
  {
4033
4490
  timers [active] = timers [timercnt + HEAP0];
4034
4491
  adjustheap (timers, timercnt, active);
@@ -4042,7 +4499,7 @@ ev_timer_stop (EV_P_ ev_timer *w) EV_NOEXCEPT
4042
4499
  EV_FREQUENT_CHECK;
4043
4500
  }
4044
4501
 
4045
- noinline
4502
+ ecb_noinline
4046
4503
  void
4047
4504
  ev_timer_again (EV_P_ ev_timer *w) EV_NOEXCEPT
4048
4505
  {
@@ -4073,17 +4530,22 @@ ev_timer_again (EV_P_ ev_timer *w) EV_NOEXCEPT
4073
4530
  ev_tstamp
4074
4531
  ev_timer_remaining (EV_P_ ev_timer *w) EV_NOEXCEPT
4075
4532
  {
4076
- 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.));
4077
4534
  }
4078
4535
 
4079
4536
  #if EV_PERIODIC_ENABLE
4080
- noinline
4537
+ ecb_noinline
4081
4538
  void
4082
4539
  ev_periodic_start (EV_P_ ev_periodic *w) EV_NOEXCEPT
4083
4540
  {
4084
- if (expect_false (ev_is_active (w)))
4541
+ if (ecb_expect_false (ev_is_active (w)))
4085
4542
  return;
4086
4543
 
4544
+ #if EV_USE_TIMERFD
4545
+ if (timerfd == -2)
4546
+ evtimerfd_init (EV_A);
4547
+ #endif
4548
+
4087
4549
  if (w->reschedule_cb)
4088
4550
  ev_at (w) = w->reschedule_cb (w, ev_rt_now);
4089
4551
  else if (w->interval)
@@ -4098,7 +4560,7 @@ ev_periodic_start (EV_P_ ev_periodic *w) EV_NOEXCEPT
4098
4560
 
4099
4561
  ++periodiccnt;
4100
4562
  ev_start (EV_A_ (W)w, periodiccnt + HEAP0 - 1);
4101
- array_needsize (ANHE, periodics, periodicmax, ev_active (w) + 1, EMPTY2);
4563
+ array_needsize (ANHE, periodics, periodicmax, ev_active (w) + 1, array_needsize_noinit);
4102
4564
  ANHE_w (periodics [ev_active (w)]) = (WT)w;
4103
4565
  ANHE_at_cache (periodics [ev_active (w)]);
4104
4566
  upheap (periodics, ev_active (w));
@@ -4108,12 +4570,12 @@ ev_periodic_start (EV_P_ ev_periodic *w) EV_NOEXCEPT
4108
4570
  /*assert (("libev: internal periodic heap corruption", ANHE_w (periodics [ev_active (w)]) == (WT)w));*/
4109
4571
  }
4110
4572
 
4111
- noinline
4573
+ ecb_noinline
4112
4574
  void
4113
4575
  ev_periodic_stop (EV_P_ ev_periodic *w) EV_NOEXCEPT
4114
4576
  {
4115
4577
  clear_pending (EV_A_ (W)w);
4116
- if (expect_false (!ev_is_active (w)))
4578
+ if (ecb_expect_false (!ev_is_active (w)))
4117
4579
  return;
4118
4580
 
4119
4581
  EV_FREQUENT_CHECK;
@@ -4125,7 +4587,7 @@ ev_periodic_stop (EV_P_ ev_periodic *w) EV_NOEXCEPT
4125
4587
 
4126
4588
  --periodiccnt;
4127
4589
 
4128
- if (expect_true (active < periodiccnt + HEAP0))
4590
+ if (ecb_expect_true (active < periodiccnt + HEAP0))
4129
4591
  {
4130
4592
  periodics [active] = periodics [periodiccnt + HEAP0];
4131
4593
  adjustheap (periodics, periodiccnt, active);
@@ -4137,7 +4599,7 @@ ev_periodic_stop (EV_P_ ev_periodic *w) EV_NOEXCEPT
4137
4599
  EV_FREQUENT_CHECK;
4138
4600
  }
4139
4601
 
4140
- noinline
4602
+ ecb_noinline
4141
4603
  void
4142
4604
  ev_periodic_again (EV_P_ ev_periodic *w) EV_NOEXCEPT
4143
4605
  {
@@ -4153,11 +4615,11 @@ ev_periodic_again (EV_P_ ev_periodic *w) EV_NOEXCEPT
4153
4615
 
4154
4616
  #if EV_SIGNAL_ENABLE
4155
4617
 
4156
- noinline
4618
+ ecb_noinline
4157
4619
  void
4158
4620
  ev_signal_start (EV_P_ ev_signal *w) EV_NOEXCEPT
4159
4621
  {
4160
- if (expect_false (ev_is_active (w)))
4622
+ if (ecb_expect_false (ev_is_active (w)))
4161
4623
  return;
4162
4624
 
4163
4625
  assert (("libev: ev_signal_start called with illegal signal number", w->signum > 0 && w->signum < EV_NSIG));
@@ -4236,12 +4698,12 @@ ev_signal_start (EV_P_ ev_signal *w) EV_NOEXCEPT
4236
4698
  EV_FREQUENT_CHECK;
4237
4699
  }
4238
4700
 
4239
- noinline
4701
+ ecb_noinline
4240
4702
  void
4241
4703
  ev_signal_stop (EV_P_ ev_signal *w) EV_NOEXCEPT
4242
4704
  {
4243
4705
  clear_pending (EV_A_ (W)w);
4244
- if (expect_false (!ev_is_active (w)))
4706
+ if (ecb_expect_false (!ev_is_active (w)))
4245
4707
  return;
4246
4708
 
4247
4709
  EV_FREQUENT_CHECK;
@@ -4284,7 +4746,7 @@ ev_child_start (EV_P_ ev_child *w) EV_NOEXCEPT
4284
4746
  #if EV_MULTIPLICITY
4285
4747
  assert (("libev: child watchers are only supported in the default loop", loop == ev_default_loop_ptr));
4286
4748
  #endif
4287
- if (expect_false (ev_is_active (w)))
4749
+ if (ecb_expect_false (ev_is_active (w)))
4288
4750
  return;
4289
4751
 
4290
4752
  EV_FREQUENT_CHECK;
@@ -4299,7 +4761,7 @@ void
4299
4761
  ev_child_stop (EV_P_ ev_child *w) EV_NOEXCEPT
4300
4762
  {
4301
4763
  clear_pending (EV_A_ (W)w);
4302
- if (expect_false (!ev_is_active (w)))
4764
+ if (ecb_expect_false (!ev_is_active (w)))
4303
4765
  return;
4304
4766
 
4305
4767
  EV_FREQUENT_CHECK;
@@ -4323,14 +4785,14 @@ ev_child_stop (EV_P_ ev_child *w) EV_NOEXCEPT
4323
4785
  #define NFS_STAT_INTERVAL 30.1074891 /* for filesystems potentially failing inotify */
4324
4786
  #define MIN_STAT_INTERVAL 0.1074891
4325
4787
 
4326
- noinline static void stat_timer_cb (EV_P_ ev_timer *w_, int revents);
4788
+ ecb_noinline static void stat_timer_cb (EV_P_ ev_timer *w_, int revents);
4327
4789
 
4328
4790
  #if EV_USE_INOTIFY
4329
4791
 
4330
4792
  /* the * 2 is to allow for alignment padding, which for some reason is >> 8 */
4331
4793
  # define EV_INOTIFY_BUFSIZE (sizeof (struct inotify_event) * 2 + NAME_MAX)
4332
4794
 
4333
- noinline
4795
+ ecb_noinline
4334
4796
  static void
4335
4797
  infy_add (EV_P_ ev_stat *w)
4336
4798
  {
@@ -4405,7 +4867,7 @@ infy_add (EV_P_ ev_stat *w)
4405
4867
  if (ev_is_active (&w->timer)) ev_unref (EV_A);
4406
4868
  }
4407
4869
 
4408
- noinline
4870
+ ecb_noinline
4409
4871
  static void
4410
4872
  infy_del (EV_P_ ev_stat *w)
4411
4873
  {
@@ -4423,7 +4885,7 @@ infy_del (EV_P_ ev_stat *w)
4423
4885
  inotify_rm_watch (fs_fd, wd);
4424
4886
  }
4425
4887
 
4426
- noinline
4888
+ ecb_noinline
4427
4889
  static void
4428
4890
  infy_wd (EV_P_ int slot, int wd, struct inotify_event *ev)
4429
4891
  {
@@ -4579,7 +5041,7 @@ ev_stat_stat (EV_P_ ev_stat *w) EV_NOEXCEPT
4579
5041
  w->attr.st_nlink = 1;
4580
5042
  }
4581
5043
 
4582
- noinline
5044
+ ecb_noinline
4583
5045
  static void
4584
5046
  stat_timer_cb (EV_P_ ev_timer *w_, int revents)
4585
5047
  {
@@ -4623,7 +5085,7 @@ stat_timer_cb (EV_P_ ev_timer *w_, int revents)
4623
5085
  void
4624
5086
  ev_stat_start (EV_P_ ev_stat *w) EV_NOEXCEPT
4625
5087
  {
4626
- if (expect_false (ev_is_active (w)))
5088
+ if (ecb_expect_false (ev_is_active (w)))
4627
5089
  return;
4628
5090
 
4629
5091
  ev_stat_stat (EV_A_ w);
@@ -4655,7 +5117,7 @@ void
4655
5117
  ev_stat_stop (EV_P_ ev_stat *w) EV_NOEXCEPT
4656
5118
  {
4657
5119
  clear_pending (EV_A_ (W)w);
4658
- if (expect_false (!ev_is_active (w)))
5120
+ if (ecb_expect_false (!ev_is_active (w)))
4659
5121
  return;
4660
5122
 
4661
5123
  EV_FREQUENT_CHECK;
@@ -4680,7 +5142,7 @@ ev_stat_stop (EV_P_ ev_stat *w) EV_NOEXCEPT
4680
5142
  void
4681
5143
  ev_idle_start (EV_P_ ev_idle *w) EV_NOEXCEPT
4682
5144
  {
4683
- if (expect_false (ev_is_active (w)))
5145
+ if (ecb_expect_false (ev_is_active (w)))
4684
5146
  return;
4685
5147
 
4686
5148
  pri_adjust (EV_A_ (W)w);
@@ -4693,7 +5155,7 @@ ev_idle_start (EV_P_ ev_idle *w) EV_NOEXCEPT
4693
5155
  ++idleall;
4694
5156
  ev_start (EV_A_ (W)w, active);
4695
5157
 
4696
- array_needsize (ev_idle *, idles [ABSPRI (w)], idlemax [ABSPRI (w)], active, EMPTY2);
5158
+ array_needsize (ev_idle *, idles [ABSPRI (w)], idlemax [ABSPRI (w)], active, array_needsize_noinit);
4697
5159
  idles [ABSPRI (w)][active - 1] = w;
4698
5160
  }
4699
5161
 
@@ -4704,7 +5166,7 @@ void
4704
5166
  ev_idle_stop (EV_P_ ev_idle *w) EV_NOEXCEPT
4705
5167
  {
4706
5168
  clear_pending (EV_A_ (W)w);
4707
- if (expect_false (!ev_is_active (w)))
5169
+ if (ecb_expect_false (!ev_is_active (w)))
4708
5170
  return;
4709
5171
 
4710
5172
  EV_FREQUENT_CHECK;
@@ -4727,13 +5189,13 @@ ev_idle_stop (EV_P_ ev_idle *w) EV_NOEXCEPT
4727
5189
  void
4728
5190
  ev_prepare_start (EV_P_ ev_prepare *w) EV_NOEXCEPT
4729
5191
  {
4730
- if (expect_false (ev_is_active (w)))
5192
+ if (ecb_expect_false (ev_is_active (w)))
4731
5193
  return;
4732
5194
 
4733
5195
  EV_FREQUENT_CHECK;
4734
5196
 
4735
5197
  ev_start (EV_A_ (W)w, ++preparecnt);
4736
- array_needsize (ev_prepare *, prepares, preparemax, preparecnt, EMPTY2);
5198
+ array_needsize (ev_prepare *, prepares, preparemax, preparecnt, array_needsize_noinit);
4737
5199
  prepares [preparecnt - 1] = w;
4738
5200
 
4739
5201
  EV_FREQUENT_CHECK;
@@ -4743,7 +5205,7 @@ void
4743
5205
  ev_prepare_stop (EV_P_ ev_prepare *w) EV_NOEXCEPT
4744
5206
  {
4745
5207
  clear_pending (EV_A_ (W)w);
4746
- if (expect_false (!ev_is_active (w)))
5208
+ if (ecb_expect_false (!ev_is_active (w)))
4747
5209
  return;
4748
5210
 
4749
5211
  EV_FREQUENT_CHECK;
@@ -4765,13 +5227,13 @@ ev_prepare_stop (EV_P_ ev_prepare *w) EV_NOEXCEPT
4765
5227
  void
4766
5228
  ev_check_start (EV_P_ ev_check *w) EV_NOEXCEPT
4767
5229
  {
4768
- if (expect_false (ev_is_active (w)))
5230
+ if (ecb_expect_false (ev_is_active (w)))
4769
5231
  return;
4770
5232
 
4771
5233
  EV_FREQUENT_CHECK;
4772
5234
 
4773
5235
  ev_start (EV_A_ (W)w, ++checkcnt);
4774
- array_needsize (ev_check *, checks, checkmax, checkcnt, EMPTY2);
5236
+ array_needsize (ev_check *, checks, checkmax, checkcnt, array_needsize_noinit);
4775
5237
  checks [checkcnt - 1] = w;
4776
5238
 
4777
5239
  EV_FREQUENT_CHECK;
@@ -4781,7 +5243,7 @@ void
4781
5243
  ev_check_stop (EV_P_ ev_check *w) EV_NOEXCEPT
4782
5244
  {
4783
5245
  clear_pending (EV_A_ (W)w);
4784
- if (expect_false (!ev_is_active (w)))
5246
+ if (ecb_expect_false (!ev_is_active (w)))
4785
5247
  return;
4786
5248
 
4787
5249
  EV_FREQUENT_CHECK;
@@ -4800,7 +5262,7 @@ ev_check_stop (EV_P_ ev_check *w) EV_NOEXCEPT
4800
5262
  #endif
4801
5263
 
4802
5264
  #if EV_EMBED_ENABLE
4803
- noinline
5265
+ ecb_noinline
4804
5266
  void
4805
5267
  ev_embed_sweep (EV_P_ ev_embed *w) EV_NOEXCEPT
4806
5268
  {
@@ -4834,6 +5296,7 @@ embed_prepare_cb (EV_P_ ev_prepare *prepare, int revents)
4834
5296
  }
4835
5297
  }
4836
5298
 
5299
+ #if EV_FORK_ENABLE
4837
5300
  static void
4838
5301
  embed_fork_cb (EV_P_ ev_fork *fork_w, int revents)
4839
5302
  {
@@ -4850,6 +5313,7 @@ embed_fork_cb (EV_P_ ev_fork *fork_w, int revents)
4850
5313
 
4851
5314
  ev_embed_start (EV_A_ w);
4852
5315
  }
5316
+ #endif
4853
5317
 
4854
5318
  #if 0
4855
5319
  static void
@@ -4862,7 +5326,7 @@ embed_idle_cb (EV_P_ ev_idle *idle, int revents)
4862
5326
  void
4863
5327
  ev_embed_start (EV_P_ ev_embed *w) EV_NOEXCEPT
4864
5328
  {
4865
- if (expect_false (ev_is_active (w)))
5329
+ if (ecb_expect_false (ev_is_active (w)))
4866
5330
  return;
4867
5331
 
4868
5332
  {
@@ -4880,8 +5344,10 @@ ev_embed_start (EV_P_ ev_embed *w) EV_NOEXCEPT
4880
5344
  ev_set_priority (&w->prepare, EV_MINPRI);
4881
5345
  ev_prepare_start (EV_A_ &w->prepare);
4882
5346
 
5347
+ #if EV_FORK_ENABLE
4883
5348
  ev_fork_init (&w->fork, embed_fork_cb);
4884
5349
  ev_fork_start (EV_A_ &w->fork);
5350
+ #endif
4885
5351
 
4886
5352
  /*ev_idle_init (&w->idle, e,bed_idle_cb);*/
4887
5353
 
@@ -4894,14 +5360,16 @@ void
4894
5360
  ev_embed_stop (EV_P_ ev_embed *w) EV_NOEXCEPT
4895
5361
  {
4896
5362
  clear_pending (EV_A_ (W)w);
4897
- if (expect_false (!ev_is_active (w)))
5363
+ if (ecb_expect_false (!ev_is_active (w)))
4898
5364
  return;
4899
5365
 
4900
5366
  EV_FREQUENT_CHECK;
4901
5367
 
4902
5368
  ev_io_stop (EV_A_ &w->io);
4903
5369
  ev_prepare_stop (EV_A_ &w->prepare);
5370
+ #if EV_FORK_ENABLE
4904
5371
  ev_fork_stop (EV_A_ &w->fork);
5372
+ #endif
4905
5373
 
4906
5374
  ev_stop (EV_A_ (W)w);
4907
5375
 
@@ -4913,13 +5381,13 @@ ev_embed_stop (EV_P_ ev_embed *w) EV_NOEXCEPT
4913
5381
  void
4914
5382
  ev_fork_start (EV_P_ ev_fork *w) EV_NOEXCEPT
4915
5383
  {
4916
- if (expect_false (ev_is_active (w)))
5384
+ if (ecb_expect_false (ev_is_active (w)))
4917
5385
  return;
4918
5386
 
4919
5387
  EV_FREQUENT_CHECK;
4920
5388
 
4921
5389
  ev_start (EV_A_ (W)w, ++forkcnt);
4922
- array_needsize (ev_fork *, forks, forkmax, forkcnt, EMPTY2);
5390
+ array_needsize (ev_fork *, forks, forkmax, forkcnt, array_needsize_noinit);
4923
5391
  forks [forkcnt - 1] = w;
4924
5392
 
4925
5393
  EV_FREQUENT_CHECK;
@@ -4929,7 +5397,7 @@ void
4929
5397
  ev_fork_stop (EV_P_ ev_fork *w) EV_NOEXCEPT
4930
5398
  {
4931
5399
  clear_pending (EV_A_ (W)w);
4932
- if (expect_false (!ev_is_active (w)))
5400
+ if (ecb_expect_false (!ev_is_active (w)))
4933
5401
  return;
4934
5402
 
4935
5403
  EV_FREQUENT_CHECK;
@@ -4951,13 +5419,13 @@ ev_fork_stop (EV_P_ ev_fork *w) EV_NOEXCEPT
4951
5419
  void
4952
5420
  ev_cleanup_start (EV_P_ ev_cleanup *w) EV_NOEXCEPT
4953
5421
  {
4954
- if (expect_false (ev_is_active (w)))
5422
+ if (ecb_expect_false (ev_is_active (w)))
4955
5423
  return;
4956
5424
 
4957
5425
  EV_FREQUENT_CHECK;
4958
5426
 
4959
5427
  ev_start (EV_A_ (W)w, ++cleanupcnt);
4960
- array_needsize (ev_cleanup *, cleanups, cleanupmax, cleanupcnt, EMPTY2);
5428
+ array_needsize (ev_cleanup *, cleanups, cleanupmax, cleanupcnt, array_needsize_noinit);
4961
5429
  cleanups [cleanupcnt - 1] = w;
4962
5430
 
4963
5431
  /* cleanup watchers should never keep a refcount on the loop */
@@ -4969,7 +5437,7 @@ void
4969
5437
  ev_cleanup_stop (EV_P_ ev_cleanup *w) EV_NOEXCEPT
4970
5438
  {
4971
5439
  clear_pending (EV_A_ (W)w);
4972
- if (expect_false (!ev_is_active (w)))
5440
+ if (ecb_expect_false (!ev_is_active (w)))
4973
5441
  return;
4974
5442
 
4975
5443
  EV_FREQUENT_CHECK;
@@ -4992,7 +5460,7 @@ ev_cleanup_stop (EV_P_ ev_cleanup *w) EV_NOEXCEPT
4992
5460
  void
4993
5461
  ev_async_start (EV_P_ ev_async *w) EV_NOEXCEPT
4994
5462
  {
4995
- if (expect_false (ev_is_active (w)))
5463
+ if (ecb_expect_false (ev_is_active (w)))
4996
5464
  return;
4997
5465
 
4998
5466
  w->sent = 0;
@@ -5002,7 +5470,7 @@ ev_async_start (EV_P_ ev_async *w) EV_NOEXCEPT
5002
5470
  EV_FREQUENT_CHECK;
5003
5471
 
5004
5472
  ev_start (EV_A_ (W)w, ++asynccnt);
5005
- array_needsize (ev_async *, asyncs, asyncmax, asynccnt, EMPTY2);
5473
+ array_needsize (ev_async *, asyncs, asyncmax, asynccnt, array_needsize_noinit);
5006
5474
  asyncs [asynccnt - 1] = w;
5007
5475
 
5008
5476
  EV_FREQUENT_CHECK;
@@ -5012,7 +5480,7 @@ void
5012
5480
  ev_async_stop (EV_P_ ev_async *w) EV_NOEXCEPT
5013
5481
  {
5014
5482
  clear_pending (EV_A_ (W)w);
5015
- if (expect_false (!ev_is_active (w)))
5483
+ if (ecb_expect_false (!ev_is_active (w)))
5016
5484
  return;
5017
5485
 
5018
5486
  EV_FREQUENT_CHECK;
@@ -5081,12 +5549,6 @@ ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, vo
5081
5549
  {
5082
5550
  struct ev_once *once = (struct ev_once *)ev_malloc (sizeof (struct ev_once));
5083
5551
 
5084
- if (expect_false (!once))
5085
- {
5086
- cb (EV_ERROR | EV_READ | EV_WRITE | EV_TIMER, arg);
5087
- return;
5088
- }
5089
-
5090
5552
  once->cb = cb;
5091
5553
  once->arg = arg;
5092
5554
 
@@ -5225,4 +5687,3 @@ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) EV_NOEXCEPT
5225
5687
  #if EV_MULTIPLICITY
5226
5688
  #include "ev_wrap.h"
5227
5689
  #endif
5228
-