1e66f31c5Sopenharmony_ci/* Copyright libuv project contributors. All rights reserved. 2e66f31c5Sopenharmony_ci * 3e66f31c5Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 4e66f31c5Sopenharmony_ci * of this software and associated documentation files (the "Software"), to 5e66f31c5Sopenharmony_ci * deal in the Software without restriction, including without limitation the 6e66f31c5Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7e66f31c5Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 8e66f31c5Sopenharmony_ci * furnished to do so, subject to the following conditions: 9e66f31c5Sopenharmony_ci * 10e66f31c5Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 11e66f31c5Sopenharmony_ci * all copies or substantial portions of the Software. 12e66f31c5Sopenharmony_ci * 13e66f31c5Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14e66f31c5Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15e66f31c5Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16e66f31c5Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17e66f31c5Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18e66f31c5Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19e66f31c5Sopenharmony_ci * IN THE SOFTWARE. 20e66f31c5Sopenharmony_ci */ 21e66f31c5Sopenharmony_ci 22e66f31c5Sopenharmony_ci#include "uv.h" 23e66f31c5Sopenharmony_ci#include "internal.h" 24e66f31c5Sopenharmony_ci#include <sys/ioctl.h> 25e66f31c5Sopenharmony_ci#include <net/if.h> 26e66f31c5Sopenharmony_ci#include <utmpx.h> 27e66f31c5Sopenharmony_ci#include <unistd.h> 28e66f31c5Sopenharmony_ci#include <sys/ps.h> 29e66f31c5Sopenharmony_ci#include <builtins.h> 30e66f31c5Sopenharmony_ci#include <termios.h> 31e66f31c5Sopenharmony_ci#include <sys/msg.h> 32e66f31c5Sopenharmony_ci#include <sys/resource.h> 33e66f31c5Sopenharmony_ci#include "zos-base.h" 34e66f31c5Sopenharmony_ci#include "zos-sys-info.h" 35e66f31c5Sopenharmony_ci#if defined(__clang__) 36e66f31c5Sopenharmony_ci#include "csrsic.h" 37e66f31c5Sopenharmony_ci#else 38e66f31c5Sopenharmony_ci#include "//'SYS1.SAMPLIB(CSRSIC)'" 39e66f31c5Sopenharmony_ci#endif 40e66f31c5Sopenharmony_ci 41e66f31c5Sopenharmony_ci#define CVT_PTR 0x10 42e66f31c5Sopenharmony_ci#define PSA_PTR 0x00 43e66f31c5Sopenharmony_ci#define CSD_OFFSET 0x294 44e66f31c5Sopenharmony_ci 45e66f31c5Sopenharmony_ci/* 46e66f31c5Sopenharmony_ci Long-term average CPU service used by this logical partition, 47e66f31c5Sopenharmony_ci in millions of service units per hour. If this value is above 48e66f31c5Sopenharmony_ci the partition's defined capacity, the partition will be capped. 49e66f31c5Sopenharmony_ci It is calculated using the physical CPU adjustment factor 50e66f31c5Sopenharmony_ci (RCTPCPUA) so it may not match other measures of service which 51e66f31c5Sopenharmony_ci are based on the logical CPU adjustment factor. It is available 52e66f31c5Sopenharmony_ci if the hardware supports LPAR cluster. 53e66f31c5Sopenharmony_ci*/ 54e66f31c5Sopenharmony_ci#define RCTLACS_OFFSET 0xC4 55e66f31c5Sopenharmony_ci 56e66f31c5Sopenharmony_ci/* 32-bit count of alive CPUs. This includes both CPs and IFAs */ 57e66f31c5Sopenharmony_ci#define CSD_NUMBER_ONLINE_CPUS 0xD4 58e66f31c5Sopenharmony_ci 59e66f31c5Sopenharmony_ci/* Address of system resources manager (SRM) control table */ 60e66f31c5Sopenharmony_ci#define CVTOPCTP_OFFSET 0x25C 61e66f31c5Sopenharmony_ci 62e66f31c5Sopenharmony_ci/* Address of the RCT table */ 63e66f31c5Sopenharmony_ci#define RMCTRCT_OFFSET 0xE4 64e66f31c5Sopenharmony_ci 65e66f31c5Sopenharmony_ci/* Address of the rsm control and enumeration area. */ 66e66f31c5Sopenharmony_ci#define CVTRCEP_OFFSET 0x490 67e66f31c5Sopenharmony_ci 68e66f31c5Sopenharmony_ci/* Total number of frames currently on all available frame queues. */ 69e66f31c5Sopenharmony_ci#define RCEAFC_OFFSET 0x088 70e66f31c5Sopenharmony_ci 71e66f31c5Sopenharmony_ci/* Pointer to the home (current) ASCB. */ 72e66f31c5Sopenharmony_ci#define PSAAOLD 0x224 73e66f31c5Sopenharmony_ci 74e66f31c5Sopenharmony_ci/* Pointer to rsm address space block extension. */ 75e66f31c5Sopenharmony_ci#define ASCBRSME 0x16C 76e66f31c5Sopenharmony_ci 77e66f31c5Sopenharmony_ci/* 78e66f31c5Sopenharmony_ci NUMBER OF FRAMES CURRENTLY IN USE BY THIS ADDRESS SPACE. 79e66f31c5Sopenharmony_ci It does not include 2G frames. 80e66f31c5Sopenharmony_ci*/ 81e66f31c5Sopenharmony_ci#define RAXFMCT 0x2C 82e66f31c5Sopenharmony_ci 83e66f31c5Sopenharmony_ci/* Thread Entry constants */ 84e66f31c5Sopenharmony_ci#define PGTH_CURRENT 1 85e66f31c5Sopenharmony_ci#define PGTH_LEN 26 86e66f31c5Sopenharmony_ci#define PGTHAPATH 0x20 87e66f31c5Sopenharmony_ci#pragma linkage(BPX4GTH, OS) 88e66f31c5Sopenharmony_ci#pragma linkage(BPX1GTH, OS) 89e66f31c5Sopenharmony_ci 90e66f31c5Sopenharmony_ci/* TOD Clock resolution in nanoseconds */ 91e66f31c5Sopenharmony_ci#define TOD_RES 4.096 92e66f31c5Sopenharmony_ci 93e66f31c5Sopenharmony_citypedef unsigned data_area_ptr_assign_type; 94e66f31c5Sopenharmony_ci 95e66f31c5Sopenharmony_citypedef union { 96e66f31c5Sopenharmony_ci struct { 97e66f31c5Sopenharmony_ci#if defined(_LP64) 98e66f31c5Sopenharmony_ci data_area_ptr_assign_type lower; 99e66f31c5Sopenharmony_ci#endif 100e66f31c5Sopenharmony_ci data_area_ptr_assign_type assign; 101e66f31c5Sopenharmony_ci }; 102e66f31c5Sopenharmony_ci char* deref; 103e66f31c5Sopenharmony_ci} data_area_ptr; 104e66f31c5Sopenharmony_ci 105e66f31c5Sopenharmony_ci 106e66f31c5Sopenharmony_civoid uv_loadavg(double avg[3]) { 107e66f31c5Sopenharmony_ci /* TODO: implement the following */ 108e66f31c5Sopenharmony_ci avg[0] = 0; 109e66f31c5Sopenharmony_ci avg[1] = 0; 110e66f31c5Sopenharmony_ci avg[2] = 0; 111e66f31c5Sopenharmony_ci} 112e66f31c5Sopenharmony_ci 113e66f31c5Sopenharmony_ci 114e66f31c5Sopenharmony_ciint uv__platform_loop_init(uv_loop_t* loop) { 115e66f31c5Sopenharmony_ci uv__os390_epoll* ep; 116e66f31c5Sopenharmony_ci 117e66f31c5Sopenharmony_ci ep = epoll_create1(0); 118e66f31c5Sopenharmony_ci loop->ep = ep; 119e66f31c5Sopenharmony_ci if (ep == NULL) 120e66f31c5Sopenharmony_ci return UV__ERR(errno); 121e66f31c5Sopenharmony_ci 122e66f31c5Sopenharmony_ci return 0; 123e66f31c5Sopenharmony_ci} 124e66f31c5Sopenharmony_ci 125e66f31c5Sopenharmony_ci 126e66f31c5Sopenharmony_civoid uv__platform_loop_delete(uv_loop_t* loop) { 127e66f31c5Sopenharmony_ci if (loop->ep != NULL) { 128e66f31c5Sopenharmony_ci epoll_queue_close(loop->ep); 129e66f31c5Sopenharmony_ci loop->ep = NULL; 130e66f31c5Sopenharmony_ci } 131e66f31c5Sopenharmony_ci} 132e66f31c5Sopenharmony_ci 133e66f31c5Sopenharmony_ci 134e66f31c5Sopenharmony_ciuint64_t uv__hrtime(uv_clocktype_t type) { 135e66f31c5Sopenharmony_ci unsigned long long timestamp; 136e66f31c5Sopenharmony_ci __stckf(×tamp); 137e66f31c5Sopenharmony_ci /* Convert to nanoseconds */ 138e66f31c5Sopenharmony_ci return timestamp / TOD_RES; 139e66f31c5Sopenharmony_ci} 140e66f31c5Sopenharmony_ci 141e66f31c5Sopenharmony_ci 142e66f31c5Sopenharmony_cistatic int getexe(char* buf, size_t len) { 143e66f31c5Sopenharmony_ci return uv__strscpy(buf, __getargv()[0], len); 144e66f31c5Sopenharmony_ci} 145e66f31c5Sopenharmony_ci 146e66f31c5Sopenharmony_ci 147e66f31c5Sopenharmony_ci/* 148e66f31c5Sopenharmony_ci * We could use a static buffer for the path manipulations that we need outside 149e66f31c5Sopenharmony_ci * of the function, but this function could be called by multiple consumers and 150e66f31c5Sopenharmony_ci * we don't want to potentially create a race condition in the use of snprintf. 151e66f31c5Sopenharmony_ci * There is no direct way of getting the exe path in zOS - either through /procfs 152e66f31c5Sopenharmony_ci * or through some libc APIs. The below approach is to parse the argv[0]'s pattern 153e66f31c5Sopenharmony_ci * and use it in conjunction with PATH environment variable to craft one. 154e66f31c5Sopenharmony_ci */ 155e66f31c5Sopenharmony_ciint uv_exepath(char* buffer, size_t* size) { 156e66f31c5Sopenharmony_ci int res; 157e66f31c5Sopenharmony_ci char args[PATH_MAX]; 158e66f31c5Sopenharmony_ci int pid; 159e66f31c5Sopenharmony_ci 160e66f31c5Sopenharmony_ci if (buffer == NULL || size == NULL || *size == 0) 161e66f31c5Sopenharmony_ci return UV_EINVAL; 162e66f31c5Sopenharmony_ci 163e66f31c5Sopenharmony_ci res = getexe(args, sizeof(args)); 164e66f31c5Sopenharmony_ci if (res < 0) 165e66f31c5Sopenharmony_ci return UV_EINVAL; 166e66f31c5Sopenharmony_ci 167e66f31c5Sopenharmony_ci return uv__search_path(args, buffer, size); 168e66f31c5Sopenharmony_ci} 169e66f31c5Sopenharmony_ci 170e66f31c5Sopenharmony_ci 171e66f31c5Sopenharmony_ciuint64_t uv_get_free_memory(void) { 172e66f31c5Sopenharmony_ci uint64_t freeram; 173e66f31c5Sopenharmony_ci 174e66f31c5Sopenharmony_ci data_area_ptr cvt = {0}; 175e66f31c5Sopenharmony_ci data_area_ptr rcep = {0}; 176e66f31c5Sopenharmony_ci cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR); 177e66f31c5Sopenharmony_ci rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET); 178e66f31c5Sopenharmony_ci freeram = (uint64_t)*((uint32_t*)(rcep.deref + RCEAFC_OFFSET)) * 4096; 179e66f31c5Sopenharmony_ci return freeram; 180e66f31c5Sopenharmony_ci} 181e66f31c5Sopenharmony_ci 182e66f31c5Sopenharmony_ci 183e66f31c5Sopenharmony_ciuint64_t uv_get_total_memory(void) { 184e66f31c5Sopenharmony_ci /* Use CVTRLSTG to get the size of actual real storage online at IPL in K. */ 185e66f31c5Sopenharmony_ci return (uint64_t)((int)((char *__ptr32 *__ptr32 *)0)[4][214]) * 1024; 186e66f31c5Sopenharmony_ci} 187e66f31c5Sopenharmony_ci 188e66f31c5Sopenharmony_ci 189e66f31c5Sopenharmony_ciuint64_t uv_get_constrained_memory(void) { 190e66f31c5Sopenharmony_ci struct rlimit rl; 191e66f31c5Sopenharmony_ci 192e66f31c5Sopenharmony_ci /* RLIMIT_MEMLIMIT return value is in megabytes rather than bytes. */ 193e66f31c5Sopenharmony_ci if (getrlimit(RLIMIT_MEMLIMIT, &rl) == 0) 194e66f31c5Sopenharmony_ci return rl.rlim_cur * 1024 * 1024; 195e66f31c5Sopenharmony_ci 196e66f31c5Sopenharmony_ci return 0; /* There is no memory limit set. */ 197e66f31c5Sopenharmony_ci} 198e66f31c5Sopenharmony_ci 199e66f31c5Sopenharmony_ci 200e66f31c5Sopenharmony_ciuint64_t uv_get_available_memory(void) { 201e66f31c5Sopenharmony_ci return uv_get_free_memory(); 202e66f31c5Sopenharmony_ci} 203e66f31c5Sopenharmony_ci 204e66f31c5Sopenharmony_ci 205e66f31c5Sopenharmony_ciint uv_resident_set_memory(size_t* rss) { 206e66f31c5Sopenharmony_ci char* ascb; 207e66f31c5Sopenharmony_ci char* rax; 208e66f31c5Sopenharmony_ci size_t nframes; 209e66f31c5Sopenharmony_ci 210e66f31c5Sopenharmony_ci ascb = *(char* __ptr32 *)(PSA_PTR + PSAAOLD); 211e66f31c5Sopenharmony_ci rax = *(char* __ptr32 *)(ascb + ASCBRSME); 212e66f31c5Sopenharmony_ci nframes = *(unsigned int*)(rax + RAXFMCT); 213e66f31c5Sopenharmony_ci 214e66f31c5Sopenharmony_ci *rss = nframes * sysconf(_SC_PAGESIZE); 215e66f31c5Sopenharmony_ci return 0; 216e66f31c5Sopenharmony_ci} 217e66f31c5Sopenharmony_ci 218e66f31c5Sopenharmony_ci 219e66f31c5Sopenharmony_ciint uv_uptime(double* uptime) { 220e66f31c5Sopenharmony_ci struct utmpx u ; 221e66f31c5Sopenharmony_ci struct utmpx *v; 222e66f31c5Sopenharmony_ci time64_t t; 223e66f31c5Sopenharmony_ci 224e66f31c5Sopenharmony_ci u.ut_type = BOOT_TIME; 225e66f31c5Sopenharmony_ci v = getutxid(&u); 226e66f31c5Sopenharmony_ci if (v == NULL) 227e66f31c5Sopenharmony_ci return -1; 228e66f31c5Sopenharmony_ci *uptime = difftime64(time64(&t), v->ut_tv.tv_sec); 229e66f31c5Sopenharmony_ci return 0; 230e66f31c5Sopenharmony_ci} 231e66f31c5Sopenharmony_ci 232e66f31c5Sopenharmony_ci 233e66f31c5Sopenharmony_ciint uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 234e66f31c5Sopenharmony_ci uv_cpu_info_t* cpu_info; 235e66f31c5Sopenharmony_ci int idx; 236e66f31c5Sopenharmony_ci siv1v2 info; 237e66f31c5Sopenharmony_ci data_area_ptr cvt = {0}; 238e66f31c5Sopenharmony_ci data_area_ptr csd = {0}; 239e66f31c5Sopenharmony_ci data_area_ptr rmctrct = {0}; 240e66f31c5Sopenharmony_ci data_area_ptr cvtopctp = {0}; 241e66f31c5Sopenharmony_ci int cpu_usage_avg; 242e66f31c5Sopenharmony_ci 243e66f31c5Sopenharmony_ci cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR); 244e66f31c5Sopenharmony_ci 245e66f31c5Sopenharmony_ci csd.assign = *((data_area_ptr_assign_type *) (cvt.deref + CSD_OFFSET)); 246e66f31c5Sopenharmony_ci cvtopctp.assign = *((data_area_ptr_assign_type *) (cvt.deref + CVTOPCTP_OFFSET)); 247e66f31c5Sopenharmony_ci rmctrct.assign = *((data_area_ptr_assign_type *) (cvtopctp.deref + RMCTRCT_OFFSET)); 248e66f31c5Sopenharmony_ci 249e66f31c5Sopenharmony_ci *count = *((int*) (csd.deref + CSD_NUMBER_ONLINE_CPUS)); 250e66f31c5Sopenharmony_ci cpu_usage_avg = *((unsigned short int*) (rmctrct.deref + RCTLACS_OFFSET)); 251e66f31c5Sopenharmony_ci 252e66f31c5Sopenharmony_ci *cpu_infos = uv__malloc(*count * sizeof(uv_cpu_info_t)); 253e66f31c5Sopenharmony_ci if (!*cpu_infos) 254e66f31c5Sopenharmony_ci return UV_ENOMEM; 255e66f31c5Sopenharmony_ci 256e66f31c5Sopenharmony_ci cpu_info = *cpu_infos; 257e66f31c5Sopenharmony_ci idx = 0; 258e66f31c5Sopenharmony_ci while (idx < *count) { 259e66f31c5Sopenharmony_ci cpu_info->speed = *(int*)(info.siv1v2si22v1.si22v1cpucapability); 260e66f31c5Sopenharmony_ci cpu_info->model = uv__malloc(ZOSCPU_MODEL_LENGTH + 1); 261e66f31c5Sopenharmony_ci if (cpu_info->model == NULL) { 262e66f31c5Sopenharmony_ci uv_free_cpu_info(*cpu_infos, idx); 263e66f31c5Sopenharmony_ci return UV_ENOMEM; 264e66f31c5Sopenharmony_ci } 265e66f31c5Sopenharmony_ci __get_cpu_model(cpu_info->model, ZOSCPU_MODEL_LENGTH + 1); 266e66f31c5Sopenharmony_ci cpu_info->cpu_times.user = cpu_usage_avg; 267e66f31c5Sopenharmony_ci /* TODO: implement the following */ 268e66f31c5Sopenharmony_ci cpu_info->cpu_times.sys = 0; 269e66f31c5Sopenharmony_ci cpu_info->cpu_times.idle = 0; 270e66f31c5Sopenharmony_ci cpu_info->cpu_times.irq = 0; 271e66f31c5Sopenharmony_ci cpu_info->cpu_times.nice = 0; 272e66f31c5Sopenharmony_ci ++cpu_info; 273e66f31c5Sopenharmony_ci ++idx; 274e66f31c5Sopenharmony_ci } 275e66f31c5Sopenharmony_ci 276e66f31c5Sopenharmony_ci return 0; 277e66f31c5Sopenharmony_ci} 278e66f31c5Sopenharmony_ci 279e66f31c5Sopenharmony_ci 280e66f31c5Sopenharmony_cistatic int uv__interface_addresses_v6(uv_interface_address_t** addresses, 281e66f31c5Sopenharmony_ci int* count) { 282e66f31c5Sopenharmony_ci uv_interface_address_t* address; 283e66f31c5Sopenharmony_ci int sockfd; 284e66f31c5Sopenharmony_ci int maxsize; 285e66f31c5Sopenharmony_ci __net_ifconf6header_t ifc; 286e66f31c5Sopenharmony_ci __net_ifconf6entry_t* ifr; 287e66f31c5Sopenharmony_ci __net_ifconf6entry_t* p; 288e66f31c5Sopenharmony_ci unsigned int i; 289e66f31c5Sopenharmony_ci int count_names; 290e66f31c5Sopenharmony_ci unsigned char netmask[16] = {0}; 291e66f31c5Sopenharmony_ci 292e66f31c5Sopenharmony_ci *count = 0; 293e66f31c5Sopenharmony_ci /* Assume maximum buffer size allowable */ 294e66f31c5Sopenharmony_ci maxsize = 16384; 295e66f31c5Sopenharmony_ci 296e66f31c5Sopenharmony_ci if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) 297e66f31c5Sopenharmony_ci return UV__ERR(errno); 298e66f31c5Sopenharmony_ci 299e66f31c5Sopenharmony_ci ifc.__nif6h_buffer = uv__calloc(1, maxsize); 300e66f31c5Sopenharmony_ci 301e66f31c5Sopenharmony_ci if (ifc.__nif6h_buffer == NULL) { 302e66f31c5Sopenharmony_ci uv__close(sockfd); 303e66f31c5Sopenharmony_ci return UV_ENOMEM; 304e66f31c5Sopenharmony_ci } 305e66f31c5Sopenharmony_ci 306e66f31c5Sopenharmony_ci ifc.__nif6h_version = 1; 307e66f31c5Sopenharmony_ci ifc.__nif6h_buflen = maxsize; 308e66f31c5Sopenharmony_ci 309e66f31c5Sopenharmony_ci if (ioctl(sockfd, SIOCGIFCONF6, &ifc) == -1) { 310e66f31c5Sopenharmony_ci /* This will error on a system that does not support IPv6. However, we want 311e66f31c5Sopenharmony_ci * to treat this as there being 0 interfaces so we can continue to get IPv4 312e66f31c5Sopenharmony_ci * interfaces in uv_interface_addresses(). So return 0 instead of the error. 313e66f31c5Sopenharmony_ci */ 314e66f31c5Sopenharmony_ci uv__free(ifc.__nif6h_buffer); 315e66f31c5Sopenharmony_ci uv__close(sockfd); 316e66f31c5Sopenharmony_ci errno = 0; 317e66f31c5Sopenharmony_ci return 0; 318e66f31c5Sopenharmony_ci } 319e66f31c5Sopenharmony_ci 320e66f31c5Sopenharmony_ci ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer); 321e66f31c5Sopenharmony_ci while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) { 322e66f31c5Sopenharmony_ci p = ifr; 323e66f31c5Sopenharmony_ci ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen); 324e66f31c5Sopenharmony_ci 325e66f31c5Sopenharmony_ci if (!(p->__nif6e_addr.sin6_family == AF_INET6)) 326e66f31c5Sopenharmony_ci continue; 327e66f31c5Sopenharmony_ci 328e66f31c5Sopenharmony_ci if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE)) 329e66f31c5Sopenharmony_ci continue; 330e66f31c5Sopenharmony_ci 331e66f31c5Sopenharmony_ci ++(*count); 332e66f31c5Sopenharmony_ci } 333e66f31c5Sopenharmony_ci 334e66f31c5Sopenharmony_ci if ((*count) == 0) { 335e66f31c5Sopenharmony_ci uv__free(ifc.__nif6h_buffer); 336e66f31c5Sopenharmony_ci uv__close(sockfd); 337e66f31c5Sopenharmony_ci return 0; 338e66f31c5Sopenharmony_ci } 339e66f31c5Sopenharmony_ci 340e66f31c5Sopenharmony_ci /* Alloc the return interface structs */ 341e66f31c5Sopenharmony_ci *addresses = uv__calloc(1, *count * sizeof(uv_interface_address_t)); 342e66f31c5Sopenharmony_ci if (!(*addresses)) { 343e66f31c5Sopenharmony_ci uv__free(ifc.__nif6h_buffer); 344e66f31c5Sopenharmony_ci uv__close(sockfd); 345e66f31c5Sopenharmony_ci return UV_ENOMEM; 346e66f31c5Sopenharmony_ci } 347e66f31c5Sopenharmony_ci address = *addresses; 348e66f31c5Sopenharmony_ci 349e66f31c5Sopenharmony_ci count_names = 0; 350e66f31c5Sopenharmony_ci ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer); 351e66f31c5Sopenharmony_ci while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) { 352e66f31c5Sopenharmony_ci p = ifr; 353e66f31c5Sopenharmony_ci ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen); 354e66f31c5Sopenharmony_ci 355e66f31c5Sopenharmony_ci if (!(p->__nif6e_addr.sin6_family == AF_INET6)) 356e66f31c5Sopenharmony_ci continue; 357e66f31c5Sopenharmony_ci 358e66f31c5Sopenharmony_ci if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE)) 359e66f31c5Sopenharmony_ci continue; 360e66f31c5Sopenharmony_ci 361e66f31c5Sopenharmony_ci /* All conditions above must match count loop */ 362e66f31c5Sopenharmony_ci 363e66f31c5Sopenharmony_ci i = 0; 364e66f31c5Sopenharmony_ci /* Ignore EBCDIC space (0x40) padding in name */ 365e66f31c5Sopenharmony_ci while (i < ARRAY_SIZE(p->__nif6e_name) && 366e66f31c5Sopenharmony_ci p->__nif6e_name[i] != 0x40 && 367e66f31c5Sopenharmony_ci p->__nif6e_name[i] != 0) 368e66f31c5Sopenharmony_ci ++i; 369e66f31c5Sopenharmony_ci address->name = uv__malloc(i + 1); 370e66f31c5Sopenharmony_ci if (address->name == NULL) { 371e66f31c5Sopenharmony_ci uv_free_interface_addresses(*addresses, count_names); 372e66f31c5Sopenharmony_ci uv__free(ifc.__nif6h_buffer); 373e66f31c5Sopenharmony_ci uv__close(sockfd); 374e66f31c5Sopenharmony_ci return UV_ENOMEM; 375e66f31c5Sopenharmony_ci } 376e66f31c5Sopenharmony_ci memcpy(address->name, p->__nif6e_name, i); 377e66f31c5Sopenharmony_ci address->name[i] = '\0'; 378e66f31c5Sopenharmony_ci __e2a_s(address->name); 379e66f31c5Sopenharmony_ci count_names++; 380e66f31c5Sopenharmony_ci 381e66f31c5Sopenharmony_ci address->address.address6 = *((struct sockaddr_in6*) &p->__nif6e_addr); 382e66f31c5Sopenharmony_ci 383e66f31c5Sopenharmony_ci for (i = 0; i < (p->__nif6e_prefixlen / 8); i++) 384e66f31c5Sopenharmony_ci netmask[i] = 0xFF; 385e66f31c5Sopenharmony_ci 386e66f31c5Sopenharmony_ci if (p->__nif6e_prefixlen % 8) 387e66f31c5Sopenharmony_ci netmask[i] = 0xFF << (8 - (p->__nif6e_prefixlen % 8)); 388e66f31c5Sopenharmony_ci 389e66f31c5Sopenharmony_ci address->netmask.netmask6.sin6_len = p->__nif6e_prefixlen; 390e66f31c5Sopenharmony_ci memcpy(&(address->netmask.netmask6.sin6_addr), netmask, 16); 391e66f31c5Sopenharmony_ci address->netmask.netmask6.sin6_family = AF_INET6; 392e66f31c5Sopenharmony_ci 393e66f31c5Sopenharmony_ci address->is_internal = p->__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0; 394e66f31c5Sopenharmony_ci address++; 395e66f31c5Sopenharmony_ci } 396e66f31c5Sopenharmony_ci 397e66f31c5Sopenharmony_ci uv__free(ifc.__nif6h_buffer); 398e66f31c5Sopenharmony_ci uv__close(sockfd); 399e66f31c5Sopenharmony_ci return 0; 400e66f31c5Sopenharmony_ci} 401e66f31c5Sopenharmony_ci 402e66f31c5Sopenharmony_ci 403e66f31c5Sopenharmony_ciint uv_interface_addresses(uv_interface_address_t** addresses, int* count) { 404e66f31c5Sopenharmony_ci uv_interface_address_t* address; 405e66f31c5Sopenharmony_ci int sockfd; 406e66f31c5Sopenharmony_ci int maxsize; 407e66f31c5Sopenharmony_ci struct ifconf ifc; 408e66f31c5Sopenharmony_ci struct ifreq flg; 409e66f31c5Sopenharmony_ci struct ifreq* ifr; 410e66f31c5Sopenharmony_ci struct ifreq* p; 411e66f31c5Sopenharmony_ci uv_interface_address_t* addresses_v6; 412e66f31c5Sopenharmony_ci int count_v6; 413e66f31c5Sopenharmony_ci unsigned int i; 414e66f31c5Sopenharmony_ci int rc; 415e66f31c5Sopenharmony_ci int count_names; 416e66f31c5Sopenharmony_ci 417e66f31c5Sopenharmony_ci *count = 0; 418e66f31c5Sopenharmony_ci *addresses = NULL; 419e66f31c5Sopenharmony_ci 420e66f31c5Sopenharmony_ci /* get the ipv6 addresses first */ 421e66f31c5Sopenharmony_ci if ((rc = uv__interface_addresses_v6(&addresses_v6, &count_v6)) != 0) 422e66f31c5Sopenharmony_ci return rc; 423e66f31c5Sopenharmony_ci 424e66f31c5Sopenharmony_ci /* now get the ipv4 addresses */ 425e66f31c5Sopenharmony_ci 426e66f31c5Sopenharmony_ci /* Assume maximum buffer size allowable */ 427e66f31c5Sopenharmony_ci maxsize = 16384; 428e66f31c5Sopenharmony_ci 429e66f31c5Sopenharmony_ci sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); 430e66f31c5Sopenharmony_ci if (0 > sockfd) { 431e66f31c5Sopenharmony_ci if (count_v6) 432e66f31c5Sopenharmony_ci uv_free_interface_addresses(addresses_v6, count_v6); 433e66f31c5Sopenharmony_ci return UV__ERR(errno); 434e66f31c5Sopenharmony_ci } 435e66f31c5Sopenharmony_ci 436e66f31c5Sopenharmony_ci ifc.ifc_req = uv__calloc(1, maxsize); 437e66f31c5Sopenharmony_ci 438e66f31c5Sopenharmony_ci if (ifc.ifc_req == NULL) { 439e66f31c5Sopenharmony_ci if (count_v6) 440e66f31c5Sopenharmony_ci uv_free_interface_addresses(addresses_v6, count_v6); 441e66f31c5Sopenharmony_ci uv__close(sockfd); 442e66f31c5Sopenharmony_ci return UV_ENOMEM; 443e66f31c5Sopenharmony_ci } 444e66f31c5Sopenharmony_ci 445e66f31c5Sopenharmony_ci ifc.ifc_len = maxsize; 446e66f31c5Sopenharmony_ci 447e66f31c5Sopenharmony_ci if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) { 448e66f31c5Sopenharmony_ci if (count_v6) 449e66f31c5Sopenharmony_ci uv_free_interface_addresses(addresses_v6, count_v6); 450e66f31c5Sopenharmony_ci uv__free(ifc.ifc_req); 451e66f31c5Sopenharmony_ci uv__close(sockfd); 452e66f31c5Sopenharmony_ci return UV__ERR(errno); 453e66f31c5Sopenharmony_ci } 454e66f31c5Sopenharmony_ci 455e66f31c5Sopenharmony_ci#define MAX(a,b) (((a)>(b))?(a):(b)) 456e66f31c5Sopenharmony_ci#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p)) 457e66f31c5Sopenharmony_ci 458e66f31c5Sopenharmony_ci /* Count all up and running ipv4/ipv6 addresses */ 459e66f31c5Sopenharmony_ci ifr = ifc.ifc_req; 460e66f31c5Sopenharmony_ci while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { 461e66f31c5Sopenharmony_ci p = ifr; 462e66f31c5Sopenharmony_ci ifr = (struct ifreq*) 463e66f31c5Sopenharmony_ci ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); 464e66f31c5Sopenharmony_ci 465e66f31c5Sopenharmony_ci if (!(p->ifr_addr.sa_family == AF_INET6 || 466e66f31c5Sopenharmony_ci p->ifr_addr.sa_family == AF_INET)) 467e66f31c5Sopenharmony_ci continue; 468e66f31c5Sopenharmony_ci 469e66f31c5Sopenharmony_ci memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); 470e66f31c5Sopenharmony_ci if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { 471e66f31c5Sopenharmony_ci if (count_v6) 472e66f31c5Sopenharmony_ci uv_free_interface_addresses(addresses_v6, count_v6); 473e66f31c5Sopenharmony_ci uv__free(ifc.ifc_req); 474e66f31c5Sopenharmony_ci uv__close(sockfd); 475e66f31c5Sopenharmony_ci return UV__ERR(errno); 476e66f31c5Sopenharmony_ci } 477e66f31c5Sopenharmony_ci 478e66f31c5Sopenharmony_ci if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) 479e66f31c5Sopenharmony_ci continue; 480e66f31c5Sopenharmony_ci 481e66f31c5Sopenharmony_ci (*count)++; 482e66f31c5Sopenharmony_ci } 483e66f31c5Sopenharmony_ci 484e66f31c5Sopenharmony_ci if (*count == 0 && count_v6 == 0) { 485e66f31c5Sopenharmony_ci uv__free(ifc.ifc_req); 486e66f31c5Sopenharmony_ci uv__close(sockfd); 487e66f31c5Sopenharmony_ci return 0; 488e66f31c5Sopenharmony_ci } 489e66f31c5Sopenharmony_ci 490e66f31c5Sopenharmony_ci /* Alloc the return interface structs */ 491e66f31c5Sopenharmony_ci *addresses = uv__calloc(1, (*count + count_v6) * 492e66f31c5Sopenharmony_ci sizeof(uv_interface_address_t)); 493e66f31c5Sopenharmony_ci 494e66f31c5Sopenharmony_ci if (!(*addresses)) { 495e66f31c5Sopenharmony_ci if (count_v6) 496e66f31c5Sopenharmony_ci uv_free_interface_addresses(addresses_v6, count_v6); 497e66f31c5Sopenharmony_ci uv__free(ifc.ifc_req); 498e66f31c5Sopenharmony_ci uv__close(sockfd); 499e66f31c5Sopenharmony_ci return UV_ENOMEM; 500e66f31c5Sopenharmony_ci } 501e66f31c5Sopenharmony_ci address = *addresses; 502e66f31c5Sopenharmony_ci 503e66f31c5Sopenharmony_ci /* copy over the ipv6 addresses if any are found */ 504e66f31c5Sopenharmony_ci if (count_v6) { 505e66f31c5Sopenharmony_ci memcpy(address, addresses_v6, count_v6 * sizeof(uv_interface_address_t)); 506e66f31c5Sopenharmony_ci address += count_v6; 507e66f31c5Sopenharmony_ci *count += count_v6; 508e66f31c5Sopenharmony_ci /* free ipv6 addresses, but keep address names */ 509e66f31c5Sopenharmony_ci uv__free(addresses_v6); 510e66f31c5Sopenharmony_ci } 511e66f31c5Sopenharmony_ci 512e66f31c5Sopenharmony_ci count_names = *count; 513e66f31c5Sopenharmony_ci ifr = ifc.ifc_req; 514e66f31c5Sopenharmony_ci while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { 515e66f31c5Sopenharmony_ci p = ifr; 516e66f31c5Sopenharmony_ci ifr = (struct ifreq*) 517e66f31c5Sopenharmony_ci ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); 518e66f31c5Sopenharmony_ci 519e66f31c5Sopenharmony_ci if (!(p->ifr_addr.sa_family == AF_INET6 || 520e66f31c5Sopenharmony_ci p->ifr_addr.sa_family == AF_INET)) 521e66f31c5Sopenharmony_ci continue; 522e66f31c5Sopenharmony_ci 523e66f31c5Sopenharmony_ci memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); 524e66f31c5Sopenharmony_ci if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { 525e66f31c5Sopenharmony_ci uv_free_interface_addresses(*addresses, count_names); 526e66f31c5Sopenharmony_ci uv__free(ifc.ifc_req); 527e66f31c5Sopenharmony_ci uv__close(sockfd); 528e66f31c5Sopenharmony_ci return UV_ENOSYS; 529e66f31c5Sopenharmony_ci } 530e66f31c5Sopenharmony_ci 531e66f31c5Sopenharmony_ci if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) 532e66f31c5Sopenharmony_ci continue; 533e66f31c5Sopenharmony_ci 534e66f31c5Sopenharmony_ci /* All conditions above must match count loop */ 535e66f31c5Sopenharmony_ci 536e66f31c5Sopenharmony_ci i = 0; 537e66f31c5Sopenharmony_ci /* Ignore EBCDIC space (0x40) padding in name */ 538e66f31c5Sopenharmony_ci while (i < ARRAY_SIZE(p->ifr_name) && 539e66f31c5Sopenharmony_ci p->ifr_name[i] != 0x40 && 540e66f31c5Sopenharmony_ci p->ifr_name[i] != 0) 541e66f31c5Sopenharmony_ci ++i; 542e66f31c5Sopenharmony_ci address->name = uv__malloc(i + 1); 543e66f31c5Sopenharmony_ci if (address->name == NULL) { 544e66f31c5Sopenharmony_ci uv_free_interface_addresses(*addresses, count_names); 545e66f31c5Sopenharmony_ci uv__free(ifc.ifc_req); 546e66f31c5Sopenharmony_ci uv__close(sockfd); 547e66f31c5Sopenharmony_ci return UV_ENOMEM; 548e66f31c5Sopenharmony_ci } 549e66f31c5Sopenharmony_ci memcpy(address->name, p->ifr_name, i); 550e66f31c5Sopenharmony_ci address->name[i] = '\0'; 551e66f31c5Sopenharmony_ci __e2a_s(address->name); 552e66f31c5Sopenharmony_ci count_names++; 553e66f31c5Sopenharmony_ci 554e66f31c5Sopenharmony_ci address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr); 555e66f31c5Sopenharmony_ci 556e66f31c5Sopenharmony_ci if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) { 557e66f31c5Sopenharmony_ci uv_free_interface_addresses(*addresses, count_names); 558e66f31c5Sopenharmony_ci uv__free(ifc.ifc_req); 559e66f31c5Sopenharmony_ci uv__close(sockfd); 560e66f31c5Sopenharmony_ci return UV__ERR(errno); 561e66f31c5Sopenharmony_ci } 562e66f31c5Sopenharmony_ci 563e66f31c5Sopenharmony_ci address->netmask.netmask4 = *((struct sockaddr_in*) &p->ifr_addr); 564e66f31c5Sopenharmony_ci address->netmask.netmask4.sin_family = AF_INET; 565e66f31c5Sopenharmony_ci address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0; 566e66f31c5Sopenharmony_ci address++; 567e66f31c5Sopenharmony_ci } 568e66f31c5Sopenharmony_ci 569e66f31c5Sopenharmony_ci#undef ADDR_SIZE 570e66f31c5Sopenharmony_ci#undef MAX 571e66f31c5Sopenharmony_ci 572e66f31c5Sopenharmony_ci uv__free(ifc.ifc_req); 573e66f31c5Sopenharmony_ci uv__close(sockfd); 574e66f31c5Sopenharmony_ci return 0; 575e66f31c5Sopenharmony_ci} 576e66f31c5Sopenharmony_ci 577e66f31c5Sopenharmony_ci 578e66f31c5Sopenharmony_civoid uv_free_interface_addresses(uv_interface_address_t* addresses, 579e66f31c5Sopenharmony_ci int count) { 580e66f31c5Sopenharmony_ci int i; 581e66f31c5Sopenharmony_ci for (i = 0; i < count; ++i) 582e66f31c5Sopenharmony_ci uv__free(addresses[i].name); 583e66f31c5Sopenharmony_ci uv__free(addresses); 584e66f31c5Sopenharmony_ci} 585e66f31c5Sopenharmony_ci 586e66f31c5Sopenharmony_ci 587e66f31c5Sopenharmony_civoid uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { 588e66f31c5Sopenharmony_ci struct epoll_event* events; 589e66f31c5Sopenharmony_ci struct epoll_event dummy; 590e66f31c5Sopenharmony_ci uintptr_t i; 591e66f31c5Sopenharmony_ci uintptr_t nfds; 592e66f31c5Sopenharmony_ci 593e66f31c5Sopenharmony_ci assert(loop->watchers != NULL); 594e66f31c5Sopenharmony_ci assert(fd >= 0); 595e66f31c5Sopenharmony_ci 596e66f31c5Sopenharmony_ci events = (struct epoll_event*) loop->watchers[loop->nwatchers]; 597e66f31c5Sopenharmony_ci nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; 598e66f31c5Sopenharmony_ci if (events != NULL) 599e66f31c5Sopenharmony_ci /* Invalidate events with same file descriptor */ 600e66f31c5Sopenharmony_ci for (i = 0; i < nfds; i++) 601e66f31c5Sopenharmony_ci if ((int) events[i].fd == fd) 602e66f31c5Sopenharmony_ci events[i].fd = -1; 603e66f31c5Sopenharmony_ci 604e66f31c5Sopenharmony_ci /* Remove the file descriptor from the epoll. */ 605e66f31c5Sopenharmony_ci if (loop->ep != NULL) 606e66f31c5Sopenharmony_ci epoll_ctl(loop->ep, EPOLL_CTL_DEL, fd, &dummy); 607e66f31c5Sopenharmony_ci} 608e66f31c5Sopenharmony_ci 609e66f31c5Sopenharmony_ci 610e66f31c5Sopenharmony_ciint uv__io_check_fd(uv_loop_t* loop, int fd) { 611e66f31c5Sopenharmony_ci struct pollfd p[1]; 612e66f31c5Sopenharmony_ci int rv; 613e66f31c5Sopenharmony_ci 614e66f31c5Sopenharmony_ci p[0].fd = fd; 615e66f31c5Sopenharmony_ci p[0].events = POLLIN; 616e66f31c5Sopenharmony_ci 617e66f31c5Sopenharmony_ci do 618e66f31c5Sopenharmony_ci rv = poll(p, 1, 0); 619e66f31c5Sopenharmony_ci while (rv == -1 && errno == EINTR); 620e66f31c5Sopenharmony_ci 621e66f31c5Sopenharmony_ci if (rv == -1) 622e66f31c5Sopenharmony_ci abort(); 623e66f31c5Sopenharmony_ci 624e66f31c5Sopenharmony_ci if (p[0].revents & POLLNVAL) 625e66f31c5Sopenharmony_ci return -1; 626e66f31c5Sopenharmony_ci 627e66f31c5Sopenharmony_ci return 0; 628e66f31c5Sopenharmony_ci} 629e66f31c5Sopenharmony_ci 630e66f31c5Sopenharmony_ci 631e66f31c5Sopenharmony_ciint uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { 632e66f31c5Sopenharmony_ci uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); 633e66f31c5Sopenharmony_ci return 0; 634e66f31c5Sopenharmony_ci} 635e66f31c5Sopenharmony_ci 636e66f31c5Sopenharmony_ci 637e66f31c5Sopenharmony_cistatic int os390_regfileint(uv_fs_event_t* handle, char* path) { 638e66f31c5Sopenharmony_ci uv__os390_epoll* ep; 639e66f31c5Sopenharmony_ci _RFIS reg_struct; 640e66f31c5Sopenharmony_ci int rc; 641e66f31c5Sopenharmony_ci 642e66f31c5Sopenharmony_ci ep = handle->loop->ep; 643e66f31c5Sopenharmony_ci assert(ep->msg_queue != -1); 644e66f31c5Sopenharmony_ci 645e66f31c5Sopenharmony_ci reg_struct.__rfis_cmd = _RFIS_REG; 646e66f31c5Sopenharmony_ci reg_struct.__rfis_qid = ep->msg_queue; 647e66f31c5Sopenharmony_ci reg_struct.__rfis_type = 1; 648e66f31c5Sopenharmony_ci memcpy(reg_struct.__rfis_utok, &handle, sizeof(handle)); 649e66f31c5Sopenharmony_ci 650e66f31c5Sopenharmony_ci rc = __w_pioctl(path, _IOCC_REGFILEINT, sizeof(reg_struct), ®_struct); 651e66f31c5Sopenharmony_ci if (rc != 0) 652e66f31c5Sopenharmony_ci return UV__ERR(errno); 653e66f31c5Sopenharmony_ci 654e66f31c5Sopenharmony_ci memcpy(handle->rfis_rftok, reg_struct.__rfis_rftok, 655e66f31c5Sopenharmony_ci sizeof(handle->rfis_rftok)); 656e66f31c5Sopenharmony_ci 657e66f31c5Sopenharmony_ci return 0; 658e66f31c5Sopenharmony_ci} 659e66f31c5Sopenharmony_ci 660e66f31c5Sopenharmony_ci 661e66f31c5Sopenharmony_ciint uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, 662e66f31c5Sopenharmony_ci const char* filename, unsigned int flags) { 663e66f31c5Sopenharmony_ci char* path; 664e66f31c5Sopenharmony_ci int rc; 665e66f31c5Sopenharmony_ci 666e66f31c5Sopenharmony_ci if (uv__is_active(handle)) 667e66f31c5Sopenharmony_ci return UV_EINVAL; 668e66f31c5Sopenharmony_ci 669e66f31c5Sopenharmony_ci path = uv__strdup(filename); 670e66f31c5Sopenharmony_ci if (path == NULL) 671e66f31c5Sopenharmony_ci return UV_ENOMEM; 672e66f31c5Sopenharmony_ci 673e66f31c5Sopenharmony_ci rc = os390_regfileint(handle, path); 674e66f31c5Sopenharmony_ci if (rc != 0) { 675e66f31c5Sopenharmony_ci uv__free(path); 676e66f31c5Sopenharmony_ci return rc; 677e66f31c5Sopenharmony_ci } 678e66f31c5Sopenharmony_ci 679e66f31c5Sopenharmony_ci uv__handle_start(handle); 680e66f31c5Sopenharmony_ci handle->path = path; 681e66f31c5Sopenharmony_ci handle->cb = cb; 682e66f31c5Sopenharmony_ci 683e66f31c5Sopenharmony_ci return 0; 684e66f31c5Sopenharmony_ci} 685e66f31c5Sopenharmony_ci 686e66f31c5Sopenharmony_ci 687e66f31c5Sopenharmony_ciint uv__fs_event_stop(uv_fs_event_t* handle) { 688e66f31c5Sopenharmony_ci uv__os390_epoll* ep; 689e66f31c5Sopenharmony_ci _RFIS reg_struct; 690e66f31c5Sopenharmony_ci int rc; 691e66f31c5Sopenharmony_ci 692e66f31c5Sopenharmony_ci if (!uv__is_active(handle)) 693e66f31c5Sopenharmony_ci return 0; 694e66f31c5Sopenharmony_ci 695e66f31c5Sopenharmony_ci ep = handle->loop->ep; 696e66f31c5Sopenharmony_ci assert(ep->msg_queue != -1); 697e66f31c5Sopenharmony_ci 698e66f31c5Sopenharmony_ci reg_struct.__rfis_cmd = _RFIS_UNREG; 699e66f31c5Sopenharmony_ci reg_struct.__rfis_qid = ep->msg_queue; 700e66f31c5Sopenharmony_ci reg_struct.__rfis_type = 1; 701e66f31c5Sopenharmony_ci memcpy(reg_struct.__rfis_rftok, handle->rfis_rftok, 702e66f31c5Sopenharmony_ci sizeof(handle->rfis_rftok)); 703e66f31c5Sopenharmony_ci 704e66f31c5Sopenharmony_ci /* 705e66f31c5Sopenharmony_ci * This call will take "/" as the path argument in case we 706e66f31c5Sopenharmony_ci * don't care to supply the correct path. The system will simply 707e66f31c5Sopenharmony_ci * ignore it. 708e66f31c5Sopenharmony_ci */ 709e66f31c5Sopenharmony_ci rc = __w_pioctl("/", _IOCC_REGFILEINT, sizeof(reg_struct), ®_struct); 710e66f31c5Sopenharmony_ci if (rc != 0 && errno != EALREADY && errno != ENOENT) 711e66f31c5Sopenharmony_ci abort(); 712e66f31c5Sopenharmony_ci 713e66f31c5Sopenharmony_ci if (handle->path != NULL) { 714e66f31c5Sopenharmony_ci uv__free(handle->path); 715e66f31c5Sopenharmony_ci handle->path = NULL; 716e66f31c5Sopenharmony_ci } 717e66f31c5Sopenharmony_ci 718e66f31c5Sopenharmony_ci if (rc != 0 && errno == EALREADY) 719e66f31c5Sopenharmony_ci return -1; 720e66f31c5Sopenharmony_ci 721e66f31c5Sopenharmony_ci uv__handle_stop(handle); 722e66f31c5Sopenharmony_ci 723e66f31c5Sopenharmony_ci return 0; 724e66f31c5Sopenharmony_ci} 725e66f31c5Sopenharmony_ci 726e66f31c5Sopenharmony_ci 727e66f31c5Sopenharmony_ciint uv_fs_event_stop(uv_fs_event_t* handle) { 728e66f31c5Sopenharmony_ci uv__fs_event_stop(handle); 729e66f31c5Sopenharmony_ci return 0; 730e66f31c5Sopenharmony_ci} 731e66f31c5Sopenharmony_ci 732e66f31c5Sopenharmony_ci 733e66f31c5Sopenharmony_civoid uv__fs_event_close(uv_fs_event_t* handle) { 734e66f31c5Sopenharmony_ci /* 735e66f31c5Sopenharmony_ci * If we were unable to unregister file interest here, then it is most likely 736e66f31c5Sopenharmony_ci * that there is a pending queued change notification. When this happens, we 737e66f31c5Sopenharmony_ci * don't want to complete the close as it will free the underlying memory for 738e66f31c5Sopenharmony_ci * the handle, causing a use-after-free problem when the event is processed. 739e66f31c5Sopenharmony_ci * We defer the final cleanup until after the event is consumed in 740e66f31c5Sopenharmony_ci * os390_message_queue_handler(). 741e66f31c5Sopenharmony_ci */ 742e66f31c5Sopenharmony_ci if (uv__fs_event_stop(handle) == 0) 743e66f31c5Sopenharmony_ci uv__make_close_pending((uv_handle_t*) handle); 744e66f31c5Sopenharmony_ci} 745e66f31c5Sopenharmony_ci 746e66f31c5Sopenharmony_ci 747e66f31c5Sopenharmony_cistatic int os390_message_queue_handler(uv__os390_epoll* ep) { 748e66f31c5Sopenharmony_ci uv_fs_event_t* handle; 749e66f31c5Sopenharmony_ci int msglen; 750e66f31c5Sopenharmony_ci int events; 751e66f31c5Sopenharmony_ci _RFIM msg; 752e66f31c5Sopenharmony_ci 753e66f31c5Sopenharmony_ci if (ep->msg_queue == -1) 754e66f31c5Sopenharmony_ci return 0; 755e66f31c5Sopenharmony_ci 756e66f31c5Sopenharmony_ci msglen = msgrcv(ep->msg_queue, &msg, sizeof(msg), 0, IPC_NOWAIT); 757e66f31c5Sopenharmony_ci 758e66f31c5Sopenharmony_ci if (msglen == -1 && errno == ENOMSG) 759e66f31c5Sopenharmony_ci return 0; 760e66f31c5Sopenharmony_ci 761e66f31c5Sopenharmony_ci if (msglen == -1) 762e66f31c5Sopenharmony_ci abort(); 763e66f31c5Sopenharmony_ci 764e66f31c5Sopenharmony_ci events = 0; 765e66f31c5Sopenharmony_ci if (msg.__rfim_event == _RFIM_ATTR || msg.__rfim_event == _RFIM_WRITE) 766e66f31c5Sopenharmony_ci events = UV_CHANGE; 767e66f31c5Sopenharmony_ci else if (msg.__rfim_event == _RFIM_RENAME || msg.__rfim_event == _RFIM_UNLINK) 768e66f31c5Sopenharmony_ci events = UV_RENAME; 769e66f31c5Sopenharmony_ci else if (msg.__rfim_event == 156) 770e66f31c5Sopenharmony_ci /* TODO(gabylb): zos - this event should not happen, need to investigate. 771e66f31c5Sopenharmony_ci * 772e66f31c5Sopenharmony_ci * This event seems to occur when the watched file is [re]moved, or an 773e66f31c5Sopenharmony_ci * editor (like vim) renames then creates the file on save (for vim, that's 774e66f31c5Sopenharmony_ci * when backupcopy=no|auto). 775e66f31c5Sopenharmony_ci */ 776e66f31c5Sopenharmony_ci events = UV_RENAME; 777e66f31c5Sopenharmony_ci else 778e66f31c5Sopenharmony_ci /* Some event that we are not interested in. */ 779e66f31c5Sopenharmony_ci return 0; 780e66f31c5Sopenharmony_ci 781e66f31c5Sopenharmony_ci /* `__rfim_utok` is treated as text when it should be treated as binary while 782e66f31c5Sopenharmony_ci * running in ASCII mode, resulting in an unwanted autoconversion. 783e66f31c5Sopenharmony_ci */ 784e66f31c5Sopenharmony_ci __a2e_l(msg.__rfim_utok, sizeof(msg.__rfim_utok)); 785e66f31c5Sopenharmony_ci handle = *(uv_fs_event_t**)(msg.__rfim_utok); 786e66f31c5Sopenharmony_ci assert(handle != NULL); 787e66f31c5Sopenharmony_ci 788e66f31c5Sopenharmony_ci assert((handle->flags & UV_HANDLE_CLOSED) == 0); 789e66f31c5Sopenharmony_ci if (uv__is_closing(handle)) { 790e66f31c5Sopenharmony_ci uv__handle_stop(handle); 791e66f31c5Sopenharmony_ci uv__make_close_pending((uv_handle_t*) handle); 792e66f31c5Sopenharmony_ci return 0; 793e66f31c5Sopenharmony_ci } else if (handle->path == NULL) { 794e66f31c5Sopenharmony_ci /* _RFIS_UNREG returned EALREADY. */ 795e66f31c5Sopenharmony_ci uv__handle_stop(handle); 796e66f31c5Sopenharmony_ci return 0; 797e66f31c5Sopenharmony_ci } 798e66f31c5Sopenharmony_ci 799e66f31c5Sopenharmony_ci /* The file is implicitly unregistered when the change notification is 800e66f31c5Sopenharmony_ci * sent, only one notification is sent per registration. So we need to 801e66f31c5Sopenharmony_ci * re-register interest in a file after each change notification we 802e66f31c5Sopenharmony_ci * receive. 803e66f31c5Sopenharmony_ci */ 804e66f31c5Sopenharmony_ci assert(handle->path != NULL); 805e66f31c5Sopenharmony_ci os390_regfileint(handle, handle->path); 806e66f31c5Sopenharmony_ci handle->cb(handle, uv__basename_r(handle->path), events, 0); 807e66f31c5Sopenharmony_ci return 1; 808e66f31c5Sopenharmony_ci} 809e66f31c5Sopenharmony_ci 810e66f31c5Sopenharmony_ci 811e66f31c5Sopenharmony_civoid uv__io_poll(uv_loop_t* loop, int timeout) { 812e66f31c5Sopenharmony_ci static const int max_safe_timeout = 1789569; 813e66f31c5Sopenharmony_ci uv__loop_internal_fields_t* lfields; 814e66f31c5Sopenharmony_ci struct epoll_event events[1024]; 815e66f31c5Sopenharmony_ci struct epoll_event* pe; 816e66f31c5Sopenharmony_ci struct epoll_event e; 817e66f31c5Sopenharmony_ci uv__os390_epoll* ep; 818e66f31c5Sopenharmony_ci int have_signals; 819e66f31c5Sopenharmony_ci int real_timeout; 820e66f31c5Sopenharmony_ci struct uv__queue* q; 821e66f31c5Sopenharmony_ci uv__io_t* w; 822e66f31c5Sopenharmony_ci uint64_t base; 823e66f31c5Sopenharmony_ci int count; 824e66f31c5Sopenharmony_ci int nfds; 825e66f31c5Sopenharmony_ci int fd; 826e66f31c5Sopenharmony_ci int op; 827e66f31c5Sopenharmony_ci int i; 828e66f31c5Sopenharmony_ci int user_timeout; 829e66f31c5Sopenharmony_ci int reset_timeout; 830e66f31c5Sopenharmony_ci 831e66f31c5Sopenharmony_ci if (loop->nfds == 0) { 832e66f31c5Sopenharmony_ci assert(uv__queue_empty(&loop->watcher_queue)); 833e66f31c5Sopenharmony_ci return; 834e66f31c5Sopenharmony_ci } 835e66f31c5Sopenharmony_ci 836e66f31c5Sopenharmony_ci lfields = uv__get_internal_fields(loop); 837e66f31c5Sopenharmony_ci 838e66f31c5Sopenharmony_ci while (!uv__queue_empty(&loop->watcher_queue)) { 839e66f31c5Sopenharmony_ci uv_stream_t* stream; 840e66f31c5Sopenharmony_ci 841e66f31c5Sopenharmony_ci q = uv__queue_head(&loop->watcher_queue); 842e66f31c5Sopenharmony_ci uv__queue_remove(q); 843e66f31c5Sopenharmony_ci uv__queue_init(q); 844e66f31c5Sopenharmony_ci w = uv__queue_data(q, uv__io_t, watcher_queue); 845e66f31c5Sopenharmony_ci 846e66f31c5Sopenharmony_ci assert(w->pevents != 0); 847e66f31c5Sopenharmony_ci assert(w->fd >= 0); 848e66f31c5Sopenharmony_ci 849e66f31c5Sopenharmony_ci stream= container_of(w, uv_stream_t, io_watcher); 850e66f31c5Sopenharmony_ci 851e66f31c5Sopenharmony_ci assert(w->fd < (int) loop->nwatchers); 852e66f31c5Sopenharmony_ci 853e66f31c5Sopenharmony_ci e.events = w->pevents; 854e66f31c5Sopenharmony_ci e.fd = w->fd; 855e66f31c5Sopenharmony_ci 856e66f31c5Sopenharmony_ci if (w->events == 0) 857e66f31c5Sopenharmony_ci op = EPOLL_CTL_ADD; 858e66f31c5Sopenharmony_ci else 859e66f31c5Sopenharmony_ci op = EPOLL_CTL_MOD; 860e66f31c5Sopenharmony_ci 861e66f31c5Sopenharmony_ci /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching 862e66f31c5Sopenharmony_ci * events, skip the syscall and squelch the events after epoll_wait(). 863e66f31c5Sopenharmony_ci */ 864e66f31c5Sopenharmony_ci if (epoll_ctl(loop->ep, op, w->fd, &e)) { 865e66f31c5Sopenharmony_ci if (errno != EEXIST) 866e66f31c5Sopenharmony_ci abort(); 867e66f31c5Sopenharmony_ci 868e66f31c5Sopenharmony_ci assert(op == EPOLL_CTL_ADD); 869e66f31c5Sopenharmony_ci 870e66f31c5Sopenharmony_ci /* We've reactivated a file descriptor that's been watched before. */ 871e66f31c5Sopenharmony_ci if (epoll_ctl(loop->ep, EPOLL_CTL_MOD, w->fd, &e)) 872e66f31c5Sopenharmony_ci abort(); 873e66f31c5Sopenharmony_ci } 874e66f31c5Sopenharmony_ci 875e66f31c5Sopenharmony_ci w->events = w->pevents; 876e66f31c5Sopenharmony_ci } 877e66f31c5Sopenharmony_ci 878e66f31c5Sopenharmony_ci assert(timeout >= -1); 879e66f31c5Sopenharmony_ci base = loop->time; 880e66f31c5Sopenharmony_ci count = 48; /* Benchmarks suggest this gives the best throughput. */ 881e66f31c5Sopenharmony_ci real_timeout = timeout; 882e66f31c5Sopenharmony_ci int nevents = 0; 883e66f31c5Sopenharmony_ci have_signals = 0; 884e66f31c5Sopenharmony_ci 885e66f31c5Sopenharmony_ci if (lfields->flags & UV_METRICS_IDLE_TIME) { 886e66f31c5Sopenharmony_ci reset_timeout = 1; 887e66f31c5Sopenharmony_ci user_timeout = timeout; 888e66f31c5Sopenharmony_ci timeout = 0; 889e66f31c5Sopenharmony_ci } else { 890e66f31c5Sopenharmony_ci reset_timeout = 0; 891e66f31c5Sopenharmony_ci } 892e66f31c5Sopenharmony_ci 893e66f31c5Sopenharmony_ci nfds = 0; 894e66f31c5Sopenharmony_ci for (;;) { 895e66f31c5Sopenharmony_ci /* Only need to set the provider_entry_time if timeout != 0. The function 896e66f31c5Sopenharmony_ci * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME. 897e66f31c5Sopenharmony_ci */ 898e66f31c5Sopenharmony_ci if (timeout != 0) 899e66f31c5Sopenharmony_ci uv__metrics_set_provider_entry_time(loop); 900e66f31c5Sopenharmony_ci 901e66f31c5Sopenharmony_ci if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout) 902e66f31c5Sopenharmony_ci timeout = max_safe_timeout; 903e66f31c5Sopenharmony_ci 904e66f31c5Sopenharmony_ci /* Store the current timeout in a location that's globally accessible so 905e66f31c5Sopenharmony_ci * other locations like uv__work_done() can determine whether the queue 906e66f31c5Sopenharmony_ci * of events in the callback were waiting when poll was called. 907e66f31c5Sopenharmony_ci */ 908e66f31c5Sopenharmony_ci lfields->current_timeout = timeout; 909e66f31c5Sopenharmony_ci 910e66f31c5Sopenharmony_ci nfds = epoll_wait(loop->ep, events, 911e66f31c5Sopenharmony_ci ARRAY_SIZE(events), timeout); 912e66f31c5Sopenharmony_ci 913e66f31c5Sopenharmony_ci /* Update loop->time unconditionally. It's tempting to skip the update when 914e66f31c5Sopenharmony_ci * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the 915e66f31c5Sopenharmony_ci * operating system didn't reschedule our process while in the syscall. 916e66f31c5Sopenharmony_ci */ 917e66f31c5Sopenharmony_ci base = loop->time; 918e66f31c5Sopenharmony_ci SAVE_ERRNO(uv__update_time(loop)); 919e66f31c5Sopenharmony_ci if (nfds == 0) { 920e66f31c5Sopenharmony_ci assert(timeout != -1); 921e66f31c5Sopenharmony_ci 922e66f31c5Sopenharmony_ci if (reset_timeout != 0) { 923e66f31c5Sopenharmony_ci timeout = user_timeout; 924e66f31c5Sopenharmony_ci reset_timeout = 0; 925e66f31c5Sopenharmony_ci } 926e66f31c5Sopenharmony_ci 927e66f31c5Sopenharmony_ci if (timeout == -1) 928e66f31c5Sopenharmony_ci continue; 929e66f31c5Sopenharmony_ci 930e66f31c5Sopenharmony_ci if (timeout == 0) 931e66f31c5Sopenharmony_ci return; 932e66f31c5Sopenharmony_ci 933e66f31c5Sopenharmony_ci /* We may have been inside the system call for longer than |timeout| 934e66f31c5Sopenharmony_ci * milliseconds so we need to update the timestamp to avoid drift. 935e66f31c5Sopenharmony_ci */ 936e66f31c5Sopenharmony_ci goto update_timeout; 937e66f31c5Sopenharmony_ci } 938e66f31c5Sopenharmony_ci 939e66f31c5Sopenharmony_ci if (nfds == -1) { 940e66f31c5Sopenharmony_ci 941e66f31c5Sopenharmony_ci if (errno != EINTR) 942e66f31c5Sopenharmony_ci abort(); 943e66f31c5Sopenharmony_ci 944e66f31c5Sopenharmony_ci if (reset_timeout != 0) { 945e66f31c5Sopenharmony_ci timeout = user_timeout; 946e66f31c5Sopenharmony_ci reset_timeout = 0; 947e66f31c5Sopenharmony_ci } 948e66f31c5Sopenharmony_ci 949e66f31c5Sopenharmony_ci if (timeout == -1) 950e66f31c5Sopenharmony_ci continue; 951e66f31c5Sopenharmony_ci 952e66f31c5Sopenharmony_ci if (timeout == 0) 953e66f31c5Sopenharmony_ci return; 954e66f31c5Sopenharmony_ci 955e66f31c5Sopenharmony_ci /* Interrupted by a signal. Update timeout and poll again. */ 956e66f31c5Sopenharmony_ci goto update_timeout; 957e66f31c5Sopenharmony_ci } 958e66f31c5Sopenharmony_ci 959e66f31c5Sopenharmony_ci 960e66f31c5Sopenharmony_ci assert(loop->watchers != NULL); 961e66f31c5Sopenharmony_ci loop->watchers[loop->nwatchers] = (void*) events; 962e66f31c5Sopenharmony_ci loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; 963e66f31c5Sopenharmony_ci for (i = 0; i < nfds; i++) { 964e66f31c5Sopenharmony_ci pe = events + i; 965e66f31c5Sopenharmony_ci fd = pe->fd; 966e66f31c5Sopenharmony_ci 967e66f31c5Sopenharmony_ci /* Skip invalidated events, see uv__platform_invalidate_fd */ 968e66f31c5Sopenharmony_ci if (fd == -1) 969e66f31c5Sopenharmony_ci continue; 970e66f31c5Sopenharmony_ci 971e66f31c5Sopenharmony_ci ep = loop->ep; 972e66f31c5Sopenharmony_ci if (pe->is_msg) { 973e66f31c5Sopenharmony_ci os390_message_queue_handler(ep); 974e66f31c5Sopenharmony_ci nevents++; 975e66f31c5Sopenharmony_ci continue; 976e66f31c5Sopenharmony_ci } 977e66f31c5Sopenharmony_ci 978e66f31c5Sopenharmony_ci assert(fd >= 0); 979e66f31c5Sopenharmony_ci assert((unsigned) fd < loop->nwatchers); 980e66f31c5Sopenharmony_ci 981e66f31c5Sopenharmony_ci w = loop->watchers[fd]; 982e66f31c5Sopenharmony_ci 983e66f31c5Sopenharmony_ci if (w == NULL) { 984e66f31c5Sopenharmony_ci /* File descriptor that we've stopped watching, disarm it. 985e66f31c5Sopenharmony_ci * 986e66f31c5Sopenharmony_ci * Ignore all errors because we may be racing with another thread 987e66f31c5Sopenharmony_ci * when the file descriptor is closed. 988e66f31c5Sopenharmony_ci */ 989e66f31c5Sopenharmony_ci epoll_ctl(loop->ep, EPOLL_CTL_DEL, fd, pe); 990e66f31c5Sopenharmony_ci continue; 991e66f31c5Sopenharmony_ci } 992e66f31c5Sopenharmony_ci 993e66f31c5Sopenharmony_ci /* Give users only events they're interested in. Prevents spurious 994e66f31c5Sopenharmony_ci * callbacks when previous callback invocation in this loop has stopped 995e66f31c5Sopenharmony_ci * the current watcher. Also, filters out events that users has not 996e66f31c5Sopenharmony_ci * requested us to watch. 997e66f31c5Sopenharmony_ci */ 998e66f31c5Sopenharmony_ci pe->events &= w->pevents | POLLERR | POLLHUP; 999e66f31c5Sopenharmony_ci 1000e66f31c5Sopenharmony_ci if (pe->events == POLLERR || pe->events == POLLHUP) 1001e66f31c5Sopenharmony_ci pe->events |= w->pevents & (POLLIN | POLLOUT); 1002e66f31c5Sopenharmony_ci 1003e66f31c5Sopenharmony_ci if (pe->events != 0) { 1004e66f31c5Sopenharmony_ci /* Run signal watchers last. This also affects child process watchers 1005e66f31c5Sopenharmony_ci * because those are implemented in terms of signal watchers. 1006e66f31c5Sopenharmony_ci */ 1007e66f31c5Sopenharmony_ci if (w == &loop->signal_io_watcher) { 1008e66f31c5Sopenharmony_ci have_signals = 1; 1009e66f31c5Sopenharmony_ci } else { 1010e66f31c5Sopenharmony_ci uv__metrics_update_idle_time(loop); 1011e66f31c5Sopenharmony_ci w->cb(loop, w, pe->events); 1012e66f31c5Sopenharmony_ci } 1013e66f31c5Sopenharmony_ci nevents++; 1014e66f31c5Sopenharmony_ci } 1015e66f31c5Sopenharmony_ci } 1016e66f31c5Sopenharmony_ci 1017e66f31c5Sopenharmony_ci uv__metrics_inc_events(loop, nevents); 1018e66f31c5Sopenharmony_ci if (reset_timeout != 0) { 1019e66f31c5Sopenharmony_ci timeout = user_timeout; 1020e66f31c5Sopenharmony_ci reset_timeout = 0; 1021e66f31c5Sopenharmony_ci uv__metrics_inc_events_waiting(loop, nevents); 1022e66f31c5Sopenharmony_ci } 1023e66f31c5Sopenharmony_ci 1024e66f31c5Sopenharmony_ci if (have_signals != 0) { 1025e66f31c5Sopenharmony_ci uv__metrics_update_idle_time(loop); 1026e66f31c5Sopenharmony_ci loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); 1027e66f31c5Sopenharmony_ci } 1028e66f31c5Sopenharmony_ci 1029e66f31c5Sopenharmony_ci loop->watchers[loop->nwatchers] = NULL; 1030e66f31c5Sopenharmony_ci loop->watchers[loop->nwatchers + 1] = NULL; 1031e66f31c5Sopenharmony_ci 1032e66f31c5Sopenharmony_ci if (have_signals != 0) 1033e66f31c5Sopenharmony_ci return; /* Event loop should cycle now so don't poll again. */ 1034e66f31c5Sopenharmony_ci 1035e66f31c5Sopenharmony_ci if (nevents != 0) { 1036e66f31c5Sopenharmony_ci if (nfds == ARRAY_SIZE(events) && --count != 0) { 1037e66f31c5Sopenharmony_ci /* Poll for more events but don't block this time. */ 1038e66f31c5Sopenharmony_ci timeout = 0; 1039e66f31c5Sopenharmony_ci continue; 1040e66f31c5Sopenharmony_ci } 1041e66f31c5Sopenharmony_ci return; 1042e66f31c5Sopenharmony_ci } 1043e66f31c5Sopenharmony_ci 1044e66f31c5Sopenharmony_ci if (timeout == 0) 1045e66f31c5Sopenharmony_ci return; 1046e66f31c5Sopenharmony_ci 1047e66f31c5Sopenharmony_ci if (timeout == -1) 1048e66f31c5Sopenharmony_ci continue; 1049e66f31c5Sopenharmony_ci 1050e66f31c5Sopenharmony_ciupdate_timeout: 1051e66f31c5Sopenharmony_ci assert(timeout > 0); 1052e66f31c5Sopenharmony_ci 1053e66f31c5Sopenharmony_ci real_timeout -= (loop->time - base); 1054e66f31c5Sopenharmony_ci if (real_timeout <= 0) 1055e66f31c5Sopenharmony_ci return; 1056e66f31c5Sopenharmony_ci 1057e66f31c5Sopenharmony_ci timeout = real_timeout; 1058e66f31c5Sopenharmony_ci } 1059e66f31c5Sopenharmony_ci} 1060e66f31c5Sopenharmony_ci 1061e66f31c5Sopenharmony_ci 1062e66f31c5Sopenharmony_ciint uv__io_fork(uv_loop_t* loop) { 1063e66f31c5Sopenharmony_ci /* 1064e66f31c5Sopenharmony_ci Nullify the msg queue but don't close it because 1065e66f31c5Sopenharmony_ci it is still being used by the parent. 1066e66f31c5Sopenharmony_ci */ 1067e66f31c5Sopenharmony_ci loop->ep = NULL; 1068e66f31c5Sopenharmony_ci 1069e66f31c5Sopenharmony_ci return uv__platform_loop_init(loop); 1070e66f31c5Sopenharmony_ci} 1071