11cb0ef41Sopenharmony_ci/* Copyright libuv project contributors. All rights reserved. 21cb0ef41Sopenharmony_ci * 31cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 41cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to 51cb0ef41Sopenharmony_ci * deal in the Software without restriction, including without limitation the 61cb0ef41Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 71cb0ef41Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 81cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions: 91cb0ef41Sopenharmony_ci * 101cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 111cb0ef41Sopenharmony_ci * all copies or substantial portions of the Software. 121cb0ef41Sopenharmony_ci * 131cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 141cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 151cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 161cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 171cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 181cb0ef41Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 191cb0ef41Sopenharmony_ci * IN THE SOFTWARE. 201cb0ef41Sopenharmony_ci */ 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci#include "internal.h" 231cb0ef41Sopenharmony_ci#include <sys/ioctl.h> 241cb0ef41Sopenharmony_ci#include <net/if.h> 251cb0ef41Sopenharmony_ci#include <utmpx.h> 261cb0ef41Sopenharmony_ci#include <unistd.h> 271cb0ef41Sopenharmony_ci#include <sys/ps.h> 281cb0ef41Sopenharmony_ci#include <builtins.h> 291cb0ef41Sopenharmony_ci#include <termios.h> 301cb0ef41Sopenharmony_ci#include <sys/msg.h> 311cb0ef41Sopenharmony_ci#include <sys/resource.h> 321cb0ef41Sopenharmony_ci#include "zos-base.h" 331cb0ef41Sopenharmony_ci#if defined(__clang__) 341cb0ef41Sopenharmony_ci#include "csrsic.h" 351cb0ef41Sopenharmony_ci#else 361cb0ef41Sopenharmony_ci#include "//'SYS1.SAMPLIB(CSRSIC)'" 371cb0ef41Sopenharmony_ci#endif 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci#define CVT_PTR 0x10 401cb0ef41Sopenharmony_ci#define PSA_PTR 0x00 411cb0ef41Sopenharmony_ci#define CSD_OFFSET 0x294 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci/* 441cb0ef41Sopenharmony_ci Long-term average CPU service used by this logical partition, 451cb0ef41Sopenharmony_ci in millions of service units per hour. If this value is above 461cb0ef41Sopenharmony_ci the partition's defined capacity, the partition will be capped. 471cb0ef41Sopenharmony_ci It is calculated using the physical CPU adjustment factor 481cb0ef41Sopenharmony_ci (RCTPCPUA) so it may not match other measures of service which 491cb0ef41Sopenharmony_ci are based on the logical CPU adjustment factor. It is available 501cb0ef41Sopenharmony_ci if the hardware supports LPAR cluster. 511cb0ef41Sopenharmony_ci*/ 521cb0ef41Sopenharmony_ci#define RCTLACS_OFFSET 0xC4 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci/* 32-bit count of alive CPUs. This includes both CPs and IFAs */ 551cb0ef41Sopenharmony_ci#define CSD_NUMBER_ONLINE_CPUS 0xD4 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci/* Address of system resources manager (SRM) control table */ 581cb0ef41Sopenharmony_ci#define CVTOPCTP_OFFSET 0x25C 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci/* Address of the RCT table */ 611cb0ef41Sopenharmony_ci#define RMCTRCT_OFFSET 0xE4 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci/* Address of the rsm control and enumeration area. */ 641cb0ef41Sopenharmony_ci#define CVTRCEP_OFFSET 0x490 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci/* Total number of frames currently on all available frame queues. */ 671cb0ef41Sopenharmony_ci#define RCEAFC_OFFSET 0x088 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci/* CPC model length from the CSRSI Service. */ 701cb0ef41Sopenharmony_ci#define CPCMODEL_LENGTH 16 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci/* Pointer to the home (current) ASCB. */ 731cb0ef41Sopenharmony_ci#define PSAAOLD 0x224 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci/* Pointer to rsm address space block extension. */ 761cb0ef41Sopenharmony_ci#define ASCBRSME 0x16C 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ci/* 791cb0ef41Sopenharmony_ci NUMBER OF FRAMES CURRENTLY IN USE BY THIS ADDRESS SPACE. 801cb0ef41Sopenharmony_ci It does not include 2G frames. 811cb0ef41Sopenharmony_ci*/ 821cb0ef41Sopenharmony_ci#define RAXFMCT 0x2C 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ci/* Thread Entry constants */ 851cb0ef41Sopenharmony_ci#define PGTH_CURRENT 1 861cb0ef41Sopenharmony_ci#define PGTH_LEN 26 871cb0ef41Sopenharmony_ci#define PGTHAPATH 0x20 881cb0ef41Sopenharmony_ci#pragma linkage(BPX4GTH, OS) 891cb0ef41Sopenharmony_ci#pragma linkage(BPX1GTH, OS) 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_ci/* TOD Clock resolution in nanoseconds */ 921cb0ef41Sopenharmony_ci#define TOD_RES 4.096 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_citypedef unsigned data_area_ptr_assign_type; 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_citypedef union { 971cb0ef41Sopenharmony_ci struct { 981cb0ef41Sopenharmony_ci#if defined(_LP64) 991cb0ef41Sopenharmony_ci data_area_ptr_assign_type lower; 1001cb0ef41Sopenharmony_ci#endif 1011cb0ef41Sopenharmony_ci data_area_ptr_assign_type assign; 1021cb0ef41Sopenharmony_ci }; 1031cb0ef41Sopenharmony_ci char* deref; 1041cb0ef41Sopenharmony_ci} data_area_ptr; 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_civoid uv_loadavg(double avg[3]) { 1081cb0ef41Sopenharmony_ci /* TODO: implement the following */ 1091cb0ef41Sopenharmony_ci avg[0] = 0; 1101cb0ef41Sopenharmony_ci avg[1] = 0; 1111cb0ef41Sopenharmony_ci avg[2] = 0; 1121cb0ef41Sopenharmony_ci} 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_ciint uv__platform_loop_init(uv_loop_t* loop) { 1161cb0ef41Sopenharmony_ci uv__os390_epoll* ep; 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ci ep = epoll_create1(0); 1191cb0ef41Sopenharmony_ci loop->ep = ep; 1201cb0ef41Sopenharmony_ci if (ep == NULL) 1211cb0ef41Sopenharmony_ci return UV__ERR(errno); 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci return 0; 1241cb0ef41Sopenharmony_ci} 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_civoid uv__platform_loop_delete(uv_loop_t* loop) { 1281cb0ef41Sopenharmony_ci if (loop->ep != NULL) { 1291cb0ef41Sopenharmony_ci epoll_queue_close(loop->ep); 1301cb0ef41Sopenharmony_ci loop->ep = NULL; 1311cb0ef41Sopenharmony_ci } 1321cb0ef41Sopenharmony_ci} 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ciuint64_t uv__hrtime(uv_clocktype_t type) { 1361cb0ef41Sopenharmony_ci unsigned long long timestamp; 1371cb0ef41Sopenharmony_ci __stckf(×tamp); 1381cb0ef41Sopenharmony_ci /* Convert to nanoseconds */ 1391cb0ef41Sopenharmony_ci return timestamp / TOD_RES; 1401cb0ef41Sopenharmony_ci} 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_cistatic int getexe(char* buf, size_t len) { 1441cb0ef41Sopenharmony_ci return uv__strscpy(buf, __getargv()[0], len); 1451cb0ef41Sopenharmony_ci} 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ci/* 1491cb0ef41Sopenharmony_ci * We could use a static buffer for the path manipulations that we need outside 1501cb0ef41Sopenharmony_ci * of the function, but this function could be called by multiple consumers and 1511cb0ef41Sopenharmony_ci * we don't want to potentially create a race condition in the use of snprintf. 1521cb0ef41Sopenharmony_ci * There is no direct way of getting the exe path in zOS - either through /procfs 1531cb0ef41Sopenharmony_ci * or through some libc APIs. The below approach is to parse the argv[0]'s pattern 1541cb0ef41Sopenharmony_ci * and use it in conjunction with PATH environment variable to craft one. 1551cb0ef41Sopenharmony_ci */ 1561cb0ef41Sopenharmony_ciint uv_exepath(char* buffer, size_t* size) { 1571cb0ef41Sopenharmony_ci int res; 1581cb0ef41Sopenharmony_ci char args[PATH_MAX]; 1591cb0ef41Sopenharmony_ci int pid; 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_ci if (buffer == NULL || size == NULL || *size == 0) 1621cb0ef41Sopenharmony_ci return UV_EINVAL; 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci res = getexe(args, sizeof(args)); 1651cb0ef41Sopenharmony_ci if (res < 0) 1661cb0ef41Sopenharmony_ci return UV_EINVAL; 1671cb0ef41Sopenharmony_ci 1681cb0ef41Sopenharmony_ci return uv__search_path(args, buffer, size); 1691cb0ef41Sopenharmony_ci} 1701cb0ef41Sopenharmony_ci 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_ciuint64_t uv_get_free_memory(void) { 1731cb0ef41Sopenharmony_ci uint64_t freeram; 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci data_area_ptr cvt = {0}; 1761cb0ef41Sopenharmony_ci data_area_ptr rcep = {0}; 1771cb0ef41Sopenharmony_ci cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR); 1781cb0ef41Sopenharmony_ci rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET); 1791cb0ef41Sopenharmony_ci freeram = (uint64_t)*((uint32_t*)(rcep.deref + RCEAFC_OFFSET)) * 4096; 1801cb0ef41Sopenharmony_ci return freeram; 1811cb0ef41Sopenharmony_ci} 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_ciuint64_t uv_get_total_memory(void) { 1851cb0ef41Sopenharmony_ci /* Use CVTRLSTG to get the size of actual real storage online at IPL in K. */ 1861cb0ef41Sopenharmony_ci return (uint64_t)((int)((char *__ptr32 *__ptr32 *)0)[4][214]) * 1024; 1871cb0ef41Sopenharmony_ci} 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ciuint64_t uv_get_constrained_memory(void) { 1911cb0ef41Sopenharmony_ci struct rlimit rl; 1921cb0ef41Sopenharmony_ci 1931cb0ef41Sopenharmony_ci /* RLIMIT_MEMLIMIT return value is in megabytes rather than bytes. */ 1941cb0ef41Sopenharmony_ci if (getrlimit(RLIMIT_MEMLIMIT, &rl) == 0) 1951cb0ef41Sopenharmony_ci return rl.rlim_cur * 1024 * 1024; 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ci return 0; /* There is no memory limit set. */ 1981cb0ef41Sopenharmony_ci} 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ciint uv_resident_set_memory(size_t* rss) { 2021cb0ef41Sopenharmony_ci char* ascb; 2031cb0ef41Sopenharmony_ci char* rax; 2041cb0ef41Sopenharmony_ci size_t nframes; 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_ci ascb = *(char* __ptr32 *)(PSA_PTR + PSAAOLD); 2071cb0ef41Sopenharmony_ci rax = *(char* __ptr32 *)(ascb + ASCBRSME); 2081cb0ef41Sopenharmony_ci nframes = *(unsigned int*)(rax + RAXFMCT); 2091cb0ef41Sopenharmony_ci 2101cb0ef41Sopenharmony_ci *rss = nframes * sysconf(_SC_PAGESIZE); 2111cb0ef41Sopenharmony_ci return 0; 2121cb0ef41Sopenharmony_ci} 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ciint uv_uptime(double* uptime) { 2161cb0ef41Sopenharmony_ci struct utmpx u ; 2171cb0ef41Sopenharmony_ci struct utmpx *v; 2181cb0ef41Sopenharmony_ci time64_t t; 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_ci u.ut_type = BOOT_TIME; 2211cb0ef41Sopenharmony_ci v = getutxid(&u); 2221cb0ef41Sopenharmony_ci if (v == NULL) 2231cb0ef41Sopenharmony_ci return -1; 2241cb0ef41Sopenharmony_ci *uptime = difftime64(time64(&t), v->ut_tv.tv_sec); 2251cb0ef41Sopenharmony_ci return 0; 2261cb0ef41Sopenharmony_ci} 2271cb0ef41Sopenharmony_ci 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ciint uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 2301cb0ef41Sopenharmony_ci uv_cpu_info_t* cpu_info; 2311cb0ef41Sopenharmony_ci int idx; 2321cb0ef41Sopenharmony_ci siv1v2 info; 2331cb0ef41Sopenharmony_ci data_area_ptr cvt = {0}; 2341cb0ef41Sopenharmony_ci data_area_ptr csd = {0}; 2351cb0ef41Sopenharmony_ci data_area_ptr rmctrct = {0}; 2361cb0ef41Sopenharmony_ci data_area_ptr cvtopctp = {0}; 2371cb0ef41Sopenharmony_ci int cpu_usage_avg; 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ci cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR); 2401cb0ef41Sopenharmony_ci 2411cb0ef41Sopenharmony_ci csd.assign = *((data_area_ptr_assign_type *) (cvt.deref + CSD_OFFSET)); 2421cb0ef41Sopenharmony_ci cvtopctp.assign = *((data_area_ptr_assign_type *) (cvt.deref + CVTOPCTP_OFFSET)); 2431cb0ef41Sopenharmony_ci rmctrct.assign = *((data_area_ptr_assign_type *) (cvtopctp.deref + RMCTRCT_OFFSET)); 2441cb0ef41Sopenharmony_ci 2451cb0ef41Sopenharmony_ci *count = *((int*) (csd.deref + CSD_NUMBER_ONLINE_CPUS)); 2461cb0ef41Sopenharmony_ci cpu_usage_avg = *((unsigned short int*) (rmctrct.deref + RCTLACS_OFFSET)); 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_ci *cpu_infos = uv__malloc(*count * sizeof(uv_cpu_info_t)); 2491cb0ef41Sopenharmony_ci if (!*cpu_infos) 2501cb0ef41Sopenharmony_ci return UV_ENOMEM; 2511cb0ef41Sopenharmony_ci 2521cb0ef41Sopenharmony_ci cpu_info = *cpu_infos; 2531cb0ef41Sopenharmony_ci idx = 0; 2541cb0ef41Sopenharmony_ci while (idx < *count) { 2551cb0ef41Sopenharmony_ci cpu_info->speed = *(int*)(info.siv1v2si22v1.si22v1cpucapability); 2561cb0ef41Sopenharmony_ci cpu_info->model = uv__malloc(CPCMODEL_LENGTH + 1); 2571cb0ef41Sopenharmony_ci memset(cpu_info->model, '\0', CPCMODEL_LENGTH + 1); 2581cb0ef41Sopenharmony_ci memcpy(cpu_info->model, info.siv1v2si11v1.si11v1cpcmodel, CPCMODEL_LENGTH); 2591cb0ef41Sopenharmony_ci cpu_info->cpu_times.user = cpu_usage_avg; 2601cb0ef41Sopenharmony_ci /* TODO: implement the following */ 2611cb0ef41Sopenharmony_ci cpu_info->cpu_times.sys = 0; 2621cb0ef41Sopenharmony_ci cpu_info->cpu_times.idle = 0; 2631cb0ef41Sopenharmony_ci cpu_info->cpu_times.irq = 0; 2641cb0ef41Sopenharmony_ci cpu_info->cpu_times.nice = 0; 2651cb0ef41Sopenharmony_ci ++cpu_info; 2661cb0ef41Sopenharmony_ci ++idx; 2671cb0ef41Sopenharmony_ci } 2681cb0ef41Sopenharmony_ci 2691cb0ef41Sopenharmony_ci return 0; 2701cb0ef41Sopenharmony_ci} 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_cistatic int uv__interface_addresses_v6(uv_interface_address_t** addresses, 2741cb0ef41Sopenharmony_ci int* count) { 2751cb0ef41Sopenharmony_ci uv_interface_address_t* address; 2761cb0ef41Sopenharmony_ci int sockfd; 2771cb0ef41Sopenharmony_ci int maxsize; 2781cb0ef41Sopenharmony_ci __net_ifconf6header_t ifc; 2791cb0ef41Sopenharmony_ci __net_ifconf6entry_t* ifr; 2801cb0ef41Sopenharmony_ci __net_ifconf6entry_t* p; 2811cb0ef41Sopenharmony_ci unsigned int i; 2821cb0ef41Sopenharmony_ci int count_names; 2831cb0ef41Sopenharmony_ci unsigned char netmask[16] = {0}; 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ci *count = 0; 2861cb0ef41Sopenharmony_ci /* Assume maximum buffer size allowable */ 2871cb0ef41Sopenharmony_ci maxsize = 16384; 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_ci if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) 2901cb0ef41Sopenharmony_ci return UV__ERR(errno); 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_ci ifc.__nif6h_buffer = uv__calloc(1, maxsize); 2931cb0ef41Sopenharmony_ci 2941cb0ef41Sopenharmony_ci if (ifc.__nif6h_buffer == NULL) { 2951cb0ef41Sopenharmony_ci uv__close(sockfd); 2961cb0ef41Sopenharmony_ci return UV_ENOMEM; 2971cb0ef41Sopenharmony_ci } 2981cb0ef41Sopenharmony_ci 2991cb0ef41Sopenharmony_ci ifc.__nif6h_version = 1; 3001cb0ef41Sopenharmony_ci ifc.__nif6h_buflen = maxsize; 3011cb0ef41Sopenharmony_ci 3021cb0ef41Sopenharmony_ci if (ioctl(sockfd, SIOCGIFCONF6, &ifc) == -1) { 3031cb0ef41Sopenharmony_ci /* This will error on a system that does not support IPv6. However, we want 3041cb0ef41Sopenharmony_ci * to treat this as there being 0 interfaces so we can continue to get IPv4 3051cb0ef41Sopenharmony_ci * interfaces in uv_interface_addresses(). So return 0 instead of the error. 3061cb0ef41Sopenharmony_ci */ 3071cb0ef41Sopenharmony_ci uv__free(ifc.__nif6h_buffer); 3081cb0ef41Sopenharmony_ci uv__close(sockfd); 3091cb0ef41Sopenharmony_ci errno = 0; 3101cb0ef41Sopenharmony_ci return 0; 3111cb0ef41Sopenharmony_ci } 3121cb0ef41Sopenharmony_ci 3131cb0ef41Sopenharmony_ci ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer); 3141cb0ef41Sopenharmony_ci while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) { 3151cb0ef41Sopenharmony_ci p = ifr; 3161cb0ef41Sopenharmony_ci ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen); 3171cb0ef41Sopenharmony_ci 3181cb0ef41Sopenharmony_ci if (!(p->__nif6e_addr.sin6_family == AF_INET6)) 3191cb0ef41Sopenharmony_ci continue; 3201cb0ef41Sopenharmony_ci 3211cb0ef41Sopenharmony_ci if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE)) 3221cb0ef41Sopenharmony_ci continue; 3231cb0ef41Sopenharmony_ci 3241cb0ef41Sopenharmony_ci ++(*count); 3251cb0ef41Sopenharmony_ci } 3261cb0ef41Sopenharmony_ci 3271cb0ef41Sopenharmony_ci if ((*count) == 0) { 3281cb0ef41Sopenharmony_ci uv__free(ifc.__nif6h_buffer); 3291cb0ef41Sopenharmony_ci uv__close(sockfd); 3301cb0ef41Sopenharmony_ci return 0; 3311cb0ef41Sopenharmony_ci } 3321cb0ef41Sopenharmony_ci 3331cb0ef41Sopenharmony_ci /* Alloc the return interface structs */ 3341cb0ef41Sopenharmony_ci *addresses = uv__calloc(1, *count * sizeof(uv_interface_address_t)); 3351cb0ef41Sopenharmony_ci if (!(*addresses)) { 3361cb0ef41Sopenharmony_ci uv__free(ifc.__nif6h_buffer); 3371cb0ef41Sopenharmony_ci uv__close(sockfd); 3381cb0ef41Sopenharmony_ci return UV_ENOMEM; 3391cb0ef41Sopenharmony_ci } 3401cb0ef41Sopenharmony_ci address = *addresses; 3411cb0ef41Sopenharmony_ci 3421cb0ef41Sopenharmony_ci count_names = 0; 3431cb0ef41Sopenharmony_ci ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer); 3441cb0ef41Sopenharmony_ci while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) { 3451cb0ef41Sopenharmony_ci p = ifr; 3461cb0ef41Sopenharmony_ci ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen); 3471cb0ef41Sopenharmony_ci 3481cb0ef41Sopenharmony_ci if (!(p->__nif6e_addr.sin6_family == AF_INET6)) 3491cb0ef41Sopenharmony_ci continue; 3501cb0ef41Sopenharmony_ci 3511cb0ef41Sopenharmony_ci if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE)) 3521cb0ef41Sopenharmony_ci continue; 3531cb0ef41Sopenharmony_ci 3541cb0ef41Sopenharmony_ci /* All conditions above must match count loop */ 3551cb0ef41Sopenharmony_ci 3561cb0ef41Sopenharmony_ci i = 0; 3571cb0ef41Sopenharmony_ci /* Ignore EBCDIC space (0x40) padding in name */ 3581cb0ef41Sopenharmony_ci while (i < ARRAY_SIZE(p->__nif6e_name) && 3591cb0ef41Sopenharmony_ci p->__nif6e_name[i] != 0x40 && 3601cb0ef41Sopenharmony_ci p->__nif6e_name[i] != 0) 3611cb0ef41Sopenharmony_ci ++i; 3621cb0ef41Sopenharmony_ci address->name = uv__malloc(i + 1); 3631cb0ef41Sopenharmony_ci if (address->name == NULL) { 3641cb0ef41Sopenharmony_ci uv_free_interface_addresses(*addresses, count_names); 3651cb0ef41Sopenharmony_ci uv__free(ifc.__nif6h_buffer); 3661cb0ef41Sopenharmony_ci uv__close(sockfd); 3671cb0ef41Sopenharmony_ci return UV_ENOMEM; 3681cb0ef41Sopenharmony_ci } 3691cb0ef41Sopenharmony_ci memcpy(address->name, p->__nif6e_name, i); 3701cb0ef41Sopenharmony_ci address->name[i] = '\0'; 3711cb0ef41Sopenharmony_ci __e2a_s(address->name); 3721cb0ef41Sopenharmony_ci count_names++; 3731cb0ef41Sopenharmony_ci 3741cb0ef41Sopenharmony_ci address->address.address6 = *((struct sockaddr_in6*) &p->__nif6e_addr); 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_ci for (i = 0; i < (p->__nif6e_prefixlen / 8); i++) 3771cb0ef41Sopenharmony_ci netmask[i] = 0xFF; 3781cb0ef41Sopenharmony_ci 3791cb0ef41Sopenharmony_ci if (p->__nif6e_prefixlen % 8) 3801cb0ef41Sopenharmony_ci netmask[i] = 0xFF << (8 - (p->__nif6e_prefixlen % 8)); 3811cb0ef41Sopenharmony_ci 3821cb0ef41Sopenharmony_ci address->netmask.netmask6.sin6_len = p->__nif6e_prefixlen; 3831cb0ef41Sopenharmony_ci memcpy(&(address->netmask.netmask6.sin6_addr), netmask, 16); 3841cb0ef41Sopenharmony_ci address->netmask.netmask6.sin6_family = AF_INET6; 3851cb0ef41Sopenharmony_ci 3861cb0ef41Sopenharmony_ci address->is_internal = p->__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0; 3871cb0ef41Sopenharmony_ci address++; 3881cb0ef41Sopenharmony_ci } 3891cb0ef41Sopenharmony_ci 3901cb0ef41Sopenharmony_ci uv__free(ifc.__nif6h_buffer); 3911cb0ef41Sopenharmony_ci uv__close(sockfd); 3921cb0ef41Sopenharmony_ci return 0; 3931cb0ef41Sopenharmony_ci} 3941cb0ef41Sopenharmony_ci 3951cb0ef41Sopenharmony_ci 3961cb0ef41Sopenharmony_ciint uv_interface_addresses(uv_interface_address_t** addresses, int* count) { 3971cb0ef41Sopenharmony_ci uv_interface_address_t* address; 3981cb0ef41Sopenharmony_ci int sockfd; 3991cb0ef41Sopenharmony_ci int maxsize; 4001cb0ef41Sopenharmony_ci struct ifconf ifc; 4011cb0ef41Sopenharmony_ci struct ifreq flg; 4021cb0ef41Sopenharmony_ci struct ifreq* ifr; 4031cb0ef41Sopenharmony_ci struct ifreq* p; 4041cb0ef41Sopenharmony_ci uv_interface_address_t* addresses_v6; 4051cb0ef41Sopenharmony_ci int count_v6; 4061cb0ef41Sopenharmony_ci unsigned int i; 4071cb0ef41Sopenharmony_ci int rc; 4081cb0ef41Sopenharmony_ci int count_names; 4091cb0ef41Sopenharmony_ci 4101cb0ef41Sopenharmony_ci *count = 0; 4111cb0ef41Sopenharmony_ci *addresses = NULL; 4121cb0ef41Sopenharmony_ci 4131cb0ef41Sopenharmony_ci /* get the ipv6 addresses first */ 4141cb0ef41Sopenharmony_ci if ((rc = uv__interface_addresses_v6(&addresses_v6, &count_v6)) != 0) 4151cb0ef41Sopenharmony_ci return rc; 4161cb0ef41Sopenharmony_ci 4171cb0ef41Sopenharmony_ci /* now get the ipv4 addresses */ 4181cb0ef41Sopenharmony_ci 4191cb0ef41Sopenharmony_ci /* Assume maximum buffer size allowable */ 4201cb0ef41Sopenharmony_ci maxsize = 16384; 4211cb0ef41Sopenharmony_ci 4221cb0ef41Sopenharmony_ci sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); 4231cb0ef41Sopenharmony_ci if (0 > sockfd) { 4241cb0ef41Sopenharmony_ci if (count_v6) 4251cb0ef41Sopenharmony_ci uv_free_interface_addresses(addresses_v6, count_v6); 4261cb0ef41Sopenharmony_ci return UV__ERR(errno); 4271cb0ef41Sopenharmony_ci } 4281cb0ef41Sopenharmony_ci 4291cb0ef41Sopenharmony_ci ifc.ifc_req = uv__calloc(1, maxsize); 4301cb0ef41Sopenharmony_ci 4311cb0ef41Sopenharmony_ci if (ifc.ifc_req == NULL) { 4321cb0ef41Sopenharmony_ci if (count_v6) 4331cb0ef41Sopenharmony_ci uv_free_interface_addresses(addresses_v6, count_v6); 4341cb0ef41Sopenharmony_ci uv__close(sockfd); 4351cb0ef41Sopenharmony_ci return UV_ENOMEM; 4361cb0ef41Sopenharmony_ci } 4371cb0ef41Sopenharmony_ci 4381cb0ef41Sopenharmony_ci ifc.ifc_len = maxsize; 4391cb0ef41Sopenharmony_ci 4401cb0ef41Sopenharmony_ci if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) { 4411cb0ef41Sopenharmony_ci if (count_v6) 4421cb0ef41Sopenharmony_ci uv_free_interface_addresses(addresses_v6, count_v6); 4431cb0ef41Sopenharmony_ci uv__free(ifc.ifc_req); 4441cb0ef41Sopenharmony_ci uv__close(sockfd); 4451cb0ef41Sopenharmony_ci return UV__ERR(errno); 4461cb0ef41Sopenharmony_ci } 4471cb0ef41Sopenharmony_ci 4481cb0ef41Sopenharmony_ci#define MAX(a,b) (((a)>(b))?(a):(b)) 4491cb0ef41Sopenharmony_ci#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p)) 4501cb0ef41Sopenharmony_ci 4511cb0ef41Sopenharmony_ci /* Count all up and running ipv4/ipv6 addresses */ 4521cb0ef41Sopenharmony_ci ifr = ifc.ifc_req; 4531cb0ef41Sopenharmony_ci while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { 4541cb0ef41Sopenharmony_ci p = ifr; 4551cb0ef41Sopenharmony_ci ifr = (struct ifreq*) 4561cb0ef41Sopenharmony_ci ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); 4571cb0ef41Sopenharmony_ci 4581cb0ef41Sopenharmony_ci if (!(p->ifr_addr.sa_family == AF_INET6 || 4591cb0ef41Sopenharmony_ci p->ifr_addr.sa_family == AF_INET)) 4601cb0ef41Sopenharmony_ci continue; 4611cb0ef41Sopenharmony_ci 4621cb0ef41Sopenharmony_ci memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); 4631cb0ef41Sopenharmony_ci if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { 4641cb0ef41Sopenharmony_ci if (count_v6) 4651cb0ef41Sopenharmony_ci uv_free_interface_addresses(addresses_v6, count_v6); 4661cb0ef41Sopenharmony_ci uv__free(ifc.ifc_req); 4671cb0ef41Sopenharmony_ci uv__close(sockfd); 4681cb0ef41Sopenharmony_ci return UV__ERR(errno); 4691cb0ef41Sopenharmony_ci } 4701cb0ef41Sopenharmony_ci 4711cb0ef41Sopenharmony_ci if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) 4721cb0ef41Sopenharmony_ci continue; 4731cb0ef41Sopenharmony_ci 4741cb0ef41Sopenharmony_ci (*count)++; 4751cb0ef41Sopenharmony_ci } 4761cb0ef41Sopenharmony_ci 4771cb0ef41Sopenharmony_ci if (*count == 0 && count_v6 == 0) { 4781cb0ef41Sopenharmony_ci uv__free(ifc.ifc_req); 4791cb0ef41Sopenharmony_ci uv__close(sockfd); 4801cb0ef41Sopenharmony_ci return 0; 4811cb0ef41Sopenharmony_ci } 4821cb0ef41Sopenharmony_ci 4831cb0ef41Sopenharmony_ci /* Alloc the return interface structs */ 4841cb0ef41Sopenharmony_ci *addresses = uv__calloc(1, (*count + count_v6) * 4851cb0ef41Sopenharmony_ci sizeof(uv_interface_address_t)); 4861cb0ef41Sopenharmony_ci 4871cb0ef41Sopenharmony_ci if (!(*addresses)) { 4881cb0ef41Sopenharmony_ci if (count_v6) 4891cb0ef41Sopenharmony_ci uv_free_interface_addresses(addresses_v6, count_v6); 4901cb0ef41Sopenharmony_ci uv__free(ifc.ifc_req); 4911cb0ef41Sopenharmony_ci uv__close(sockfd); 4921cb0ef41Sopenharmony_ci return UV_ENOMEM; 4931cb0ef41Sopenharmony_ci } 4941cb0ef41Sopenharmony_ci address = *addresses; 4951cb0ef41Sopenharmony_ci 4961cb0ef41Sopenharmony_ci /* copy over the ipv6 addresses if any are found */ 4971cb0ef41Sopenharmony_ci if (count_v6) { 4981cb0ef41Sopenharmony_ci memcpy(address, addresses_v6, count_v6 * sizeof(uv_interface_address_t)); 4991cb0ef41Sopenharmony_ci address += count_v6; 5001cb0ef41Sopenharmony_ci *count += count_v6; 5011cb0ef41Sopenharmony_ci /* free ipv6 addresses, but keep address names */ 5021cb0ef41Sopenharmony_ci uv__free(addresses_v6); 5031cb0ef41Sopenharmony_ci } 5041cb0ef41Sopenharmony_ci 5051cb0ef41Sopenharmony_ci count_names = *count; 5061cb0ef41Sopenharmony_ci ifr = ifc.ifc_req; 5071cb0ef41Sopenharmony_ci while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { 5081cb0ef41Sopenharmony_ci p = ifr; 5091cb0ef41Sopenharmony_ci ifr = (struct ifreq*) 5101cb0ef41Sopenharmony_ci ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); 5111cb0ef41Sopenharmony_ci 5121cb0ef41Sopenharmony_ci if (!(p->ifr_addr.sa_family == AF_INET6 || 5131cb0ef41Sopenharmony_ci p->ifr_addr.sa_family == AF_INET)) 5141cb0ef41Sopenharmony_ci continue; 5151cb0ef41Sopenharmony_ci 5161cb0ef41Sopenharmony_ci memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); 5171cb0ef41Sopenharmony_ci if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { 5181cb0ef41Sopenharmony_ci uv_free_interface_addresses(*addresses, count_names); 5191cb0ef41Sopenharmony_ci uv__free(ifc.ifc_req); 5201cb0ef41Sopenharmony_ci uv__close(sockfd); 5211cb0ef41Sopenharmony_ci return UV_ENOSYS; 5221cb0ef41Sopenharmony_ci } 5231cb0ef41Sopenharmony_ci 5241cb0ef41Sopenharmony_ci if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) 5251cb0ef41Sopenharmony_ci continue; 5261cb0ef41Sopenharmony_ci 5271cb0ef41Sopenharmony_ci /* All conditions above must match count loop */ 5281cb0ef41Sopenharmony_ci 5291cb0ef41Sopenharmony_ci i = 0; 5301cb0ef41Sopenharmony_ci /* Ignore EBCDIC space (0x40) padding in name */ 5311cb0ef41Sopenharmony_ci while (i < ARRAY_SIZE(p->ifr_name) && 5321cb0ef41Sopenharmony_ci p->ifr_name[i] != 0x40 && 5331cb0ef41Sopenharmony_ci p->ifr_name[i] != 0) 5341cb0ef41Sopenharmony_ci ++i; 5351cb0ef41Sopenharmony_ci address->name = uv__malloc(i + 1); 5361cb0ef41Sopenharmony_ci if (address->name == NULL) { 5371cb0ef41Sopenharmony_ci uv_free_interface_addresses(*addresses, count_names); 5381cb0ef41Sopenharmony_ci uv__free(ifc.ifc_req); 5391cb0ef41Sopenharmony_ci uv__close(sockfd); 5401cb0ef41Sopenharmony_ci return UV_ENOMEM; 5411cb0ef41Sopenharmony_ci } 5421cb0ef41Sopenharmony_ci memcpy(address->name, p->ifr_name, i); 5431cb0ef41Sopenharmony_ci address->name[i] = '\0'; 5441cb0ef41Sopenharmony_ci __e2a_s(address->name); 5451cb0ef41Sopenharmony_ci count_names++; 5461cb0ef41Sopenharmony_ci 5471cb0ef41Sopenharmony_ci address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr); 5481cb0ef41Sopenharmony_ci 5491cb0ef41Sopenharmony_ci if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) { 5501cb0ef41Sopenharmony_ci uv_free_interface_addresses(*addresses, count_names); 5511cb0ef41Sopenharmony_ci uv__free(ifc.ifc_req); 5521cb0ef41Sopenharmony_ci uv__close(sockfd); 5531cb0ef41Sopenharmony_ci return UV__ERR(errno); 5541cb0ef41Sopenharmony_ci } 5551cb0ef41Sopenharmony_ci 5561cb0ef41Sopenharmony_ci address->netmask.netmask4 = *((struct sockaddr_in*) &p->ifr_addr); 5571cb0ef41Sopenharmony_ci address->netmask.netmask4.sin_family = AF_INET; 5581cb0ef41Sopenharmony_ci address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0; 5591cb0ef41Sopenharmony_ci address++; 5601cb0ef41Sopenharmony_ci } 5611cb0ef41Sopenharmony_ci 5621cb0ef41Sopenharmony_ci#undef ADDR_SIZE 5631cb0ef41Sopenharmony_ci#undef MAX 5641cb0ef41Sopenharmony_ci 5651cb0ef41Sopenharmony_ci uv__free(ifc.ifc_req); 5661cb0ef41Sopenharmony_ci uv__close(sockfd); 5671cb0ef41Sopenharmony_ci return 0; 5681cb0ef41Sopenharmony_ci} 5691cb0ef41Sopenharmony_ci 5701cb0ef41Sopenharmony_ci 5711cb0ef41Sopenharmony_civoid uv_free_interface_addresses(uv_interface_address_t* addresses, 5721cb0ef41Sopenharmony_ci int count) { 5731cb0ef41Sopenharmony_ci int i; 5741cb0ef41Sopenharmony_ci for (i = 0; i < count; ++i) 5751cb0ef41Sopenharmony_ci uv__free(addresses[i].name); 5761cb0ef41Sopenharmony_ci uv__free(addresses); 5771cb0ef41Sopenharmony_ci} 5781cb0ef41Sopenharmony_ci 5791cb0ef41Sopenharmony_ci 5801cb0ef41Sopenharmony_civoid uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { 5811cb0ef41Sopenharmony_ci struct epoll_event* events; 5821cb0ef41Sopenharmony_ci struct epoll_event dummy; 5831cb0ef41Sopenharmony_ci uintptr_t i; 5841cb0ef41Sopenharmony_ci uintptr_t nfds; 5851cb0ef41Sopenharmony_ci 5861cb0ef41Sopenharmony_ci assert(loop->watchers != NULL); 5871cb0ef41Sopenharmony_ci assert(fd >= 0); 5881cb0ef41Sopenharmony_ci 5891cb0ef41Sopenharmony_ci events = (struct epoll_event*) loop->watchers[loop->nwatchers]; 5901cb0ef41Sopenharmony_ci nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; 5911cb0ef41Sopenharmony_ci if (events != NULL) 5921cb0ef41Sopenharmony_ci /* Invalidate events with same file descriptor */ 5931cb0ef41Sopenharmony_ci for (i = 0; i < nfds; i++) 5941cb0ef41Sopenharmony_ci if ((int) events[i].fd == fd) 5951cb0ef41Sopenharmony_ci events[i].fd = -1; 5961cb0ef41Sopenharmony_ci 5971cb0ef41Sopenharmony_ci /* Remove the file descriptor from the epoll. */ 5981cb0ef41Sopenharmony_ci if (loop->ep != NULL) 5991cb0ef41Sopenharmony_ci epoll_ctl(loop->ep, EPOLL_CTL_DEL, fd, &dummy); 6001cb0ef41Sopenharmony_ci} 6011cb0ef41Sopenharmony_ci 6021cb0ef41Sopenharmony_ci 6031cb0ef41Sopenharmony_ciint uv__io_check_fd(uv_loop_t* loop, int fd) { 6041cb0ef41Sopenharmony_ci struct pollfd p[1]; 6051cb0ef41Sopenharmony_ci int rv; 6061cb0ef41Sopenharmony_ci 6071cb0ef41Sopenharmony_ci p[0].fd = fd; 6081cb0ef41Sopenharmony_ci p[0].events = POLLIN; 6091cb0ef41Sopenharmony_ci 6101cb0ef41Sopenharmony_ci do 6111cb0ef41Sopenharmony_ci rv = poll(p, 1, 0); 6121cb0ef41Sopenharmony_ci while (rv == -1 && errno == EINTR); 6131cb0ef41Sopenharmony_ci 6141cb0ef41Sopenharmony_ci if (rv == -1) 6151cb0ef41Sopenharmony_ci abort(); 6161cb0ef41Sopenharmony_ci 6171cb0ef41Sopenharmony_ci if (p[0].revents & POLLNVAL) 6181cb0ef41Sopenharmony_ci return -1; 6191cb0ef41Sopenharmony_ci 6201cb0ef41Sopenharmony_ci return 0; 6211cb0ef41Sopenharmony_ci} 6221cb0ef41Sopenharmony_ci 6231cb0ef41Sopenharmony_ci 6241cb0ef41Sopenharmony_ciint uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { 6251cb0ef41Sopenharmony_ci uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); 6261cb0ef41Sopenharmony_ci return 0; 6271cb0ef41Sopenharmony_ci} 6281cb0ef41Sopenharmony_ci 6291cb0ef41Sopenharmony_ci 6301cb0ef41Sopenharmony_cistatic int os390_regfileint(uv_fs_event_t* handle, char* path) { 6311cb0ef41Sopenharmony_ci uv__os390_epoll* ep; 6321cb0ef41Sopenharmony_ci _RFIS reg_struct; 6331cb0ef41Sopenharmony_ci int rc; 6341cb0ef41Sopenharmony_ci 6351cb0ef41Sopenharmony_ci ep = handle->loop->ep; 6361cb0ef41Sopenharmony_ci assert(ep->msg_queue != -1); 6371cb0ef41Sopenharmony_ci 6381cb0ef41Sopenharmony_ci reg_struct.__rfis_cmd = _RFIS_REG; 6391cb0ef41Sopenharmony_ci reg_struct.__rfis_qid = ep->msg_queue; 6401cb0ef41Sopenharmony_ci reg_struct.__rfis_type = 1; 6411cb0ef41Sopenharmony_ci memcpy(reg_struct.__rfis_utok, &handle, sizeof(handle)); 6421cb0ef41Sopenharmony_ci 6431cb0ef41Sopenharmony_ci rc = __w_pioctl(path, _IOCC_REGFILEINT, sizeof(reg_struct), ®_struct); 6441cb0ef41Sopenharmony_ci if (rc != 0) 6451cb0ef41Sopenharmony_ci return UV__ERR(errno); 6461cb0ef41Sopenharmony_ci 6471cb0ef41Sopenharmony_ci memcpy(handle->rfis_rftok, reg_struct.__rfis_rftok, 6481cb0ef41Sopenharmony_ci sizeof(handle->rfis_rftok)); 6491cb0ef41Sopenharmony_ci 6501cb0ef41Sopenharmony_ci return 0; 6511cb0ef41Sopenharmony_ci} 6521cb0ef41Sopenharmony_ci 6531cb0ef41Sopenharmony_ci 6541cb0ef41Sopenharmony_ciint uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, 6551cb0ef41Sopenharmony_ci const char* filename, unsigned int flags) { 6561cb0ef41Sopenharmony_ci char* path; 6571cb0ef41Sopenharmony_ci int rc; 6581cb0ef41Sopenharmony_ci 6591cb0ef41Sopenharmony_ci if (uv__is_active(handle)) 6601cb0ef41Sopenharmony_ci return UV_EINVAL; 6611cb0ef41Sopenharmony_ci 6621cb0ef41Sopenharmony_ci path = uv__strdup(filename); 6631cb0ef41Sopenharmony_ci if (path == NULL) 6641cb0ef41Sopenharmony_ci return UV_ENOMEM; 6651cb0ef41Sopenharmony_ci 6661cb0ef41Sopenharmony_ci rc = os390_regfileint(handle, path); 6671cb0ef41Sopenharmony_ci if (rc != 0) { 6681cb0ef41Sopenharmony_ci uv__free(path); 6691cb0ef41Sopenharmony_ci return rc; 6701cb0ef41Sopenharmony_ci } 6711cb0ef41Sopenharmony_ci 6721cb0ef41Sopenharmony_ci uv__handle_start(handle); 6731cb0ef41Sopenharmony_ci handle->path = path; 6741cb0ef41Sopenharmony_ci handle->cb = cb; 6751cb0ef41Sopenharmony_ci 6761cb0ef41Sopenharmony_ci return 0; 6771cb0ef41Sopenharmony_ci} 6781cb0ef41Sopenharmony_ci 6791cb0ef41Sopenharmony_ci 6801cb0ef41Sopenharmony_ciint uv__fs_event_stop(uv_fs_event_t* handle) { 6811cb0ef41Sopenharmony_ci uv__os390_epoll* ep; 6821cb0ef41Sopenharmony_ci _RFIS reg_struct; 6831cb0ef41Sopenharmony_ci int rc; 6841cb0ef41Sopenharmony_ci 6851cb0ef41Sopenharmony_ci if (!uv__is_active(handle)) 6861cb0ef41Sopenharmony_ci return 0; 6871cb0ef41Sopenharmony_ci 6881cb0ef41Sopenharmony_ci ep = handle->loop->ep; 6891cb0ef41Sopenharmony_ci assert(ep->msg_queue != -1); 6901cb0ef41Sopenharmony_ci 6911cb0ef41Sopenharmony_ci reg_struct.__rfis_cmd = _RFIS_UNREG; 6921cb0ef41Sopenharmony_ci reg_struct.__rfis_qid = ep->msg_queue; 6931cb0ef41Sopenharmony_ci reg_struct.__rfis_type = 1; 6941cb0ef41Sopenharmony_ci memcpy(reg_struct.__rfis_rftok, handle->rfis_rftok, 6951cb0ef41Sopenharmony_ci sizeof(handle->rfis_rftok)); 6961cb0ef41Sopenharmony_ci 6971cb0ef41Sopenharmony_ci /* 6981cb0ef41Sopenharmony_ci * This call will take "/" as the path argument in case we 6991cb0ef41Sopenharmony_ci * don't care to supply the correct path. The system will simply 7001cb0ef41Sopenharmony_ci * ignore it. 7011cb0ef41Sopenharmony_ci */ 7021cb0ef41Sopenharmony_ci rc = __w_pioctl("/", _IOCC_REGFILEINT, sizeof(reg_struct), ®_struct); 7031cb0ef41Sopenharmony_ci if (rc != 0 && errno != EALREADY && errno != ENOENT) 7041cb0ef41Sopenharmony_ci abort(); 7051cb0ef41Sopenharmony_ci 7061cb0ef41Sopenharmony_ci if (handle->path != NULL) { 7071cb0ef41Sopenharmony_ci uv__free(handle->path); 7081cb0ef41Sopenharmony_ci handle->path = NULL; 7091cb0ef41Sopenharmony_ci } 7101cb0ef41Sopenharmony_ci 7111cb0ef41Sopenharmony_ci if (rc != 0 && errno == EALREADY) 7121cb0ef41Sopenharmony_ci return -1; 7131cb0ef41Sopenharmony_ci 7141cb0ef41Sopenharmony_ci uv__handle_stop(handle); 7151cb0ef41Sopenharmony_ci 7161cb0ef41Sopenharmony_ci return 0; 7171cb0ef41Sopenharmony_ci} 7181cb0ef41Sopenharmony_ci 7191cb0ef41Sopenharmony_ci 7201cb0ef41Sopenharmony_ciint uv_fs_event_stop(uv_fs_event_t* handle) { 7211cb0ef41Sopenharmony_ci uv__fs_event_stop(handle); 7221cb0ef41Sopenharmony_ci return 0; 7231cb0ef41Sopenharmony_ci} 7241cb0ef41Sopenharmony_ci 7251cb0ef41Sopenharmony_ci 7261cb0ef41Sopenharmony_civoid uv__fs_event_close(uv_fs_event_t* handle) { 7271cb0ef41Sopenharmony_ci /* 7281cb0ef41Sopenharmony_ci * If we were unable to unregister file interest here, then it is most likely 7291cb0ef41Sopenharmony_ci * that there is a pending queued change notification. When this happens, we 7301cb0ef41Sopenharmony_ci * don't want to complete the close as it will free the underlying memory for 7311cb0ef41Sopenharmony_ci * the handle, causing a use-after-free problem when the event is processed. 7321cb0ef41Sopenharmony_ci * We defer the final cleanup until after the event is consumed in 7331cb0ef41Sopenharmony_ci * os390_message_queue_handler(). 7341cb0ef41Sopenharmony_ci */ 7351cb0ef41Sopenharmony_ci if (uv__fs_event_stop(handle) == 0) 7361cb0ef41Sopenharmony_ci uv__make_close_pending((uv_handle_t*) handle); 7371cb0ef41Sopenharmony_ci} 7381cb0ef41Sopenharmony_ci 7391cb0ef41Sopenharmony_ci 7401cb0ef41Sopenharmony_cistatic int os390_message_queue_handler(uv__os390_epoll* ep) { 7411cb0ef41Sopenharmony_ci uv_fs_event_t* handle; 7421cb0ef41Sopenharmony_ci int msglen; 7431cb0ef41Sopenharmony_ci int events; 7441cb0ef41Sopenharmony_ci _RFIM msg; 7451cb0ef41Sopenharmony_ci 7461cb0ef41Sopenharmony_ci if (ep->msg_queue == -1) 7471cb0ef41Sopenharmony_ci return 0; 7481cb0ef41Sopenharmony_ci 7491cb0ef41Sopenharmony_ci msglen = msgrcv(ep->msg_queue, &msg, sizeof(msg), 0, IPC_NOWAIT); 7501cb0ef41Sopenharmony_ci 7511cb0ef41Sopenharmony_ci if (msglen == -1 && errno == ENOMSG) 7521cb0ef41Sopenharmony_ci return 0; 7531cb0ef41Sopenharmony_ci 7541cb0ef41Sopenharmony_ci if (msglen == -1) 7551cb0ef41Sopenharmony_ci abort(); 7561cb0ef41Sopenharmony_ci 7571cb0ef41Sopenharmony_ci events = 0; 7581cb0ef41Sopenharmony_ci if (msg.__rfim_event == _RFIM_ATTR || msg.__rfim_event == _RFIM_WRITE) 7591cb0ef41Sopenharmony_ci events = UV_CHANGE; 7601cb0ef41Sopenharmony_ci else if (msg.__rfim_event == _RFIM_RENAME || msg.__rfim_event == _RFIM_UNLINK) 7611cb0ef41Sopenharmony_ci events = UV_RENAME; 7621cb0ef41Sopenharmony_ci else if (msg.__rfim_event == 156) 7631cb0ef41Sopenharmony_ci /* TODO(gabylb): zos - this event should not happen, need to investigate. 7641cb0ef41Sopenharmony_ci * 7651cb0ef41Sopenharmony_ci * This event seems to occur when the watched file is [re]moved, or an 7661cb0ef41Sopenharmony_ci * editor (like vim) renames then creates the file on save (for vim, that's 7671cb0ef41Sopenharmony_ci * when backupcopy=no|auto). 7681cb0ef41Sopenharmony_ci */ 7691cb0ef41Sopenharmony_ci events = UV_RENAME; 7701cb0ef41Sopenharmony_ci else 7711cb0ef41Sopenharmony_ci /* Some event that we are not interested in. */ 7721cb0ef41Sopenharmony_ci return 0; 7731cb0ef41Sopenharmony_ci 7741cb0ef41Sopenharmony_ci /* `__rfim_utok` is treated as text when it should be treated as binary while 7751cb0ef41Sopenharmony_ci * running in ASCII mode, resulting in an unwanted autoconversion. 7761cb0ef41Sopenharmony_ci */ 7771cb0ef41Sopenharmony_ci __a2e_l(msg.__rfim_utok, sizeof(msg.__rfim_utok)); 7781cb0ef41Sopenharmony_ci handle = *(uv_fs_event_t**)(msg.__rfim_utok); 7791cb0ef41Sopenharmony_ci assert(handle != NULL); 7801cb0ef41Sopenharmony_ci 7811cb0ef41Sopenharmony_ci assert((handle->flags & UV_HANDLE_CLOSED) == 0); 7821cb0ef41Sopenharmony_ci if (uv__is_closing(handle)) { 7831cb0ef41Sopenharmony_ci uv__handle_stop(handle); 7841cb0ef41Sopenharmony_ci uv__make_close_pending((uv_handle_t*) handle); 7851cb0ef41Sopenharmony_ci return 0; 7861cb0ef41Sopenharmony_ci } else if (handle->path == NULL) { 7871cb0ef41Sopenharmony_ci /* _RFIS_UNREG returned EALREADY. */ 7881cb0ef41Sopenharmony_ci uv__handle_stop(handle); 7891cb0ef41Sopenharmony_ci return 0; 7901cb0ef41Sopenharmony_ci } 7911cb0ef41Sopenharmony_ci 7921cb0ef41Sopenharmony_ci /* The file is implicitly unregistered when the change notification is 7931cb0ef41Sopenharmony_ci * sent, only one notification is sent per registration. So we need to 7941cb0ef41Sopenharmony_ci * re-register interest in a file after each change notification we 7951cb0ef41Sopenharmony_ci * receive. 7961cb0ef41Sopenharmony_ci */ 7971cb0ef41Sopenharmony_ci assert(handle->path != NULL); 7981cb0ef41Sopenharmony_ci os390_regfileint(handle, handle->path); 7991cb0ef41Sopenharmony_ci handle->cb(handle, uv__basename_r(handle->path), events, 0); 8001cb0ef41Sopenharmony_ci return 1; 8011cb0ef41Sopenharmony_ci} 8021cb0ef41Sopenharmony_ci 8031cb0ef41Sopenharmony_ci 8041cb0ef41Sopenharmony_civoid uv__io_poll(uv_loop_t* loop, int timeout) { 8051cb0ef41Sopenharmony_ci static const int max_safe_timeout = 1789569; 8061cb0ef41Sopenharmony_ci struct epoll_event events[1024]; 8071cb0ef41Sopenharmony_ci struct epoll_event* pe; 8081cb0ef41Sopenharmony_ci struct epoll_event e; 8091cb0ef41Sopenharmony_ci uv__os390_epoll* ep; 8101cb0ef41Sopenharmony_ci int have_signals; 8111cb0ef41Sopenharmony_ci int real_timeout; 8121cb0ef41Sopenharmony_ci QUEUE* q; 8131cb0ef41Sopenharmony_ci uv__io_t* w; 8141cb0ef41Sopenharmony_ci uint64_t base; 8151cb0ef41Sopenharmony_ci int count; 8161cb0ef41Sopenharmony_ci int nfds; 8171cb0ef41Sopenharmony_ci int fd; 8181cb0ef41Sopenharmony_ci int op; 8191cb0ef41Sopenharmony_ci int i; 8201cb0ef41Sopenharmony_ci int user_timeout; 8211cb0ef41Sopenharmony_ci int reset_timeout; 8221cb0ef41Sopenharmony_ci 8231cb0ef41Sopenharmony_ci if (loop->nfds == 0) { 8241cb0ef41Sopenharmony_ci assert(QUEUE_EMPTY(&loop->watcher_queue)); 8251cb0ef41Sopenharmony_ci return; 8261cb0ef41Sopenharmony_ci } 8271cb0ef41Sopenharmony_ci 8281cb0ef41Sopenharmony_ci while (!QUEUE_EMPTY(&loop->watcher_queue)) { 8291cb0ef41Sopenharmony_ci uv_stream_t* stream; 8301cb0ef41Sopenharmony_ci 8311cb0ef41Sopenharmony_ci q = QUEUE_HEAD(&loop->watcher_queue); 8321cb0ef41Sopenharmony_ci QUEUE_REMOVE(q); 8331cb0ef41Sopenharmony_ci QUEUE_INIT(q); 8341cb0ef41Sopenharmony_ci w = QUEUE_DATA(q, uv__io_t, watcher_queue); 8351cb0ef41Sopenharmony_ci 8361cb0ef41Sopenharmony_ci assert(w->pevents != 0); 8371cb0ef41Sopenharmony_ci assert(w->fd >= 0); 8381cb0ef41Sopenharmony_ci 8391cb0ef41Sopenharmony_ci stream= container_of(w, uv_stream_t, io_watcher); 8401cb0ef41Sopenharmony_ci 8411cb0ef41Sopenharmony_ci assert(w->fd < (int) loop->nwatchers); 8421cb0ef41Sopenharmony_ci 8431cb0ef41Sopenharmony_ci e.events = w->pevents; 8441cb0ef41Sopenharmony_ci e.fd = w->fd; 8451cb0ef41Sopenharmony_ci 8461cb0ef41Sopenharmony_ci if (w->events == 0) 8471cb0ef41Sopenharmony_ci op = EPOLL_CTL_ADD; 8481cb0ef41Sopenharmony_ci else 8491cb0ef41Sopenharmony_ci op = EPOLL_CTL_MOD; 8501cb0ef41Sopenharmony_ci 8511cb0ef41Sopenharmony_ci /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching 8521cb0ef41Sopenharmony_ci * events, skip the syscall and squelch the events after epoll_wait(). 8531cb0ef41Sopenharmony_ci */ 8541cb0ef41Sopenharmony_ci if (epoll_ctl(loop->ep, op, w->fd, &e)) { 8551cb0ef41Sopenharmony_ci if (errno != EEXIST) 8561cb0ef41Sopenharmony_ci abort(); 8571cb0ef41Sopenharmony_ci 8581cb0ef41Sopenharmony_ci assert(op == EPOLL_CTL_ADD); 8591cb0ef41Sopenharmony_ci 8601cb0ef41Sopenharmony_ci /* We've reactivated a file descriptor that's been watched before. */ 8611cb0ef41Sopenharmony_ci if (epoll_ctl(loop->ep, EPOLL_CTL_MOD, w->fd, &e)) 8621cb0ef41Sopenharmony_ci abort(); 8631cb0ef41Sopenharmony_ci } 8641cb0ef41Sopenharmony_ci 8651cb0ef41Sopenharmony_ci w->events = w->pevents; 8661cb0ef41Sopenharmony_ci } 8671cb0ef41Sopenharmony_ci 8681cb0ef41Sopenharmony_ci assert(timeout >= -1); 8691cb0ef41Sopenharmony_ci base = loop->time; 8701cb0ef41Sopenharmony_ci count = 48; /* Benchmarks suggest this gives the best throughput. */ 8711cb0ef41Sopenharmony_ci real_timeout = timeout; 8721cb0ef41Sopenharmony_ci int nevents = 0; 8731cb0ef41Sopenharmony_ci have_signals = 0; 8741cb0ef41Sopenharmony_ci 8751cb0ef41Sopenharmony_ci if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) { 8761cb0ef41Sopenharmony_ci reset_timeout = 1; 8771cb0ef41Sopenharmony_ci user_timeout = timeout; 8781cb0ef41Sopenharmony_ci timeout = 0; 8791cb0ef41Sopenharmony_ci } else { 8801cb0ef41Sopenharmony_ci reset_timeout = 0; 8811cb0ef41Sopenharmony_ci } 8821cb0ef41Sopenharmony_ci 8831cb0ef41Sopenharmony_ci nfds = 0; 8841cb0ef41Sopenharmony_ci for (;;) { 8851cb0ef41Sopenharmony_ci /* Only need to set the provider_entry_time if timeout != 0. The function 8861cb0ef41Sopenharmony_ci * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME. 8871cb0ef41Sopenharmony_ci */ 8881cb0ef41Sopenharmony_ci if (timeout != 0) 8891cb0ef41Sopenharmony_ci uv__metrics_set_provider_entry_time(loop); 8901cb0ef41Sopenharmony_ci 8911cb0ef41Sopenharmony_ci if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout) 8921cb0ef41Sopenharmony_ci timeout = max_safe_timeout; 8931cb0ef41Sopenharmony_ci 8941cb0ef41Sopenharmony_ci nfds = epoll_wait(loop->ep, events, 8951cb0ef41Sopenharmony_ci ARRAY_SIZE(events), timeout); 8961cb0ef41Sopenharmony_ci 8971cb0ef41Sopenharmony_ci /* Update loop->time unconditionally. It's tempting to skip the update when 8981cb0ef41Sopenharmony_ci * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the 8991cb0ef41Sopenharmony_ci * operating system didn't reschedule our process while in the syscall. 9001cb0ef41Sopenharmony_ci */ 9011cb0ef41Sopenharmony_ci base = loop->time; 9021cb0ef41Sopenharmony_ci SAVE_ERRNO(uv__update_time(loop)); 9031cb0ef41Sopenharmony_ci if (nfds == 0) { 9041cb0ef41Sopenharmony_ci assert(timeout != -1); 9051cb0ef41Sopenharmony_ci 9061cb0ef41Sopenharmony_ci if (reset_timeout != 0) { 9071cb0ef41Sopenharmony_ci timeout = user_timeout; 9081cb0ef41Sopenharmony_ci reset_timeout = 0; 9091cb0ef41Sopenharmony_ci } 9101cb0ef41Sopenharmony_ci 9111cb0ef41Sopenharmony_ci if (timeout == -1) 9121cb0ef41Sopenharmony_ci continue; 9131cb0ef41Sopenharmony_ci 9141cb0ef41Sopenharmony_ci if (timeout == 0) 9151cb0ef41Sopenharmony_ci return; 9161cb0ef41Sopenharmony_ci 9171cb0ef41Sopenharmony_ci /* We may have been inside the system call for longer than |timeout| 9181cb0ef41Sopenharmony_ci * milliseconds so we need to update the timestamp to avoid drift. 9191cb0ef41Sopenharmony_ci */ 9201cb0ef41Sopenharmony_ci goto update_timeout; 9211cb0ef41Sopenharmony_ci } 9221cb0ef41Sopenharmony_ci 9231cb0ef41Sopenharmony_ci if (nfds == -1) { 9241cb0ef41Sopenharmony_ci 9251cb0ef41Sopenharmony_ci if (errno != EINTR) 9261cb0ef41Sopenharmony_ci abort(); 9271cb0ef41Sopenharmony_ci 9281cb0ef41Sopenharmony_ci if (reset_timeout != 0) { 9291cb0ef41Sopenharmony_ci timeout = user_timeout; 9301cb0ef41Sopenharmony_ci reset_timeout = 0; 9311cb0ef41Sopenharmony_ci } 9321cb0ef41Sopenharmony_ci 9331cb0ef41Sopenharmony_ci if (timeout == -1) 9341cb0ef41Sopenharmony_ci continue; 9351cb0ef41Sopenharmony_ci 9361cb0ef41Sopenharmony_ci if (timeout == 0) 9371cb0ef41Sopenharmony_ci return; 9381cb0ef41Sopenharmony_ci 9391cb0ef41Sopenharmony_ci /* Interrupted by a signal. Update timeout and poll again. */ 9401cb0ef41Sopenharmony_ci goto update_timeout; 9411cb0ef41Sopenharmony_ci } 9421cb0ef41Sopenharmony_ci 9431cb0ef41Sopenharmony_ci 9441cb0ef41Sopenharmony_ci assert(loop->watchers != NULL); 9451cb0ef41Sopenharmony_ci loop->watchers[loop->nwatchers] = (void*) events; 9461cb0ef41Sopenharmony_ci loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; 9471cb0ef41Sopenharmony_ci for (i = 0; i < nfds; i++) { 9481cb0ef41Sopenharmony_ci pe = events + i; 9491cb0ef41Sopenharmony_ci fd = pe->fd; 9501cb0ef41Sopenharmony_ci 9511cb0ef41Sopenharmony_ci /* Skip invalidated events, see uv__platform_invalidate_fd */ 9521cb0ef41Sopenharmony_ci if (fd == -1) 9531cb0ef41Sopenharmony_ci continue; 9541cb0ef41Sopenharmony_ci 9551cb0ef41Sopenharmony_ci ep = loop->ep; 9561cb0ef41Sopenharmony_ci if (pe->is_msg) { 9571cb0ef41Sopenharmony_ci os390_message_queue_handler(ep); 9581cb0ef41Sopenharmony_ci nevents++; 9591cb0ef41Sopenharmony_ci continue; 9601cb0ef41Sopenharmony_ci } 9611cb0ef41Sopenharmony_ci 9621cb0ef41Sopenharmony_ci assert(fd >= 0); 9631cb0ef41Sopenharmony_ci assert((unsigned) fd < loop->nwatchers); 9641cb0ef41Sopenharmony_ci 9651cb0ef41Sopenharmony_ci w = loop->watchers[fd]; 9661cb0ef41Sopenharmony_ci 9671cb0ef41Sopenharmony_ci if (w == NULL) { 9681cb0ef41Sopenharmony_ci /* File descriptor that we've stopped watching, disarm it. 9691cb0ef41Sopenharmony_ci * 9701cb0ef41Sopenharmony_ci * Ignore all errors because we may be racing with another thread 9711cb0ef41Sopenharmony_ci * when the file descriptor is closed. 9721cb0ef41Sopenharmony_ci */ 9731cb0ef41Sopenharmony_ci epoll_ctl(loop->ep, EPOLL_CTL_DEL, fd, pe); 9741cb0ef41Sopenharmony_ci continue; 9751cb0ef41Sopenharmony_ci } 9761cb0ef41Sopenharmony_ci 9771cb0ef41Sopenharmony_ci /* Give users only events they're interested in. Prevents spurious 9781cb0ef41Sopenharmony_ci * callbacks when previous callback invocation in this loop has stopped 9791cb0ef41Sopenharmony_ci * the current watcher. Also, filters out events that users has not 9801cb0ef41Sopenharmony_ci * requested us to watch. 9811cb0ef41Sopenharmony_ci */ 9821cb0ef41Sopenharmony_ci pe->events &= w->pevents | POLLERR | POLLHUP; 9831cb0ef41Sopenharmony_ci 9841cb0ef41Sopenharmony_ci if (pe->events == POLLERR || pe->events == POLLHUP) 9851cb0ef41Sopenharmony_ci pe->events |= w->pevents & (POLLIN | POLLOUT); 9861cb0ef41Sopenharmony_ci 9871cb0ef41Sopenharmony_ci if (pe->events != 0) { 9881cb0ef41Sopenharmony_ci /* Run signal watchers last. This also affects child process watchers 9891cb0ef41Sopenharmony_ci * because those are implemented in terms of signal watchers. 9901cb0ef41Sopenharmony_ci */ 9911cb0ef41Sopenharmony_ci if (w == &loop->signal_io_watcher) { 9921cb0ef41Sopenharmony_ci have_signals = 1; 9931cb0ef41Sopenharmony_ci } else { 9941cb0ef41Sopenharmony_ci uv__metrics_update_idle_time(loop); 9951cb0ef41Sopenharmony_ci w->cb(loop, w, pe->events); 9961cb0ef41Sopenharmony_ci } 9971cb0ef41Sopenharmony_ci nevents++; 9981cb0ef41Sopenharmony_ci } 9991cb0ef41Sopenharmony_ci } 10001cb0ef41Sopenharmony_ci 10011cb0ef41Sopenharmony_ci if (reset_timeout != 0) { 10021cb0ef41Sopenharmony_ci timeout = user_timeout; 10031cb0ef41Sopenharmony_ci reset_timeout = 0; 10041cb0ef41Sopenharmony_ci } 10051cb0ef41Sopenharmony_ci 10061cb0ef41Sopenharmony_ci if (have_signals != 0) { 10071cb0ef41Sopenharmony_ci uv__metrics_update_idle_time(loop); 10081cb0ef41Sopenharmony_ci loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); 10091cb0ef41Sopenharmony_ci } 10101cb0ef41Sopenharmony_ci 10111cb0ef41Sopenharmony_ci loop->watchers[loop->nwatchers] = NULL; 10121cb0ef41Sopenharmony_ci loop->watchers[loop->nwatchers + 1] = NULL; 10131cb0ef41Sopenharmony_ci 10141cb0ef41Sopenharmony_ci if (have_signals != 0) 10151cb0ef41Sopenharmony_ci return; /* Event loop should cycle now so don't poll again. */ 10161cb0ef41Sopenharmony_ci 10171cb0ef41Sopenharmony_ci if (nevents != 0) { 10181cb0ef41Sopenharmony_ci if (nfds == ARRAY_SIZE(events) && --count != 0) { 10191cb0ef41Sopenharmony_ci /* Poll for more events but don't block this time. */ 10201cb0ef41Sopenharmony_ci timeout = 0; 10211cb0ef41Sopenharmony_ci continue; 10221cb0ef41Sopenharmony_ci } 10231cb0ef41Sopenharmony_ci return; 10241cb0ef41Sopenharmony_ci } 10251cb0ef41Sopenharmony_ci 10261cb0ef41Sopenharmony_ci if (timeout == 0) 10271cb0ef41Sopenharmony_ci return; 10281cb0ef41Sopenharmony_ci 10291cb0ef41Sopenharmony_ci if (timeout == -1) 10301cb0ef41Sopenharmony_ci continue; 10311cb0ef41Sopenharmony_ci 10321cb0ef41Sopenharmony_ciupdate_timeout: 10331cb0ef41Sopenharmony_ci assert(timeout > 0); 10341cb0ef41Sopenharmony_ci 10351cb0ef41Sopenharmony_ci real_timeout -= (loop->time - base); 10361cb0ef41Sopenharmony_ci if (real_timeout <= 0) 10371cb0ef41Sopenharmony_ci return; 10381cb0ef41Sopenharmony_ci 10391cb0ef41Sopenharmony_ci timeout = real_timeout; 10401cb0ef41Sopenharmony_ci } 10411cb0ef41Sopenharmony_ci} 10421cb0ef41Sopenharmony_ci 10431cb0ef41Sopenharmony_ci 10441cb0ef41Sopenharmony_ciint uv__io_fork(uv_loop_t* loop) { 10451cb0ef41Sopenharmony_ci /* 10461cb0ef41Sopenharmony_ci Nullify the msg queue but don't close it because 10471cb0ef41Sopenharmony_ci it is still being used by the parent. 10481cb0ef41Sopenharmony_ci */ 10491cb0ef41Sopenharmony_ci loop->ep = NULL; 10501cb0ef41Sopenharmony_ci 10511cb0ef41Sopenharmony_ci return uv__platform_loop_init(loop); 10521cb0ef41Sopenharmony_ci} 1053