nio4r 0.4.6 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 44e9badbf0722bce4a3d7b1ddd3453b1fd850201
4
- data.tar.gz: ced65bb66863f948af9ce5b90233c252511b8627
3
+ metadata.gz: 3f003ce03885c6b5029c3adac1440958302ad814
4
+ data.tar.gz: 12ba4fbebda0e4b470627eeaefe39650651ac5dc
5
5
  SHA512:
6
- metadata.gz: 16a70f5bf679bce2b557ebbdb511ec932f1af2b46086515089867a3aa1624f31cde2dd51ad6dd65576982696f23fb232fd75704ea55a9ed4a7d6ce2915363a20
7
- data.tar.gz: f4605f368d50c963e1e513f2d0ec8b689b27c305ed0c30e6549451ff4fee3f80e056132d13cc946949d178c8bc18beebbe74a1c7f5b3401f1a0c71886bf5e158
6
+ metadata.gz: e4f9306f866dce0e04dd5f5243f757f67ba05c289036f46b0fbd5693e58a2bc094de39112a46f7080269ce8c9ff6b7e3efa61c143c14489831739b917b8b203b
7
+ data.tar.gz: 290986bcc1442b86a029ce860ee5f48607f7434776866302ceb66ce113020adbc836bd4e684ca71ebf9da276ad8d7781abbcc63dd7683df4494e165832f78d42
@@ -12,7 +12,12 @@ rvm:
12
12
 
13
13
  matrix:
14
14
  allow_failures:
15
+ - rvm: 1.8.7 # not sure why 1.8 isn't passing, but it's dead
16
+ - rvm: ree # also dead
15
17
  - rvm: ruby-head
16
18
  - rvm: jruby-head
17
- - rvm: rbx-18mode
18
- - rvm: rbx-19mode
19
+ - rvm: rbx-18mode # sure would like to get this fixed!
20
+ - rvm: rbx-19mode # ditto
21
+
22
+ notifications:
23
+ irc: "irc.freenode.org#celluloid"
data/CHANGES.md CHANGED
@@ -1,3 +1,9 @@
1
+ 0.5.0 (2013-08-06)
2
+ ------------------
3
+ * Fix segv when attempting to register to a closed selector
4
+ * Fix Windows support on Ruby 2.0.0
5
+ * Upgrade to libev 4.15
6
+
1
7
  0.4.6 (2013-05-27)
2
8
  ------------------
3
9
  * Fix for JRuby on Windows
data/Gemfile CHANGED
@@ -1,6 +1,7 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gem 'jruby-openssl' if defined? JRUBY_VERSION
4
+ gem 'coveralls', :require => false
4
5
 
5
6
  # Specify your gem's dependencies in nio4r.gemspec
6
7
  gemspec
@@ -2,6 +2,63 @@ Revision history for libev, a high-performance and full-featured event loop.
2
2
 
3
3
  TODO: ev_loop_wakeup
4
4
  TODO: EV_STANDALONE == NO_HASSEL (do not use clock_gettime in ev_standalone)
5
+ TODO: faq, process a thing in each iteration
6
+ TODO: dbeugging tips, ev_verify, ev_init twice
7
+ TODO: ev_break for immediate exit (EVBREAK_NOW?)
8
+ TODO: ev_feed_child_event
9
+ TODO: document the special problem of signals around fork.
10
+ TODO: store pid for each signal
11
+ TODO: document file descriptor usage per loop
12
+ TODO: store loop pid_t and compare isndie signal handler,store 1 for same, 2 for differign pid, clean up in loop_fork
13
+ TODO: embed watchers need updating when fd changes
14
+ TODO: document portbaility requirements for atomic pointer access
15
+
16
+ 4.15 Fri Mar 1 12:04:50 CET 2013
17
+ - destroying a non-default loop would stop the global waitpid
18
+ watcher (Denis Bilenko).
19
+ - queueing pending watchers of higher priority from a watcher now invokes
20
+ them in a timely fashion (reported by Denis Bilenko).
21
+ - add throw() to all libev functions that cannot throw exceptions, for
22
+ further code size decrease when compiling for C++.
23
+ - add throw () to callbacks that must not throw exceptions (allocator,
24
+ syserr, loop acquire/release, periodic reschedule cbs).
25
+ - fix event_base_loop return code, add event_get_callback, event_base_new,
26
+ event_base_get_method calls to improve libevent 1.x emulation and add
27
+ some libevent 2.x functionality (based on a patch by Jeff Davey).
28
+ - add more memory fences to fix a bug reported by Jeff Davey. Better
29
+ be overfenced than underprotected.
30
+ - ev_run now returns a boolean status (true meaning watchers are
31
+ still active).
32
+ - ev_once: undef EV_ERROR in ev_kqueue.c, to avoid clashing with
33
+ libev's EV_ERROR (reported by 191919).
34
+ - (ecb) add memory fence support for xlC (Darin McBride).
35
+ - (ecb) add memory fence support for gcc-mips (Anton Kirilov).
36
+ - (ecb) add memory fence support for gcc-alpha (Christian Weisgerber).
37
+ - work around some kernels losing file descriptors by leaking
38
+ the kqueue descriptor in the child.
39
+ - work around linux inotify not reporting IN_ATTRIB changes for directories
40
+ in many cases.
41
+ - include sys/syscall.h instead of plain syscall.h.
42
+ - check for io watcher loops in ev_verify, check for the most
43
+ common reported usage bug in ev_io_start.
44
+ - chose socket vs. WSASocket at compiletime using EV_USE_WSASOCKET.
45
+ - always use WSASend/WSARecv directly on windows, hoping that this
46
+ works in all cases (unlike read/write/send/recv...).
47
+ - try to detect signals around a fork faster (test program by
48
+ Denis Bilenko).
49
+ - work around recent glibc versions that leak memory in realloc.
50
+ - rename ev::embed::set to ev::embed::set_embed to avoid clashing
51
+ the watcher base set (loop) method.
52
+ - rewrite the async/signal pipe logic to always keep a valid fd, which
53
+ simplifies (and hopefuly correctifies :) the race checking
54
+ on fork, at the cost of one extra fd.
55
+ - add fat, msdos, jffs2, ramfs, ntfs and btrfs to the list of
56
+ inotify-supporting filesystems.
57
+ - move orig_CFLAGS assignment to after AC_INIT, as newer autoconf
58
+ versions ignore it before
59
+ (https://bugzilla.redhat.com/show_bug.cgi?id=908096).
60
+ - add some untested android support.
61
+ - enum expressions must be of type int (reported by Juan Pablo L).
5
62
 
6
63
  4.11 Sat Feb 4 19:52:39 CET 2012
7
64
  - INCOMPATIBLE CHANGE: ev_timer_again now clears the pending status, as
@@ -1,4 +1,5 @@
1
- All files in libev are Copyright (C)2007,2008,2009 Marc Alexander Lehmann.
1
+ All files in libev are
2
+ Copyright (c)2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann.
2
3
 
3
4
  Redistribution and use in source and binary forms, with or without
4
5
  modification, are permitted provided that the following conditions are
@@ -24,23 +24,23 @@ ABOUT
24
24
  - relative timers/timeouts (handle time jumps).
25
25
  - fast intra-thread communication between multiple
26
26
  event loops (with optional fast linux eventfd backend).
27
- - extremely easy to embed.
28
- - very small codebase, no bloated library.
27
+ - extremely easy to embed (fully documented, no dependencies,
28
+ autoconf supported but optional).
29
+ - very small codebase, no bloated library, simple code.
29
30
  - fully extensible by being able to plug into the event loop,
30
31
  integrate other event loops, integrate other event loop users.
31
32
  - very little memory use (small watchers, small event loop data).
32
33
  - optional C++ interface allowing method and function callbacks
33
34
  at no extra memory or runtime overhead.
34
35
  - optional Perl interface with similar characteristics (capable
35
- of running Glib/Gtk2 on libev, interfaces with Net::SNMP and
36
- libadns).
36
+ of running Glib/Gtk2 on libev).
37
37
  - support for other languages (multiple C++ interfaces, D, Ruby,
38
38
  Python) available from third-parties.
39
39
 
40
- Examples of programs that embed libev: the EV perl module,
41
- rxvt-unicode, gvpe (GNU Virtual Private Ethernet), the Deliantra MMORPG
42
- server (http://www.deliantra.net/), Rubinius (a next-generation Ruby
43
- VM), the Ebb web server, the Rev event toolkit.
40
+ Examples of programs that embed libev: the EV perl module, node.js,
41
+ auditd, rxvt-unicode, gvpe (GNU Virtual Private Ethernet), the
42
+ Deliantra MMORPG server (http://www.deliantra.net/), Rubinius (a
43
+ next-generation Ruby VM), the Ebb web server, the Rev event toolkit.
44
44
 
45
45
 
46
46
  CONTRIBUTORS
@@ -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-
@@ -65,7 +65,7 @@
65
65
  # define EV_USE_MONOTONIC 1
66
66
  # endif
67
67
  # endif
68
- # elif !defined(EV_USE_CLOCK_SYSCALL)
68
+ # elif !defined EV_USE_CLOCK_SYSCALL
69
69
  # define EV_USE_CLOCK_SYSCALL 0
70
70
  # endif
71
71
 
@@ -207,6 +207,7 @@
207
207
  #else
208
208
  # include <io.h>
209
209
  # define WIN32_LEAN_AND_MEAN
210
+ # include <winsock2.h>
210
211
  # include <windows.h>
211
212
  # ifndef EV_SELECT_IS_WINSOCKET
212
213
  # define EV_SELECT_IS_WINSOCKET 1
@@ -225,25 +226,25 @@
225
226
  /* this block tries to deduce configuration from header-defined symbols and defaults */
226
227
 
227
228
  /* try to deduce the maximum number of signals on this platform */
228
- #if defined (EV_NSIG)
229
+ #if defined EV_NSIG
229
230
  /* use what's provided */
230
- #elif defined (NSIG)
231
+ #elif defined NSIG
231
232
  # define EV_NSIG (NSIG)
232
- #elif defined(_NSIG)
233
+ #elif defined _NSIG
233
234
  # define EV_NSIG (_NSIG)
234
- #elif defined (SIGMAX)
235
+ #elif defined SIGMAX
235
236
  # define EV_NSIG (SIGMAX+1)
236
- #elif defined (SIG_MAX)
237
+ #elif defined SIG_MAX
237
238
  # define EV_NSIG (SIG_MAX+1)
238
- #elif defined (_SIG_MAX)
239
+ #elif defined _SIG_MAX
239
240
  # define EV_NSIG (_SIG_MAX+1)
240
- #elif defined (MAXSIG)
241
+ #elif defined MAXSIG
241
242
  # define EV_NSIG (MAXSIG+1)
242
- #elif defined (MAX_SIG)
243
+ #elif defined MAX_SIG
243
244
  # define EV_NSIG (MAX_SIG+1)
244
- #elif defined (SIGARRAYSIZE)
245
+ #elif defined SIGARRAYSIZE
245
246
  # define EV_NSIG (SIGARRAYSIZE) /* Assume ary[SIGARRAYSIZE] */
246
- #elif defined (_sys_nsig)
247
+ #elif defined _sys_nsig
247
248
  # define EV_NSIG (_sys_nsig) /* Solaris 2.5 */
248
249
  #else
249
250
  # error "unable to find value for NSIG, please report"
@@ -265,7 +266,7 @@
265
266
  #endif
266
267
 
267
268
  #ifndef EV_USE_MONOTONIC
268
- # if defined (_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
269
+ # if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
269
270
  # define EV_USE_MONOTONIC EV_FEATURE_OS
270
271
  # else
271
272
  # define EV_USE_MONOTONIC 0
@@ -362,10 +363,26 @@
362
363
  # define EV_HEAP_CACHE_AT EV_FEATURE_DATA
363
364
  #endif
364
365
 
366
+ #ifdef ANDROID
367
+ /* supposedly, android doesn't typedef fd_mask */
368
+ # undef EV_USE_SELECT
369
+ # define EV_USE_SELECT 0
370
+ /* supposedly, we need to include syscall.h, not sys/syscall.h, so just disable */
371
+ # undef EV_USE_CLOCK_SYSCALL
372
+ # define EV_USE_CLOCK_SYSCALL 0
373
+ #endif
374
+
375
+ /* aix's poll.h seems to cause lots of trouble */
376
+ #ifdef _AIX
377
+ /* AIX has a completely broken poll.h header */
378
+ # undef EV_USE_POLL
379
+ # define EV_USE_POLL 0
380
+ #endif
381
+
365
382
  /* on linux, we can use a (slow) syscall to avoid a dependency on pthread, */
366
383
  /* which makes programs even slower. might work on other unices, too. */
367
384
  #if EV_USE_CLOCK_SYSCALL
368
- # include <syscall.h>
385
+ # include <sys/syscall.h>
369
386
  # ifdef SYS_clock_gettime
370
387
  # define clock_gettime(id, ts) syscall (SYS_clock_gettime, (id), (ts))
371
388
  # undef EV_USE_MONOTONIC
@@ -378,12 +395,6 @@
378
395
 
379
396
  /* this block fixes any misconfiguration where we know we run into trouble otherwise */
380
397
 
381
- #ifdef _AIX
382
- /* AIX has a completely broken poll.h header */
383
- # undef EV_USE_POLL
384
- # define EV_USE_POLL 0
385
- #endif
386
-
387
398
  #ifndef CLOCK_MONOTONIC
388
399
  # undef EV_USE_MONOTONIC
389
400
  # define EV_USE_MONOTONIC 0
@@ -401,7 +412,7 @@
401
412
 
402
413
  #if !EV_USE_NANOSLEEP
403
414
  /* hp-ux has it in sys/time.h, which we unconditionally include above */
404
- # if !defined(_WIN32) && !defined(__hpux)
415
+ # if !defined _WIN32 && !defined __hpux
405
416
  # include <sys/select.h>
406
417
  # endif
407
418
  #endif
@@ -416,10 +427,6 @@
416
427
  # endif
417
428
  #endif
418
429
 
419
- #if EV_SELECT_IS_WINSOCKET
420
- # include <winsock.h>
421
- #endif
422
-
423
430
  #if EV_USE_EVENTFD
424
431
  /* our minimum requirement is glibc 2.7 which has the stub, but not the header */
425
432
  # include <stdint.h>
@@ -513,6 +520,9 @@ struct signalfd_siginfo
513
520
  #ifndef ECB_H
514
521
  #define ECB_H
515
522
 
523
+ /* 16 bits major, 16 bits minor */
524
+ #define ECB_VERSION 0x00010003
525
+
516
526
  #ifdef _WIN32
517
527
  typedef signed char int8_t;
518
528
  typedef unsigned char uint8_t;
@@ -527,8 +537,31 @@ struct signalfd_siginfo
527
537
  typedef signed __int64 int64_t;
528
538
  typedef unsigned __int64 uint64_t;
529
539
  #endif
540
+ #ifdef _WIN64
541
+ #define ECB_PTRSIZE 8
542
+ typedef uint64_t uintptr_t;
543
+ typedef int64_t intptr_t;
544
+ #else
545
+ #define ECB_PTRSIZE 4
546
+ typedef uint32_t uintptr_t;
547
+ typedef int32_t intptr_t;
548
+ #endif
530
549
  #else
531
550
  #include <inttypes.h>
551
+ #if UINTMAX_MAX > 0xffffffffU
552
+ #define ECB_PTRSIZE 8
553
+ #else
554
+ #define ECB_PTRSIZE 4
555
+ #endif
556
+ #endif
557
+
558
+ /* work around x32 idiocy by defining proper macros */
559
+ #if __x86_64 || _M_AMD64
560
+ #if __ILP32
561
+ #define ECB_AMD64_X32 1
562
+ #else
563
+ #define ECB_AMD64 1
564
+ #endif
532
565
  #endif
533
566
 
534
567
  /* many compilers define _GNUC_ to some versions but then only implement
@@ -539,65 +572,101 @@ struct signalfd_siginfo
539
572
  * an issue with that they should have done it right in the first place.
540
573
  */
541
574
  #ifndef ECB_GCC_VERSION
542
- #if !defined(__GNUC_MINOR__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__llvm__) || defined(__clang__)
575
+ #if !defined __GNUC_MINOR__ || defined __INTEL_COMPILER || defined __SUNPRO_C || defined __SUNPRO_CC || defined __llvm__ || defined __clang__
543
576
  #define ECB_GCC_VERSION(major,minor) 0
544
577
  #else
545
578
  #define ECB_GCC_VERSION(major,minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
546
579
  #endif
547
580
  #endif
548
581
 
582
+ #define ECB_C (__STDC__+0) /* this assumes that __STDC__ is either empty or a number */
583
+ #define ECB_C99 (__STDC_VERSION__ >= 199901L)
584
+ #define ECB_C11 (__STDC_VERSION__ >= 201112L)
585
+ #define ECB_CPP (__cplusplus+0)
586
+ #define ECB_CPP11 (__cplusplus >= 201103L)
587
+
588
+ #if ECB_CPP
589
+ #define ECB_EXTERN_C extern "C"
590
+ #define ECB_EXTERN_C_BEG ECB_EXTERN_C {
591
+ #define ECB_EXTERN_C_END }
592
+ #else
593
+ #define ECB_EXTERN_C extern
594
+ #define ECB_EXTERN_C_BEG
595
+ #define ECB_EXTERN_C_END
596
+ #endif
597
+
549
598
  /*****************************************************************************/
550
599
 
551
600
  /* ECB_NO_THREADS - ecb is not used by multiple threads, ever */
552
601
  /* ECB_NO_SMP - ecb might be used in multiple threads, but only on a single cpu */
553
602
 
554
603
  #if ECB_NO_THREADS
555
- # define ECB_NO_SMP 1
604
+ #define ECB_NO_SMP 1
556
605
  #endif
557
606
 
558
- #if ECB_NO_THREADS || ECB_NO_SMP
607
+ #if ECB_NO_SMP
559
608
  #define ECB_MEMORY_FENCE do { } while (0)
560
609
  #endif
561
610
 
562
611
  #ifndef ECB_MEMORY_FENCE
563
- #if ECB_GCC_VERSION(2,5) || defined(__INTEL_COMPILER) || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
612
+ #if ECB_GCC_VERSION(2,5) || defined __INTEL_COMPILER || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
564
613
  #if __i386 || __i386__
565
614
  #define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory")
566
- #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE /* non-lock xchg might be enough */
567
- #define ECB_MEMORY_FENCE_RELEASE do { } while (0) /* unlikely to change in future cpus */
615
+ #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory")
616
+ #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
568
617
  #elif __amd64 || __amd64__ || __x86_64 || __x86_64__
569
- #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mfence" : : : "memory")
570
- #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("lfence" : : : "memory")
571
- #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("sfence") /* play safe - not needed in any current cpu */
618
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mfence" : : : "memory")
619
+ #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory")
620
+ #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
572
621
  #elif __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__
573
- #define ECB_MEMORY_FENCE __asm__ __volatile__ ("sync" : : : "memory")
574
- #elif defined(__ARM_ARCH_6__ ) || defined(__ARM_ARCH_6J__ ) \
575
- || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6ZK__)
576
- #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mcr p15,0,%0,c7,c10,5" : : "r" (0) : "memory")
577
- #elif defined(__ARM_ARCH_7__ ) || defined(__ARM_ARCH_7A__ ) \
578
- || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7R__ )
579
- #define ECB_MEMORY_FENCE __asm__ __volatile__ ("dmb" : : : "memory")
622
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("sync" : : : "memory")
623
+ #elif defined __ARM_ARCH_6__ || defined __ARM_ARCH_6J__ \
624
+ || defined __ARM_ARCH_6K__ || defined __ARM_ARCH_6ZK__
625
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mcr p15,0,%0,c7,c10,5" : : "r" (0) : "memory")
626
+ #elif defined __ARM_ARCH_7__ || defined __ARM_ARCH_7A__ \
627
+ || defined __ARM_ARCH_7M__ || defined __ARM_ARCH_7R__
628
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("dmb" : : : "memory")
580
629
  #elif __sparc || __sparc__
581
- #define ECB_MEMORY_FENCE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad | #StoreStore | #StoreLoad | " : : : "memory")
582
- #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad" : : : "memory")
583
- #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("membar #LoadStore | #StoreStore")
584
- #elif defined(__s390__) || defined(__s390x__)
630
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad | #StoreStore | #StoreLoad" : : : "memory")
631
+ #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad" : : : "memory")
632
+ #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("membar #LoadStore | #StoreStore")
633
+ #elif defined __s390__ || defined __s390x__
585
634
  #define ECB_MEMORY_FENCE __asm__ __volatile__ ("bcr 15,0" : : : "memory")
635
+ #elif defined __mips__
636
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("sync" : : : "memory")
637
+ #elif defined __alpha__
638
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mb" : : : "memory")
639
+ #elif defined __hppa__
640
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("" : : : "memory")
641
+ #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
642
+ #elif defined __ia64__
643
+ #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mf" : : : "memory")
586
644
  #endif
587
645
  #endif
588
646
  #endif
589
647
 
590
648
  #ifndef ECB_MEMORY_FENCE
591
- #if ECB_GCC_VERSION(4,4) || defined(__INTEL_COMPILER) || defined(__clang__)
649
+ #if ECB_GCC_VERSION(4,7)
650
+ /* see comment below (stdatomic.h) about the C11 memory model. */
651
+ #define ECB_MEMORY_FENCE __atomic_thread_fence (__ATOMIC_SEQ_CST)
652
+
653
+ /* The __has_feature syntax from clang is so misdesigned that we cannot use it
654
+ * without risking compile time errors with other compilers. We *could*
655
+ * define our own ecb_clang_has_feature, but I just can't be bothered to work
656
+ * around this shit time and again.
657
+ * #elif defined __clang && __has_feature (cxx_atomic)
658
+ * // see comment below (stdatomic.h) about the C11 memory model.
659
+ * #define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST)
660
+ */
661
+
662
+ #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__
592
663
  #define ECB_MEMORY_FENCE __sync_synchronize ()
593
- /*#define ECB_MEMORY_FENCE_ACQUIRE ({ char dummy = 0; __sync_lock_test_and_set (&dummy, 1); }) */
594
- /*#define ECB_MEMORY_FENCE_RELEASE ({ char dummy = 1; __sync_lock_release (&dummy ); }) */
595
664
  #elif _MSC_VER >= 1400 /* VC++ 2005 */
596
665
  #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier)
597
666
  #define ECB_MEMORY_FENCE _ReadWriteBarrier ()
598
667
  #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier () /* according to msdn, _ReadBarrier is not a load fence */
599
668
  #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier ()
600
- #elif defined(_WIN32)
669
+ #elif defined _WIN32
601
670
  #include <WinNT.h>
602
671
  #define ECB_MEMORY_FENCE MemoryBarrier () /* actually just xchg on x86... scary */
603
672
  #elif __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
@@ -605,6 +674,23 @@ struct signalfd_siginfo
605
674
  #define ECB_MEMORY_FENCE __machine_rw_barrier ()
606
675
  #define ECB_MEMORY_FENCE_ACQUIRE __machine_r_barrier ()
607
676
  #define ECB_MEMORY_FENCE_RELEASE __machine_w_barrier ()
677
+ #elif __xlC__
678
+ #define ECB_MEMORY_FENCE __sync ()
679
+ #endif
680
+ #endif
681
+
682
+ #ifndef ECB_MEMORY_FENCE
683
+ #if ECB_C11 && !defined __STDC_NO_ATOMICS__
684
+ /* we assume that these memory fences work on all variables/all memory accesses, */
685
+ /* not just C11 atomics and atomic accesses */
686
+ #include <stdatomic.h>
687
+ /* Unfortunately, neither gcc 4.7 nor clang 3.1 generate any instructions for */
688
+ /* any fence other than seq_cst, which isn't very efficient for us. */
689
+ /* Why that is, we don't know - either the C11 memory model is quite useless */
690
+ /* for most usages, or gcc and clang have a bug */
691
+ /* I *currently* lean towards the latter, and inefficiently implement */
692
+ /* all three of ecb's fences as a seq_cst fence */
693
+ #define ECB_MEMORY_FENCE atomic_thread_fence (memory_order_seq_cst)
608
694
  #endif
609
695
  #endif
610
696
 
@@ -626,18 +712,16 @@ struct signalfd_siginfo
626
712
  #endif
627
713
  #endif
628
714
 
629
- #if !defined(ECB_MEMORY_FENCE_ACQUIRE) && defined(ECB_MEMORY_FENCE)
715
+ #if !defined ECB_MEMORY_FENCE_ACQUIRE && defined ECB_MEMORY_FENCE
630
716
  #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE
631
717
  #endif
632
718
 
633
- #if !defined(ECB_MEMORY_FENCE_RELEASE) && defined(ECB_MEMORY_FENCE)
719
+ #if !defined ECB_MEMORY_FENCE_RELEASE && defined ECB_MEMORY_FENCE
634
720
  #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE
635
721
  #endif
636
722
 
637
723
  /*****************************************************************************/
638
724
 
639
- #define ECB_C99 (__STDC_VERSION__ >= 199901L)
640
-
641
725
  #if __cplusplus
642
726
  #define ecb_inline static inline
643
727
  #elif ECB_GCC_VERSION(2,5)
@@ -685,11 +769,16 @@ typedef int ecb_bool;
685
769
  #endif
686
770
 
687
771
  #define ecb_noinline ecb_attribute ((__noinline__))
688
- #define ecb_noreturn ecb_attribute ((__noreturn__))
689
772
  #define ecb_unused ecb_attribute ((__unused__))
690
773
  #define ecb_const ecb_attribute ((__const__))
691
774
  #define ecb_pure ecb_attribute ((__pure__))
692
775
 
776
+ #if ECB_C11
777
+ #define ecb_noreturn _Noreturn
778
+ #else
779
+ #define ecb_noreturn ecb_attribute ((__noreturn__))
780
+ #endif
781
+
693
782
  #if ECB_GCC_VERSION(4,3)
694
783
  #define ecb_artificial ecb_attribute ((__artificial__))
695
784
  #define ecb_hot ecb_attribute ((__hot__))
@@ -789,6 +878,11 @@ typedef int ecb_bool;
789
878
  }
790
879
  #endif
791
880
 
881
+ ecb_function_ ecb_bool ecb_is_pot32 (uint32_t x) ecb_const;
882
+ ecb_function_ ecb_bool ecb_is_pot32 (uint32_t x) { return !(x & (x - 1)); }
883
+ ecb_function_ ecb_bool ecb_is_pot64 (uint64_t x) ecb_const;
884
+ ecb_function_ ecb_bool ecb_is_pot64 (uint64_t x) { return !(x & (x - 1)); }
885
+
792
886
  ecb_function_ uint8_t ecb_bitrev8 (uint8_t x) ecb_const;
793
887
  ecb_function_ uint8_t ecb_bitrev8 (uint8_t x)
794
888
  {
@@ -882,14 +976,32 @@ ecb_inline uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (
882
976
  #endif
883
977
 
884
978
  /* try to tell the compiler that some condition is definitely true */
885
- #define ecb_assume(cond) do { if (!(cond)) ecb_unreachable (); } while (0)
979
+ #define ecb_assume(cond) if (!(cond)) ecb_unreachable (); else 0
886
980
 
887
981
  ecb_inline unsigned char ecb_byteorder_helper (void) ecb_const;
888
982
  ecb_inline unsigned char
889
983
  ecb_byteorder_helper (void)
890
984
  {
891
- const uint32_t u = 0x11223344;
892
- return *(unsigned char *)&u;
985
+ /* the union code still generates code under pressure in gcc, */
986
+ /* but less than using pointers, and always seems to */
987
+ /* successfully return a constant. */
988
+ /* the reason why we have this horrible preprocessor mess */
989
+ /* is to avoid it in all cases, at least on common architectures */
990
+ /* or when using a recent enough gcc version (>= 4.6) */
991
+ #if __i386 || __i386__ || _M_X86 || __amd64 || __amd64__ || _M_X64
992
+ return 0x44;
993
+ #elif __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
994
+ return 0x44;
995
+ #elif __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
996
+ return 0x11;
997
+ #else
998
+ union
999
+ {
1000
+ uint32_t i;
1001
+ uint8_t c;
1002
+ } u = { 0x11223344 };
1003
+ return u.c;
1004
+ #endif
893
1005
  }
894
1006
 
895
1007
  ecb_inline ecb_bool ecb_big_endian (void) ecb_const;
@@ -930,6 +1042,173 @@ ecb_inline ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () ==
930
1042
  #define ecb_array_length(name) (sizeof (name) / sizeof (name [0]))
931
1043
  #endif
932
1044
 
1045
+ /*******************************************************************************/
1046
+ /* floating point stuff, can be disabled by defining ECB_NO_LIBM */
1047
+
1048
+ /* basically, everything uses "ieee pure-endian" floating point numbers */
1049
+ /* the only noteworthy exception is ancient armle, which uses order 43218765 */
1050
+ #if 0 \
1051
+ || __i386 || __i386__ \
1052
+ || __amd64 || __amd64__ || __x86_64 || __x86_64__ \
1053
+ || __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__ \
1054
+ || defined __arm__ && defined __ARM_EABI__ \
1055
+ || defined __s390__ || defined __s390x__ \
1056
+ || defined __mips__ \
1057
+ || defined __alpha__ \
1058
+ || defined __hppa__ \
1059
+ || defined __ia64__ \
1060
+ || defined _M_IX86 || defined _M_AMD64 || defined _M_IA64
1061
+ #define ECB_STDFP 1
1062
+ #include <string.h> /* for memcpy */
1063
+ #else
1064
+ #define ECB_STDFP 0
1065
+ #include <math.h> /* for frexp*, ldexp* */
1066
+ #endif
1067
+
1068
+ #ifndef ECB_NO_LIBM
1069
+
1070
+ /* convert a float to ieee single/binary32 */
1071
+ ecb_function_ uint32_t ecb_float_to_binary32 (float x) ecb_const;
1072
+ ecb_function_ uint32_t
1073
+ ecb_float_to_binary32 (float x)
1074
+ {
1075
+ uint32_t r;
1076
+
1077
+ #if ECB_STDFP
1078
+ memcpy (&r, &x, 4);
1079
+ #else
1080
+ /* slow emulation, works for anything but -0 */
1081
+ uint32_t m;
1082
+ int e;
1083
+
1084
+ if (x == 0e0f ) return 0x00000000U;
1085
+ if (x > +3.40282346638528860e+38f) return 0x7f800000U;
1086
+ if (x < -3.40282346638528860e+38f) return 0xff800000U;
1087
+ if (x != x ) return 0x7fbfffffU;
1088
+
1089
+ m = frexpf (x, &e) * 0x1000000U;
1090
+
1091
+ r = m & 0x80000000U;
1092
+
1093
+ if (r)
1094
+ m = -m;
1095
+
1096
+ if (e <= -126)
1097
+ {
1098
+ m &= 0xffffffU;
1099
+ m >>= (-125 - e);
1100
+ e = -126;
1101
+ }
1102
+
1103
+ r |= (e + 126) << 23;
1104
+ r |= m & 0x7fffffU;
1105
+ #endif
1106
+
1107
+ return r;
1108
+ }
1109
+
1110
+ /* converts an ieee single/binary32 to a float */
1111
+ ecb_function_ float ecb_binary32_to_float (uint32_t x) ecb_const;
1112
+ ecb_function_ float
1113
+ ecb_binary32_to_float (uint32_t x)
1114
+ {
1115
+ float r;
1116
+
1117
+ #if ECB_STDFP
1118
+ memcpy (&r, &x, 4);
1119
+ #else
1120
+ /* emulation, only works for normals and subnormals and +0 */
1121
+ int neg = x >> 31;
1122
+ int e = (x >> 23) & 0xffU;
1123
+
1124
+ x &= 0x7fffffU;
1125
+
1126
+ if (e)
1127
+ x |= 0x800000U;
1128
+ else
1129
+ e = 1;
1130
+
1131
+ /* we distrust ldexpf a bit and do the 2**-24 scaling by an extra multiply */
1132
+ r = ldexpf (x * (0.5f / 0x800000U), e - 126);
1133
+
1134
+ r = neg ? -r : r;
1135
+ #endif
1136
+
1137
+ return r;
1138
+ }
1139
+
1140
+ /* convert a double to ieee double/binary64 */
1141
+ ecb_function_ uint64_t ecb_double_to_binary64 (double x) ecb_const;
1142
+ ecb_function_ uint64_t
1143
+ ecb_double_to_binary64 (double x)
1144
+ {
1145
+ uint64_t r;
1146
+
1147
+ #if ECB_STDFP
1148
+ memcpy (&r, &x, 8);
1149
+ #else
1150
+ /* slow emulation, works for anything but -0 */
1151
+ uint64_t m;
1152
+ int e;
1153
+
1154
+ if (x == 0e0 ) return 0x0000000000000000U;
1155
+ if (x > +1.79769313486231470e+308) return 0x7ff0000000000000U;
1156
+ if (x < -1.79769313486231470e+308) return 0xfff0000000000000U;
1157
+ if (x != x ) return 0X7ff7ffffffffffffU;
1158
+
1159
+ m = frexp (x, &e) * 0x20000000000000U;
1160
+
1161
+ r = m & 0x8000000000000000;;
1162
+
1163
+ if (r)
1164
+ m = -m;
1165
+
1166
+ if (e <= -1022)
1167
+ {
1168
+ m &= 0x1fffffffffffffU;
1169
+ m >>= (-1021 - e);
1170
+ e = -1022;
1171
+ }
1172
+
1173
+ r |= ((uint64_t)(e + 1022)) << 52;
1174
+ r |= m & 0xfffffffffffffU;
1175
+ #endif
1176
+
1177
+ return r;
1178
+ }
1179
+
1180
+ /* converts an ieee double/binary64 to a double */
1181
+ ecb_function_ double ecb_binary64_to_double (uint64_t x) ecb_const;
1182
+ ecb_function_ double
1183
+ ecb_binary64_to_double (uint64_t x)
1184
+ {
1185
+ double r;
1186
+
1187
+ #if ECB_STDFP
1188
+ memcpy (&r, &x, 8);
1189
+ #else
1190
+ /* emulation, only works for normals and subnormals and +0 */
1191
+ int neg = x >> 63;
1192
+ int e = (x >> 52) & 0x7ffU;
1193
+
1194
+ x &= 0xfffffffffffffU;
1195
+
1196
+ if (e)
1197
+ x |= 0x10000000000000U;
1198
+ else
1199
+ e = 1;
1200
+
1201
+ /* we distrust ldexp a bit and do the 2**-53 scaling by an extra multiply */
1202
+ r = ldexp (x * (0.5 / 0x10000000000000U), e - 1022);
1203
+
1204
+ r = neg ? -r : r;
1205
+ #endif
1206
+
1207
+ return r;
1208
+ }
1209
+
1210
+ #endif
1211
+
933
1212
  #endif
934
1213
 
935
1214
  /* ECB.H END */
@@ -1105,10 +1384,10 @@ ev_printerr (const char *msg)
1105
1384
  }
1106
1385
  #endif
1107
1386
 
1108
- static void (*syserr_cb)(const char *msg);
1387
+ static void (*syserr_cb)(const char *msg) EV_THROW;
1109
1388
 
1110
1389
  void ecb_cold
1111
- ev_set_syserr_cb (void (*cb)(const char *msg))
1390
+ ev_set_syserr_cb (void (*cb)(const char *msg) EV_THROW) EV_THROW
1112
1391
  {
1113
1392
  syserr_cb = cb;
1114
1393
  }
@@ -1136,14 +1415,13 @@ ev_syserr (const char *msg)
1136
1415
  }
1137
1416
 
1138
1417
  static void *
1139
- ev_realloc_emul (void *ptr, long size)
1418
+ ev_realloc_emul (void *ptr, long size) EV_THROW
1140
1419
  {
1141
- #if __GLIBC__
1142
- return realloc (ptr, size);
1143
- #else
1144
1420
  /* some systems, notably openbsd and darwin, fail to properly
1145
1421
  * implement realloc (x, 0) (as required by both ansi c-89 and
1146
1422
  * the single unix specification, so work around them here.
1423
+ * recently, also (at least) fedora and debian started breaking it,
1424
+ * despite documenting it otherwise.
1147
1425
  */
1148
1426
 
1149
1427
  if (size)
@@ -1151,13 +1429,12 @@ ev_realloc_emul (void *ptr, long size)
1151
1429
 
1152
1430
  free (ptr);
1153
1431
  return 0;
1154
- #endif
1155
1432
  }
1156
1433
 
1157
- static void *(*alloc)(void *ptr, long size) = ev_realloc_emul;
1434
+ static void *(*alloc)(void *ptr, long size) EV_THROW = ev_realloc_emul;
1158
1435
 
1159
1436
  void ecb_cold
1160
- ev_set_allocator (void *(*cb)(void *ptr, long size))
1437
+ ev_set_allocator (void *(*cb)(void *ptr, long size) EV_THROW) EV_THROW
1161
1438
  {
1162
1439
  alloc = cb;
1163
1440
  }
@@ -1284,7 +1561,7 @@ typedef struct
1284
1561
 
1285
1562
  #ifndef EV_HAVE_EV_TIME
1286
1563
  ev_tstamp
1287
- ev_time (void)
1564
+ ev_time (void) EV_THROW
1288
1565
  {
1289
1566
  #if EV_USE_REALTIME
1290
1567
  if (expect_true (have_realtime))
@@ -1318,14 +1595,14 @@ get_clock (void)
1318
1595
 
1319
1596
  #if EV_MULTIPLICITY
1320
1597
  ev_tstamp
1321
- ev_now (EV_P)
1598
+ ev_now (EV_P) EV_THROW
1322
1599
  {
1323
1600
  return ev_rt_now;
1324
1601
  }
1325
1602
  #endif
1326
1603
 
1327
1604
  void
1328
- ev_sleep (ev_tstamp delay)
1605
+ ev_sleep (ev_tstamp delay) EV_THROW
1329
1606
  {
1330
1607
  if (delay > 0.)
1331
1608
  {
@@ -1334,7 +1611,7 @@ ev_sleep (ev_tstamp delay)
1334
1611
 
1335
1612
  EV_TS_SET (ts, delay);
1336
1613
  nanosleep (&ts, 0);
1337
- #elif defined(_WIN32)
1614
+ #elif defined _WIN32
1338
1615
  Sleep ((unsigned long)(delay * 1e3));
1339
1616
  #else
1340
1617
  struct timeval tv;
@@ -1416,7 +1693,7 @@ pendingcb (EV_P_ ev_prepare *w, int revents)
1416
1693
  }
1417
1694
 
1418
1695
  void noinline
1419
- ev_feed_event (EV_P_ void *w, int revents)
1696
+ ev_feed_event (EV_P_ void *w, int revents) EV_THROW
1420
1697
  {
1421
1698
  W w_ = (W)w;
1422
1699
  int pri = ABSPRI (w_);
@@ -1430,6 +1707,8 @@ ev_feed_event (EV_P_ void *w, int revents)
1430
1707
  pendings [pri][w_->pending - 1].w = w_;
1431
1708
  pendings [pri][w_->pending - 1].events = revents;
1432
1709
  }
1710
+
1711
+ pendingpri = NUMPRI - 1;
1433
1712
  }
1434
1713
 
1435
1714
  inline_speed void
@@ -1485,7 +1764,7 @@ fd_event (EV_P_ int fd, int revents)
1485
1764
  }
1486
1765
 
1487
1766
  void
1488
- ev_feed_fd_event (EV_P_ int fd, int revents)
1767
+ ev_feed_fd_event (EV_P_ int fd, int revents) EV_THROW
1489
1768
  {
1490
1769
  if (fd >= 0 && fd < anfdmax)
1491
1770
  fd_event_nocheck (EV_A_ fd, revents);
@@ -1814,28 +2093,41 @@ evpipe_init (EV_P)
1814
2093
  {
1815
2094
  if (!ev_is_active (&pipe_w))
1816
2095
  {
2096
+ int fds [2];
2097
+
1817
2098
  # if EV_USE_EVENTFD
1818
- evfd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
1819
- if (evfd < 0 && errno == EINVAL)
1820
- evfd = eventfd (0, 0);
2099
+ fds [0] = -1;
2100
+ fds [1] = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
2101
+ if (fds [1] < 0 && errno == EINVAL)
2102
+ fds [1] = eventfd (0, 0);
1821
2103
 
1822
- if (evfd >= 0)
2104
+ if (fds [1] < 0)
2105
+ # endif
1823
2106
  {
1824
- evpipe [0] = -1;
1825
- fd_intern (evfd); /* doing it twice doesn't hurt */
1826
- ev_io_set (&pipe_w, evfd, EV_READ);
2107
+ while (pipe (fds))
2108
+ ev_syserr ("(libev) error creating signal/async pipe");
2109
+
2110
+ fd_intern (fds [0]);
1827
2111
  }
2112
+
2113
+ fd_intern (fds [1]);
2114
+
2115
+ evpipe [0] = fds [0];
2116
+
2117
+ if (evpipe [1] < 0)
2118
+ evpipe [1] = fds [1]; /* first call, set write fd */
1828
2119
  else
1829
- # endif
1830
2120
  {
1831
- while (pipe (evpipe))
1832
- ev_syserr ("(libev) error creating signal/async pipe");
2121
+ /* on subsequent calls, do not change evpipe [1] */
2122
+ /* so that evpipe_write can always rely on its value. */
2123
+ /* this branch does not do anything sensible on windows, */
2124
+ /* so must not be executed on windows */
1833
2125
 
1834
- fd_intern (evpipe [0]);
1835
- fd_intern (evpipe [1]);
1836
- ev_io_set (&pipe_w, evpipe [0], EV_READ);
2126
+ dup2 (fds [1], evpipe [1]);
2127
+ close (fds [1]);
1837
2128
  }
1838
2129
 
2130
+ ev_io_set (&pipe_w, evpipe [0] < 0 ? evpipe [1] : evpipe [0], EV_READ);
1839
2131
  ev_io_start (EV_A_ &pipe_w);
1840
2132
  ev_unref (EV_A); /* watcher should not keep loop alive */
1841
2133
  }
@@ -1844,11 +2136,12 @@ evpipe_init (EV_P)
1844
2136
  inline_speed void
1845
2137
  evpipe_write (EV_P_ EV_ATOMIC_T *flag)
1846
2138
  {
2139
+ ECB_MEMORY_FENCE; /* push out the write before this function was called, acquire flag */
2140
+
1847
2141
  if (expect_true (*flag))
1848
2142
  return;
1849
2143
 
1850
2144
  *flag = 1;
1851
-
1852
2145
  ECB_MEMORY_FENCE_RELEASE; /* make sure flag is visible before the wakeup */
1853
2146
 
1854
2147
  pipe_write_skipped = 1;
@@ -1859,25 +2152,29 @@ evpipe_write (EV_P_ EV_ATOMIC_T *flag)
1859
2152
  {
1860
2153
  int old_errno;
1861
2154
 
1862
- pipe_write_skipped = 0; /* just an optimisation, no fence needed */
2155
+ pipe_write_skipped = 0;
2156
+ ECB_MEMORY_FENCE_RELEASE;
1863
2157
 
1864
2158
  old_errno = errno; /* save errno because write will clobber it */
1865
2159
 
1866
2160
  #if EV_USE_EVENTFD
1867
- if (evfd >= 0)
2161
+ if (evpipe [0] < 0)
1868
2162
  {
1869
2163
  uint64_t counter = 1;
1870
- write (evfd, &counter, sizeof (uint64_t));
2164
+ write (evpipe [1], &counter, sizeof (uint64_t));
1871
2165
  }
1872
2166
  else
1873
2167
  #endif
1874
2168
  {
1875
- /* win32 people keep sending patches that change this write() to send() */
1876
- /* and then run away. but send() is wrong, it wants a socket handle on win32 */
1877
- /* so when you think this write should be a send instead, please find out */
1878
- /* where your send() is from - it's definitely not the microsoft send, and */
1879
- /* tell me. thank you. */
2169
+ #ifdef _WIN32
2170
+ WSABUF buf;
2171
+ DWORD sent;
2172
+ buf.buf = &buf;
2173
+ buf.len = 1;
2174
+ WSASend (EV_FD_TO_WIN32_HANDLE (evpipe [1]), &buf, 1, &sent, 0, 0, 0);
2175
+ #else
1880
2176
  write (evpipe [1], &(evpipe [1]), 1);
2177
+ #endif
1881
2178
  }
1882
2179
 
1883
2180
  errno = old_errno;
@@ -1894,27 +2191,39 @@ pipecb (EV_P_ ev_io *iow, int revents)
1894
2191
  if (revents & EV_READ)
1895
2192
  {
1896
2193
  #if EV_USE_EVENTFD
1897
- if (evfd >= 0)
2194
+ if (evpipe [0] < 0)
1898
2195
  {
1899
2196
  uint64_t counter;
1900
- read (evfd, &counter, sizeof (uint64_t));
2197
+ read (evpipe [1], &counter, sizeof (uint64_t));
1901
2198
  }
1902
2199
  else
1903
2200
  #endif
1904
2201
  {
1905
- char dummy;
1906
- /* see discussion in evpipe_write when you think this read should be recv in win32 */
1907
- read (evpipe [0], &dummy, 1);
2202
+ char dummy[4];
2203
+ #ifdef _WIN32
2204
+ WSABUF buf;
2205
+ DWORD recvd;
2206
+ DWORD flags = 0;
2207
+ buf.buf = dummy;
2208
+ buf.len = sizeof (dummy);
2209
+ WSARecv (EV_FD_TO_WIN32_HANDLE (evpipe [0]), &buf, 1, &recvd, &flags, 0, 0);
2210
+ #else
2211
+ read (evpipe [0], &dummy, sizeof (dummy));
2212
+ #endif
1908
2213
  }
1909
2214
  }
1910
2215
 
1911
2216
  pipe_write_skipped = 0;
1912
2217
 
2218
+ ECB_MEMORY_FENCE; /* push out skipped, acquire flags */
2219
+
1913
2220
  #if EV_SIGNAL_ENABLE
1914
2221
  if (sig_pending)
1915
2222
  {
1916
2223
  sig_pending = 0;
1917
2224
 
2225
+ ECB_MEMORY_FENCE;
2226
+
1918
2227
  for (i = EV_NSIG - 1; i--; )
1919
2228
  if (expect_false (signals [i].pending))
1920
2229
  ev_feed_signal_event (EV_A_ i + 1);
@@ -1926,10 +2235,13 @@ pipecb (EV_P_ ev_io *iow, int revents)
1926
2235
  {
1927
2236
  async_pending = 0;
1928
2237
 
2238
+ ECB_MEMORY_FENCE;
2239
+
1929
2240
  for (i = asynccnt; i--; )
1930
2241
  if (asyncs [i]->sent)
1931
2242
  {
1932
2243
  asyncs [i]->sent = 0;
2244
+ ECB_MEMORY_FENCE_RELEASE;
1933
2245
  ev_feed_event (EV_A_ asyncs [i], EV_ASYNC);
1934
2246
  }
1935
2247
  }
@@ -1939,18 +2251,17 @@ pipecb (EV_P_ ev_io *iow, int revents)
1939
2251
  /*****************************************************************************/
1940
2252
 
1941
2253
  void
1942
- ev_feed_signal (int signum)
2254
+ ev_feed_signal (int signum) EV_THROW
1943
2255
  {
1944
2256
  #if EV_MULTIPLICITY
1945
- EV_P = signals [signum - 1].loop;
2257
+ EV_P;
2258
+ ECB_MEMORY_FENCE_ACQUIRE;
2259
+ EV_A = signals [signum - 1].loop;
1946
2260
 
1947
2261
  if (!EV_A)
1948
2262
  return;
1949
2263
  #endif
1950
2264
 
1951
- if (!ev_active (&pipe_w))
1952
- return;
1953
-
1954
2265
  signals [signum - 1].pending = 1;
1955
2266
  evpipe_write (EV_A_ &sig_pending);
1956
2267
  }
@@ -1966,11 +2277,11 @@ ev_sighandler (int signum)
1966
2277
  }
1967
2278
 
1968
2279
  void noinline
1969
- ev_feed_signal_event (EV_P_ int signum)
2280
+ ev_feed_signal_event (EV_P_ int signum) EV_THROW
1970
2281
  {
1971
2282
  WL w;
1972
2283
 
1973
- if (expect_false (signum <= 0 || signum > EV_NSIG))
2284
+ if (expect_false (signum <= 0 || signum >= EV_NSIG))
1974
2285
  return;
1975
2286
 
1976
2287
  --signum;
@@ -1984,6 +2295,7 @@ ev_feed_signal_event (EV_P_ int signum)
1984
2295
  #endif
1985
2296
 
1986
2297
  signals [signum].pending = 0;
2298
+ ECB_MEMORY_FENCE_RELEASE;
1987
2299
 
1988
2300
  for (w = signals [signum].head; w; w = w->next)
1989
2301
  ev_feed_event (EV_A_ (W)w, EV_SIGNAL);
@@ -2092,13 +2404,13 @@ childcb (EV_P_ ev_signal *sw, int revents)
2092
2404
  #endif
2093
2405
 
2094
2406
  int ecb_cold
2095
- ev_version_major (void)
2407
+ ev_version_major (void) EV_THROW
2096
2408
  {
2097
2409
  return EV_VERSION_MAJOR;
2098
2410
  }
2099
2411
 
2100
2412
  int ecb_cold
2101
- ev_version_minor (void)
2413
+ ev_version_minor (void) EV_THROW
2102
2414
  {
2103
2415
  return EV_VERSION_MINOR;
2104
2416
  }
@@ -2116,7 +2428,7 @@ enable_secure (void)
2116
2428
  }
2117
2429
 
2118
2430
  unsigned int ecb_cold
2119
- ev_supported_backends (void)
2431
+ ev_supported_backends (void) EV_THROW
2120
2432
  {
2121
2433
  unsigned int flags = 0;
2122
2434
 
@@ -2130,7 +2442,7 @@ ev_supported_backends (void)
2130
2442
  }
2131
2443
 
2132
2444
  unsigned int ecb_cold
2133
- ev_recommended_backends (void)
2445
+ ev_recommended_backends (void) EV_THROW
2134
2446
  {
2135
2447
  unsigned int flags = ev_supported_backends ();
2136
2448
 
@@ -2152,7 +2464,7 @@ ev_recommended_backends (void)
2152
2464
  }
2153
2465
 
2154
2466
  unsigned int ecb_cold
2155
- ev_embeddable_backends (void)
2467
+ ev_embeddable_backends (void) EV_THROW
2156
2468
  {
2157
2469
  int flags = EVBACKEND_EPOLL | EVBACKEND_KQUEUE | EVBACKEND_PORT;
2158
2470
 
@@ -2164,56 +2476,56 @@ ev_embeddable_backends (void)
2164
2476
  }
2165
2477
 
2166
2478
  unsigned int
2167
- ev_backend (EV_P)
2479
+ ev_backend (EV_P) EV_THROW
2168
2480
  {
2169
2481
  return backend;
2170
2482
  }
2171
2483
 
2172
2484
  #if EV_FEATURE_API
2173
2485
  unsigned int
2174
- ev_iteration (EV_P)
2486
+ ev_iteration (EV_P) EV_THROW
2175
2487
  {
2176
2488
  return loop_count;
2177
2489
  }
2178
2490
 
2179
2491
  unsigned int
2180
- ev_depth (EV_P)
2492
+ ev_depth (EV_P) EV_THROW
2181
2493
  {
2182
2494
  return loop_depth;
2183
2495
  }
2184
2496
 
2185
2497
  void
2186
- ev_set_io_collect_interval (EV_P_ ev_tstamp interval)
2498
+ ev_set_io_collect_interval (EV_P_ ev_tstamp interval) EV_THROW
2187
2499
  {
2188
2500
  io_blocktime = interval;
2189
2501
  }
2190
2502
 
2191
2503
  void
2192
- ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval)
2504
+ ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval) EV_THROW
2193
2505
  {
2194
2506
  timeout_blocktime = interval;
2195
2507
  }
2196
2508
 
2197
2509
  void
2198
- ev_set_userdata (EV_P_ void *data)
2510
+ ev_set_userdata (EV_P_ void *data) EV_THROW
2199
2511
  {
2200
2512
  userdata = data;
2201
2513
  }
2202
2514
 
2203
2515
  void *
2204
- ev_userdata (EV_P)
2516
+ ev_userdata (EV_P) EV_THROW
2205
2517
  {
2206
2518
  return userdata;
2207
2519
  }
2208
2520
 
2209
2521
  void
2210
- ev_set_invoke_pending_cb (EV_P_ void (*invoke_pending_cb)(EV_P))
2522
+ ev_set_invoke_pending_cb (EV_P_ void (*invoke_pending_cb)(EV_P)) EV_THROW
2211
2523
  {
2212
2524
  invoke_cb = invoke_pending_cb;
2213
2525
  }
2214
2526
 
2215
2527
  void
2216
- ev_set_loop_release_cb (EV_P_ void (*release)(EV_P), void (*acquire)(EV_P))
2528
+ ev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_THROW, void (*acquire)(EV_P) EV_THROW) EV_THROW
2217
2529
  {
2218
2530
  release_cb = release;
2219
2531
  acquire_cb = acquire;
@@ -2222,7 +2534,7 @@ ev_set_loop_release_cb (EV_P_ void (*release)(EV_P), void (*acquire)(EV_P))
2222
2534
 
2223
2535
  /* initialise a loop structure, must be zero-initialised */
2224
2536
  static void noinline ecb_cold
2225
- loop_init (EV_P_ unsigned int flags)
2537
+ loop_init (EV_P_ unsigned int flags) EV_THROW
2226
2538
  {
2227
2539
  if (!backend)
2228
2540
  {
@@ -2277,6 +2589,8 @@ loop_init (EV_P_ unsigned int flags)
2277
2589
  #endif
2278
2590
  pipe_write_skipped = 0;
2279
2591
  pipe_write_wanted = 0;
2592
+ evpipe [0] = -1;
2593
+ evpipe [1] = -1;
2280
2594
  #if EV_USE_INOTIFY
2281
2595
  fs_fd = flags & EVFLAG_NOINOTIFY ? -1 : -2;
2282
2596
  #endif
@@ -2337,7 +2651,7 @@ ev_loop_destroy (EV_P)
2337
2651
  #endif
2338
2652
 
2339
2653
  #if EV_CHILD_ENABLE
2340
- if (ev_is_active (&childev))
2654
+ if (ev_is_default_loop (EV_A) && ev_is_active (&childev))
2341
2655
  {
2342
2656
  ev_ref (EV_A); /* child watcher */
2343
2657
  ev_signal_stop (EV_A_ &childev);
@@ -2349,16 +2663,8 @@ ev_loop_destroy (EV_P)
2349
2663
  /*ev_ref (EV_A);*/
2350
2664
  /*ev_io_stop (EV_A_ &pipe_w);*/
2351
2665
 
2352
- #if EV_USE_EVENTFD
2353
- if (evfd >= 0)
2354
- close (evfd);
2355
- #endif
2356
-
2357
- if (evpipe [0] >= 0)
2358
- {
2359
- EV_WIN32_CLOSE_FD (evpipe [0]);
2360
- EV_WIN32_CLOSE_FD (evpipe [1]);
2361
- }
2666
+ if (evpipe [0] >= 0) EV_WIN32_CLOSE_FD (evpipe [0]);
2667
+ if (evpipe [1] >= 0) EV_WIN32_CLOSE_FD (evpipe [1]);
2362
2668
  }
2363
2669
 
2364
2670
  #if EV_USE_SIGNALFD
@@ -2454,6 +2760,7 @@ loop_fork (EV_P)
2454
2760
  infy_fork (EV_A);
2455
2761
  #endif
2456
2762
 
2763
+ #if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
2457
2764
  if (ev_is_active (&pipe_w))
2458
2765
  {
2459
2766
  /* pipe_write_wanted must be false now, so modifying fd vars should be safe */
@@ -2461,23 +2768,14 @@ loop_fork (EV_P)
2461
2768
  ev_ref (EV_A);
2462
2769
  ev_io_stop (EV_A_ &pipe_w);
2463
2770
 
2464
- #if EV_USE_EVENTFD
2465
- if (evfd >= 0)
2466
- close (evfd);
2467
- #endif
2468
-
2469
2771
  if (evpipe [0] >= 0)
2470
- {
2471
- EV_WIN32_CLOSE_FD (evpipe [0]);
2472
- EV_WIN32_CLOSE_FD (evpipe [1]);
2473
- }
2772
+ EV_WIN32_CLOSE_FD (evpipe [0]);
2474
2773
 
2475
- #if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
2476
2774
  evpipe_init (EV_A);
2477
- /* now iterate over everything, in case we missed something */
2478
- pipecb (EV_A_ &pipe_w, EV_READ);
2479
- #endif
2775
+ /* iterate over everything, in case we missed something before */
2776
+ ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);
2480
2777
  }
2778
+ #endif
2481
2779
 
2482
2780
  postfork = 0;
2483
2781
  }
@@ -2485,7 +2783,7 @@ loop_fork (EV_P)
2485
2783
  #if EV_MULTIPLICITY
2486
2784
 
2487
2785
  struct ev_loop * ecb_cold
2488
- ev_loop_new (unsigned int flags)
2786
+ ev_loop_new (unsigned int flags) EV_THROW
2489
2787
  {
2490
2788
  EV_P = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop));
2491
2789
 
@@ -2539,11 +2837,11 @@ array_verify (EV_P_ W *ws, int cnt)
2539
2837
 
2540
2838
  #if EV_FEATURE_API
2541
2839
  void ecb_cold
2542
- ev_verify (EV_P)
2840
+ ev_verify (EV_P) EV_THROW
2543
2841
  {
2544
2842
  #if EV_VERIFY
2545
2843
  int i;
2546
- WL w;
2844
+ WL w, w2;
2547
2845
 
2548
2846
  assert (activecnt >= -1);
2549
2847
 
@@ -2553,12 +2851,23 @@ ev_verify (EV_P)
2553
2851
 
2554
2852
  assert (anfdmax >= 0);
2555
2853
  for (i = 0; i < anfdmax; ++i)
2556
- for (w = anfds [i].head; w; w = w->next)
2557
- {
2558
- verify_watcher (EV_A_ (W)w);
2559
- assert (("libev: inactive fd watcher on anfd list", ev_active (w) == 1));
2560
- assert (("libev: fd mismatch between watcher and anfd", ((ev_io *)w)->fd == i));
2561
- }
2854
+ {
2855
+ int j = 0;
2856
+
2857
+ for (w = w2 = anfds [i].head; w; w = w->next)
2858
+ {
2859
+ verify_watcher (EV_A_ (W)w);
2860
+
2861
+ if (j++ & 1)
2862
+ {
2863
+ assert (("libev: io watcher list contains a loop", w != w2));
2864
+ w2 = w2->next;
2865
+ }
2866
+
2867
+ assert (("libev: inactive fd watcher on anfd list", ev_active (w) == 1));
2868
+ assert (("libev: fd mismatch between watcher and anfd", ((ev_io *)w)->fd == i));
2869
+ }
2870
+ }
2562
2871
 
2563
2872
  assert (timermax >= timercnt);
2564
2873
  verify_heap (EV_A_ timers, timercnt);
@@ -2618,7 +2927,7 @@ struct ev_loop * ecb_cold
2618
2927
  #else
2619
2928
  int
2620
2929
  #endif
2621
- ev_default_loop (unsigned int flags)
2930
+ ev_default_loop (unsigned int flags) EV_THROW
2622
2931
  {
2623
2932
  if (!ev_default_loop_ptr)
2624
2933
  {
@@ -2647,9 +2956,9 @@ ev_default_loop (unsigned int flags)
2647
2956
  }
2648
2957
 
2649
2958
  void
2650
- ev_loop_fork (EV_P)
2959
+ ev_loop_fork (EV_P) EV_THROW
2651
2960
  {
2652
- postfork = 1; /* must be in line with ev_default_fork */
2961
+ postfork = 1;
2653
2962
  }
2654
2963
 
2655
2964
  /*****************************************************************************/
@@ -2661,7 +2970,7 @@ ev_invoke (EV_P_ void *w, int revents)
2661
2970
  }
2662
2971
 
2663
2972
  unsigned int
2664
- ev_pending_count (EV_P)
2973
+ ev_pending_count (EV_P) EV_THROW
2665
2974
  {
2666
2975
  int pri;
2667
2976
  unsigned int count = 0;
@@ -2675,17 +2984,21 @@ ev_pending_count (EV_P)
2675
2984
  void noinline
2676
2985
  ev_invoke_pending (EV_P)
2677
2986
  {
2678
- int pri;
2987
+ pendingpri = NUMPRI;
2679
2988
 
2680
- for (pri = NUMPRI; pri--; )
2681
- while (pendingcnt [pri])
2682
- {
2683
- ANPENDING *p = pendings [pri] + --pendingcnt [pri];
2989
+ while (pendingpri) /* pendingpri possibly gets modified in the inner loop */
2990
+ {
2991
+ --pendingpri;
2684
2992
 
2685
- p->w->pending = 0;
2686
- EV_CB_INVOKE (p->w, p->events);
2687
- EV_FREQUENT_CHECK;
2688
- }
2993
+ while (pendingcnt [pendingpri])
2994
+ {
2995
+ ANPENDING *p = pendings [pendingpri] + --pendingcnt [pendingpri];
2996
+
2997
+ p->w->pending = 0;
2998
+ EV_CB_INVOKE (p->w, p->events);
2999
+ EV_FREQUENT_CHECK;
3000
+ }
3001
+ }
2689
3002
  }
2690
3003
 
2691
3004
  #if EV_IDLE_ENABLE
@@ -2785,8 +3098,6 @@ periodics_reify (EV_P)
2785
3098
 
2786
3099
  while (periodiccnt && ANHE_at (periodics [HEAP0]) < ev_rt_now)
2787
3100
  {
2788
- int feed_count = 0;
2789
-
2790
3101
  do
2791
3102
  {
2792
3103
  ev_periodic *w = (ev_periodic *)ANHE_w (periodics [HEAP0]);
@@ -2947,7 +3258,7 @@ VALUE ev_backend_poll(void *ptr)
2947
3258
  #endif
2948
3259
  /* ######################################## */
2949
3260
 
2950
- void
3261
+ int
2951
3262
  ev_run (EV_P_ int flags)
2952
3263
  {
2953
3264
  /* ########## NIO4R PATCHERY HO! ########## */
@@ -3129,6 +3440,7 @@ rb_thread_unsafe_dangerous_crazy_blocking_region_end(...);
3129
3440
 
3130
3441
  pipe_write_wanted = 0; /* just an optimisation, no fence needed */
3131
3442
 
3443
+ ECB_MEMORY_FENCE_ACQUIRE;
3132
3444
  if (pipe_write_skipped)
3133
3445
  {
3134
3446
  assert (("libev: pipe_w not active, but pipe not written", ev_is_active (&pipe_w)));
@@ -3171,40 +3483,42 @@ rb_thread_unsafe_dangerous_crazy_blocking_region_end(...);
3171
3483
  #if EV_FEATURE_API
3172
3484
  --loop_depth;
3173
3485
  #endif
3486
+
3487
+ return activecnt;
3174
3488
  }
3175
3489
 
3176
3490
  void
3177
- ev_break (EV_P_ int how)
3491
+ ev_break (EV_P_ int how) EV_THROW
3178
3492
  {
3179
3493
  loop_done = how;
3180
3494
  }
3181
3495
 
3182
3496
  void
3183
- ev_ref (EV_P)
3497
+ ev_ref (EV_P) EV_THROW
3184
3498
  {
3185
3499
  ++activecnt;
3186
3500
  }
3187
3501
 
3188
3502
  void
3189
- ev_unref (EV_P)
3503
+ ev_unref (EV_P) EV_THROW
3190
3504
  {
3191
3505
  --activecnt;
3192
3506
  }
3193
3507
 
3194
3508
  void
3195
- ev_now_update (EV_P)
3509
+ ev_now_update (EV_P) EV_THROW
3196
3510
  {
3197
3511
  time_update (EV_A_ 1e100);
3198
3512
  }
3199
3513
 
3200
3514
  void
3201
- ev_suspend (EV_P)
3515
+ ev_suspend (EV_P) EV_THROW
3202
3516
  {
3203
3517
  ev_now_update (EV_A);
3204
3518
  }
3205
3519
 
3206
3520
  void
3207
- ev_resume (EV_P)
3521
+ ev_resume (EV_P) EV_THROW
3208
3522
  {
3209
3523
  ev_tstamp mn_prev = mn_now;
3210
3524
 
@@ -3253,7 +3567,7 @@ clear_pending (EV_P_ W w)
3253
3567
  }
3254
3568
 
3255
3569
  int
3256
- ev_clear_pending (EV_P_ void *w)
3570
+ ev_clear_pending (EV_P_ void *w) EV_THROW
3257
3571
  {
3258
3572
  W w_ = (W)w;
3259
3573
  int pending = w_->pending;
@@ -3296,7 +3610,7 @@ ev_stop (EV_P_ W w)
3296
3610
  /*****************************************************************************/
3297
3611
 
3298
3612
  void noinline
3299
- ev_io_start (EV_P_ ev_io *w)
3613
+ ev_io_start (EV_P_ ev_io *w) EV_THROW
3300
3614
  {
3301
3615
  int fd = w->fd;
3302
3616
 
@@ -3312,6 +3626,9 @@ ev_io_start (EV_P_ ev_io *w)
3312
3626
  array_needsize (ANFD, anfds, anfdmax, fd + 1, array_init_zero);
3313
3627
  wlist_add (&anfds[fd].head, (WL)w);
3314
3628
 
3629
+ /* common bug, apparently */
3630
+ assert (("libev: ev_io_start called with corrupted watcher", ((WL)w)->next != (WL)w));
3631
+
3315
3632
  fd_change (EV_A_ fd, w->events & EV__IOFDSET | EV_ANFD_REIFY);
3316
3633
  w->events &= ~EV__IOFDSET;
3317
3634
 
@@ -3319,7 +3636,7 @@ ev_io_start (EV_P_ ev_io *w)
3319
3636
  }
3320
3637
 
3321
3638
  void noinline
3322
- ev_io_stop (EV_P_ ev_io *w)
3639
+ ev_io_stop (EV_P_ ev_io *w) EV_THROW
3323
3640
  {
3324
3641
  clear_pending (EV_A_ (W)w);
3325
3642
  if (expect_false (!ev_is_active (w)))
@@ -3338,7 +3655,7 @@ ev_io_stop (EV_P_ ev_io *w)
3338
3655
  }
3339
3656
 
3340
3657
  void noinline
3341
- ev_timer_start (EV_P_ ev_timer *w)
3658
+ ev_timer_start (EV_P_ ev_timer *w) EV_THROW
3342
3659
  {
3343
3660
  if (expect_false (ev_is_active (w)))
3344
3661
  return;
@@ -3362,7 +3679,7 @@ ev_timer_start (EV_P_ ev_timer *w)
3362
3679
  }
3363
3680
 
3364
3681
  void noinline
3365
- ev_timer_stop (EV_P_ ev_timer *w)
3682
+ ev_timer_stop (EV_P_ ev_timer *w) EV_THROW
3366
3683
  {
3367
3684
  clear_pending (EV_A_ (W)w);
3368
3685
  if (expect_false (!ev_is_active (w)))
@@ -3392,7 +3709,7 @@ ev_timer_stop (EV_P_ ev_timer *w)
3392
3709
  }
3393
3710
 
3394
3711
  void noinline
3395
- ev_timer_again (EV_P_ ev_timer *w)
3712
+ ev_timer_again (EV_P_ ev_timer *w) EV_THROW
3396
3713
  {
3397
3714
  EV_FREQUENT_CHECK;
3398
3715
 
@@ -3419,14 +3736,14 @@ ev_timer_again (EV_P_ ev_timer *w)
3419
3736
  }
3420
3737
 
3421
3738
  ev_tstamp
3422
- ev_timer_remaining (EV_P_ ev_timer *w)
3739
+ ev_timer_remaining (EV_P_ ev_timer *w) EV_THROW
3423
3740
  {
3424
3741
  return ev_at (w) - (ev_is_active (w) ? mn_now : 0.);
3425
3742
  }
3426
3743
 
3427
3744
  #if EV_PERIODIC_ENABLE
3428
3745
  void noinline
3429
- ev_periodic_start (EV_P_ ev_periodic *w)
3746
+ ev_periodic_start (EV_P_ ev_periodic *w) EV_THROW
3430
3747
  {
3431
3748
  if (expect_false (ev_is_active (w)))
3432
3749
  return;
@@ -3456,7 +3773,7 @@ ev_periodic_start (EV_P_ ev_periodic *w)
3456
3773
  }
3457
3774
 
3458
3775
  void noinline
3459
- ev_periodic_stop (EV_P_ ev_periodic *w)
3776
+ ev_periodic_stop (EV_P_ ev_periodic *w) EV_THROW
3460
3777
  {
3461
3778
  clear_pending (EV_A_ (W)w);
3462
3779
  if (expect_false (!ev_is_active (w)))
@@ -3484,7 +3801,7 @@ ev_periodic_stop (EV_P_ ev_periodic *w)
3484
3801
  }
3485
3802
 
3486
3803
  void noinline
3487
- ev_periodic_again (EV_P_ ev_periodic *w)
3804
+ ev_periodic_again (EV_P_ ev_periodic *w) EV_THROW
3488
3805
  {
3489
3806
  /* TODO: use adjustheap and recalculation */
3490
3807
  ev_periodic_stop (EV_A_ w);
@@ -3499,7 +3816,7 @@ ev_periodic_again (EV_P_ ev_periodic *w)
3499
3816
  #if EV_SIGNAL_ENABLE
3500
3817
 
3501
3818
  void noinline
3502
- ev_signal_start (EV_P_ ev_signal *w)
3819
+ ev_signal_start (EV_P_ ev_signal *w) EV_THROW
3503
3820
  {
3504
3821
  if (expect_false (ev_is_active (w)))
3505
3822
  return;
@@ -3511,6 +3828,7 @@ ev_signal_start (EV_P_ ev_signal *w)
3511
3828
  !signals [w->signum - 1].loop || signals [w->signum - 1].loop == loop));
3512
3829
 
3513
3830
  signals [w->signum - 1].loop = EV_A;
3831
+ ECB_MEMORY_FENCE_RELEASE;
3514
3832
  #endif
3515
3833
 
3516
3834
  EV_FREQUENT_CHECK;
@@ -3580,7 +3898,7 @@ ev_signal_start (EV_P_ ev_signal *w)
3580
3898
  }
3581
3899
 
3582
3900
  void noinline
3583
- ev_signal_stop (EV_P_ ev_signal *w)
3901
+ ev_signal_stop (EV_P_ ev_signal *w) EV_THROW
3584
3902
  {
3585
3903
  clear_pending (EV_A_ (W)w);
3586
3904
  if (expect_false (!ev_is_active (w)))
@@ -3621,7 +3939,7 @@ ev_signal_stop (EV_P_ ev_signal *w)
3621
3939
  #if EV_CHILD_ENABLE
3622
3940
 
3623
3941
  void
3624
- ev_child_start (EV_P_ ev_child *w)
3942
+ ev_child_start (EV_P_ ev_child *w) EV_THROW
3625
3943
  {
3626
3944
  #if EV_MULTIPLICITY
3627
3945
  assert (("libev: child watchers are only supported in the default loop", loop == ev_default_loop_ptr));
@@ -3638,7 +3956,7 @@ ev_child_start (EV_P_ ev_child *w)
3638
3956
  }
3639
3957
 
3640
3958
  void
3641
- ev_child_stop (EV_P_ ev_child *w)
3959
+ ev_child_stop (EV_P_ ev_child *w) EV_THROW
3642
3960
  {
3643
3961
  clear_pending (EV_A_ (W)w);
3644
3962
  if (expect_false (!ev_is_active (w)))
@@ -3675,7 +3993,10 @@ static void noinline stat_timer_cb (EV_P_ ev_timer *w_, int revents);
3675
3993
  static void noinline
3676
3994
  infy_add (EV_P_ ev_stat *w)
3677
3995
  {
3678
- 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);
3996
+ w->wd = inotify_add_watch (fs_fd, w->path,
3997
+ IN_ATTRIB | IN_DELETE_SELF | IN_MOVE_SELF | IN_MODIFY
3998
+ | IN_CREATE | IN_DELETE | IN_MOVED_FROM | IN_MOVED_TO
3999
+ | IN_DONT_FOLLOW | IN_MASK_ADD);
3679
4000
 
3680
4001
  if (w->wd >= 0)
3681
4002
  {
@@ -3689,10 +4010,16 @@ infy_add (EV_P_ ev_stat *w)
3689
4010
  w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL;
3690
4011
  else if (!statfs (w->path, &sfs)
3691
4012
  && (sfs.f_type == 0x1373 /* devfs */
4013
+ || sfs.f_type == 0x4006 /* fat */
4014
+ || sfs.f_type == 0x4d44 /* msdos */
3692
4015
  || sfs.f_type == 0xEF53 /* ext2/3 */
4016
+ || sfs.f_type == 0x72b6 /* jffs2 */
4017
+ || sfs.f_type == 0x858458f6 /* ramfs */
4018
+ || sfs.f_type == 0x5346544e /* ntfs */
3693
4019
  || sfs.f_type == 0x3153464a /* jfs */
4020
+ || sfs.f_type == 0x9123683e /* btrfs */
3694
4021
  || sfs.f_type == 0x52654973 /* reiser3 */
3695
- || sfs.f_type == 0x01021994 /* tempfs */
4022
+ || sfs.f_type == 0x01021994 /* tmpfs */
3696
4023
  || sfs.f_type == 0x58465342 /* xfs */))
3697
4024
  w->timer.repeat = 0.; /* filesystem is local, kernel new enough */
3698
4025
  else
@@ -3815,7 +4142,7 @@ ev_check_2625 (EV_P)
3815
4142
  inline_size int
3816
4143
  infy_newfd (void)
3817
4144
  {
3818
- #if defined (IN_CLOEXEC) && defined (IN_NONBLOCK)
4145
+ #if defined IN_CLOEXEC && defined IN_NONBLOCK
3819
4146
  int fd = inotify_init1 (IN_CLOEXEC | IN_NONBLOCK);
3820
4147
  if (fd >= 0)
3821
4148
  return fd;
@@ -3900,7 +4227,7 @@ infy_fork (EV_P)
3900
4227
  #endif
3901
4228
 
3902
4229
  void
3903
- ev_stat_stat (EV_P_ ev_stat *w)
4230
+ ev_stat_stat (EV_P_ ev_stat *w) EV_THROW
3904
4231
  {
3905
4232
  if (lstat (w->path, &w->attr) < 0)
3906
4233
  w->attr.st_nlink = 0;
@@ -3949,7 +4276,7 @@ stat_timer_cb (EV_P_ ev_timer *w_, int revents)
3949
4276
  }
3950
4277
 
3951
4278
  void
3952
- ev_stat_start (EV_P_ ev_stat *w)
4279
+ ev_stat_start (EV_P_ ev_stat *w) EV_THROW
3953
4280
  {
3954
4281
  if (expect_false (ev_is_active (w)))
3955
4282
  return;
@@ -3980,7 +4307,7 @@ ev_stat_start (EV_P_ ev_stat *w)
3980
4307
  }
3981
4308
 
3982
4309
  void
3983
- ev_stat_stop (EV_P_ ev_stat *w)
4310
+ ev_stat_stop (EV_P_ ev_stat *w) EV_THROW
3984
4311
  {
3985
4312
  clear_pending (EV_A_ (W)w);
3986
4313
  if (expect_false (!ev_is_active (w)))
@@ -4006,7 +4333,7 @@ ev_stat_stop (EV_P_ ev_stat *w)
4006
4333
 
4007
4334
  #if EV_IDLE_ENABLE
4008
4335
  void
4009
- ev_idle_start (EV_P_ ev_idle *w)
4336
+ ev_idle_start (EV_P_ ev_idle *w) EV_THROW
4010
4337
  {
4011
4338
  if (expect_false (ev_is_active (w)))
4012
4339
  return;
@@ -4029,7 +4356,7 @@ ev_idle_start (EV_P_ ev_idle *w)
4029
4356
  }
4030
4357
 
4031
4358
  void
4032
- ev_idle_stop (EV_P_ ev_idle *w)
4359
+ ev_idle_stop (EV_P_ ev_idle *w) EV_THROW
4033
4360
  {
4034
4361
  clear_pending (EV_A_ (W)w);
4035
4362
  if (expect_false (!ev_is_active (w)))
@@ -4053,7 +4380,7 @@ ev_idle_stop (EV_P_ ev_idle *w)
4053
4380
 
4054
4381
  #if EV_PREPARE_ENABLE
4055
4382
  void
4056
- ev_prepare_start (EV_P_ ev_prepare *w)
4383
+ ev_prepare_start (EV_P_ ev_prepare *w) EV_THROW
4057
4384
  {
4058
4385
  if (expect_false (ev_is_active (w)))
4059
4386
  return;
@@ -4068,7 +4395,7 @@ ev_prepare_start (EV_P_ ev_prepare *w)
4068
4395
  }
4069
4396
 
4070
4397
  void
4071
- ev_prepare_stop (EV_P_ ev_prepare *w)
4398
+ ev_prepare_stop (EV_P_ ev_prepare *w) EV_THROW
4072
4399
  {
4073
4400
  clear_pending (EV_A_ (W)w);
4074
4401
  if (expect_false (!ev_is_active (w)))
@@ -4091,7 +4418,7 @@ ev_prepare_stop (EV_P_ ev_prepare *w)
4091
4418
 
4092
4419
  #if EV_CHECK_ENABLE
4093
4420
  void
4094
- ev_check_start (EV_P_ ev_check *w)
4421
+ ev_check_start (EV_P_ ev_check *w) EV_THROW
4095
4422
  {
4096
4423
  if (expect_false (ev_is_active (w)))
4097
4424
  return;
@@ -4106,7 +4433,7 @@ ev_check_start (EV_P_ ev_check *w)
4106
4433
  }
4107
4434
 
4108
4435
  void
4109
- ev_check_stop (EV_P_ ev_check *w)
4436
+ ev_check_stop (EV_P_ ev_check *w) EV_THROW
4110
4437
  {
4111
4438
  clear_pending (EV_A_ (W)w);
4112
4439
  if (expect_false (!ev_is_active (w)))
@@ -4129,7 +4456,7 @@ ev_check_stop (EV_P_ ev_check *w)
4129
4456
 
4130
4457
  #if EV_EMBED_ENABLE
4131
4458
  void noinline
4132
- ev_embed_sweep (EV_P_ ev_embed *w)
4459
+ ev_embed_sweep (EV_P_ ev_embed *w) EV_THROW
4133
4460
  {
4134
4461
  ev_run (w->other, EVRUN_NOWAIT);
4135
4462
  }
@@ -4187,7 +4514,7 @@ embed_idle_cb (EV_P_ ev_idle *idle, int revents)
4187
4514
  #endif
4188
4515
 
4189
4516
  void
4190
- ev_embed_start (EV_P_ ev_embed *w)
4517
+ ev_embed_start (EV_P_ ev_embed *w) EV_THROW
4191
4518
  {
4192
4519
  if (expect_false (ev_is_active (w)))
4193
4520
  return;
@@ -4218,7 +4545,7 @@ ev_embed_start (EV_P_ ev_embed *w)
4218
4545
  }
4219
4546
 
4220
4547
  void
4221
- ev_embed_stop (EV_P_ ev_embed *w)
4548
+ ev_embed_stop (EV_P_ ev_embed *w) EV_THROW
4222
4549
  {
4223
4550
  clear_pending (EV_A_ (W)w);
4224
4551
  if (expect_false (!ev_is_active (w)))
@@ -4238,7 +4565,7 @@ ev_embed_stop (EV_P_ ev_embed *w)
4238
4565
 
4239
4566
  #if EV_FORK_ENABLE
4240
4567
  void
4241
- ev_fork_start (EV_P_ ev_fork *w)
4568
+ ev_fork_start (EV_P_ ev_fork *w) EV_THROW
4242
4569
  {
4243
4570
  if (expect_false (ev_is_active (w)))
4244
4571
  return;
@@ -4253,7 +4580,7 @@ ev_fork_start (EV_P_ ev_fork *w)
4253
4580
  }
4254
4581
 
4255
4582
  void
4256
- ev_fork_stop (EV_P_ ev_fork *w)
4583
+ ev_fork_stop (EV_P_ ev_fork *w) EV_THROW
4257
4584
  {
4258
4585
  clear_pending (EV_A_ (W)w);
4259
4586
  if (expect_false (!ev_is_active (w)))
@@ -4276,7 +4603,7 @@ ev_fork_stop (EV_P_ ev_fork *w)
4276
4603
 
4277
4604
  #if EV_CLEANUP_ENABLE
4278
4605
  void
4279
- ev_cleanup_start (EV_P_ ev_cleanup *w)
4606
+ ev_cleanup_start (EV_P_ ev_cleanup *w) EV_THROW
4280
4607
  {
4281
4608
  if (expect_false (ev_is_active (w)))
4282
4609
  return;
@@ -4293,7 +4620,7 @@ ev_cleanup_start (EV_P_ ev_cleanup *w)
4293
4620
  }
4294
4621
 
4295
4622
  void
4296
- ev_cleanup_stop (EV_P_ ev_cleanup *w)
4623
+ ev_cleanup_stop (EV_P_ ev_cleanup *w) EV_THROW
4297
4624
  {
4298
4625
  clear_pending (EV_A_ (W)w);
4299
4626
  if (expect_false (!ev_is_active (w)))
@@ -4317,7 +4644,7 @@ ev_cleanup_stop (EV_P_ ev_cleanup *w)
4317
4644
 
4318
4645
  #if EV_ASYNC_ENABLE
4319
4646
  void
4320
- ev_async_start (EV_P_ ev_async *w)
4647
+ ev_async_start (EV_P_ ev_async *w) EV_THROW
4321
4648
  {
4322
4649
  if (expect_false (ev_is_active (w)))
4323
4650
  return;
@@ -4336,7 +4663,7 @@ ev_async_start (EV_P_ ev_async *w)
4336
4663
  }
4337
4664
 
4338
4665
  void
4339
- ev_async_stop (EV_P_ ev_async *w)
4666
+ ev_async_stop (EV_P_ ev_async *w) EV_THROW
4340
4667
  {
4341
4668
  clear_pending (EV_A_ (W)w);
4342
4669
  if (expect_false (!ev_is_active (w)))
@@ -4357,7 +4684,7 @@ ev_async_stop (EV_P_ ev_async *w)
4357
4684
  }
4358
4685
 
4359
4686
  void
4360
- ev_async_send (EV_P_ ev_async *w)
4687
+ ev_async_send (EV_P_ ev_async *w) EV_THROW
4361
4688
  {
4362
4689
  w->sent = 1;
4363
4690
  evpipe_write (EV_A_ &async_pending);
@@ -4404,7 +4731,7 @@ once_cb_to (EV_P_ ev_timer *w, int revents)
4404
4731
  }
4405
4732
 
4406
4733
  void
4407
- ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg)
4734
+ ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) EV_THROW
4408
4735
  {
4409
4736
  struct ev_once *once = (struct ev_once *)ev_malloc (sizeof (struct ev_once));
4410
4737
 
@@ -4436,7 +4763,7 @@ ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, vo
4436
4763
 
4437
4764
  #if EV_WALK_ENABLE
4438
4765
  void ecb_cold
4439
- ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
4766
+ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) EV_THROW
4440
4767
  {
4441
4768
  int i, j;
4442
4769
  ev_watcher_list *wl, *wn;