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(×tamp);
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), ®_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), ®_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