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