xref: /libuv/src/unix/os390.c (revision fc4840eb)
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 
93 typedef unsigned data_area_ptr_assign_type;
94 
95 typedef 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 
uv_loadavg(double avg[3])106 void 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 
uv__platform_loop_init(uv_loop_t * loop)114 int 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 
uv__platform_loop_delete(uv_loop_t * loop)126 void 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 
uv__hrtime(uv_clocktype_t type)134 uint64_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 
getexe(char * buf,size_t len)142 static 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  */
uv_exepath(char * buffer,size_t * size)155 int 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 
uv_get_free_memory(void)171 uint64_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 
uv_get_total_memory(void)183 uint64_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 
uv_get_constrained_memory(void)189 uint64_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 
uv_get_available_memory(void)200 uint64_t uv_get_available_memory(void) {
201   return uv_get_free_memory();
202 }
203 
204 
uv_resident_set_memory(size_t * rss)205 int 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 
uv_uptime(double * uptime)219 int 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 
uv_cpu_info(uv_cpu_info_t ** cpu_infos,int * count)233 int 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 
uv__interface_addresses_v6(uv_interface_address_t ** addresses,int * count)280 static 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 
uv_interface_addresses(uv_interface_address_t ** addresses,int * count)403 int 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 
uv_free_interface_addresses(uv_interface_address_t * addresses,int count)578 void 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 
uv__platform_invalidate_fd(uv_loop_t * loop,int fd)587 void 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 
uv__io_check_fd(uv_loop_t * loop,int fd)610 int 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 
uv_fs_event_init(uv_loop_t * loop,uv_fs_event_t * handle)631 int 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 
os390_regfileint(uv_fs_event_t * handle,char * path)637 static 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 
uv_fs_event_start(uv_fs_event_t * handle,uv_fs_event_cb cb,const char * filename,unsigned int flags)661 int 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 
uv__fs_event_stop(uv_fs_event_t * handle)687 int 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 
uv_fs_event_stop(uv_fs_event_t * handle)727 int uv_fs_event_stop(uv_fs_event_t* handle) {
728   uv__fs_event_stop(handle);
729   return 0;
730 }
731 
732 
uv__fs_event_close(uv_fs_event_t * handle)733 void 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 
os390_message_queue_handler(uv__os390_epoll * ep)747 static 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 
uv__io_poll(uv_loop_t * loop,int timeout)811 void 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 
1050 update_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 
uv__io_fork(uv_loop_t * loop)1062 int 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