cool.io 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
-