cool.io 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * libev event processing core, watcher management
3
3
  *
4
- * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
4
+ * Copyright (c) 2007,2008,2009,2010,2011,2012 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-
@@ -45,6 +45,12 @@
45
45
  # include "config.h"
46
46
  # endif
47
47
 
48
+ #if HAVE_FLOOR
49
+ # ifndef EV_USE_FLOOR
50
+ # define EV_USE_FLOOR 1
51
+ # endif
52
+ #endif
53
+
48
54
  # if HAVE_CLOCK_SYSCALL
49
55
  # ifndef EV_USE_CLOCK_SYSCALL
50
56
  # define EV_USE_CLOCK_SYSCALL 1
@@ -55,7 +61,7 @@
55
61
  # define EV_USE_MONOTONIC 1
56
62
  # endif
57
63
  # endif
58
- # elif !defined(EV_USE_CLOCK_SYSCALL)
64
+ # elif !defined EV_USE_CLOCK_SYSCALL
59
65
  # define EV_USE_CLOCK_SYSCALL 0
60
66
  # endif
61
67
 
@@ -158,7 +164,6 @@
158
164
 
159
165
  #endif
160
166
 
161
- #include <math.h>
162
167
  #include <stdlib.h>
163
168
  #include <string.h>
164
169
  #include <fcntl.h>
@@ -180,7 +185,16 @@
180
185
  # include "ev.h"
181
186
  #endif
182
187
 
183
- EV_CPP(extern "C" {)
188
+ #if EV_NO_THREADS
189
+ # undef EV_NO_SMP
190
+ # define EV_NO_SMP 1
191
+ # undef ECB_NO_THREADS
192
+ # define ECB_NO_THREADS 1
193
+ #endif
194
+ #if EV_NO_SMP
195
+ # undef EV_NO_SMP
196
+ # define ECB_NO_SMP 1
197
+ #endif
184
198
 
185
199
  #ifndef _WIN32
186
200
  # include <sys/time.h>
@@ -189,6 +203,7 @@ EV_CPP(extern "C" {)
189
203
  #else
190
204
  # include <io.h>
191
205
  # define WIN32_LEAN_AND_MEAN
206
+ # include <winsock2.h>
192
207
  # include <windows.h>
193
208
  # ifndef EV_SELECT_IS_WINSOCKET
194
209
  # define EV_SELECT_IS_WINSOCKET 1
@@ -207,25 +222,25 @@ EV_CPP(extern "C" {)
207
222
  /* this block tries to deduce configuration from header-defined symbols and defaults */
208
223
 
209
224
  /* try to deduce the maximum number of signals on this platform */
210
- #if defined (EV_NSIG)
225
+ #if defined EV_NSIG
211
226
  /* use what's provided */
212
- #elif defined (NSIG)
227
+ #elif defined NSIG
213
228
  # define EV_NSIG (NSIG)
214
- #elif defined(_NSIG)
229
+ #elif defined _NSIG
215
230
  # define EV_NSIG (_NSIG)
216
- #elif defined (SIGMAX)
231
+ #elif defined SIGMAX
217
232
  # define EV_NSIG (SIGMAX+1)
218
- #elif defined (SIG_MAX)
233
+ #elif defined SIG_MAX
219
234
  # define EV_NSIG (SIG_MAX+1)
220
- #elif defined (_SIG_MAX)
235
+ #elif defined _SIG_MAX
221
236
  # define EV_NSIG (_SIG_MAX+1)
222
- #elif defined (MAXSIG)
237
+ #elif defined MAXSIG
223
238
  # define EV_NSIG (MAXSIG+1)
224
- #elif defined (MAX_SIG)
239
+ #elif defined MAX_SIG
225
240
  # define EV_NSIG (MAX_SIG+1)
226
- #elif defined (SIGARRAYSIZE)
241
+ #elif defined SIGARRAYSIZE
227
242
  # define EV_NSIG (SIGARRAYSIZE) /* Assume ary[SIGARRAYSIZE] */
228
- #elif defined (_sys_nsig)
243
+ #elif defined _sys_nsig
229
244
  # define EV_NSIG (_sys_nsig) /* Solaris 2.5 */
230
245
  #else
231
246
  # error "unable to find value for NSIG, please report"
@@ -234,6 +249,10 @@ EV_CPP(extern "C" {)
234
249
  # define EV_NSIG 65
235
250
  #endif
236
251
 
252
+ #ifndef EV_USE_FLOOR
253
+ # define EV_USE_FLOOR 0
254
+ #endif
255
+
237
256
  #ifndef EV_USE_CLOCK_SYSCALL
238
257
  # if __linux && __GLIBC__ >= 2
239
258
  # define EV_USE_CLOCK_SYSCALL EV_FEATURE_OS
@@ -243,7 +262,7 @@ EV_CPP(extern "C" {)
243
262
  #endif
244
263
 
245
264
  #ifndef EV_USE_MONOTONIC
246
- # if defined (_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
265
+ # if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
247
266
  # define EV_USE_MONOTONIC EV_FEATURE_OS
248
267
  # else
249
268
  # define EV_USE_MONOTONIC 0
@@ -340,10 +359,26 @@ EV_CPP(extern "C" {)
340
359
  # define EV_HEAP_CACHE_AT EV_FEATURE_DATA
341
360
  #endif
342
361
 
362
+ #ifdef ANDROID
363
+ /* supposedly, android doesn't typedef fd_mask */
364
+ # undef EV_USE_SELECT
365
+ # define EV_USE_SELECT 0
366
+ /* supposedly, we need to include syscall.h, not sys/syscall.h, so just disable */
367
+ # undef EV_USE_CLOCK_SYSCALL
368
+ # define EV_USE_CLOCK_SYSCALL 0
369
+ #endif
370
+
371
+ /* aix's poll.h seems to cause lots of trouble */
372
+ #ifdef _AIX
373
+ /* AIX has a completely broken poll.h header */
374
+ # undef EV_USE_POLL
375
+ # define EV_USE_POLL 0
376
+ #endif
377
+
343
378
  /* on linux, we can use a (slow) syscall to avoid a dependency on pthread, */
344
379
  /* which makes programs even slower. might work on other unices, too. */
345
380
  #if EV_USE_CLOCK_SYSCALL
346
- # include <syscall.h>
381
+ # include <sys/syscall.h>
347
382
  # ifdef SYS_clock_gettime
348
383
  # define clock_gettime(id, ts) syscall (SYS_clock_gettime, (id), (ts))
349
384
  # undef EV_USE_MONOTONIC
@@ -356,12 +391,6 @@ EV_CPP(extern "C" {)
356
391
 
357
392
  /* this block fixes any misconfiguration where we know we run into trouble otherwise */
358
393
 
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
394
  #ifndef CLOCK_MONOTONIC
366
395
  # undef EV_USE_MONOTONIC
367
396
  # define EV_USE_MONOTONIC 0
@@ -379,7 +408,7 @@ EV_CPP(extern "C" {)
379
408
 
380
409
  #if !EV_USE_NANOSLEEP
381
410
  /* hp-ux has it in sys/time.h, which we unconditionally include above */
382
- # if !defined(_WIN32) && !defined(__hpux)
411
+ # if !defined _WIN32 && !defined __hpux
383
412
  # include <sys/select.h>
384
413
  # endif
385
414
  #endif
@@ -394,10 +423,6 @@ EV_CPP(extern "C" {)
394
423
  # endif
395
424
  #endif
396
425
 
397
- #if EV_SELECT_IS_WINSOCKET
398
- # include <winsock.h>
399
- #endif
400
-
401
426
  #if EV_USE_EVENTFD
402
427
  /* our minimum requirement is glibc 2.7 which has the stub, but not the header */
403
428
  # include <stdint.h>
@@ -445,14 +470,11 @@ struct signalfd_siginfo
445
470
  #endif
446
471
 
447
472
  /*
448
- * This is used to avoid floating point rounding problems.
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.
473
+ * This is used to work around floating point rounding problems.
452
474
  * This value is good at least till the year 4000.
453
- * Better solutions welcome.
454
475
  */
455
- #define TIME_EPSILON 0.0001220703125 /* 1/8192 */
476
+ #define MIN_INTERVAL 0.0001220703125 /* 1/2**13, good till 4000 */
477
+ /*#define MIN_INTERVAL 0.00000095367431640625 /* 1/2**20, good till 2200 */
456
478
 
457
479
  #define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */
458
480
  #define MAX_BLOCKTIME 59.743 /* never wait longer than this time (to detect time jumps) */
@@ -460,23 +482,758 @@ struct signalfd_siginfo
460
482
  #define EV_TV_SET(tv,t) do { tv.tv_sec = (long)t; tv.tv_usec = (long)((t - tv.tv_sec) * 1e6); } while (0)
461
483
  #define EV_TS_SET(ts,t) do { ts.tv_sec = (long)t; ts.tv_nsec = (long)((t - ts.tv_sec) * 1e9); } while (0)
462
484
 
463
- #if __GNUC__ >= 4
464
- # define expect(expr,value) __builtin_expect ((expr),(value))
465
- # define noinline __attribute__ ((noinline))
485
+ /* the following is ecb.h embedded into libev - use update_ev_c to update from an external copy */
486
+ /* ECB.H BEGIN */
487
+ /*
488
+ * libecb - http://software.schmorp.de/pkg/libecb
489
+ *
490
+ * Copyright (©) 2009-2012 Marc Alexander Lehmann <libecb@schmorp.de>
491
+ * Copyright (©) 2011 Emanuele Giaquinta
492
+ * All rights reserved.
493
+ *
494
+ * Redistribution and use in source and binary forms, with or without modifica-
495
+ * tion, are permitted provided that the following conditions are met:
496
+ *
497
+ * 1. Redistributions of source code must retain the above copyright notice,
498
+ * this list of conditions and the following disclaimer.
499
+ *
500
+ * 2. Redistributions in binary form must reproduce the above copyright
501
+ * notice, this list of conditions and the following disclaimer in the
502
+ * documentation and/or other materials provided with the distribution.
503
+ *
504
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
505
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
506
+ * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
507
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
508
+ * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
509
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
510
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
511
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
512
+ * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
513
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
514
+ */
515
+
516
+ #ifndef ECB_H
517
+ #define ECB_H
518
+
519
+ /* 16 bits major, 16 bits minor */
520
+ #define ECB_VERSION 0x00010003
521
+
522
+ #ifdef _WIN32
523
+ typedef signed char int8_t;
524
+ typedef unsigned char uint8_t;
525
+ typedef signed short int16_t;
526
+ typedef unsigned short uint16_t;
527
+ typedef signed int int32_t;
528
+ typedef unsigned int uint32_t;
529
+ #if __GNUC__
530
+ typedef signed long long int64_t;
531
+ typedef unsigned long long uint64_t;
532
+ #else /* _MSC_VER || __BORLANDC__ */
533
+ typedef signed __int64 int64_t;
534
+ typedef unsigned __int64 uint64_t;
535
+ #endif
536
+ #ifdef _WIN64
537
+ #define ECB_PTRSIZE 8
538
+ typedef uint64_t uintptr_t;
539
+ typedef int64_t intptr_t;
540
+ #else
541
+ #define ECB_PTRSIZE 4
542
+ typedef uint32_t uintptr_t;
543
+ typedef int32_t intptr_t;
544
+ #endif
466
545
  #else
467
- # define expect(expr,value) (expr)
468
- # define noinline
469
- # if __STDC_VERSION__ < 199901L && __GNUC__ < 2
470
- # define inline
471
- # endif
546
+ #include <inttypes.h>
547
+ #if UINTMAX_MAX > 0xffffffffU
548
+ #define ECB_PTRSIZE 8
549
+ #else
550
+ #define ECB_PTRSIZE 4
551
+ #endif
552
+ #endif
553
+
554
+ /* work around x32 idiocy by defining proper macros */
555
+ #if __x86_64 || _M_AMD64
556
+ #if __ILP32
557
+ #define ECB_AMD64_X32 1
558
+ #else
559
+ #define ECB_AMD64 1
560
+ #endif
561
+ #endif
562
+
563
+ /* many compilers define _GNUC_ to some versions but then only implement
564
+ * what their idiot authors think are the "more important" extensions,
565
+ * causing enormous grief in return for some better fake benchmark numbers.
566
+ * or so.
567
+ * we try to detect these and simply assume they are not gcc - if they have
568
+ * an issue with that they should have done it right in the first place.
569
+ */
570
+ #ifndef ECB_GCC_VERSION
571
+ #if !defined __GNUC_MINOR__ || defined __INTEL_COMPILER || defined __SUNPRO_C || defined __SUNPRO_CC || defined __llvm__ || defined __clang__
572
+ #define ECB_GCC_VERSION(major,minor) 0
573
+ #else
574
+ #define ECB_GCC_VERSION(major,minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
575
+ #endif
576
+ #endif
577
+
578
+ #define ECB_C (__STDC__+0) /* this assumes that __STDC__ is either empty or a number */
579
+ #define ECB_C99 (__STDC_VERSION__ >= 199901L)
580
+ #define ECB_C11 (__STDC_VERSION__ >= 201112L)
581
+ #define ECB_CPP (__cplusplus+0)
582
+ #define ECB_CPP11 (__cplusplus >= 201103L)
583
+
584
+ #if ECB_CPP
585
+ #define ECB_EXTERN_C extern "C"
586
+ #define ECB_EXTERN_C_BEG ECB_EXTERN_C {
587
+ #define ECB_EXTERN_C_END }
588
+ #else
589
+ #define ECB_EXTERN_C extern
590
+ #define ECB_EXTERN_C_BEG
591
+ #define ECB_EXTERN_C_END
592
+ #endif
593
+
594
+ /*****************************************************************************/
595
+
596
+ /* ECB_NO_THREADS - ecb is not used by multiple threads, ever */
597
+ /* ECB_NO_SMP - ecb might be used in multiple threads, but only on a single cpu */
598
+
599
+ #if ECB_NO_THREADS
600
+ #define ECB_NO_SMP 1
601
+ #endif
602
+
603
+ #if ECB_NO_SMP
604
+ #define ECB_MEMORY_FENCE do { } while (0)
605
+ #endif
606
+
607
+ #ifndef ECB_MEMORY_FENCE
608
+ #if ECB_GCC_VERSION(2,5) || defined __INTEL_COMPILER || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
609
+ #if __i386 || __i386__
610
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory")
611
+ #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory")
612
+ #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
613
+ #elif __amd64 || __amd64__ || __x86_64 || __x86_64__
614
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mfence" : : : "memory")
615
+ #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory")
616
+ #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
617
+ #elif __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__
618
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("sync" : : : "memory")
619
+ #elif defined __ARM_ARCH_6__ || defined __ARM_ARCH_6J__ \
620
+ || defined __ARM_ARCH_6K__ || defined __ARM_ARCH_6ZK__
621
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mcr p15,0,%0,c7,c10,5" : : "r" (0) : "memory")
622
+ #elif defined __ARM_ARCH_7__ || defined __ARM_ARCH_7A__ \
623
+ || defined __ARM_ARCH_7M__ || defined __ARM_ARCH_7R__
624
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("dmb" : : : "memory")
625
+ #elif __sparc || __sparc__
626
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad | #StoreStore | #StoreLoad" : : : "memory")
627
+ #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad" : : : "memory")
628
+ #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("membar #LoadStore | #StoreStore")
629
+ #elif defined __s390__ || defined __s390x__
630
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("bcr 15,0" : : : "memory")
631
+ #elif defined __mips__
632
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("sync" : : : "memory")
633
+ #elif defined __alpha__
634
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mb" : : : "memory")
635
+ #elif defined __hppa__
636
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("" : : : "memory")
637
+ #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
638
+ #elif defined __ia64__
639
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mf" : : : "memory")
640
+ #endif
641
+ #endif
642
+ #endif
643
+
644
+ #ifndef ECB_MEMORY_FENCE
645
+ #if ECB_GCC_VERSION(4,7)
646
+ /* see comment below (stdatomic.h) about the C11 memory model. */
647
+ #define ECB_MEMORY_FENCE __atomic_thread_fence (__ATOMIC_SEQ_CST)
648
+
649
+ /* The __has_feature syntax from clang is so misdesigned that we cannot use it
650
+ * without risking compile time errors with other compilers. We *could*
651
+ * define our own ecb_clang_has_feature, but I just can't be bothered to work
652
+ * around this shit time and again.
653
+ * #elif defined __clang && __has_feature (cxx_atomic)
654
+ * // see comment below (stdatomic.h) about the C11 memory model.
655
+ * #define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST)
656
+ */
657
+
658
+ #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__
659
+ #define ECB_MEMORY_FENCE __sync_synchronize ()
660
+ #elif _MSC_VER >= 1400 /* VC++ 2005 */
661
+ #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier)
662
+ #define ECB_MEMORY_FENCE _ReadWriteBarrier ()
663
+ #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier () /* according to msdn, _ReadBarrier is not a load fence */
664
+ #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier ()
665
+ #elif defined _WIN32
666
+ #include <WinNT.h>
667
+ #define ECB_MEMORY_FENCE MemoryBarrier () /* actually just xchg on x86... scary */
668
+ #elif __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
669
+ #include <mbarrier.h>
670
+ #define ECB_MEMORY_FENCE __machine_rw_barrier ()
671
+ #define ECB_MEMORY_FENCE_ACQUIRE __machine_r_barrier ()
672
+ #define ECB_MEMORY_FENCE_RELEASE __machine_w_barrier ()
673
+ #elif __xlC__
674
+ #define ECB_MEMORY_FENCE __sync ()
675
+ #endif
676
+ #endif
677
+
678
+ #ifndef ECB_MEMORY_FENCE
679
+ #if ECB_C11 && !defined __STDC_NO_ATOMICS__
680
+ /* we assume that these memory fences work on all variables/all memory accesses, */
681
+ /* not just C11 atomics and atomic accesses */
682
+ #include <stdatomic.h>
683
+ /* Unfortunately, neither gcc 4.7 nor clang 3.1 generate any instructions for */
684
+ /* any fence other than seq_cst, which isn't very efficient for us. */
685
+ /* Why that is, we don't know - either the C11 memory model is quite useless */
686
+ /* for most usages, or gcc and clang have a bug */
687
+ /* I *currently* lean towards the latter, and inefficiently implement */
688
+ /* all three of ecb's fences as a seq_cst fence */
689
+ #define ECB_MEMORY_FENCE atomic_thread_fence (memory_order_seq_cst)
690
+ #endif
691
+ #endif
692
+
693
+ #ifndef ECB_MEMORY_FENCE
694
+ #if !ECB_AVOID_PTHREADS
695
+ /*
696
+ * if you get undefined symbol references to pthread_mutex_lock,
697
+ * or failure to find pthread.h, then you should implement
698
+ * the ECB_MEMORY_FENCE operations for your cpu/compiler
699
+ * OR provide pthread.h and link against the posix thread library
700
+ * of your system.
701
+ */
702
+ #include <pthread.h>
703
+ #define ECB_NEEDS_PTHREADS 1
704
+ #define ECB_MEMORY_FENCE_NEEDS_PTHREADS 1
705
+
706
+ static pthread_mutex_t ecb_mf_lock = PTHREAD_MUTEX_INITIALIZER;
707
+ #define ECB_MEMORY_FENCE do { pthread_mutex_lock (&ecb_mf_lock); pthread_mutex_unlock (&ecb_mf_lock); } while (0)
708
+ #endif
709
+ #endif
710
+
711
+ #if !defined ECB_MEMORY_FENCE_ACQUIRE && defined ECB_MEMORY_FENCE
712
+ #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE
713
+ #endif
714
+
715
+ #if !defined ECB_MEMORY_FENCE_RELEASE && defined ECB_MEMORY_FENCE
716
+ #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE
717
+ #endif
718
+
719
+ /*****************************************************************************/
720
+
721
+ #if __cplusplus
722
+ #define ecb_inline static inline
723
+ #elif ECB_GCC_VERSION(2,5)
724
+ #define ecb_inline static __inline__
725
+ #elif ECB_C99
726
+ #define ecb_inline static inline
727
+ #else
728
+ #define ecb_inline static
729
+ #endif
730
+
731
+ #if ECB_GCC_VERSION(3,3)
732
+ #define ecb_restrict __restrict__
733
+ #elif ECB_C99
734
+ #define ecb_restrict restrict
735
+ #else
736
+ #define ecb_restrict
737
+ #endif
738
+
739
+ typedef int ecb_bool;
740
+
741
+ #define ECB_CONCAT_(a, b) a ## b
742
+ #define ECB_CONCAT(a, b) ECB_CONCAT_(a, b)
743
+ #define ECB_STRINGIFY_(a) # a
744
+ #define ECB_STRINGIFY(a) ECB_STRINGIFY_(a)
745
+
746
+ #define ecb_function_ ecb_inline
747
+
748
+ #if ECB_GCC_VERSION(3,1)
749
+ #define ecb_attribute(attrlist) __attribute__(attrlist)
750
+ #define ecb_is_constant(expr) __builtin_constant_p (expr)
751
+ #define ecb_expect(expr,value) __builtin_expect ((expr),(value))
752
+ #define ecb_prefetch(addr,rw,locality) __builtin_prefetch (addr, rw, locality)
753
+ #else
754
+ #define ecb_attribute(attrlist)
755
+ #define ecb_is_constant(expr) 0
756
+ #define ecb_expect(expr,value) (expr)
757
+ #define ecb_prefetch(addr,rw,locality)
758
+ #endif
759
+
760
+ /* no emulation for ecb_decltype */
761
+ #if ECB_GCC_VERSION(4,5)
762
+ #define ecb_decltype(x) __decltype(x)
763
+ #elif ECB_GCC_VERSION(3,0)
764
+ #define ecb_decltype(x) __typeof(x)
765
+ #endif
766
+
767
+ #define ecb_noinline ecb_attribute ((__noinline__))
768
+ #define ecb_unused ecb_attribute ((__unused__))
769
+ #define ecb_const ecb_attribute ((__const__))
770
+ #define ecb_pure ecb_attribute ((__pure__))
771
+
772
+ #if ECB_C11
773
+ #define ecb_noreturn _Noreturn
774
+ #else
775
+ #define ecb_noreturn ecb_attribute ((__noreturn__))
776
+ #endif
777
+
778
+ #if ECB_GCC_VERSION(4,3)
779
+ #define ecb_artificial ecb_attribute ((__artificial__))
780
+ #define ecb_hot ecb_attribute ((__hot__))
781
+ #define ecb_cold ecb_attribute ((__cold__))
782
+ #else
783
+ #define ecb_artificial
784
+ #define ecb_hot
785
+ #define ecb_cold
786
+ #endif
787
+
788
+ /* put around conditional expressions if you are very sure that the */
789
+ /* expression is mostly true or mostly false. note that these return */
790
+ /* booleans, not the expression. */
791
+ #define ecb_expect_false(expr) ecb_expect (!!(expr), 0)
792
+ #define ecb_expect_true(expr) ecb_expect (!!(expr), 1)
793
+ /* for compatibility to the rest of the world */
794
+ #define ecb_likely(expr) ecb_expect_true (expr)
795
+ #define ecb_unlikely(expr) ecb_expect_false (expr)
796
+
797
+ /* count trailing zero bits and count # of one bits */
798
+ #if ECB_GCC_VERSION(3,4)
799
+ /* we assume int == 32 bit, long == 32 or 64 bit and long long == 64 bit */
800
+ #define ecb_ld32(x) (__builtin_clz (x) ^ 31)
801
+ #define ecb_ld64(x) (__builtin_clzll (x) ^ 63)
802
+ #define ecb_ctz32(x) __builtin_ctz (x)
803
+ #define ecb_ctz64(x) __builtin_ctzll (x)
804
+ #define ecb_popcount32(x) __builtin_popcount (x)
805
+ /* no popcountll */
806
+ #else
807
+ ecb_function_ int ecb_ctz32 (uint32_t x) ecb_const;
808
+ ecb_function_ int
809
+ ecb_ctz32 (uint32_t x)
810
+ {
811
+ int r = 0;
812
+
813
+ x &= ~x + 1; /* this isolates the lowest bit */
814
+
815
+ #if ECB_branchless_on_i386
816
+ r += !!(x & 0xaaaaaaaa) << 0;
817
+ r += !!(x & 0xcccccccc) << 1;
818
+ r += !!(x & 0xf0f0f0f0) << 2;
819
+ r += !!(x & 0xff00ff00) << 3;
820
+ r += !!(x & 0xffff0000) << 4;
821
+ #else
822
+ if (x & 0xaaaaaaaa) r += 1;
823
+ if (x & 0xcccccccc) r += 2;
824
+ if (x & 0xf0f0f0f0) r += 4;
825
+ if (x & 0xff00ff00) r += 8;
826
+ if (x & 0xffff0000) r += 16;
827
+ #endif
828
+
829
+ return r;
830
+ }
831
+
832
+ ecb_function_ int ecb_ctz64 (uint64_t x) ecb_const;
833
+ ecb_function_ int
834
+ ecb_ctz64 (uint64_t x)
835
+ {
836
+ int shift = x & 0xffffffffU ? 0 : 32;
837
+ return ecb_ctz32 (x >> shift) + shift;
838
+ }
839
+
840
+ ecb_function_ int ecb_popcount32 (uint32_t x) ecb_const;
841
+ ecb_function_ int
842
+ ecb_popcount32 (uint32_t x)
843
+ {
844
+ x -= (x >> 1) & 0x55555555;
845
+ x = ((x >> 2) & 0x33333333) + (x & 0x33333333);
846
+ x = ((x >> 4) + x) & 0x0f0f0f0f;
847
+ x *= 0x01010101;
848
+
849
+ return x >> 24;
850
+ }
851
+
852
+ ecb_function_ int ecb_ld32 (uint32_t x) ecb_const;
853
+ ecb_function_ int ecb_ld32 (uint32_t x)
854
+ {
855
+ int r = 0;
856
+
857
+ if (x >> 16) { x >>= 16; r += 16; }
858
+ if (x >> 8) { x >>= 8; r += 8; }
859
+ if (x >> 4) { x >>= 4; r += 4; }
860
+ if (x >> 2) { x >>= 2; r += 2; }
861
+ if (x >> 1) { r += 1; }
862
+
863
+ return r;
864
+ }
865
+
866
+ ecb_function_ int ecb_ld64 (uint64_t x) ecb_const;
867
+ ecb_function_ int ecb_ld64 (uint64_t x)
868
+ {
869
+ int r = 0;
870
+
871
+ if (x >> 32) { x >>= 32; r += 32; }
872
+
873
+ return r + ecb_ld32 (x);
874
+ }
472
875
  #endif
473
876
 
474
- #define expect_false(expr) expect ((expr) != 0, 0)
475
- #define expect_true(expr) expect ((expr) != 0, 1)
476
- #define inline_size static inline
877
+ ecb_function_ ecb_bool ecb_is_pot32 (uint32_t x) ecb_const;
878
+ ecb_function_ ecb_bool ecb_is_pot32 (uint32_t x) { return !(x & (x - 1)); }
879
+ ecb_function_ ecb_bool ecb_is_pot64 (uint64_t x) ecb_const;
880
+ ecb_function_ ecb_bool ecb_is_pot64 (uint64_t x) { return !(x & (x - 1)); }
881
+
882
+ ecb_function_ uint8_t ecb_bitrev8 (uint8_t x) ecb_const;
883
+ ecb_function_ uint8_t ecb_bitrev8 (uint8_t x)
884
+ {
885
+ return ( (x * 0x0802U & 0x22110U)
886
+ | (x * 0x8020U & 0x88440U)) * 0x10101U >> 16;
887
+ }
888
+
889
+ ecb_function_ uint16_t ecb_bitrev16 (uint16_t x) ecb_const;
890
+ ecb_function_ uint16_t ecb_bitrev16 (uint16_t x)
891
+ {
892
+ x = ((x >> 1) & 0x5555) | ((x & 0x5555) << 1);
893
+ x = ((x >> 2) & 0x3333) | ((x & 0x3333) << 2);
894
+ x = ((x >> 4) & 0x0f0f) | ((x & 0x0f0f) << 4);
895
+ x = ( x >> 8 ) | ( x << 8);
896
+
897
+ return x;
898
+ }
899
+
900
+ ecb_function_ uint32_t ecb_bitrev32 (uint32_t x) ecb_const;
901
+ ecb_function_ uint32_t ecb_bitrev32 (uint32_t x)
902
+ {
903
+ x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1);
904
+ x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2);
905
+ x = ((x >> 4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) << 4);
906
+ x = ((x >> 8) & 0x00ff00ff) | ((x & 0x00ff00ff) << 8);
907
+ x = ( x >> 16 ) | ( x << 16);
908
+
909
+ return x;
910
+ }
911
+
912
+ /* popcount64 is only available on 64 bit cpus as gcc builtin */
913
+ /* so for this version we are lazy */
914
+ ecb_function_ int ecb_popcount64 (uint64_t x) ecb_const;
915
+ ecb_function_ int
916
+ ecb_popcount64 (uint64_t x)
917
+ {
918
+ return ecb_popcount32 (x) + ecb_popcount32 (x >> 32);
919
+ }
920
+
921
+ ecb_inline uint8_t ecb_rotl8 (uint8_t x, unsigned int count) ecb_const;
922
+ ecb_inline uint8_t ecb_rotr8 (uint8_t x, unsigned int count) ecb_const;
923
+ ecb_inline uint16_t ecb_rotl16 (uint16_t x, unsigned int count) ecb_const;
924
+ ecb_inline uint16_t ecb_rotr16 (uint16_t x, unsigned int count) ecb_const;
925
+ ecb_inline uint32_t ecb_rotl32 (uint32_t x, unsigned int count) ecb_const;
926
+ ecb_inline uint32_t ecb_rotr32 (uint32_t x, unsigned int count) ecb_const;
927
+ ecb_inline uint64_t ecb_rotl64 (uint64_t x, unsigned int count) ecb_const;
928
+ ecb_inline uint64_t ecb_rotr64 (uint64_t x, unsigned int count) ecb_const;
929
+
930
+ ecb_inline uint8_t ecb_rotl8 (uint8_t x, unsigned int count) { return (x >> ( 8 - count)) | (x << count); }
931
+ ecb_inline uint8_t ecb_rotr8 (uint8_t x, unsigned int count) { return (x << ( 8 - count)) | (x >> count); }
932
+ ecb_inline uint16_t ecb_rotl16 (uint16_t x, unsigned int count) { return (x >> (16 - count)) | (x << count); }
933
+ ecb_inline uint16_t ecb_rotr16 (uint16_t x, unsigned int count) { return (x << (16 - count)) | (x >> count); }
934
+ ecb_inline uint32_t ecb_rotl32 (uint32_t x, unsigned int count) { return (x >> (32 - count)) | (x << count); }
935
+ ecb_inline uint32_t ecb_rotr32 (uint32_t x, unsigned int count) { return (x << (32 - count)) | (x >> count); }
936
+ ecb_inline uint64_t ecb_rotl64 (uint64_t x, unsigned int count) { return (x >> (64 - count)) | (x << count); }
937
+ ecb_inline uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (64 - count)) | (x >> count); }
938
+
939
+ #if ECB_GCC_VERSION(4,3)
940
+ #define ecb_bswap16(x) (__builtin_bswap32 (x) >> 16)
941
+ #define ecb_bswap32(x) __builtin_bswap32 (x)
942
+ #define ecb_bswap64(x) __builtin_bswap64 (x)
943
+ #else
944
+ ecb_function_ uint16_t ecb_bswap16 (uint16_t x) ecb_const;
945
+ ecb_function_ uint16_t
946
+ ecb_bswap16 (uint16_t x)
947
+ {
948
+ return ecb_rotl16 (x, 8);
949
+ }
950
+
951
+ ecb_function_ uint32_t ecb_bswap32 (uint32_t x) ecb_const;
952
+ ecb_function_ uint32_t
953
+ ecb_bswap32 (uint32_t x)
954
+ {
955
+ return (((uint32_t)ecb_bswap16 (x)) << 16) | ecb_bswap16 (x >> 16);
956
+ }
957
+
958
+ ecb_function_ uint64_t ecb_bswap64 (uint64_t x) ecb_const;
959
+ ecb_function_ uint64_t
960
+ ecb_bswap64 (uint64_t x)
961
+ {
962
+ return (((uint64_t)ecb_bswap32 (x)) << 32) | ecb_bswap32 (x >> 32);
963
+ }
964
+ #endif
965
+
966
+ #if ECB_GCC_VERSION(4,5)
967
+ #define ecb_unreachable() __builtin_unreachable ()
968
+ #else
969
+ /* this seems to work fine, but gcc always emits a warning for it :/ */
970
+ ecb_inline void ecb_unreachable (void) ecb_noreturn;
971
+ ecb_inline void ecb_unreachable (void) { }
972
+ #endif
973
+
974
+ /* try to tell the compiler that some condition is definitely true */
975
+ #define ecb_assume(cond) if (!(cond)) ecb_unreachable (); else 0
976
+
977
+ ecb_inline unsigned char ecb_byteorder_helper (void) ecb_const;
978
+ ecb_inline unsigned char
979
+ ecb_byteorder_helper (void)
980
+ {
981
+ /* the union code still generates code under pressure in gcc, */
982
+ /* but less than using pointers, and always seems to */
983
+ /* successfully return a constant. */
984
+ /* the reason why we have this horrible preprocessor mess */
985
+ /* is to avoid it in all cases, at least on common architectures */
986
+ /* or when using a recent enough gcc version (>= 4.6) */
987
+ #if __i386 || __i386__ || _M_X86 || __amd64 || __amd64__ || _M_X64
988
+ return 0x44;
989
+ #elif __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
990
+ return 0x44;
991
+ #elif __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
992
+ return 0x11;
993
+ #else
994
+ union
995
+ {
996
+ uint32_t i;
997
+ uint8_t c;
998
+ } u = { 0x11223344 };
999
+ return u.c;
1000
+ #endif
1001
+ }
1002
+
1003
+ ecb_inline ecb_bool ecb_big_endian (void) ecb_const;
1004
+ ecb_inline ecb_bool ecb_big_endian (void) { return ecb_byteorder_helper () == 0x11; }
1005
+ ecb_inline ecb_bool ecb_little_endian (void) ecb_const;
1006
+ ecb_inline ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44; }
1007
+
1008
+ #if ECB_GCC_VERSION(3,0) || ECB_C99
1009
+ #define ecb_mod(m,n) ((m) % (n) + ((m) % (n) < 0 ? (n) : 0))
1010
+ #else
1011
+ #define ecb_mod(m,n) ((m) < 0 ? ((n) - 1 - ((-1 - (m)) % (n))) : ((m) % (n)))
1012
+ #endif
1013
+
1014
+ #if __cplusplus
1015
+ template<typename T>
1016
+ static inline T ecb_div_rd (T val, T div)
1017
+ {
1018
+ return val < 0 ? - ((-val + div - 1) / div) : (val ) / div;
1019
+ }
1020
+ template<typename T>
1021
+ static inline T ecb_div_ru (T val, T div)
1022
+ {
1023
+ return val < 0 ? - ((-val ) / div) : (val + div - 1) / div;
1024
+ }
1025
+ #else
1026
+ #define ecb_div_rd(val,div) ((val) < 0 ? - ((-(val) + (div) - 1) / (div)) : ((val) ) / (div))
1027
+ #define ecb_div_ru(val,div) ((val) < 0 ? - ((-(val) ) / (div)) : ((val) + (div) - 1) / (div))
1028
+ #endif
1029
+
1030
+ #if ecb_cplusplus_does_not_suck
1031
+ /* does not work for local types (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm) */
1032
+ template<typename T, int N>
1033
+ static inline int ecb_array_length (const T (&arr)[N])
1034
+ {
1035
+ return N;
1036
+ }
1037
+ #else
1038
+ #define ecb_array_length(name) (sizeof (name) / sizeof (name [0]))
1039
+ #endif
1040
+
1041
+ /*******************************************************************************/
1042
+ /* floating point stuff, can be disabled by defining ECB_NO_LIBM */
1043
+
1044
+ /* basically, everything uses "ieee pure-endian" floating point numbers */
1045
+ /* the only noteworthy exception is ancient armle, which uses order 43218765 */
1046
+ #if 0 \
1047
+ || __i386 || __i386__ \
1048
+ || __amd64 || __amd64__ || __x86_64 || __x86_64__ \
1049
+ || __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__ \
1050
+ || defined __arm__ && defined __ARM_EABI__ \
1051
+ || defined __s390__ || defined __s390x__ \
1052
+ || defined __mips__ \
1053
+ || defined __alpha__ \
1054
+ || defined __hppa__ \
1055
+ || defined __ia64__ \
1056
+ || defined _M_IX86 || defined _M_AMD64 || defined _M_IA64
1057
+ #define ECB_STDFP 1
1058
+ #include <string.h> /* for memcpy */
1059
+ #else
1060
+ #define ECB_STDFP 0
1061
+ #include <math.h> /* for frexp*, ldexp* */
1062
+ #endif
1063
+
1064
+ #ifndef ECB_NO_LIBM
1065
+
1066
+ /* convert a float to ieee single/binary32 */
1067
+ ecb_function_ uint32_t ecb_float_to_binary32 (float x) ecb_const;
1068
+ ecb_function_ uint32_t
1069
+ ecb_float_to_binary32 (float x)
1070
+ {
1071
+ uint32_t r;
1072
+
1073
+ #if ECB_STDFP
1074
+ memcpy (&r, &x, 4);
1075
+ #else
1076
+ /* slow emulation, works for anything but -0 */
1077
+ uint32_t m;
1078
+ int e;
1079
+
1080
+ if (x == 0e0f ) return 0x00000000U;
1081
+ if (x > +3.40282346638528860e+38f) return 0x7f800000U;
1082
+ if (x < -3.40282346638528860e+38f) return 0xff800000U;
1083
+ if (x != x ) return 0x7fbfffffU;
1084
+
1085
+ m = frexpf (x, &e) * 0x1000000U;
1086
+
1087
+ r = m & 0x80000000U;
1088
+
1089
+ if (r)
1090
+ m = -m;
1091
+
1092
+ if (e <= -126)
1093
+ {
1094
+ m &= 0xffffffU;
1095
+ m >>= (-125 - e);
1096
+ e = -126;
1097
+ }
1098
+
1099
+ r |= (e + 126) << 23;
1100
+ r |= m & 0x7fffffU;
1101
+ #endif
1102
+
1103
+ return r;
1104
+ }
1105
+
1106
+ /* converts an ieee single/binary32 to a float */
1107
+ ecb_function_ float ecb_binary32_to_float (uint32_t x) ecb_const;
1108
+ ecb_function_ float
1109
+ ecb_binary32_to_float (uint32_t x)
1110
+ {
1111
+ float r;
1112
+
1113
+ #if ECB_STDFP
1114
+ memcpy (&r, &x, 4);
1115
+ #else
1116
+ /* emulation, only works for normals and subnormals and +0 */
1117
+ int neg = x >> 31;
1118
+ int e = (x >> 23) & 0xffU;
1119
+
1120
+ x &= 0x7fffffU;
1121
+
1122
+ if (e)
1123
+ x |= 0x800000U;
1124
+ else
1125
+ e = 1;
1126
+
1127
+ /* we distrust ldexpf a bit and do the 2**-24 scaling by an extra multiply */
1128
+ r = ldexpf (x * (0.5f / 0x800000U), e - 126);
1129
+
1130
+ r = neg ? -r : r;
1131
+ #endif
1132
+
1133
+ return r;
1134
+ }
1135
+
1136
+ /* convert a double to ieee double/binary64 */
1137
+ ecb_function_ uint64_t ecb_double_to_binary64 (double x) ecb_const;
1138
+ ecb_function_ uint64_t
1139
+ ecb_double_to_binary64 (double x)
1140
+ {
1141
+ uint64_t r;
1142
+
1143
+ #if ECB_STDFP
1144
+ memcpy (&r, &x, 8);
1145
+ #else
1146
+ /* slow emulation, works for anything but -0 */
1147
+ uint64_t m;
1148
+ int e;
1149
+
1150
+ if (x == 0e0 ) return 0x0000000000000000U;
1151
+ if (x > +1.79769313486231470e+308) return 0x7ff0000000000000U;
1152
+ if (x < -1.79769313486231470e+308) return 0xfff0000000000000U;
1153
+ if (x != x ) return 0X7ff7ffffffffffffU;
1154
+
1155
+ m = frexp (x, &e) * 0x20000000000000U;
1156
+
1157
+ r = m & 0x8000000000000000;;
1158
+
1159
+ if (r)
1160
+ m = -m;
1161
+
1162
+ if (e <= -1022)
1163
+ {
1164
+ m &= 0x1fffffffffffffU;
1165
+ m >>= (-1021 - e);
1166
+ e = -1022;
1167
+ }
1168
+
1169
+ r |= ((uint64_t)(e + 1022)) << 52;
1170
+ r |= m & 0xfffffffffffffU;
1171
+ #endif
1172
+
1173
+ return r;
1174
+ }
1175
+
1176
+ /* converts an ieee double/binary64 to a double */
1177
+ ecb_function_ double ecb_binary64_to_double (uint64_t x) ecb_const;
1178
+ ecb_function_ double
1179
+ ecb_binary64_to_double (uint64_t x)
1180
+ {
1181
+ double r;
1182
+
1183
+ #if ECB_STDFP
1184
+ memcpy (&r, &x, 8);
1185
+ #else
1186
+ /* emulation, only works for normals and subnormals and +0 */
1187
+ int neg = x >> 63;
1188
+ int e = (x >> 52) & 0x7ffU;
1189
+
1190
+ x &= 0xfffffffffffffU;
1191
+
1192
+ if (e)
1193
+ x |= 0x10000000000000U;
1194
+ else
1195
+ e = 1;
1196
+
1197
+ /* we distrust ldexp a bit and do the 2**-53 scaling by an extra multiply */
1198
+ r = ldexp (x * (0.5 / 0x10000000000000U), e - 1022);
1199
+
1200
+ r = neg ? -r : r;
1201
+ #endif
1202
+
1203
+ return r;
1204
+ }
1205
+
1206
+ #endif
1207
+
1208
+ #endif
1209
+
1210
+ /* ECB.H END */
1211
+
1212
+ #if ECB_MEMORY_FENCE_NEEDS_PTHREADS
1213
+ /* if your architecture doesn't need memory fences, e.g. because it is
1214
+ * single-cpu/core, or if you use libev in a project that doesn't use libev
1215
+ * from multiple threads, then you can define ECB_AVOID_PTHREADS when compiling
1216
+ * libev, in which cases the memory fences become nops.
1217
+ * alternatively, you can remove this #error and link against libpthread,
1218
+ * which will then provide the memory fences.
1219
+ */
1220
+ # error "memory fences not defined for your architecture, please report"
1221
+ #endif
1222
+
1223
+ #ifndef ECB_MEMORY_FENCE
1224
+ # define ECB_MEMORY_FENCE do { } while (0)
1225
+ # define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE
1226
+ # define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE
1227
+ #endif
1228
+
1229
+ #define expect_false(cond) ecb_expect_false (cond)
1230
+ #define expect_true(cond) ecb_expect_true (cond)
1231
+ #define noinline ecb_noinline
1232
+
1233
+ #define inline_size ecb_inline
477
1234
 
478
1235
  #if EV_FEATURE_CODE
479
- # define inline_speed static inline
1236
+ # define inline_speed ecb_inline
480
1237
  #else
481
1238
  # define inline_speed static noinline
482
1239
  #endif
@@ -525,11 +1282,59 @@ static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work?
525
1282
 
526
1283
  /*****************************************************************************/
527
1284
 
1285
+ /* define a suitable floor function (only used by periodics atm) */
1286
+
1287
+ #if EV_USE_FLOOR
1288
+ # include <math.h>
1289
+ # define ev_floor(v) floor (v)
1290
+ #else
1291
+
1292
+ #include <float.h>
1293
+
1294
+ /* a floor() replacement function, should be independent of ev_tstamp type */
1295
+ static ev_tstamp noinline
1296
+ ev_floor (ev_tstamp v)
1297
+ {
1298
+ /* the choice of shift factor is not terribly important */
1299
+ #if FLT_RADIX != 2 /* assume FLT_RADIX == 10 */
1300
+ const ev_tstamp shift = sizeof (unsigned long) >= 8 ? 10000000000000000000. : 1000000000.;
1301
+ #else
1302
+ const ev_tstamp shift = sizeof (unsigned long) >= 8 ? 18446744073709551616. : 4294967296.;
1303
+ #endif
1304
+
1305
+ /* argument too large for an unsigned long? */
1306
+ if (expect_false (v >= shift))
1307
+ {
1308
+ ev_tstamp f;
1309
+
1310
+ if (v == v - 1.)
1311
+ return v; /* very large number */
1312
+
1313
+ f = shift * ev_floor (v * (1. / shift));
1314
+ return f + ev_floor (v - f);
1315
+ }
1316
+
1317
+ /* special treatment for negative args? */
1318
+ if (expect_false (v < 0.))
1319
+ {
1320
+ ev_tstamp f = -ev_floor (-v);
1321
+
1322
+ return f - (f == v ? 0 : 1);
1323
+ }
1324
+
1325
+ /* fits into an unsigned long */
1326
+ return (unsigned long)v;
1327
+ }
1328
+
1329
+ #endif
1330
+
1331
+ /*****************************************************************************/
1332
+
528
1333
  #ifdef __linux
529
1334
  # include <sys/utsname.h>
530
1335
  #endif
531
1336
 
532
- static unsigned int noinline
1337
+ static unsigned int noinline ecb_cold
533
1338
  ev_linux_version (void)
534
1339
  {
535
1340
  #ifdef __linux
@@ -568,22 +1373,22 @@ ev_linux_version (void)
568
1373
  /*****************************************************************************/
569
1374
 
570
1375
  #if EV_AVOID_STDIO
571
- static void noinline
1376
+ static void noinline ecb_cold
572
1377
  ev_printerr (const char *msg)
573
1378
  {
574
1379
  write (STDERR_FILENO, msg, strlen (msg));
575
1380
  }
576
1381
  #endif
577
1382
 
578
- static void (*syserr_cb)(const char *msg);
1383
+ static void (*syserr_cb)(const char *msg) EV_THROW;
579
1384
 
580
- void
581
- ev_set_syserr_cb (void (*cb)(const char *msg))
1385
+ void ecb_cold
1386
+ ev_set_syserr_cb (void (*cb)(const char *msg) EV_THROW) EV_THROW
582
1387
  {
583
1388
  syserr_cb = cb;
584
1389
  }
585
1390
 
586
- static void noinline
1391
+ static void noinline ecb_cold
587
1392
  ev_syserr (const char *msg)
588
1393
  {
589
1394
  if (!msg)
@@ -606,14 +1411,13 @@ ev_syserr (const char *msg)
606
1411
  }
607
1412
 
608
1413
  static void *
609
- ev_realloc_emul (void *ptr, long size)
1414
+ ev_realloc_emul (void *ptr, long size) EV_THROW
610
1415
  {
611
- #if __GLIBC__
612
- return realloc (ptr, size);
613
- #else
614
1416
  /* some systems, notably openbsd and darwin, fail to properly
615
1417
  * implement realloc (x, 0) (as required by both ansi c-89 and
616
1418
  * the single unix specification, so work around them here.
1419
+ * recently, also (at least) fedora and debian started breaking it,
1420
+ * despite documenting it otherwise.
617
1421
  */
618
1422
 
619
1423
  if (size)
@@ -621,13 +1425,12 @@ ev_realloc_emul (void *ptr, long size)
621
1425
 
622
1426
  free (ptr);
623
1427
  return 0;
624
- #endif
625
1428
  }
626
1429
 
627
- static void *(*alloc)(void *ptr, long size) = ev_realloc_emul;
1430
+ static void *(*alloc)(void *ptr, long size) EV_THROW = ev_realloc_emul;
628
1431
 
629
- void
630
- ev_set_allocator (void *(*cb)(void *ptr, long size))
1432
+ void ecb_cold
1433
+ ev_set_allocator (void *(*cb)(void *ptr, long size) EV_THROW) EV_THROW
631
1434
  {
632
1435
  alloc = cb;
633
1436
  }
@@ -725,11 +1528,11 @@ typedef struct
725
1528
  #include "ev_wrap.h"
726
1529
 
727
1530
  static struct ev_loop default_loop_struct;
728
- struct ev_loop *ev_default_loop_ptr;
1531
+ EV_API_DECL struct ev_loop *ev_default_loop_ptr = 0; /* needs to be initialised to make it a definition despite extern */
729
1532
 
730
1533
  #else
731
1534
 
732
- ev_tstamp ev_rt_now;
1535
+ EV_API_DECL ev_tstamp ev_rt_now = 0; /* needs to be initialised to make it a definition despite extern */
733
1536
  #define VAR(name,decl) static decl;
734
1537
  #include "ev_vars.h"
735
1538
  #undef VAR
@@ -754,7 +1557,7 @@ typedef struct
754
1557
 
755
1558
  #ifndef EV_HAVE_EV_TIME
756
1559
  ev_tstamp
757
- ev_time (void)
1560
+ ev_time (void) EV_THROW
758
1561
  {
759
1562
  #if EV_USE_REALTIME
760
1563
  if (expect_true (have_realtime))
@@ -788,14 +1591,14 @@ get_clock (void)
788
1591
 
789
1592
  #if EV_MULTIPLICITY
790
1593
  ev_tstamp
791
- ev_now (EV_P)
1594
+ ev_now (EV_P) EV_THROW
792
1595
  {
793
1596
  return ev_rt_now;
794
1597
  }
795
1598
  #endif
796
1599
 
797
1600
  void
798
- ev_sleep (ev_tstamp delay)
1601
+ ev_sleep (ev_tstamp delay) EV_THROW
799
1602
  {
800
1603
  if (delay > 0.)
801
1604
  {
@@ -804,7 +1607,7 @@ ev_sleep (ev_tstamp delay)
804
1607
 
805
1608
  EV_TS_SET (ts, delay);
806
1609
  nanosleep (&ts, 0);
807
- #elif defined(_WIN32)
1610
+ #elif defined _WIN32
808
1611
  Sleep ((unsigned long)(delay * 1e3));
809
1612
  #else
810
1613
  struct timeval tv;
@@ -818,14 +1621,6 @@ ev_sleep (ev_tstamp delay)
818
1621
  }
819
1622
  }
820
1623
 
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
1624
  /*****************************************************************************/
830
1625
 
831
1626
  #define MALLOC_ROUND 4096 /* prefer to allocate in chunks of this size, must be 2**n and >> 4 longs */
@@ -841,7 +1636,7 @@ array_nextsize (int elem, int cur, int cnt)
841
1636
  ncur <<= 1;
842
1637
  while (cnt > ncur);
843
1638
 
844
- /* if size is large, round to MALLOC_ROUND - 4 * longs to accomodate malloc overhead */
1639
+ /* if size is large, round to MALLOC_ROUND - 4 * longs to accommodate malloc overhead */
845
1640
  if (elem * ncur > MALLOC_ROUND - sizeof (void *) * 4)
846
1641
  {
847
1642
  ncur *= elem;
@@ -853,7 +1648,7 @@ array_nextsize (int elem, int cur, int cnt)
853
1648
  return ncur;
854
1649
  }
855
1650
 
856
- static noinline void *
1651
+ static void * noinline ecb_cold
857
1652
  array_realloc (int elem, void *base, int *cur, int cnt)
858
1653
  {
859
1654
  *cur = array_nextsize (elem, *cur, cnt);
@@ -866,7 +1661,7 @@ array_realloc (int elem, void *base, int *cur, int cnt)
866
1661
  #define array_needsize(type,base,cur,cnt,init) \
867
1662
  if (expect_false ((cnt) > (cur))) \
868
1663
  { \
869
- int ocur_ = (cur); \
1664
+ int ecb_unused ocur_ = (cur); \
870
1665
  (base) = (type *)array_realloc \
871
1666
  (sizeof (type), (base), &(cur), (cnt)); \
872
1667
  init ((base) + (ocur_), (cur) - ocur_); \
@@ -894,7 +1689,7 @@ pendingcb (EV_P_ ev_prepare *w, int revents)
894
1689
  }
895
1690
 
896
1691
  void noinline
897
- ev_feed_event (EV_P_ void *w, int revents)
1692
+ ev_feed_event (EV_P_ void *w, int revents) EV_THROW
898
1693
  {
899
1694
  W w_ = (W)w;
900
1695
  int pri = ABSPRI (w_);
@@ -908,6 +1703,8 @@ ev_feed_event (EV_P_ void *w, int revents)
908
1703
  pendings [pri][w_->pending - 1].w = w_;
909
1704
  pendings [pri][w_->pending - 1].events = revents;
910
1705
  }
1706
+
1707
+ pendingpri = NUMPRI - 1;
911
1708
  }
912
1709
 
913
1710
  inline_speed void
@@ -963,7 +1760,7 @@ fd_event (EV_P_ int fd, int revents)
963
1760
  }
964
1761
 
965
1762
  void
966
- ev_feed_fd_event (EV_P_ int fd, int revents)
1763
+ ev_feed_fd_event (EV_P_ int fd, int revents) EV_THROW
967
1764
  {
968
1765
  if (fd >= 0 && fd < anfdmax)
969
1766
  fd_event_nocheck (EV_A_ fd, revents);
@@ -982,7 +1779,7 @@ fd_reify (EV_P)
982
1779
  int fd = fdchanges [i];
983
1780
  ANFD *anfd = anfds + fd;
984
1781
 
985
- if (anfd->reify & EV__IOFDSET)
1782
+ if (anfd->reify & EV__IOFDSET && anfd->head)
986
1783
  {
987
1784
  SOCKET handle = EV_FD_TO_WIN32_HANDLE (fd);
988
1785
 
@@ -1046,7 +1843,7 @@ fd_change (EV_P_ int fd, int flags)
1046
1843
  }
1047
1844
 
1048
1845
  /* the given fd is invalid/unusable, so make sure it doesn't hurt us anymore */
1049
- inline_speed void
1846
+ inline_speed void ecb_cold
1050
1847
  fd_kill (EV_P_ int fd)
1051
1848
  {
1052
1849
  ev_io *w;
@@ -1059,7 +1856,7 @@ fd_kill (EV_P_ int fd)
1059
1856
  }
1060
1857
 
1061
1858
  /* check whether the given fd is actually valid, for error recovery */
1062
- inline_size int
1859
+ inline_size int ecb_cold
1063
1860
  fd_valid (int fd)
1064
1861
  {
1065
1862
  #ifdef _WIN32
@@ -1070,7 +1867,7 @@ fd_valid (int fd)
1070
1867
  }
1071
1868
 
1072
1869
  /* called on EBADF to verify fds */
1073
- static void noinline
1870
+ static void noinline ecb_cold
1074
1871
  fd_ebadf (EV_P)
1075
1872
  {
1076
1873
  int fd;
@@ -1082,7 +1879,7 @@ fd_ebadf (EV_P)
1082
1879
  }
1083
1880
 
1084
1881
  /* called on ENOMEM in select/poll to kill some fds and retry */
1085
- static void noinline
1882
+ static void noinline ecb_cold
1086
1883
  fd_enomem (EV_P)
1087
1884
  {
1088
1885
  int fd;
@@ -1287,62 +2084,94 @@ static ANSIG signals [EV_NSIG - 1];
1287
2084
 
1288
2085
  #if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
1289
2086
 
1290
- static void noinline
2087
+ static void noinline ecb_cold
1291
2088
  evpipe_init (EV_P)
1292
2089
  {
1293
2090
  if (!ev_is_active (&pipe_w))
1294
2091
  {
2092
+ int fds [2];
2093
+
1295
2094
  # if EV_USE_EVENTFD
1296
- evfd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
1297
- if (evfd < 0 && errno == EINVAL)
1298
- evfd = eventfd (0, 0);
2095
+ fds [0] = -1;
2096
+ fds [1] = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
2097
+ if (fds [1] < 0 && errno == EINVAL)
2098
+ fds [1] = eventfd (0, 0);
1299
2099
 
1300
- if (evfd >= 0)
2100
+ if (fds [1] < 0)
2101
+ # endif
1301
2102
  {
1302
- evpipe [0] = -1;
1303
- fd_intern (evfd); /* doing it twice doesn't hurt */
1304
- ev_io_set (&pipe_w, evfd, EV_READ);
2103
+ while (pipe (fds))
2104
+ ev_syserr ("(libev) error creating signal/async pipe");
2105
+
2106
+ fd_intern (fds [0]);
1305
2107
  }
2108
+
2109
+ fd_intern (fds [1]);
2110
+
2111
+ evpipe [0] = fds [0];
2112
+
2113
+ if (evpipe [1] < 0)
2114
+ evpipe [1] = fds [1]; /* first call, set write fd */
1306
2115
  else
1307
- # endif
1308
2116
  {
1309
- while (pipe (evpipe))
1310
- ev_syserr ("(libev) error creating signal/async pipe");
2117
+ /* on subsequent calls, do not change evpipe [1] */
2118
+ /* so that evpipe_write can always rely on its value. */
2119
+ /* this branch does not do anything sensible on windows, */
2120
+ /* so must not be executed on windows */
1311
2121
 
1312
- fd_intern (evpipe [0]);
1313
- fd_intern (evpipe [1]);
1314
- ev_io_set (&pipe_w, evpipe [0], EV_READ);
2122
+ dup2 (fds [1], evpipe [1]);
2123
+ close (fds [1]);
1315
2124
  }
1316
2125
 
2126
+ ev_io_set (&pipe_w, evpipe [0] < 0 ? evpipe [1] : evpipe [0], EV_READ);
1317
2127
  ev_io_start (EV_A_ &pipe_w);
1318
2128
  ev_unref (EV_A); /* watcher should not keep loop alive */
1319
2129
  }
1320
2130
  }
1321
2131
 
1322
- inline_size void
2132
+ inline_speed void
1323
2133
  evpipe_write (EV_P_ EV_ATOMIC_T *flag)
1324
2134
  {
1325
- if (!*flag)
2135
+ ECB_MEMORY_FENCE; /* push out the write before this function was called, acquire flag */
2136
+
2137
+ if (expect_true (*flag))
2138
+ return;
2139
+
2140
+ *flag = 1;
2141
+ ECB_MEMORY_FENCE_RELEASE; /* make sure flag is visible before the wakeup */
2142
+
2143
+ pipe_write_skipped = 1;
2144
+
2145
+ ECB_MEMORY_FENCE; /* make sure pipe_write_skipped is visible before we check pipe_write_wanted */
2146
+
2147
+ if (pipe_write_wanted)
1326
2148
  {
1327
- int old_errno = errno; /* save errno because write might clobber it */
1328
- char dummy;
2149
+ int old_errno;
2150
+
2151
+ pipe_write_skipped = 0;
2152
+ ECB_MEMORY_FENCE_RELEASE;
1329
2153
 
1330
- *flag = 1;
2154
+ old_errno = errno; /* save errno because write will clobber it */
1331
2155
 
1332
2156
  #if EV_USE_EVENTFD
1333
- if (evfd >= 0)
2157
+ if (evpipe [0] < 0)
1334
2158
  {
1335
2159
  uint64_t counter = 1;
1336
- write (evfd, &counter, sizeof (uint64_t));
2160
+ write (evpipe [1], &counter, sizeof (uint64_t));
1337
2161
  }
1338
2162
  else
1339
2163
  #endif
1340
- /* win32 people keep sending patches that change this write() to send() */
1341
- /* and then run away. but send() is wrong, it wants a socket handle on win32 */
1342
- /* so when you think this write should be a send instead, please find out */
1343
- /* where your send() is from - it's definitely not the microsoft send, and */
1344
- /* tell me. thank you. */
1345
- write (evpipe [1], &dummy, 1);
2164
+ {
2165
+ #ifdef _WIN32
2166
+ WSABUF buf;
2167
+ DWORD sent;
2168
+ buf.buf = &buf;
2169
+ buf.len = 1;
2170
+ WSASend (EV_FD_TO_WIN32_HANDLE (evpipe [1]), &buf, 1, &sent, 0, 0, 0);
2171
+ #else
2172
+ write (evpipe [1], &(evpipe [1]), 1);
2173
+ #endif
2174
+ }
1346
2175
 
1347
2176
  errno = old_errno;
1348
2177
  }
@@ -1355,25 +2184,42 @@ pipecb (EV_P_ ev_io *iow, int revents)
1355
2184
  {
1356
2185
  int i;
1357
2186
 
1358
- #if EV_USE_EVENTFD
1359
- if (evfd >= 0)
2187
+ if (revents & EV_READ)
1360
2188
  {
1361
- uint64_t counter;
1362
- read (evfd, &counter, sizeof (uint64_t));
1363
- }
1364
- else
2189
+ #if EV_USE_EVENTFD
2190
+ if (evpipe [0] < 0)
2191
+ {
2192
+ uint64_t counter;
2193
+ read (evpipe [1], &counter, sizeof (uint64_t));
2194
+ }
2195
+ else
1365
2196
  #endif
1366
- {
1367
- char dummy;
1368
- /* see discussion in evpipe_write when you think this read should be recv in win32 */
1369
- read (evpipe [0], &dummy, 1);
2197
+ {
2198
+ char dummy[4];
2199
+ #ifdef _WIN32
2200
+ WSABUF buf;
2201
+ DWORD recvd;
2202
+ DWORD flags = 0;
2203
+ buf.buf = dummy;
2204
+ buf.len = sizeof (dummy);
2205
+ WSARecv (EV_FD_TO_WIN32_HANDLE (evpipe [0]), &buf, 1, &recvd, &flags, 0, 0);
2206
+ #else
2207
+ read (evpipe [0], &dummy, sizeof (dummy));
2208
+ #endif
2209
+ }
1370
2210
  }
1371
2211
 
2212
+ pipe_write_skipped = 0;
2213
+
2214
+ ECB_MEMORY_FENCE; /* push out skipped, acquire flags */
2215
+
1372
2216
  #if EV_SIGNAL_ENABLE
1373
2217
  if (sig_pending)
1374
2218
  {
1375
2219
  sig_pending = 0;
1376
2220
 
2221
+ ECB_MEMORY_FENCE;
2222
+
1377
2223
  for (i = EV_NSIG - 1; i--; )
1378
2224
  if (expect_false (signals [i].pending))
1379
2225
  ev_feed_signal_event (EV_A_ i + 1);
@@ -1385,10 +2231,13 @@ pipecb (EV_P_ ev_io *iow, int revents)
1385
2231
  {
1386
2232
  async_pending = 0;
1387
2233
 
2234
+ ECB_MEMORY_FENCE;
2235
+
1388
2236
  for (i = asynccnt; i--; )
1389
2237
  if (asyncs [i]->sent)
1390
2238
  {
1391
2239
  asyncs [i]->sent = 0;
2240
+ ECB_MEMORY_FENCE_RELEASE;
1392
2241
  ev_feed_event (EV_A_ asyncs [i], EV_ASYNC);
1393
2242
  }
1394
2243
  }
@@ -1398,10 +2247,12 @@ pipecb (EV_P_ ev_io *iow, int revents)
1398
2247
  /*****************************************************************************/
1399
2248
 
1400
2249
  void
1401
- ev_feed_signal (int signum)
2250
+ ev_feed_signal (int signum) EV_THROW
1402
2251
  {
1403
2252
  #if EV_MULTIPLICITY
1404
- EV_P = signals [signum - 1].loop;
2253
+ EV_P;
2254
+ ECB_MEMORY_FENCE_ACQUIRE;
2255
+ EV_A = signals [signum - 1].loop;
1405
2256
 
1406
2257
  if (!EV_A)
1407
2258
  return;
@@ -1422,11 +2273,11 @@ ev_sighandler (int signum)
1422
2273
  }
1423
2274
 
1424
2275
  void noinline
1425
- ev_feed_signal_event (EV_P_ int signum)
2276
+ ev_feed_signal_event (EV_P_ int signum) EV_THROW
1426
2277
  {
1427
2278
  WL w;
1428
2279
 
1429
- if (expect_false (signum <= 0 || signum > EV_NSIG))
2280
+ if (expect_false (signum <= 0 || signum >= EV_NSIG))
1430
2281
  return;
1431
2282
 
1432
2283
  --signum;
@@ -1440,6 +2291,7 @@ ev_feed_signal_event (EV_P_ int signum)
1440
2291
  #endif
1441
2292
 
1442
2293
  signals [signum].pending = 0;
2294
+ ECB_MEMORY_FENCE_RELEASE;
1443
2295
 
1444
2296
  for (w = signals [signum].head; w; w = w->next)
1445
2297
  ev_feed_event (EV_A_ (W)w, EV_SIGNAL);
@@ -1547,20 +2399,20 @@ childcb (EV_P_ ev_signal *sw, int revents)
1547
2399
  # include "ev_select.c"
1548
2400
  #endif
1549
2401
 
1550
- int
1551
- ev_version_major (void)
2402
+ int ecb_cold
2403
+ ev_version_major (void) EV_THROW
1552
2404
  {
1553
2405
  return EV_VERSION_MAJOR;
1554
2406
  }
1555
2407
 
1556
- int
1557
- ev_version_minor (void)
2408
+ int ecb_cold
2409
+ ev_version_minor (void) EV_THROW
1558
2410
  {
1559
2411
  return EV_VERSION_MINOR;
1560
2412
  }
1561
2413
 
1562
2414
  /* return true if we are running with elevated privileges and should ignore env variables */
1563
- int inline_size
2415
+ int inline_size ecb_cold
1564
2416
  enable_secure (void)
1565
2417
  {
1566
2418
  #ifdef _WIN32
@@ -1571,8 +2423,8 @@ enable_secure (void)
1571
2423
  #endif
1572
2424
  }
1573
2425
 
1574
- unsigned int
1575
- ev_supported_backends (void)
2426
+ unsigned int ecb_cold
2427
+ ev_supported_backends (void) EV_THROW
1576
2428
  {
1577
2429
  unsigned int flags = 0;
1578
2430
 
@@ -1585,8 +2437,8 @@ ev_supported_backends (void)
1585
2437
  return flags;
1586
2438
  }
1587
2439
 
1588
- unsigned int
1589
- ev_recommended_backends (void)
2440
+ unsigned int ecb_cold
2441
+ ev_recommended_backends (void) EV_THROW
1590
2442
  {
1591
2443
  unsigned int flags = ev_supported_backends ();
1592
2444
 
@@ -1607,8 +2459,8 @@ ev_recommended_backends (void)
1607
2459
  return flags;
1608
2460
  }
1609
2461
 
1610
- unsigned int
1611
- ev_embeddable_backends (void)
2462
+ unsigned int ecb_cold
2463
+ ev_embeddable_backends (void) EV_THROW
1612
2464
  {
1613
2465
  int flags = EVBACKEND_EPOLL | EVBACKEND_KQUEUE | EVBACKEND_PORT;
1614
2466
 
@@ -1620,54 +2472,56 @@ ev_embeddable_backends (void)
1620
2472
  }
1621
2473
 
1622
2474
  unsigned int
1623
- ev_backend (EV_P)
2475
+ ev_backend (EV_P) EV_THROW
1624
2476
  {
1625
2477
  return backend;
1626
2478
  }
1627
2479
 
1628
2480
  #if EV_FEATURE_API
1629
2481
  unsigned int
1630
- ev_iteration (EV_P)
2482
+ ev_iteration (EV_P) EV_THROW
1631
2483
  {
1632
2484
  return loop_count;
1633
2485
  }
1634
2486
 
1635
2487
  unsigned int
1636
- ev_depth (EV_P)
2488
+ ev_depth (EV_P) EV_THROW
1637
2489
  {
1638
2490
  return loop_depth;
1639
2491
  }
1640
2492
 
1641
2493
  void
1642
- ev_set_io_collect_interval (EV_P_ ev_tstamp interval)
2494
+ ev_set_io_collect_interval (EV_P_ ev_tstamp interval) EV_THROW
1643
2495
  {
1644
2496
  io_blocktime = interval;
1645
2497
  }
1646
2498
 
1647
2499
  void
1648
- ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval)
2500
+ ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval) EV_THROW
1649
2501
  {
1650
2502
  timeout_blocktime = interval;
1651
2503
  }
1652
2504
 
1653
2505
  void
1654
- ev_set_userdata (EV_P_ void *data)
2506
+ ev_set_userdata (EV_P_ void *data) EV_THROW
1655
2507
  {
1656
2508
  userdata = data;
1657
2509
  }
1658
2510
 
1659
2511
  void *
1660
- ev_userdata (EV_P)
2512
+ ev_userdata (EV_P) EV_THROW
1661
2513
  {
1662
2514
  return userdata;
1663
2515
  }
1664
2516
 
1665
- void ev_set_invoke_pending_cb (EV_P_ void (*invoke_pending_cb)(EV_P))
2517
+ void
2518
+ ev_set_invoke_pending_cb (EV_P_ void (*invoke_pending_cb)(EV_P)) EV_THROW
1666
2519
  {
1667
2520
  invoke_cb = invoke_pending_cb;
1668
2521
  }
1669
2522
 
1670
- void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P), void (*acquire)(EV_P))
2523
+ void
2524
+ ev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_THROW, void (*acquire)(EV_P) EV_THROW) EV_THROW
1671
2525
  {
1672
2526
  release_cb = release;
1673
2527
  acquire_cb = acquire;
@@ -1675,8 +2529,8 @@ void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P), void (*acquire)(EV_P))
1675
2529
  #endif
1676
2530
 
1677
2531
  /* initialise a loop structure, must be zero-initialised */
1678
- static void noinline
1679
- loop_init (EV_P_ unsigned int flags)
2532
+ static void noinline ecb_cold
2533
+ loop_init (EV_P_ unsigned int flags) EV_THROW
1680
2534
  {
1681
2535
  if (!backend)
1682
2536
  {
@@ -1713,27 +2567,31 @@ loop_init (EV_P_ unsigned int flags)
1713
2567
  && getenv ("LIBEV_FLAGS"))
1714
2568
  flags = atoi (getenv ("LIBEV_FLAGS"));
1715
2569
 
1716
- ev_rt_now = ev_time ();
1717
- mn_now = get_clock ();
1718
- now_floor = mn_now;
1719
- rtmn_diff = ev_rt_now - mn_now;
2570
+ ev_rt_now = ev_time ();
2571
+ mn_now = get_clock ();
2572
+ now_floor = mn_now;
2573
+ rtmn_diff = ev_rt_now - mn_now;
1720
2574
  #if EV_FEATURE_API
1721
- invoke_cb = ev_invoke_pending;
2575
+ invoke_cb = ev_invoke_pending;
1722
2576
  #endif
1723
2577
 
1724
- io_blocktime = 0.;
1725
- timeout_blocktime = 0.;
1726
- backend = 0;
1727
- backend_fd = -1;
1728
- sig_pending = 0;
2578
+ io_blocktime = 0.;
2579
+ timeout_blocktime = 0.;
2580
+ backend = 0;
2581
+ backend_fd = -1;
2582
+ sig_pending = 0;
1729
2583
  #if EV_ASYNC_ENABLE
1730
- async_pending = 0;
2584
+ async_pending = 0;
1731
2585
  #endif
2586
+ pipe_write_skipped = 0;
2587
+ pipe_write_wanted = 0;
2588
+ evpipe [0] = -1;
2589
+ evpipe [1] = -1;
1732
2590
  #if EV_USE_INOTIFY
1733
- fs_fd = flags & EVFLAG_NOINOTIFY ? -1 : -2;
2591
+ fs_fd = flags & EVFLAG_NOINOTIFY ? -1 : -2;
1734
2592
  #endif
1735
2593
  #if EV_USE_SIGNALFD
1736
- sigfd = flags & EVFLAG_SIGNALFD ? -2 : -1;
2594
+ sigfd = flags & EVFLAG_SIGNALFD ? -2 : -1;
1737
2595
  #endif
1738
2596
 
1739
2597
  if (!(flags & EVBACKEND_MASK))
@@ -1768,7 +2626,7 @@ loop_init (EV_P_ unsigned int flags)
1768
2626
  }
1769
2627
 
1770
2628
  /* free up a loop structure */
1771
- void
2629
+ void ecb_cold
1772
2630
  ev_loop_destroy (EV_P)
1773
2631
  {
1774
2632
  int i;
@@ -1789,7 +2647,7 @@ ev_loop_destroy (EV_P)
1789
2647
  #endif
1790
2648
 
1791
2649
  #if EV_CHILD_ENABLE
1792
- if (ev_is_active (&childev))
2650
+ if (ev_is_default_loop (EV_A) && ev_is_active (&childev))
1793
2651
  {
1794
2652
  ev_ref (EV_A); /* child watcher */
1795
2653
  ev_signal_stop (EV_A_ &childev);
@@ -1801,16 +2659,8 @@ ev_loop_destroy (EV_P)
1801
2659
  /*ev_ref (EV_A);*/
1802
2660
  /*ev_io_stop (EV_A_ &pipe_w);*/
1803
2661
 
1804
- #if EV_USE_EVENTFD
1805
- if (evfd >= 0)
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
- }
2662
+ if (evpipe [0] >= 0) EV_WIN32_CLOSE_FD (evpipe [0]);
2663
+ if (evpipe [1] >= 0) EV_WIN32_CLOSE_FD (evpipe [1]);
1814
2664
  }
1815
2665
 
1816
2666
  #if EV_USE_SIGNALFD
@@ -1906,43 +2756,30 @@ loop_fork (EV_P)
1906
2756
  infy_fork (EV_A);
1907
2757
  #endif
1908
2758
 
2759
+ #if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
1909
2760
  if (ev_is_active (&pipe_w))
1910
2761
  {
1911
- /* this "locks" the handlers against writing to the pipe */
1912
- /* while we modify the fd vars */
1913
- sig_pending = 1;
1914
- #if EV_ASYNC_ENABLE
1915
- async_pending = 1;
1916
- #endif
2762
+ /* pipe_write_wanted must be false now, so modifying fd vars should be safe */
1917
2763
 
1918
2764
  ev_ref (EV_A);
1919
2765
  ev_io_stop (EV_A_ &pipe_w);
1920
2766
 
1921
- #if EV_USE_EVENTFD
1922
- if (evfd >= 0)
1923
- close (evfd);
1924
- #endif
1925
-
1926
2767
  if (evpipe [0] >= 0)
1927
- {
1928
- EV_WIN32_CLOSE_FD (evpipe [0]);
1929
- EV_WIN32_CLOSE_FD (evpipe [1]);
1930
- }
2768
+ EV_WIN32_CLOSE_FD (evpipe [0]);
1931
2769
 
1932
- #if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
1933
2770
  evpipe_init (EV_A);
1934
- /* now iterate over everything, in case we missed something */
1935
- pipecb (EV_A_ &pipe_w, EV_READ);
1936
- #endif
2771
+ /* iterate over everything, in case we missed something before */
2772
+ ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);
1937
2773
  }
2774
+ #endif
1938
2775
 
1939
2776
  postfork = 0;
1940
2777
  }
1941
2778
 
1942
2779
  #if EV_MULTIPLICITY
1943
2780
 
1944
- struct ev_loop *
1945
- ev_loop_new (unsigned int flags)
2781
+ struct ev_loop * ecb_cold
2782
+ ev_loop_new (unsigned int flags) EV_THROW
1946
2783
  {
1947
2784
  EV_P = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop));
1948
2785
 
@@ -1959,7 +2796,7 @@ ev_loop_new (unsigned int flags)
1959
2796
  #endif /* multiplicity */
1960
2797
 
1961
2798
  #if EV_VERIFY
1962
- static void noinline
2799
+ static void noinline ecb_cold
1963
2800
  verify_watcher (EV_P_ W w)
1964
2801
  {
1965
2802
  assert (("libev: watcher has invalid priority", ABSPRI (w) >= 0 && ABSPRI (w) < NUMPRI));
@@ -1968,7 +2805,7 @@ verify_watcher (EV_P_ W w)
1968
2805
  assert (("libev: pending watcher not on pending queue", pendings [ABSPRI (w)][w->pending - 1].w == w));
1969
2806
  }
1970
2807
 
1971
- static void noinline
2808
+ static void noinline ecb_cold
1972
2809
  verify_heap (EV_P_ ANHE *heap, int N)
1973
2810
  {
1974
2811
  int i;
@@ -1983,7 +2820,7 @@ verify_heap (EV_P_ ANHE *heap, int N)
1983
2820
  }
1984
2821
  }
1985
2822
 
1986
- static void noinline
2823
+ static void noinline ecb_cold
1987
2824
  array_verify (EV_P_ W *ws, int cnt)
1988
2825
  {
1989
2826
  while (cnt--)
@@ -1995,12 +2832,12 @@ array_verify (EV_P_ W *ws, int cnt)
1995
2832
  #endif
1996
2833
 
1997
2834
  #if EV_FEATURE_API
1998
- void
1999
- ev_verify (EV_P)
2835
+ void ecb_cold
2836
+ ev_verify (EV_P) EV_THROW
2000
2837
  {
2001
2838
  #if EV_VERIFY
2002
2839
  int i;
2003
- WL w;
2840
+ WL w, w2;
2004
2841
 
2005
2842
  assert (activecnt >= -1);
2006
2843
 
@@ -2010,12 +2847,23 @@ ev_verify (EV_P)
2010
2847
 
2011
2848
  assert (anfdmax >= 0);
2012
2849
  for (i = 0; i < anfdmax; ++i)
2013
- for (w = anfds [i].head; w; w = w->next)
2014
- {
2015
- verify_watcher (EV_A_ (W)w);
2016
- assert (("libev: inactive fd watcher on anfd list", ev_active (w) == 1));
2017
- assert (("libev: fd mismatch between watcher and anfd", ((ev_io *)w)->fd == i));
2018
- }
2850
+ {
2851
+ int j = 0;
2852
+
2853
+ for (w = w2 = anfds [i].head; w; w = w->next)
2854
+ {
2855
+ verify_watcher (EV_A_ (W)w);
2856
+
2857
+ if (j++ & 1)
2858
+ {
2859
+ assert (("libev: io watcher list contains a loop", w != w2));
2860
+ w2 = w2->next;
2861
+ }
2862
+
2863
+ assert (("libev: inactive fd watcher on anfd list", ev_active (w) == 1));
2864
+ assert (("libev: fd mismatch between watcher and anfd", ((ev_io *)w)->fd == i));
2865
+ }
2866
+ }
2019
2867
 
2020
2868
  assert (timermax >= timercnt);
2021
2869
  verify_heap (EV_A_ timers, timercnt);
@@ -2071,11 +2919,11 @@ ev_verify (EV_P)
2071
2919
  #endif
2072
2920
 
2073
2921
  #if EV_MULTIPLICITY
2074
- struct ev_loop *
2922
+ struct ev_loop * ecb_cold
2075
2923
  #else
2076
2924
  int
2077
2925
  #endif
2078
- ev_default_loop (unsigned int flags)
2926
+ ev_default_loop (unsigned int flags) EV_THROW
2079
2927
  {
2080
2928
  if (!ev_default_loop_ptr)
2081
2929
  {
@@ -2104,9 +2952,9 @@ ev_default_loop (unsigned int flags)
2104
2952
  }
2105
2953
 
2106
2954
  void
2107
- ev_loop_fork (EV_P)
2955
+ ev_loop_fork (EV_P) EV_THROW
2108
2956
  {
2109
- postfork = 1; /* must be in line with ev_default_fork */
2957
+ postfork = 1;
2110
2958
  }
2111
2959
 
2112
2960
  /*****************************************************************************/
@@ -2118,7 +2966,7 @@ ev_invoke (EV_P_ void *w, int revents)
2118
2966
  }
2119
2967
 
2120
2968
  unsigned int
2121
- ev_pending_count (EV_P)
2969
+ ev_pending_count (EV_P) EV_THROW
2122
2970
  {
2123
2971
  int pri;
2124
2972
  unsigned int count = 0;
@@ -2132,17 +2980,21 @@ ev_pending_count (EV_P)
2132
2980
  void noinline
2133
2981
  ev_invoke_pending (EV_P)
2134
2982
  {
2135
- int pri;
2983
+ pendingpri = NUMPRI;
2136
2984
 
2137
- for (pri = NUMPRI; pri--; )
2138
- while (pendingcnt [pri])
2139
- {
2140
- ANPENDING *p = pendings [pri] + --pendingcnt [pri];
2985
+ while (pendingpri) /* pendingpri possibly gets modified in the inner loop */
2986
+ {
2987
+ --pendingpri;
2141
2988
 
2142
- p->w->pending = 0;
2143
- EV_CB_INVOKE (p->w, p->events);
2144
- EV_FREQUENT_CHECK;
2145
- }
2989
+ while (pendingcnt [pendingpri])
2990
+ {
2991
+ ANPENDING *p = pendings [pendingpri] + --pendingcnt [pendingpri];
2992
+
2993
+ p->w->pending = 0;
2994
+ EV_CB_INVOKE (p->w, p->events);
2995
+ EV_FREQUENT_CHECK;
2996
+ }
2997
+ }
2146
2998
  }
2147
2999
 
2148
3000
  #if EV_IDLE_ENABLE
@@ -2210,12 +3062,28 @@ timers_reify (EV_P)
2210
3062
 
2211
3063
  #if EV_PERIODIC_ENABLE
2212
3064
 
2213
- inline_speed void
3065
+ static void noinline
2214
3066
  periodic_recalc (EV_P_ ev_periodic *w)
2215
3067
  {
2216
- /* TODO: use slow but potentially more correct incremental algo, */
2217
- /* also do not rely on ceil */
2218
- ev_at (w) = w->offset + ceil ((ev_rt_now - w->offset) / w->interval) * w->interval;
3068
+ ev_tstamp interval = w->interval > MIN_INTERVAL ? w->interval : MIN_INTERVAL;
3069
+ ev_tstamp at = w->offset + interval * ev_floor ((ev_rt_now - w->offset) / interval);
3070
+
3071
+ /* the above almost always errs on the low side */
3072
+ while (at <= ev_rt_now)
3073
+ {
3074
+ ev_tstamp nat = at + w->interval;
3075
+
3076
+ /* when resolution fails us, we use ev_rt_now */
3077
+ if (expect_false (nat == at))
3078
+ {
3079
+ at = ev_rt_now;
3080
+ break;
3081
+ }
3082
+
3083
+ at = nat;
3084
+ }
3085
+
3086
+ ev_at (w) = at;
2219
3087
  }
2220
3088
 
2221
3089
  /* make periodics pending */
@@ -2226,8 +3094,6 @@ periodics_reify (EV_P)
2226
3094
 
2227
3095
  while (periodiccnt && ANHE_at (periodics [HEAP0]) < ev_rt_now)
2228
3096
  {
2229
- int feed_count = 0;
2230
-
2231
3097
  do
2232
3098
  {
2233
3099
  ev_periodic *w = (ev_periodic *)ANHE_w (periodics [HEAP0]);
@@ -2247,20 +3113,6 @@ periodics_reify (EV_P)
2247
3113
  else if (w->interval)
2248
3114
  {
2249
3115
  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
3116
  ANHE_at_cache (periodics [HEAP0]);
2265
3117
  downheap (periodics, periodiccnt, HEAP0);
2266
3118
  }
@@ -2278,7 +3130,7 @@ periodics_reify (EV_P)
2278
3130
 
2279
3131
  /* simply recalculate all periodics */
2280
3132
  /* TODO: maybe ensure that at least one event happens when jumping forward? */
2281
- static void noinline
3133
+ static void noinline ecb_cold
2282
3134
  periodics_reschedule (EV_P)
2283
3135
  {
2284
3136
  int i;
@@ -2301,7 +3153,7 @@ periodics_reschedule (EV_P)
2301
3153
  #endif
2302
3154
 
2303
3155
  /* adjust all timers by a given offset */
2304
- static void noinline
3156
+ static void noinline ecb_cold
2305
3157
  timers_reschedule (EV_P_ ev_tstamp adjust)
2306
3158
  {
2307
3159
  int i;
@@ -2348,9 +3200,12 @@ time_update (EV_P_ ev_tstamp max_block)
2348
3200
  */
2349
3201
  for (i = 4; --i; )
2350
3202
  {
3203
+ ev_tstamp diff;
2351
3204
  rtmn_diff = ev_rt_now - mn_now;
2352
3205
 
2353
- if (expect_true (fabs (odiff - rtmn_diff) < MIN_TIMEJUMP))
3206
+ diff = odiff - rtmn_diff;
3207
+
3208
+ if (expect_true ((diff < 0. ? -diff : diff) < MIN_TIMEJUMP))
2354
3209
  return; /* all is well */
2355
3210
 
2356
3211
  ev_rt_now = ev_time ();
@@ -2382,7 +3237,7 @@ time_update (EV_P_ ev_tstamp max_block)
2382
3237
  }
2383
3238
  }
2384
3239
 
2385
- void
3240
+ int
2386
3241
  ev_run (EV_P_ int flags)
2387
3242
  {
2388
3243
  #if EV_FEATURE_API
@@ -2450,20 +3305,25 @@ ev_run (EV_P_ int flags)
2450
3305
  /* update time to cancel out callback processing overhead */
2451
3306
  time_update (EV_A_ 1e100);
2452
3307
 
2453
- if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt)))
3308
+ /* from now on, we want a pipe-wake-up */
3309
+ pipe_write_wanted = 1;
3310
+
3311
+ ECB_MEMORY_FENCE; /* make sure pipe_write_wanted is visible before we check for potential skips */
3312
+
3313
+ if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt || pipe_write_skipped)))
2454
3314
  {
2455
3315
  waittime = MAX_BLOCKTIME;
2456
3316
 
2457
3317
  if (timercnt)
2458
3318
  {
2459
- ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now + backend_fudge;
3319
+ ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now;
2460
3320
  if (waittime > to) waittime = to;
2461
3321
  }
2462
3322
 
2463
3323
  #if EV_PERIODIC_ENABLE
2464
3324
  if (periodiccnt)
2465
3325
  {
2466
- ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now + backend_fudge;
3326
+ ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now;
2467
3327
  if (waittime > to) waittime = to;
2468
3328
  }
2469
3329
  #endif
@@ -2472,13 +3332,18 @@ ev_run (EV_P_ int flags)
2472
3332
  if (expect_false (waittime < timeout_blocktime))
2473
3333
  waittime = timeout_blocktime;
2474
3334
 
3335
+ /* at this point, we NEED to wait, so we have to ensure */
3336
+ /* to pass a minimum nonzero value to the backend */
3337
+ if (expect_false (waittime < backend_mintime))
3338
+ waittime = backend_mintime;
3339
+
2475
3340
  /* extra check because io_blocktime is commonly 0 */
2476
3341
  if (expect_false (io_blocktime))
2477
3342
  {
2478
3343
  sleeptime = io_blocktime - (mn_now - prev_mn_now);
2479
3344
 
2480
- if (sleeptime > waittime - backend_fudge)
2481
- sleeptime = waittime - backend_fudge;
3345
+ if (sleeptime > waittime - backend_mintime)
3346
+ sleeptime = waittime - backend_mintime;
2482
3347
 
2483
3348
  if (expect_true (sleeptime > 0.))
2484
3349
  {
@@ -2495,6 +3360,16 @@ ev_run (EV_P_ int flags)
2495
3360
  backend_poll (EV_A_ waittime);
2496
3361
  assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */
2497
3362
 
3363
+ pipe_write_wanted = 0; /* just an optimisation, no fence needed */
3364
+
3365
+ ECB_MEMORY_FENCE_ACQUIRE;
3366
+ if (pipe_write_skipped)
3367
+ {
3368
+ assert (("libev: pipe_w not active, but pipe not written", ev_is_active (&pipe_w)));
3369
+ ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);
3370
+ }
3371
+
3372
+
2498
3373
  /* update ev_rt_now, do magic */
2499
3374
  time_update (EV_A_ waittime + sleeptime);
2500
3375
  }
@@ -2530,40 +3405,42 @@ ev_run (EV_P_ int flags)
2530
3405
  #if EV_FEATURE_API
2531
3406
  --loop_depth;
2532
3407
  #endif
3408
+
3409
+ return activecnt;
2533
3410
  }
2534
3411
 
2535
3412
  void
2536
- ev_break (EV_P_ int how)
3413
+ ev_break (EV_P_ int how) EV_THROW
2537
3414
  {
2538
3415
  loop_done = how;
2539
3416
  }
2540
3417
 
2541
3418
  void
2542
- ev_ref (EV_P)
3419
+ ev_ref (EV_P) EV_THROW
2543
3420
  {
2544
3421
  ++activecnt;
2545
3422
  }
2546
3423
 
2547
3424
  void
2548
- ev_unref (EV_P)
3425
+ ev_unref (EV_P) EV_THROW
2549
3426
  {
2550
3427
  --activecnt;
2551
3428
  }
2552
3429
 
2553
3430
  void
2554
- ev_now_update (EV_P)
3431
+ ev_now_update (EV_P) EV_THROW
2555
3432
  {
2556
3433
  time_update (EV_A_ 1e100);
2557
3434
  }
2558
3435
 
2559
3436
  void
2560
- ev_suspend (EV_P)
3437
+ ev_suspend (EV_P) EV_THROW
2561
3438
  {
2562
3439
  ev_now_update (EV_A);
2563
3440
  }
2564
3441
 
2565
3442
  void
2566
- ev_resume (EV_P)
3443
+ ev_resume (EV_P) EV_THROW
2567
3444
  {
2568
3445
  ev_tstamp mn_prev = mn_now;
2569
3446
 
@@ -2612,7 +3489,7 @@ clear_pending (EV_P_ W w)
2612
3489
  }
2613
3490
 
2614
3491
  int
2615
- ev_clear_pending (EV_P_ void *w)
3492
+ ev_clear_pending (EV_P_ void *w) EV_THROW
2616
3493
  {
2617
3494
  W w_ = (W)w;
2618
3495
  int pending = w_->pending;
@@ -2655,7 +3532,7 @@ ev_stop (EV_P_ W w)
2655
3532
  /*****************************************************************************/
2656
3533
 
2657
3534
  void noinline
2658
- ev_io_start (EV_P_ ev_io *w)
3535
+ ev_io_start (EV_P_ ev_io *w) EV_THROW
2659
3536
  {
2660
3537
  int fd = w->fd;
2661
3538
 
@@ -2671,6 +3548,9 @@ ev_io_start (EV_P_ ev_io *w)
2671
3548
  array_needsize (ANFD, anfds, anfdmax, fd + 1, array_init_zero);
2672
3549
  wlist_add (&anfds[fd].head, (WL)w);
2673
3550
 
3551
+ /* common bug, apparently */
3552
+ assert (("libev: ev_io_start called with corrupted watcher", ((WL)w)->next != (WL)w));
3553
+
2674
3554
  fd_change (EV_A_ fd, w->events & EV__IOFDSET | EV_ANFD_REIFY);
2675
3555
  w->events &= ~EV__IOFDSET;
2676
3556
 
@@ -2678,7 +3558,7 @@ ev_io_start (EV_P_ ev_io *w)
2678
3558
  }
2679
3559
 
2680
3560
  void noinline
2681
- ev_io_stop (EV_P_ ev_io *w)
3561
+ ev_io_stop (EV_P_ ev_io *w) EV_THROW
2682
3562
  {
2683
3563
  clear_pending (EV_A_ (W)w);
2684
3564
  if (expect_false (!ev_is_active (w)))
@@ -2697,7 +3577,7 @@ ev_io_stop (EV_P_ ev_io *w)
2697
3577
  }
2698
3578
 
2699
3579
  void noinline
2700
- ev_timer_start (EV_P_ ev_timer *w)
3580
+ ev_timer_start (EV_P_ ev_timer *w) EV_THROW
2701
3581
  {
2702
3582
  if (expect_false (ev_is_active (w)))
2703
3583
  return;
@@ -2721,7 +3601,7 @@ ev_timer_start (EV_P_ ev_timer *w)
2721
3601
  }
2722
3602
 
2723
3603
  void noinline
2724
- ev_timer_stop (EV_P_ ev_timer *w)
3604
+ ev_timer_stop (EV_P_ ev_timer *w) EV_THROW
2725
3605
  {
2726
3606
  clear_pending (EV_A_ (W)w);
2727
3607
  if (expect_false (!ev_is_active (w)))
@@ -2751,10 +3631,12 @@ ev_timer_stop (EV_P_ ev_timer *w)
2751
3631
  }
2752
3632
 
2753
3633
  void noinline
2754
- ev_timer_again (EV_P_ ev_timer *w)
3634
+ ev_timer_again (EV_P_ ev_timer *w) EV_THROW
2755
3635
  {
2756
3636
  EV_FREQUENT_CHECK;
2757
3637
 
3638
+ clear_pending (EV_A_ (W)w);
3639
+
2758
3640
  if (ev_is_active (w))
2759
3641
  {
2760
3642
  if (w->repeat)
@@ -2776,14 +3658,14 @@ ev_timer_again (EV_P_ ev_timer *w)
2776
3658
  }
2777
3659
 
2778
3660
  ev_tstamp
2779
- ev_timer_remaining (EV_P_ ev_timer *w)
3661
+ ev_timer_remaining (EV_P_ ev_timer *w) EV_THROW
2780
3662
  {
2781
3663
  return ev_at (w) - (ev_is_active (w) ? mn_now : 0.);
2782
3664
  }
2783
3665
 
2784
3666
  #if EV_PERIODIC_ENABLE
2785
3667
  void noinline
2786
- ev_periodic_start (EV_P_ ev_periodic *w)
3668
+ ev_periodic_start (EV_P_ ev_periodic *w) EV_THROW
2787
3669
  {
2788
3670
  if (expect_false (ev_is_active (w)))
2789
3671
  return;
@@ -2813,7 +3695,7 @@ ev_periodic_start (EV_P_ ev_periodic *w)
2813
3695
  }
2814
3696
 
2815
3697
  void noinline
2816
- ev_periodic_stop (EV_P_ ev_periodic *w)
3698
+ ev_periodic_stop (EV_P_ ev_periodic *w) EV_THROW
2817
3699
  {
2818
3700
  clear_pending (EV_A_ (W)w);
2819
3701
  if (expect_false (!ev_is_active (w)))
@@ -2841,7 +3723,7 @@ ev_periodic_stop (EV_P_ ev_periodic *w)
2841
3723
  }
2842
3724
 
2843
3725
  void noinline
2844
- ev_periodic_again (EV_P_ ev_periodic *w)
3726
+ ev_periodic_again (EV_P_ ev_periodic *w) EV_THROW
2845
3727
  {
2846
3728
  /* TODO: use adjustheap and recalculation */
2847
3729
  ev_periodic_stop (EV_A_ w);
@@ -2856,7 +3738,7 @@ ev_periodic_again (EV_P_ ev_periodic *w)
2856
3738
  #if EV_SIGNAL_ENABLE
2857
3739
 
2858
3740
  void noinline
2859
- ev_signal_start (EV_P_ ev_signal *w)
3741
+ ev_signal_start (EV_P_ ev_signal *w) EV_THROW
2860
3742
  {
2861
3743
  if (expect_false (ev_is_active (w)))
2862
3744
  return;
@@ -2868,6 +3750,7 @@ ev_signal_start (EV_P_ ev_signal *w)
2868
3750
  !signals [w->signum - 1].loop || signals [w->signum - 1].loop == loop));
2869
3751
 
2870
3752
  signals [w->signum - 1].loop = EV_A;
3753
+ ECB_MEMORY_FENCE_RELEASE;
2871
3754
  #endif
2872
3755
 
2873
3756
  EV_FREQUENT_CHECK;
@@ -2937,7 +3820,7 @@ ev_signal_start (EV_P_ ev_signal *w)
2937
3820
  }
2938
3821
 
2939
3822
  void noinline
2940
- ev_signal_stop (EV_P_ ev_signal *w)
3823
+ ev_signal_stop (EV_P_ ev_signal *w) EV_THROW
2941
3824
  {
2942
3825
  clear_pending (EV_A_ (W)w);
2943
3826
  if (expect_false (!ev_is_active (w)))
@@ -2978,7 +3861,7 @@ ev_signal_stop (EV_P_ ev_signal *w)
2978
3861
  #if EV_CHILD_ENABLE
2979
3862
 
2980
3863
  void
2981
- ev_child_start (EV_P_ ev_child *w)
3864
+ ev_child_start (EV_P_ ev_child *w) EV_THROW
2982
3865
  {
2983
3866
  #if EV_MULTIPLICITY
2984
3867
  assert (("libev: child watchers are only supported in the default loop", loop == ev_default_loop_ptr));
@@ -2995,7 +3878,7 @@ ev_child_start (EV_P_ ev_child *w)
2995
3878
  }
2996
3879
 
2997
3880
  void
2998
- ev_child_stop (EV_P_ ev_child *w)
3881
+ ev_child_stop (EV_P_ ev_child *w) EV_THROW
2999
3882
  {
3000
3883
  clear_pending (EV_A_ (W)w);
3001
3884
  if (expect_false (!ev_is_active (w)))
@@ -3032,7 +3915,10 @@ static void noinline stat_timer_cb (EV_P_ ev_timer *w_, int revents);
3032
3915
  static void noinline
3033
3916
  infy_add (EV_P_ ev_stat *w)
3034
3917
  {
3035
- w->wd = inotify_add_watch (fs_fd, w->path, IN_ATTRIB | IN_DELETE_SELF | IN_MOVE_SELF | IN_MODIFY | IN_DONT_FOLLOW | IN_MASK_ADD);
3918
+ w->wd = inotify_add_watch (fs_fd, w->path,
3919
+ IN_ATTRIB | IN_DELETE_SELF | IN_MOVE_SELF | IN_MODIFY
3920
+ | IN_CREATE | IN_DELETE | IN_MOVED_FROM | IN_MOVED_TO
3921
+ | IN_DONT_FOLLOW | IN_MASK_ADD);
3036
3922
 
3037
3923
  if (w->wd >= 0)
3038
3924
  {
@@ -3046,10 +3932,16 @@ infy_add (EV_P_ ev_stat *w)
3046
3932
  w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL;
3047
3933
  else if (!statfs (w->path, &sfs)
3048
3934
  && (sfs.f_type == 0x1373 /* devfs */
3935
+ || sfs.f_type == 0x4006 /* fat */
3936
+ || sfs.f_type == 0x4d44 /* msdos */
3049
3937
  || sfs.f_type == 0xEF53 /* ext2/3 */
3938
+ || sfs.f_type == 0x72b6 /* jffs2 */
3939
+ || sfs.f_type == 0x858458f6 /* ramfs */
3940
+ || sfs.f_type == 0x5346544e /* ntfs */
3050
3941
  || sfs.f_type == 0x3153464a /* jfs */
3942
+ || sfs.f_type == 0x9123683e /* btrfs */
3051
3943
  || sfs.f_type == 0x52654973 /* reiser3 */
3052
- || sfs.f_type == 0x01021994 /* tempfs */
3944
+ || sfs.f_type == 0x01021994 /* tmpfs */
3053
3945
  || sfs.f_type == 0x58465342 /* xfs */))
3054
3946
  w->timer.repeat = 0.; /* filesystem is local, kernel new enough */
3055
3947
  else
@@ -3157,7 +4049,7 @@ infy_cb (EV_P_ ev_io *w, int revents)
3157
4049
  }
3158
4050
  }
3159
4051
 
3160
- inline_size void
4052
+ inline_size void ecb_cold
3161
4053
  ev_check_2625 (EV_P)
3162
4054
  {
3163
4055
  /* kernels < 2.6.25 are borked
@@ -3172,7 +4064,7 @@ ev_check_2625 (EV_P)
3172
4064
  inline_size int
3173
4065
  infy_newfd (void)
3174
4066
  {
3175
- #if defined (IN_CLOEXEC) && defined (IN_NONBLOCK)
4067
+ #if defined IN_CLOEXEC && defined IN_NONBLOCK
3176
4068
  int fd = inotify_init1 (IN_CLOEXEC | IN_NONBLOCK);
3177
4069
  if (fd >= 0)
3178
4070
  return fd;
@@ -3257,7 +4149,7 @@ infy_fork (EV_P)
3257
4149
  #endif
3258
4150
 
3259
4151
  void
3260
- ev_stat_stat (EV_P_ ev_stat *w)
4152
+ ev_stat_stat (EV_P_ ev_stat *w) EV_THROW
3261
4153
  {
3262
4154
  if (lstat (w->path, &w->attr) < 0)
3263
4155
  w->attr.st_nlink = 0;
@@ -3306,7 +4198,7 @@ stat_timer_cb (EV_P_ ev_timer *w_, int revents)
3306
4198
  }
3307
4199
 
3308
4200
  void
3309
- ev_stat_start (EV_P_ ev_stat *w)
4201
+ ev_stat_start (EV_P_ ev_stat *w) EV_THROW
3310
4202
  {
3311
4203
  if (expect_false (ev_is_active (w)))
3312
4204
  return;
@@ -3337,7 +4229,7 @@ ev_stat_start (EV_P_ ev_stat *w)
3337
4229
  }
3338
4230
 
3339
4231
  void
3340
- ev_stat_stop (EV_P_ ev_stat *w)
4232
+ ev_stat_stop (EV_P_ ev_stat *w) EV_THROW
3341
4233
  {
3342
4234
  clear_pending (EV_A_ (W)w);
3343
4235
  if (expect_false (!ev_is_active (w)))
@@ -3363,7 +4255,7 @@ ev_stat_stop (EV_P_ ev_stat *w)
3363
4255
 
3364
4256
  #if EV_IDLE_ENABLE
3365
4257
  void
3366
- ev_idle_start (EV_P_ ev_idle *w)
4258
+ ev_idle_start (EV_P_ ev_idle *w) EV_THROW
3367
4259
  {
3368
4260
  if (expect_false (ev_is_active (w)))
3369
4261
  return;
@@ -3386,7 +4278,7 @@ ev_idle_start (EV_P_ ev_idle *w)
3386
4278
  }
3387
4279
 
3388
4280
  void
3389
- ev_idle_stop (EV_P_ ev_idle *w)
4281
+ ev_idle_stop (EV_P_ ev_idle *w) EV_THROW
3390
4282
  {
3391
4283
  clear_pending (EV_A_ (W)w);
3392
4284
  if (expect_false (!ev_is_active (w)))
@@ -3410,7 +4302,7 @@ ev_idle_stop (EV_P_ ev_idle *w)
3410
4302
 
3411
4303
  #if EV_PREPARE_ENABLE
3412
4304
  void
3413
- ev_prepare_start (EV_P_ ev_prepare *w)
4305
+ ev_prepare_start (EV_P_ ev_prepare *w) EV_THROW
3414
4306
  {
3415
4307
  if (expect_false (ev_is_active (w)))
3416
4308
  return;
@@ -3425,7 +4317,7 @@ ev_prepare_start (EV_P_ ev_prepare *w)
3425
4317
  }
3426
4318
 
3427
4319
  void
3428
- ev_prepare_stop (EV_P_ ev_prepare *w)
4320
+ ev_prepare_stop (EV_P_ ev_prepare *w) EV_THROW
3429
4321
  {
3430
4322
  clear_pending (EV_A_ (W)w);
3431
4323
  if (expect_false (!ev_is_active (w)))
@@ -3448,7 +4340,7 @@ ev_prepare_stop (EV_P_ ev_prepare *w)
3448
4340
 
3449
4341
  #if EV_CHECK_ENABLE
3450
4342
  void
3451
- ev_check_start (EV_P_ ev_check *w)
4343
+ ev_check_start (EV_P_ ev_check *w) EV_THROW
3452
4344
  {
3453
4345
  if (expect_false (ev_is_active (w)))
3454
4346
  return;
@@ -3463,7 +4355,7 @@ ev_check_start (EV_P_ ev_check *w)
3463
4355
  }
3464
4356
 
3465
4357
  void
3466
- ev_check_stop (EV_P_ ev_check *w)
4358
+ ev_check_stop (EV_P_ ev_check *w) EV_THROW
3467
4359
  {
3468
4360
  clear_pending (EV_A_ (W)w);
3469
4361
  if (expect_false (!ev_is_active (w)))
@@ -3486,7 +4378,7 @@ ev_check_stop (EV_P_ ev_check *w)
3486
4378
 
3487
4379
  #if EV_EMBED_ENABLE
3488
4380
  void noinline
3489
- ev_embed_sweep (EV_P_ ev_embed *w)
4381
+ ev_embed_sweep (EV_P_ ev_embed *w) EV_THROW
3490
4382
  {
3491
4383
  ev_run (w->other, EVRUN_NOWAIT);
3492
4384
  }
@@ -3544,7 +4436,7 @@ embed_idle_cb (EV_P_ ev_idle *idle, int revents)
3544
4436
  #endif
3545
4437
 
3546
4438
  void
3547
- ev_embed_start (EV_P_ ev_embed *w)
4439
+ ev_embed_start (EV_P_ ev_embed *w) EV_THROW
3548
4440
  {
3549
4441
  if (expect_false (ev_is_active (w)))
3550
4442
  return;
@@ -3575,7 +4467,7 @@ ev_embed_start (EV_P_ ev_embed *w)
3575
4467
  }
3576
4468
 
3577
4469
  void
3578
- ev_embed_stop (EV_P_ ev_embed *w)
4470
+ ev_embed_stop (EV_P_ ev_embed *w) EV_THROW
3579
4471
  {
3580
4472
  clear_pending (EV_A_ (W)w);
3581
4473
  if (expect_false (!ev_is_active (w)))
@@ -3595,7 +4487,7 @@ ev_embed_stop (EV_P_ ev_embed *w)
3595
4487
 
3596
4488
  #if EV_FORK_ENABLE
3597
4489
  void
3598
- ev_fork_start (EV_P_ ev_fork *w)
4490
+ ev_fork_start (EV_P_ ev_fork *w) EV_THROW
3599
4491
  {
3600
4492
  if (expect_false (ev_is_active (w)))
3601
4493
  return;
@@ -3610,7 +4502,7 @@ ev_fork_start (EV_P_ ev_fork *w)
3610
4502
  }
3611
4503
 
3612
4504
  void
3613
- ev_fork_stop (EV_P_ ev_fork *w)
4505
+ ev_fork_stop (EV_P_ ev_fork *w) EV_THROW
3614
4506
  {
3615
4507
  clear_pending (EV_A_ (W)w);
3616
4508
  if (expect_false (!ev_is_active (w)))
@@ -3633,7 +4525,7 @@ ev_fork_stop (EV_P_ ev_fork *w)
3633
4525
 
3634
4526
  #if EV_CLEANUP_ENABLE
3635
4527
  void
3636
- ev_cleanup_start (EV_P_ ev_cleanup *w)
4528
+ ev_cleanup_start (EV_P_ ev_cleanup *w) EV_THROW
3637
4529
  {
3638
4530
  if (expect_false (ev_is_active (w)))
3639
4531
  return;
@@ -3650,7 +4542,7 @@ ev_cleanup_start (EV_P_ ev_cleanup *w)
3650
4542
  }
3651
4543
 
3652
4544
  void
3653
- ev_cleanup_stop (EV_P_ ev_cleanup *w)
4545
+ ev_cleanup_stop (EV_P_ ev_cleanup *w) EV_THROW
3654
4546
  {
3655
4547
  clear_pending (EV_A_ (W)w);
3656
4548
  if (expect_false (!ev_is_active (w)))
@@ -3674,7 +4566,7 @@ ev_cleanup_stop (EV_P_ ev_cleanup *w)
3674
4566
 
3675
4567
  #if EV_ASYNC_ENABLE
3676
4568
  void
3677
- ev_async_start (EV_P_ ev_async *w)
4569
+ ev_async_start (EV_P_ ev_async *w) EV_THROW
3678
4570
  {
3679
4571
  if (expect_false (ev_is_active (w)))
3680
4572
  return;
@@ -3693,7 +4585,7 @@ ev_async_start (EV_P_ ev_async *w)
3693
4585
  }
3694
4586
 
3695
4587
  void
3696
- ev_async_stop (EV_P_ ev_async *w)
4588
+ ev_async_stop (EV_P_ ev_async *w) EV_THROW
3697
4589
  {
3698
4590
  clear_pending (EV_A_ (W)w);
3699
4591
  if (expect_false (!ev_is_active (w)))
@@ -3714,7 +4606,7 @@ ev_async_stop (EV_P_ ev_async *w)
3714
4606
  }
3715
4607
 
3716
4608
  void
3717
- ev_async_send (EV_P_ ev_async *w)
4609
+ ev_async_send (EV_P_ ev_async *w) EV_THROW
3718
4610
  {
3719
4611
  w->sent = 1;
3720
4612
  evpipe_write (EV_A_ &async_pending);
@@ -3761,7 +4653,7 @@ once_cb_to (EV_P_ ev_timer *w, int revents)
3761
4653
  }
3762
4654
 
3763
4655
  void
3764
- ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg)
4656
+ ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) EV_THROW
3765
4657
  {
3766
4658
  struct ev_once *once = (struct ev_once *)ev_malloc (sizeof (struct ev_once));
3767
4659
 
@@ -3792,8 +4684,8 @@ ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, vo
3792
4684
  /*****************************************************************************/
3793
4685
 
3794
4686
  #if EV_WALK_ENABLE
3795
- void
3796
- ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
4687
+ void ecb_cold
4688
+ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) EV_THROW
3797
4689
  {
3798
4690
  int i, j;
3799
4691
  ev_watcher_list *wl, *wn;
@@ -3846,7 +4738,7 @@ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
3846
4738
 
3847
4739
  #if EV_IDLE_ENABLE
3848
4740
  if (types & EV_IDLE)
3849
- for (j = NUMPRI; i--; )
4741
+ for (j = NUMPRI; j--; )
3850
4742
  for (i = idlecnt [j]; i--; )
3851
4743
  cb (EV_A_ EV_IDLE, idles [j][i]);
3852
4744
  #endif
@@ -3909,5 +4801,3 @@ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
3909
4801
  #include "ev_wrap.h"
3910
4802
  #endif
3911
4803
 
3912
- EV_CPP(})
3913
-