nio4r 0.4.6-java → 0.5.0-java

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.
data/.travis.yml CHANGED
@@ -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
data/ext/libev/Changes CHANGED
@@ -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
data/ext/libev/LICENSE CHANGED
@@ -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
data/ext/libev/README CHANGED
@@ -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
data/ext/libev/ev.c CHANGED
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * libev event processing core, watcher management
3
3
  *
4
- * Copyright (c) 2007,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;