1e66f31c5Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2e66f31c5Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 3e66f31c5Sopenharmony_ci * of this software and associated documentation files (the "Software"), to 4e66f31c5Sopenharmony_ci * deal in the Software without restriction, including without limitation the 5e66f31c5Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 6e66f31c5Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 7e66f31c5Sopenharmony_ci * furnished to do so, subject to the following conditions: 8e66f31c5Sopenharmony_ci * 9e66f31c5Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 10e66f31c5Sopenharmony_ci * all copies or substantial portions of the Software. 11e66f31c5Sopenharmony_ci * 12e66f31c5Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13e66f31c5Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14e66f31c5Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15e66f31c5Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16e66f31c5Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17e66f31c5Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 18e66f31c5Sopenharmony_ci * IN THE SOFTWARE. 19e66f31c5Sopenharmony_ci */ 20e66f31c5Sopenharmony_ci 21e66f31c5Sopenharmony_ci/* This file contains both the uv__async internal infrastructure and the 22e66f31c5Sopenharmony_ci * user-facing uv_async_t functions. 23e66f31c5Sopenharmony_ci */ 24e66f31c5Sopenharmony_ci 25e66f31c5Sopenharmony_ci#include "uv.h" 26e66f31c5Sopenharmony_ci#include "internal.h" 27e66f31c5Sopenharmony_ci#include "uv_log.h" 28e66f31c5Sopenharmony_ci 29e66f31c5Sopenharmony_ci#include <errno.h> 30e66f31c5Sopenharmony_ci#include <stdatomic.h> 31e66f31c5Sopenharmony_ci#include <stdio.h> /* snprintf() */ 32e66f31c5Sopenharmony_ci#include <assert.h> 33e66f31c5Sopenharmony_ci#include <stdlib.h> 34e66f31c5Sopenharmony_ci#include <string.h> 35e66f31c5Sopenharmony_ci#include <unistd.h> 36e66f31c5Sopenharmony_ci#include <sched.h> /* sched_yield() */ 37e66f31c5Sopenharmony_ci 38e66f31c5Sopenharmony_ci#ifdef __linux__ 39e66f31c5Sopenharmony_ci#include <sys/eventfd.h> 40e66f31c5Sopenharmony_ci#endif 41e66f31c5Sopenharmony_ci 42e66f31c5Sopenharmony_ci#ifdef USE_FFRT 43e66f31c5Sopenharmony_ci#include "ffrt.h" 44e66f31c5Sopenharmony_ci#include "c/executor_task.h" 45e66f31c5Sopenharmony_ci#endif 46e66f31c5Sopenharmony_ci 47e66f31c5Sopenharmony_cistatic void uv__async_send(uv_async_t* handle); 48e66f31c5Sopenharmony_cistatic int uv__async_start(uv_loop_t* loop); 49e66f31c5Sopenharmony_ci 50e66f31c5Sopenharmony_ci 51e66f31c5Sopenharmony_ciint uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) { 52e66f31c5Sopenharmony_ci int err; 53e66f31c5Sopenharmony_ci 54e66f31c5Sopenharmony_ci err = uv__async_start(loop); 55e66f31c5Sopenharmony_ci if (err) 56e66f31c5Sopenharmony_ci return err; 57e66f31c5Sopenharmony_ci 58e66f31c5Sopenharmony_ci uv__handle_init(loop, (uv_handle_t*)handle, UV_ASYNC); 59e66f31c5Sopenharmony_ci handle->async_cb = async_cb; 60e66f31c5Sopenharmony_ci handle->pending = 0; 61e66f31c5Sopenharmony_ci 62e66f31c5Sopenharmony_ci uv__queue_insert_tail(&loop->async_handles, &handle->queue); 63e66f31c5Sopenharmony_ci uv__handle_start(handle); 64e66f31c5Sopenharmony_ci 65e66f31c5Sopenharmony_ci return 0; 66e66f31c5Sopenharmony_ci} 67e66f31c5Sopenharmony_ci 68e66f31c5Sopenharmony_ci 69e66f31c5Sopenharmony_ciint uv_async_send(uv_async_t* handle) { 70e66f31c5Sopenharmony_ci _Atomic int* pending; 71e66f31c5Sopenharmony_ci 72e66f31c5Sopenharmony_ci#ifdef USE_OHOS_DFX 73e66f31c5Sopenharmony_ci if (handle == NULL) { 74e66f31c5Sopenharmony_ci UV_LOGF("handle is NULL"); 75e66f31c5Sopenharmony_ci return -1; 76e66f31c5Sopenharmony_ci } 77e66f31c5Sopenharmony_ci#endif 78e66f31c5Sopenharmony_ci 79e66f31c5Sopenharmony_ci pending = (_Atomic int*) &handle->pending; 80e66f31c5Sopenharmony_ci 81e66f31c5Sopenharmony_ci 82e66f31c5Sopenharmony_ci /* Do a cheap read first. */ 83e66f31c5Sopenharmony_ci if (atomic_load_explicit(pending, memory_order_relaxed) != 0) 84e66f31c5Sopenharmony_ci return 0; 85e66f31c5Sopenharmony_ci 86e66f31c5Sopenharmony_ci /* Wake up the other thread's event loop. */ 87e66f31c5Sopenharmony_ci if (atomic_exchange(pending, 1) != 0) 88e66f31c5Sopenharmony_ci return 0; 89e66f31c5Sopenharmony_ci 90e66f31c5Sopenharmony_ci /* Wake up the other thread's event loop. */ 91e66f31c5Sopenharmony_ci uv__async_send(handle); 92e66f31c5Sopenharmony_ci return 0; 93e66f31c5Sopenharmony_ci} 94e66f31c5Sopenharmony_ci 95e66f31c5Sopenharmony_ci 96e66f31c5Sopenharmony_ci 97e66f31c5Sopenharmony_civoid uv__async_close(uv_async_t* handle) { 98e66f31c5Sopenharmony_ci atomic_exchange((_Atomic int*) &handle->pending, 0); 99e66f31c5Sopenharmony_ci uv__queue_remove(&handle->queue); 100e66f31c5Sopenharmony_ci uv__handle_stop(handle); 101e66f31c5Sopenharmony_ci} 102e66f31c5Sopenharmony_ci 103e66f31c5Sopenharmony_ci 104e66f31c5Sopenharmony_cistatic void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { 105e66f31c5Sopenharmony_ci char buf[1024]; 106e66f31c5Sopenharmony_ci ssize_t r; 107e66f31c5Sopenharmony_ci struct uv__queue queue; 108e66f31c5Sopenharmony_ci struct uv__queue* q; 109e66f31c5Sopenharmony_ci uv_async_t* h; 110e66f31c5Sopenharmony_ci _Atomic int *pending; 111e66f31c5Sopenharmony_ci 112e66f31c5Sopenharmony_ci assert(w == &loop->async_io_watcher); 113e66f31c5Sopenharmony_ci 114e66f31c5Sopenharmony_ci for (;;) { 115e66f31c5Sopenharmony_ci r = read(w->fd, buf, sizeof(buf)); 116e66f31c5Sopenharmony_ci 117e66f31c5Sopenharmony_ci if (r == sizeof(buf)) 118e66f31c5Sopenharmony_ci continue; 119e66f31c5Sopenharmony_ci 120e66f31c5Sopenharmony_ci if (r != -1) 121e66f31c5Sopenharmony_ci break; 122e66f31c5Sopenharmony_ci 123e66f31c5Sopenharmony_ci if (errno == EAGAIN || errno == EWOULDBLOCK) 124e66f31c5Sopenharmony_ci break; 125e66f31c5Sopenharmony_ci 126e66f31c5Sopenharmony_ci if (errno == EINTR) 127e66f31c5Sopenharmony_ci continue; 128e66f31c5Sopenharmony_ci 129e66f31c5Sopenharmony_ci#ifdef PRINT_ERRNO_ABORT 130e66f31c5Sopenharmony_ci UV_ERRNO_ABORT("errno is %d, loop addr is %zu, fd is %d (%s:%s:%d)", 131e66f31c5Sopenharmony_ci errno, (size_t)loop, w->fd, __FILE__, __func__, __LINE__); 132e66f31c5Sopenharmony_ci#else 133e66f31c5Sopenharmony_ci abort(); 134e66f31c5Sopenharmony_ci#endif 135e66f31c5Sopenharmony_ci } 136e66f31c5Sopenharmony_ci 137e66f31c5Sopenharmony_ci uv__queue_move(&loop->async_handles, &queue); 138e66f31c5Sopenharmony_ci while (!uv__queue_empty(&queue)) { 139e66f31c5Sopenharmony_ci q = uv__queue_head(&queue); 140e66f31c5Sopenharmony_ci h = uv__queue_data(q, uv_async_t, queue); 141e66f31c5Sopenharmony_ci 142e66f31c5Sopenharmony_ci uv__queue_remove(q); 143e66f31c5Sopenharmony_ci uv__queue_insert_tail(&loop->async_handles, q); 144e66f31c5Sopenharmony_ci 145e66f31c5Sopenharmony_ci /* Atomically fetch and clear pending flag */ 146e66f31c5Sopenharmony_ci pending = (_Atomic int*) &h->pending; 147e66f31c5Sopenharmony_ci if (atomic_exchange(pending, 0) == 0) 148e66f31c5Sopenharmony_ci continue; 149e66f31c5Sopenharmony_ci 150e66f31c5Sopenharmony_ci if (h->async_cb == NULL) 151e66f31c5Sopenharmony_ci continue; 152e66f31c5Sopenharmony_ci 153e66f31c5Sopenharmony_ci h->async_cb(h); 154e66f31c5Sopenharmony_ci } 155e66f31c5Sopenharmony_ci} 156e66f31c5Sopenharmony_ci 157e66f31c5Sopenharmony_ci 158e66f31c5Sopenharmony_cistatic void uv__async_send(uv_async_t* handle) { 159e66f31c5Sopenharmony_ci const void* buf; 160e66f31c5Sopenharmony_ci ssize_t len; 161e66f31c5Sopenharmony_ci int fd; 162e66f31c5Sopenharmony_ci int r; 163e66f31c5Sopenharmony_ci 164e66f31c5Sopenharmony_ci uv_loop_t* loop = handle->loop; 165e66f31c5Sopenharmony_ci if (loop == NULL) { 166e66f31c5Sopenharmony_ci UV_LOGF("loop is NULL"); 167e66f31c5Sopenharmony_ci return; 168e66f31c5Sopenharmony_ci } 169e66f31c5Sopenharmony_ci 170e66f31c5Sopenharmony_ci buf = ""; 171e66f31c5Sopenharmony_ci len = 1; 172e66f31c5Sopenharmony_ci fd = loop->async_wfd; 173e66f31c5Sopenharmony_ci 174e66f31c5Sopenharmony_ci#if defined(__linux__) 175e66f31c5Sopenharmony_ci if (fd == -1) { 176e66f31c5Sopenharmony_ci static const uint64_t val = 1; 177e66f31c5Sopenharmony_ci buf = &val; 178e66f31c5Sopenharmony_ci len = sizeof(val); 179e66f31c5Sopenharmony_ci fd = loop->async_io_watcher.fd; /* eventfd */ 180e66f31c5Sopenharmony_ci } 181e66f31c5Sopenharmony_ci#endif 182e66f31c5Sopenharmony_ci 183e66f31c5Sopenharmony_ci do 184e66f31c5Sopenharmony_ci r = write(fd, buf, len); 185e66f31c5Sopenharmony_ci while (r == -1 && errno == EINTR && atomic_load_explicit((_Atomic int*) &handle->pending, memory_order_relaxed) == 1); 186e66f31c5Sopenharmony_ci 187e66f31c5Sopenharmony_ci if (r == len) 188e66f31c5Sopenharmony_ci return; 189e66f31c5Sopenharmony_ci 190e66f31c5Sopenharmony_ci if (r == -1) 191e66f31c5Sopenharmony_ci if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) 192e66f31c5Sopenharmony_ci return; 193e66f31c5Sopenharmony_ci 194e66f31c5Sopenharmony_ci#ifdef PRINT_ERRNO_ABORT 195e66f31c5Sopenharmony_ci UV_ERRNO_ABORT("errno is %d, loop addr is %zu, fd is %d (%s:%s:%d)", 196e66f31c5Sopenharmony_ci errno, (size_t)loop, fd, __FILE__, __func__, __LINE__); 197e66f31c5Sopenharmony_ci#else 198e66f31c5Sopenharmony_ci abort(); 199e66f31c5Sopenharmony_ci#endif 200e66f31c5Sopenharmony_ci} 201e66f31c5Sopenharmony_ci 202e66f31c5Sopenharmony_ci 203e66f31c5Sopenharmony_cistatic int uv__async_start(uv_loop_t* loop) { 204e66f31c5Sopenharmony_ci int pipefd[2]; 205e66f31c5Sopenharmony_ci int err; 206e66f31c5Sopenharmony_ci 207e66f31c5Sopenharmony_ci if (loop->async_io_watcher.fd != -1) 208e66f31c5Sopenharmony_ci return 0; 209e66f31c5Sopenharmony_ci 210e66f31c5Sopenharmony_ci#ifdef __linux__ 211e66f31c5Sopenharmony_ci err = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); 212e66f31c5Sopenharmony_ci if (err < 0) 213e66f31c5Sopenharmony_ci return UV__ERR(errno); 214e66f31c5Sopenharmony_ci 215e66f31c5Sopenharmony_ci pipefd[0] = err; 216e66f31c5Sopenharmony_ci pipefd[1] = -1; 217e66f31c5Sopenharmony_ci#ifdef USE_OHOS_DFX 218e66f31c5Sopenharmony_ci fdsan_exchange_owner_tag(pipefd[0], 0, uv__get_addr_tag((void *)&loop->async_io_watcher)); 219e66f31c5Sopenharmony_ci#endif 220e66f31c5Sopenharmony_ci#else 221e66f31c5Sopenharmony_ci err = uv__make_pipe(pipefd, UV_NONBLOCK_PIPE); 222e66f31c5Sopenharmony_ci if (err < 0) 223e66f31c5Sopenharmony_ci return err; 224e66f31c5Sopenharmony_ci#endif 225e66f31c5Sopenharmony_ci 226e66f31c5Sopenharmony_ci uv__io_init(&loop->async_io_watcher, uv__async_io, pipefd[0]); 227e66f31c5Sopenharmony_ci uv__io_start(loop, &loop->async_io_watcher, POLLIN); 228e66f31c5Sopenharmony_ci loop->async_wfd = pipefd[1]; 229e66f31c5Sopenharmony_ci UV_LOGI("open:%{public}zu, pipefd[0]:%{public}d", (size_t)loop, pipefd[0]); 230e66f31c5Sopenharmony_ci return 0; 231e66f31c5Sopenharmony_ci} 232e66f31c5Sopenharmony_ci 233e66f31c5Sopenharmony_ci 234e66f31c5Sopenharmony_ciint uv__async_fork(uv_loop_t* loop) { 235e66f31c5Sopenharmony_ci if (loop->async_io_watcher.fd == -1) /* never started */ 236e66f31c5Sopenharmony_ci return 0; 237e66f31c5Sopenharmony_ci 238e66f31c5Sopenharmony_ci uv__async_stop(loop); 239e66f31c5Sopenharmony_ci 240e66f31c5Sopenharmony_ci return uv__async_start(loop); 241e66f31c5Sopenharmony_ci} 242e66f31c5Sopenharmony_ci 243e66f31c5Sopenharmony_ci 244e66f31c5Sopenharmony_civoid uv__async_stop(uv_loop_t* loop) { 245e66f31c5Sopenharmony_ci if (loop->async_io_watcher.fd == -1) 246e66f31c5Sopenharmony_ci return; 247e66f31c5Sopenharmony_ci 248e66f31c5Sopenharmony_ci if (loop->async_wfd != -1) { 249e66f31c5Sopenharmony_ci if (loop->async_wfd != loop->async_io_watcher.fd) { 250e66f31c5Sopenharmony_ci UV_LOGI("close:%{public}zu, async_wfd:%{public}d", (size_t)loop, loop->async_wfd); 251e66f31c5Sopenharmony_ci uv__close(loop->async_wfd); 252e66f31c5Sopenharmony_ci } 253e66f31c5Sopenharmony_ci loop->async_wfd = -1; 254e66f31c5Sopenharmony_ci } 255e66f31c5Sopenharmony_ci 256e66f31c5Sopenharmony_ci uv__io_stop(loop, &loop->async_io_watcher, POLLIN); 257e66f31c5Sopenharmony_ci#ifdef USE_FFRT 258e66f31c5Sopenharmony_ci if (ffrt_get_cur_task() != NULL) { 259e66f31c5Sopenharmony_ci uv__epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, loop->async_io_watcher.fd, NULL); 260e66f31c5Sopenharmony_ci } 261e66f31c5Sopenharmony_ci#endif 262e66f31c5Sopenharmony_ci 263e66f31c5Sopenharmony_ci#if defined(__linux__) && defined(USE_OHOS_DFX) 264e66f31c5Sopenharmony_ci fdsan_close_with_tag(loop->async_io_watcher.fd, uv__get_addr_tag((void *)&loop->async_io_watcher)); 265e66f31c5Sopenharmony_ci#else 266e66f31c5Sopenharmony_ci uv__close(loop->async_io_watcher.fd); 267e66f31c5Sopenharmony_ci#endif 268e66f31c5Sopenharmony_ci UV_LOGI("close:%{public}zu, async_io_wfd:%{public}d", (size_t)loop, loop->async_io_watcher.fd); 269e66f31c5Sopenharmony_ci loop->async_io_watcher.fd = -1; 270e66f31c5Sopenharmony_ci} 271e66f31c5Sopenharmony_ci 272