• 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   __net_ifconf6entry_t flg;
282 
283   *count = 0;
284   /* Assume maximum buffer size allowable */
285   maxsize = 16384;
286 
287   if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)))
288     return UV__ERR(errno);
289 
290   ifc.__nif6h_version = 1;
291   ifc.__nif6h_buflen = maxsize;
292   ifc.__nif6h_buffer = uv__calloc(1, maxsize);;
293 
294   if (ioctl(sockfd, SIOCGIFCONF6, &ifc) == -1) {
295     uv__close(sockfd);
296     return UV__ERR(errno);
297   }
298 
299 
300   *count = 0;
301   ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer);
302   while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) {
303     p = ifr;
304     ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen);
305 
306     if (!(p->__nif6e_addr.sin6_family == AF_INET6 ||
307           p->__nif6e_addr.sin6_family == AF_INET))
308       continue;
309 
310     if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE))
311       continue;
312 
313     ++(*count);
314   }
315 
316   /* Alloc the return interface structs */
317   *addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
318   if (!(*addresses)) {
319     uv__close(sockfd);
320     return UV_ENOMEM;
321   }
322   address = *addresses;
323 
324   ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer);
325   while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) {
326     p = ifr;
327     ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen);
328 
329     if (!(p->__nif6e_addr.sin6_family == AF_INET6 ||
330           p->__nif6e_addr.sin6_family == AF_INET))
331       continue;
332 
333     if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE))
334       continue;
335 
336     /* All conditions above must match count loop */
337 
338     address->name = uv__strdup(p->__nif6e_name);
339 
340     if (p->__nif6e_addr.sin6_family == AF_INET6)
341       address->address.address6 = *((struct sockaddr_in6*) &p->__nif6e_addr);
342     else
343       address->address.address4 = *((struct sockaddr_in*) &p->__nif6e_addr);
344 
345     /* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */
346 
347     address->is_internal = flg.__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0;
348     memset(address->phys_addr, 0, sizeof(address->phys_addr));
349     address++;
350   }
351 
352   uv__close(sockfd);
353   return 0;
354 }
355 
356 
uv_interface_addresses(uv_interface_address_t ** addresses,int * count)357 int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
358   uv_interface_address_t* address;
359   int sockfd;
360   int maxsize;
361   struct ifconf ifc;
362   struct ifreq flg;
363   struct ifreq* ifr;
364   struct ifreq* p;
365   int count_v6;
366 
367   *count = 0;
368   *addresses = NULL;
369 
370   /* get the ipv6 addresses first */
371   uv_interface_address_t* addresses_v6;
372   uv__interface_addresses_v6(&addresses_v6, &count_v6);
373 
374   /* now get the ipv4 addresses */
375 
376   /* Assume maximum buffer size allowable */
377   maxsize = 16384;
378 
379   sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
380   if (0 > sockfd)
381     return UV__ERR(errno);
382 
383   ifc.ifc_req = uv__calloc(1, maxsize);
384   ifc.ifc_len = maxsize;
385   if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
386     uv__close(sockfd);
387     return UV__ERR(errno);
388   }
389 
390 #define MAX(a,b) (((a)>(b))?(a):(b))
391 #define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
392 
393   /* Count all up and running ipv4/ipv6 addresses */
394   ifr = ifc.ifc_req;
395   while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
396     p = ifr;
397     ifr = (struct ifreq*)
398       ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
399 
400     if (!(p->ifr_addr.sa_family == AF_INET6 ||
401           p->ifr_addr.sa_family == AF_INET))
402       continue;
403 
404     memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
405     if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
406       uv__close(sockfd);
407       return UV__ERR(errno);
408     }
409 
410     if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
411       continue;
412 
413     (*count)++;
414   }
415 
416   if (*count == 0) {
417     uv__close(sockfd);
418     return 0;
419   }
420 
421   /* Alloc the return interface structs */
422   *addresses = uv__malloc((*count + count_v6) *
423                           sizeof(uv_interface_address_t));
424 
425   if (!(*addresses)) {
426     uv__close(sockfd);
427     return UV_ENOMEM;
428   }
429   address = *addresses;
430 
431   /* copy over the ipv6 addresses */
432   memcpy(address, addresses_v6, count_v6 * sizeof(uv_interface_address_t));
433   address += count_v6;
434   *count += count_v6;
435   uv__free(addresses_v6);
436 
437   ifr = ifc.ifc_req;
438   while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
439     p = ifr;
440     ifr = (struct ifreq*)
441       ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
442 
443     if (!(p->ifr_addr.sa_family == AF_INET6 ||
444           p->ifr_addr.sa_family == AF_INET))
445       continue;
446 
447     memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
448     if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
449       uv__close(sockfd);
450       return UV_ENOSYS;
451     }
452 
453     if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
454       continue;
455 
456     /* All conditions above must match count loop */
457 
458     address->name = uv__strdup(p->ifr_name);
459 
460     if (p->ifr_addr.sa_family == AF_INET6) {
461       address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
462     } else {
463       address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr);
464     }
465 
466     address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
467     memset(address->phys_addr, 0, sizeof(address->phys_addr));
468     address++;
469   }
470 
471 #undef ADDR_SIZE
472 #undef MAX
473 
474   uv__close(sockfd);
475   return 0;
476 }
477 
478 
uv_free_interface_addresses(uv_interface_address_t * addresses,int count)479 void uv_free_interface_addresses(uv_interface_address_t* addresses,
480                                  int count) {
481   int i;
482   for (i = 0; i < count; ++i)
483     uv__free(addresses[i].name);
484   uv__free(addresses);
485 }
486 
487 
uv__platform_invalidate_fd(uv_loop_t * loop,int fd)488 void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
489   struct epoll_event* events;
490   struct epoll_event dummy;
491   uintptr_t i;
492   uintptr_t nfds;
493 
494   assert(loop->watchers != NULL);
495   assert(fd >= 0);
496 
497   events = (struct epoll_event*) loop->watchers[loop->nwatchers];
498   nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
499   if (events != NULL)
500     /* Invalidate events with same file descriptor */
501     for (i = 0; i < nfds; i++)
502       if ((int) events[i].fd == fd)
503         events[i].fd = -1;
504 
505   /* Remove the file descriptor from the epoll. */
506   if (loop->ep != NULL)
507     epoll_ctl(loop->ep, EPOLL_CTL_DEL, fd, &dummy);
508 }
509 
510 
uv__io_check_fd(uv_loop_t * loop,int fd)511 int uv__io_check_fd(uv_loop_t* loop, int fd) {
512   struct pollfd p[1];
513   int rv;
514 
515   p[0].fd = fd;
516   p[0].events = POLLIN;
517 
518   do
519     rv = poll(p, 1, 0);
520   while (rv == -1 && errno == EINTR);
521 
522   if (rv == -1)
523     abort();
524 
525   if (p[0].revents & POLLNVAL)
526     return -1;
527 
528   return 0;
529 }
530 
531 
uv__fs_event_close(uv_fs_event_t * handle)532 void uv__fs_event_close(uv_fs_event_t* handle) {
533   uv_fs_event_stop(handle);
534 }
535 
536 
uv_fs_event_init(uv_loop_t * loop,uv_fs_event_t * handle)537 int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
538   uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
539   return 0;
540 }
541 
542 
uv_fs_event_start(uv_fs_event_t * handle,uv_fs_event_cb cb,const char * filename,unsigned int flags)543 int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
544                       const char* filename, unsigned int flags) {
545   uv__os390_epoll* ep;
546   _RFIS reg_struct;
547   char* path;
548   int rc;
549 
550   if (uv__is_active(handle))
551     return UV_EINVAL;
552 
553   ep = handle->loop->ep;
554   assert(ep->msg_queue != -1);
555 
556   reg_struct.__rfis_cmd  = _RFIS_REG;
557   reg_struct.__rfis_qid  = ep->msg_queue;
558   reg_struct.__rfis_type = 1;
559   memcpy(reg_struct.__rfis_utok, &handle, sizeof(handle));
560 
561   path = uv__strdup(filename);
562   if (path == NULL)
563     return UV_ENOMEM;
564 
565   rc = __w_pioctl(path, _IOCC_REGFILEINT, sizeof(reg_struct), &reg_struct);
566   if (rc != 0)
567     return UV__ERR(errno);
568 
569   uv__handle_start(handle);
570   handle->path = path;
571   handle->cb = cb;
572   memcpy(handle->rfis_rftok, reg_struct.__rfis_rftok,
573          sizeof(handle->rfis_rftok));
574 
575   return 0;
576 }
577 
578 
uv_fs_event_stop(uv_fs_event_t * handle)579 int uv_fs_event_stop(uv_fs_event_t* handle) {
580   uv__os390_epoll* ep;
581   _RFIS reg_struct;
582   int rc;
583 
584   if (!uv__is_active(handle))
585     return 0;
586 
587   ep = handle->loop->ep;
588   assert(ep->msg_queue != -1);
589 
590   reg_struct.__rfis_cmd  = _RFIS_UNREG;
591   reg_struct.__rfis_qid  = ep->msg_queue;
592   reg_struct.__rfis_type = 1;
593   memcpy(reg_struct.__rfis_rftok, handle->rfis_rftok,
594          sizeof(handle->rfis_rftok));
595 
596   /*
597    * This call will take "/" as the path argument in case we
598    * don't care to supply the correct path. The system will simply
599    * ignore it.
600    */
601   rc = __w_pioctl("/", _IOCC_REGFILEINT, sizeof(reg_struct), &reg_struct);
602   if (rc != 0 && errno != EALREADY && errno != ENOENT)
603     abort();
604 
605   uv__handle_stop(handle);
606 
607   return 0;
608 }
609 
610 
os390_message_queue_handler(uv__os390_epoll * ep)611 static int os390_message_queue_handler(uv__os390_epoll* ep) {
612   uv_fs_event_t* handle;
613   int msglen;
614   int events;
615   _RFIM msg;
616 
617   if (ep->msg_queue == -1)
618     return 0;
619 
620   msglen = msgrcv(ep->msg_queue, &msg, sizeof(msg), 0, IPC_NOWAIT);
621 
622   if (msglen == -1 && errno == ENOMSG)
623     return 0;
624 
625   if (msglen == -1)
626     abort();
627 
628   events = 0;
629   if (msg.__rfim_event == _RFIM_ATTR || msg.__rfim_event == _RFIM_WRITE)
630     events = UV_CHANGE;
631   else if (msg.__rfim_event == _RFIM_RENAME)
632     events = UV_RENAME;
633   else
634     /* Some event that we are not interested in. */
635     return 0;
636 
637   /* `__rfim_utok` is treated as text when it should be treated as binary while
638    * running in ASCII mode, resulting in an unwanted autoconversion.
639    */
640   __a2e_l(msg.__rfim_utok, sizeof(msg.__rfim_utok));
641   handle = *(uv_fs_event_t**)(msg.__rfim_utok);
642   handle->cb(handle, uv__basename_r(handle->path), events, 0);
643   return 1;
644 }
645 
646 
uv__io_poll(uv_loop_t * loop,int timeout)647 void uv__io_poll(uv_loop_t* loop, int timeout) {
648   static const int max_safe_timeout = 1789569;
649   struct epoll_event events[1024];
650   struct epoll_event* pe;
651   struct epoll_event e;
652   uv__os390_epoll* ep;
653   int real_timeout;
654   QUEUE* q;
655   uv__io_t* w;
656   uint64_t base;
657   int count;
658   int nfds;
659   int fd;
660   int op;
661   int i;
662   int user_timeout;
663   int reset_timeout;
664 
665   if (loop->nfds == 0) {
666     assert(QUEUE_EMPTY(&loop->watcher_queue));
667     return;
668   }
669 
670   while (!QUEUE_EMPTY(&loop->watcher_queue)) {
671     uv_stream_t* stream;
672 
673     q = QUEUE_HEAD(&loop->watcher_queue);
674     QUEUE_REMOVE(q);
675     QUEUE_INIT(q);
676     w = QUEUE_DATA(q, uv__io_t, watcher_queue);
677 
678     assert(w->pevents != 0);
679     assert(w->fd >= 0);
680 
681     stream= container_of(w, uv_stream_t, io_watcher);
682 
683     assert(w->fd < (int) loop->nwatchers);
684 
685     e.events = w->pevents;
686     e.fd = w->fd;
687 
688     if (w->events == 0)
689       op = EPOLL_CTL_ADD;
690     else
691       op = EPOLL_CTL_MOD;
692 
693     /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching
694      * events, skip the syscall and squelch the events after epoll_wait().
695      */
696     if (epoll_ctl(loop->ep, op, w->fd, &e)) {
697       if (errno != EEXIST)
698         abort();
699 
700       assert(op == EPOLL_CTL_ADD);
701 
702       /* We've reactivated a file descriptor that's been watched before. */
703       if (epoll_ctl(loop->ep, EPOLL_CTL_MOD, w->fd, &e))
704         abort();
705     }
706 
707     w->events = w->pevents;
708   }
709 
710   assert(timeout >= -1);
711   base = loop->time;
712   count = 48; /* Benchmarks suggest this gives the best throughput. */
713   real_timeout = timeout;
714   int nevents = 0;
715 
716   if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) {
717     reset_timeout = 1;
718     user_timeout = timeout;
719     timeout = 0;
720   } else {
721     reset_timeout = 0;
722   }
723 
724   nfds = 0;
725   for (;;) {
726     /* Only need to set the provider_entry_time if timeout != 0. The function
727      * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME.
728      */
729     if (timeout != 0)
730       uv__metrics_set_provider_entry_time(loop);
731 
732     if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)
733       timeout = max_safe_timeout;
734 
735     nfds = epoll_wait(loop->ep, events,
736                       ARRAY_SIZE(events), timeout);
737 
738     /* Update loop->time unconditionally. It's tempting to skip the update when
739      * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
740      * operating system didn't reschedule our process while in the syscall.
741      */
742     base = loop->time;
743     SAVE_ERRNO(uv__update_time(loop));
744     if (nfds == 0) {
745       assert(timeout != -1);
746 
747       if (reset_timeout != 0) {
748         timeout = user_timeout;
749         reset_timeout = 0;
750       }
751 
752       if (timeout == -1)
753         continue;
754 
755       if (timeout == 0)
756         return;
757 
758       /* We may have been inside the system call for longer than |timeout|
759        * milliseconds so we need to update the timestamp to avoid drift.
760        */
761       goto update_timeout;
762     }
763 
764     if (nfds == -1) {
765 
766       if (errno != EINTR)
767         abort();
768 
769       if (reset_timeout != 0) {
770         timeout = user_timeout;
771         reset_timeout = 0;
772       }
773 
774       if (timeout == -1)
775         continue;
776 
777       if (timeout == 0)
778         return;
779 
780       /* Interrupted by a signal. Update timeout and poll again. */
781       goto update_timeout;
782     }
783 
784 
785     assert(loop->watchers != NULL);
786     loop->watchers[loop->nwatchers] = (void*) events;
787     loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
788     for (i = 0; i < nfds; i++) {
789       pe = events + i;
790       fd = pe->fd;
791 
792       /* Skip invalidated events, see uv__platform_invalidate_fd */
793       if (fd == -1)
794         continue;
795 
796       ep = loop->ep;
797       if (pe->is_msg) {
798         os390_message_queue_handler(ep);
799         continue;
800       }
801 
802       assert(fd >= 0);
803       assert((unsigned) fd < loop->nwatchers);
804 
805       w = loop->watchers[fd];
806 
807       if (w == NULL) {
808         /* File descriptor that we've stopped watching, disarm it.
809          *
810          * Ignore all errors because we may be racing with another thread
811          * when the file descriptor is closed.
812          */
813         epoll_ctl(loop->ep, EPOLL_CTL_DEL, fd, pe);
814         continue;
815       }
816 
817       /* Give users only events they're interested in. Prevents spurious
818        * callbacks when previous callback invocation in this loop has stopped
819        * the current watcher. Also, filters out events that users has not
820        * requested us to watch.
821        */
822       pe->events &= w->pevents | POLLERR | POLLHUP;
823 
824       if (pe->events == POLLERR || pe->events == POLLHUP)
825         pe->events |= w->pevents & (POLLIN | POLLOUT);
826 
827       if (pe->events != 0) {
828         uv__metrics_update_idle_time(loop);
829         w->cb(loop, w, pe->events);
830         nevents++;
831       }
832     }
833     loop->watchers[loop->nwatchers] = NULL;
834     loop->watchers[loop->nwatchers + 1] = NULL;
835 
836     if (reset_timeout != 0) {
837       timeout = user_timeout;
838       reset_timeout = 0;
839     }
840 
841     if (nevents != 0) {
842       if (nfds == ARRAY_SIZE(events) && --count != 0) {
843         /* Poll for more events but don't block this time. */
844         timeout = 0;
845         continue;
846       }
847       return;
848     }
849 
850     if (timeout == 0)
851       return;
852 
853     if (timeout == -1)
854       continue;
855 
856 update_timeout:
857     assert(timeout > 0);
858 
859     real_timeout -= (loop->time - base);
860     if (real_timeout <= 0)
861       return;
862 
863     timeout = real_timeout;
864   }
865 }
866 
867 
uv__io_fork(uv_loop_t * loop)868 int uv__io_fork(uv_loop_t* loop) {
869   /*
870     Nullify the msg queue but don't close it because
871     it is still being used by the parent.
872   */
873   loop->ep = NULL;
874 
875   uv__platform_loop_delete(loop);
876   return uv__platform_loop_init(loop);
877 }
878