24
24
25
25
#include "uv.h"
26
26
#include "internal.h"
27
+ #include "atomic-ops.h"
27
28
28
29
#include <errno.h>
29
30
#include <stdio.h> /* snprintf() */
35
36
static void uv__async_event (uv_loop_t * loop ,
36
37
struct uv__async * w ,
37
38
unsigned int nevents );
38
- static int uv__async_make_pending (int * pending );
39
39
static int uv__async_eventfd (void );
40
40
41
41
@@ -58,7 +58,11 @@ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
58
58
59
59
60
60
int uv_async_send (uv_async_t * handle ) {
61
- if (uv__async_make_pending (& handle -> pending ) == 0 )
61
+ /* Do a cheap read first. */
62
+ if (ACCESS_ONCE (int , handle -> pending ) != 0 )
63
+ return 0 ;
64
+
65
+ if (cmpxchgi (& handle -> pending , 0 , 1 ) == 0 )
62
66
uv__async_send (& handle -> loop -> async_watcher );
63
67
64
68
return 0 ;
@@ -80,9 +84,8 @@ static void uv__async_event(uv_loop_t* loop,
80
84
QUEUE_FOREACH (q , & loop -> async_handles ) {
81
85
h = QUEUE_DATA (q , uv_async_t , queue );
82
86
83
- if (h -> pending == 0 )
87
+ if (cmpxchgi ( & h -> pending , 1 , 0 ) == 0 )
84
88
continue ;
85
- h -> pending = 0 ;
86
89
87
90
if (h -> async_cb == NULL )
88
91
continue ;
@@ -91,37 +94,6 @@ static void uv__async_event(uv_loop_t* loop,
91
94
}
92
95
93
96
94
- static int uv__async_make_pending (int * pending ) {
95
- /* Do a cheap read first. */
96
- if (ACCESS_ONCE (int , * pending ) != 0 )
97
- return 1 ;
98
-
99
- /* Micro-optimization: use atomic memory operations to detect if we've been
100
- * preempted by another thread and don't have to make an expensive syscall.
101
- * This speeds up the heavily contended case by about 1-2% and has little
102
- * if any impact on the non-contended case.
103
- *
104
- * Use XCHG instead of the CMPXCHG that __sync_val_compare_and_swap() emits
105
- * on x86, it's about 4x faster. It probably makes zero difference in the
106
- * grand scheme of things but I'm OCD enough not to let this one pass.
107
- */
108
- #if defined(__i386__ ) || defined(__x86_64__ )
109
- {
110
- unsigned int val = 1 ;
111
- __asm__ __volatile__ ("xchgl %0, %1"
112
- : "+r" (val )
113
- : "m" (* pending ));
114
- return val != 0 ;
115
- }
116
- #elif defined(__GNUC__ ) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ > 0 )
117
- return __sync_val_compare_and_swap (pending , 0 , 1 ) != 0 ;
118
- #else
119
- ACCESS_ONCE (int , * pending ) = 1 ;
120
- return 0 ;
121
- #endif
122
- }
123
-
124
-
125
97
static void uv__async_io (uv_loop_t * loop , uv__io_t * w , unsigned int events ) {
126
98
struct uv__async * wa ;
127
99
char buf [1024 ];
0 commit comments