diff options
author | libuv upstream <libuv@googlegroups.com> | 2019-06-10 13:17:21 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2019-06-18 11:45:34 (GMT) |
commit | b4069b04ff63b327ff4881282200c3c73fded34d (patch) | |
tree | f1c97b98e2253ec8e4a9b75ee2f8f99426e9b2f6 /src/unix/async.c | |
parent | 4fcb0d0213112bb2fdb04bb27e82543b93cfe41d (diff) | |
download | CMake-b4069b04ff63b327ff4881282200c3c73fded34d.zip CMake-b4069b04ff63b327ff4881282200c3c73fded34d.tar.gz CMake-b4069b04ff63b327ff4881282200c3c73fded34d.tar.bz2 |
libuv 2019-06-10 (ee24ce90)
Code extracted from:
https://github.com/libuv/libuv.git
at commit ee24ce900e5714c950b248da2bdd311b01c983be (v1.x).
Diffstat (limited to 'src/unix/async.c')
-rw-r--r-- | src/unix/async.c | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/src/unix/async.c b/src/unix/async.c index 0b450ae..a5c47bc 100644 --- a/src/unix/async.c +++ b/src/unix/async.c @@ -61,14 +61,43 @@ int uv_async_send(uv_async_t* handle) { if (ACCESS_ONCE(int, handle->pending) != 0) return 0; - if (cmpxchgi(&handle->pending, 0, 1) == 0) - uv__async_send(handle->loop); + /* Tell the other thread we're busy with the handle. */ + if (cmpxchgi(&handle->pending, 0, 1) != 0) + return 0; + + /* Wake up the other thread's event loop. */ + uv__async_send(handle->loop); + + /* Tell the other thread we're done. */ + if (cmpxchgi(&handle->pending, 1, 2) != 1) + abort(); return 0; } +/* Only call this from the event loop thread. */ +static int uv__async_spin(uv_async_t* handle) { + int rc; + + for (;;) { + /* rc=0 -- handle is not pending. + * rc=1 -- handle is pending, other thread is still working with it. + * rc=2 -- handle is pending, other thread is done. + */ + rc = cmpxchgi(&handle->pending, 2, 0); + + if (rc != 1) + return rc; + + /* Other thread is busy with this handle, spin until it's done. */ + cpu_relax(); + } +} + + void uv__async_close(uv_async_t* handle) { + uv__async_spin(handle); QUEUE_REMOVE(&handle->queue); uv__handle_stop(handle); } @@ -109,8 +138,8 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { QUEUE_REMOVE(q); QUEUE_INSERT_TAIL(&loop->async_handles, q); - if (cmpxchgi(&h->pending, 1, 0) == 0) - continue; + if (0 == uv__async_spin(h)) + continue; /* Not pending. */ if (h->async_cb == NULL) continue; |