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