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(&timestamp);
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), &reg_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), &reg_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