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