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