1e66f31c5Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2e66f31c5Sopenharmony_ci * 3e66f31c5Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 4e66f31c5Sopenharmony_ci * of this software and associated documentation files (the "Software"), to 5e66f31c5Sopenharmony_ci * deal in the Software without restriction, including without limitation the 6e66f31c5Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7e66f31c5Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 8e66f31c5Sopenharmony_ci * furnished to do so, subject to the following conditions: 9e66f31c5Sopenharmony_ci * 10e66f31c5Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 11e66f31c5Sopenharmony_ci * all copies or substantial portions of the Software. 12e66f31c5Sopenharmony_ci * 13e66f31c5Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14e66f31c5Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15e66f31c5Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16e66f31c5Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17e66f31c5Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18e66f31c5Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19e66f31c5Sopenharmony_ci * IN THE SOFTWARE. 20e66f31c5Sopenharmony_ci */ 21e66f31c5Sopenharmony_ci 22e66f31c5Sopenharmony_ci#include "uv.h" 23e66f31c5Sopenharmony_ci#include "internal.h" 24e66f31c5Sopenharmony_ci 25e66f31c5Sopenharmony_ci#include <stdio.h> 26e66f31c5Sopenharmony_ci#include <stdint.h> 27e66f31c5Sopenharmony_ci#include <stdlib.h> 28e66f31c5Sopenharmony_ci#include <string.h> 29e66f31c5Sopenharmony_ci#include <assert.h> 30e66f31c5Sopenharmony_ci#include <errno.h> 31e66f31c5Sopenharmony_ci 32e66f31c5Sopenharmony_ci#include <sys/types.h> 33e66f31c5Sopenharmony_ci#include <sys/socket.h> 34e66f31c5Sopenharmony_ci#include <sys/ioctl.h> 35e66f31c5Sopenharmony_ci#include <net/if.h> 36e66f31c5Sopenharmony_ci#include <netinet/in.h> 37e66f31c5Sopenharmony_ci#include <arpa/inet.h> 38e66f31c5Sopenharmony_ci 39e66f31c5Sopenharmony_ci#include <sys/time.h> 40e66f31c5Sopenharmony_ci#include <unistd.h> 41e66f31c5Sopenharmony_ci#include <fcntl.h> 42e66f31c5Sopenharmony_ci#include <utmp.h> 43e66f31c5Sopenharmony_ci#include <libgen.h> 44e66f31c5Sopenharmony_ci 45e66f31c5Sopenharmony_ci#include <sys/protosw.h> 46e66f31c5Sopenharmony_ci#include <libperfstat.h> 47e66f31c5Sopenharmony_ci#include <procinfo.h> 48e66f31c5Sopenharmony_ci#include <sys/proc.h> 49e66f31c5Sopenharmony_ci#include <sys/procfs.h> 50e66f31c5Sopenharmony_ci 51e66f31c5Sopenharmony_ci#include <sys/poll.h> 52e66f31c5Sopenharmony_ci 53e66f31c5Sopenharmony_ci#include <sys/pollset.h> 54e66f31c5Sopenharmony_ci#include <ctype.h> 55e66f31c5Sopenharmony_ci#ifdef HAVE_SYS_AHAFS_EVPRODS_H 56e66f31c5Sopenharmony_ci#include <sys/ahafs_evProds.h> 57e66f31c5Sopenharmony_ci#endif 58e66f31c5Sopenharmony_ci 59e66f31c5Sopenharmony_ci#include <sys/mntctl.h> 60e66f31c5Sopenharmony_ci#include <sys/vmount.h> 61e66f31c5Sopenharmony_ci#include <limits.h> 62e66f31c5Sopenharmony_ci#include <strings.h> 63e66f31c5Sopenharmony_ci#include <sys/vnode.h> 64e66f31c5Sopenharmony_ci 65e66f31c5Sopenharmony_ci#define RDWR_BUF_SIZE 4096 66e66f31c5Sopenharmony_ci#define EQ(a,b) (strcmp(a,b) == 0) 67e66f31c5Sopenharmony_ci 68e66f31c5Sopenharmony_cichar* original_exepath = NULL; 69e66f31c5Sopenharmony_ciuv_mutex_t process_title_mutex; 70e66f31c5Sopenharmony_ciuv_once_t process_title_mutex_once = UV_ONCE_INIT; 71e66f31c5Sopenharmony_cistatic void* args_mem = NULL; 72e66f31c5Sopenharmony_cistatic char** process_argv = NULL; 73e66f31c5Sopenharmony_cistatic int process_argc = 0; 74e66f31c5Sopenharmony_cistatic char* process_title_ptr = NULL; 75e66f31c5Sopenharmony_ci 76e66f31c5Sopenharmony_civoid init_process_title_mutex_once(void) { 77e66f31c5Sopenharmony_ci uv_mutex_init(&process_title_mutex); 78e66f31c5Sopenharmony_ci} 79e66f31c5Sopenharmony_ci 80e66f31c5Sopenharmony_ci 81e66f31c5Sopenharmony_ciint uv__platform_loop_init(uv_loop_t* loop) { 82e66f31c5Sopenharmony_ci loop->fs_fd = -1; 83e66f31c5Sopenharmony_ci 84e66f31c5Sopenharmony_ci /* Passing maxfd of -1 should mean the limit is determined 85e66f31c5Sopenharmony_ci * by the user's ulimit or the global limit as per the doc */ 86e66f31c5Sopenharmony_ci loop->backend_fd = pollset_create(-1); 87e66f31c5Sopenharmony_ci 88e66f31c5Sopenharmony_ci if (loop->backend_fd == -1) 89e66f31c5Sopenharmony_ci return -1; 90e66f31c5Sopenharmony_ci 91e66f31c5Sopenharmony_ci return 0; 92e66f31c5Sopenharmony_ci} 93e66f31c5Sopenharmony_ci 94e66f31c5Sopenharmony_ci 95e66f31c5Sopenharmony_civoid uv__platform_loop_delete(uv_loop_t* loop) { 96e66f31c5Sopenharmony_ci if (loop->fs_fd != -1) { 97e66f31c5Sopenharmony_ci uv__close(loop->fs_fd); 98e66f31c5Sopenharmony_ci loop->fs_fd = -1; 99e66f31c5Sopenharmony_ci } 100e66f31c5Sopenharmony_ci 101e66f31c5Sopenharmony_ci if (loop->backend_fd != -1) { 102e66f31c5Sopenharmony_ci pollset_destroy(loop->backend_fd); 103e66f31c5Sopenharmony_ci loop->backend_fd = -1; 104e66f31c5Sopenharmony_ci } 105e66f31c5Sopenharmony_ci} 106e66f31c5Sopenharmony_ci 107e66f31c5Sopenharmony_ci 108e66f31c5Sopenharmony_ciint uv__io_fork(uv_loop_t* loop) { 109e66f31c5Sopenharmony_ci uv__platform_loop_delete(loop); 110e66f31c5Sopenharmony_ci 111e66f31c5Sopenharmony_ci return uv__platform_loop_init(loop); 112e66f31c5Sopenharmony_ci} 113e66f31c5Sopenharmony_ci 114e66f31c5Sopenharmony_ci 115e66f31c5Sopenharmony_ciint uv__io_check_fd(uv_loop_t* loop, int fd) { 116e66f31c5Sopenharmony_ci struct poll_ctl pc; 117e66f31c5Sopenharmony_ci 118e66f31c5Sopenharmony_ci pc.events = POLLIN; 119e66f31c5Sopenharmony_ci pc.cmd = PS_MOD; /* Equivalent to PS_ADD if the fd is not in the pollset. */ 120e66f31c5Sopenharmony_ci pc.fd = fd; 121e66f31c5Sopenharmony_ci 122e66f31c5Sopenharmony_ci if (pollset_ctl(loop->backend_fd, &pc, 1)) 123e66f31c5Sopenharmony_ci return UV__ERR(errno); 124e66f31c5Sopenharmony_ci 125e66f31c5Sopenharmony_ci pc.cmd = PS_DELETE; 126e66f31c5Sopenharmony_ci if (pollset_ctl(loop->backend_fd, &pc, 1)) 127e66f31c5Sopenharmony_ci abort(); 128e66f31c5Sopenharmony_ci 129e66f31c5Sopenharmony_ci return 0; 130e66f31c5Sopenharmony_ci} 131e66f31c5Sopenharmony_ci 132e66f31c5Sopenharmony_ci 133e66f31c5Sopenharmony_civoid uv__io_poll(uv_loop_t* loop, int timeout) { 134e66f31c5Sopenharmony_ci uv__loop_internal_fields_t* lfields; 135e66f31c5Sopenharmony_ci struct pollfd events[1024]; 136e66f31c5Sopenharmony_ci struct pollfd pqry; 137e66f31c5Sopenharmony_ci struct pollfd* pe; 138e66f31c5Sopenharmony_ci struct poll_ctl pc; 139e66f31c5Sopenharmony_ci struct uv__queue* q; 140e66f31c5Sopenharmony_ci uv__io_t* w; 141e66f31c5Sopenharmony_ci uint64_t base; 142e66f31c5Sopenharmony_ci uint64_t diff; 143e66f31c5Sopenharmony_ci int have_signals; 144e66f31c5Sopenharmony_ci int nevents; 145e66f31c5Sopenharmony_ci int count; 146e66f31c5Sopenharmony_ci int nfds; 147e66f31c5Sopenharmony_ci int i; 148e66f31c5Sopenharmony_ci int rc; 149e66f31c5Sopenharmony_ci int add_failed; 150e66f31c5Sopenharmony_ci int user_timeout; 151e66f31c5Sopenharmony_ci int reset_timeout; 152e66f31c5Sopenharmony_ci 153e66f31c5Sopenharmony_ci if (loop->nfds == 0) { 154e66f31c5Sopenharmony_ci assert(uv__queue_empty(&loop->watcher_queue)); 155e66f31c5Sopenharmony_ci return; 156e66f31c5Sopenharmony_ci } 157e66f31c5Sopenharmony_ci 158e66f31c5Sopenharmony_ci lfields = uv__get_internal_fields(loop); 159e66f31c5Sopenharmony_ci 160e66f31c5Sopenharmony_ci while (!uv__queue_empty(&loop->watcher_queue)) { 161e66f31c5Sopenharmony_ci q = uv__queue_head(&loop->watcher_queue); 162e66f31c5Sopenharmony_ci uv__queue_remove(q); 163e66f31c5Sopenharmony_ci uv__queue_init(q); 164e66f31c5Sopenharmony_ci 165e66f31c5Sopenharmony_ci w = uv__queue_data(q, uv__io_t, watcher_queue); 166e66f31c5Sopenharmony_ci assert(w->pevents != 0); 167e66f31c5Sopenharmony_ci assert(w->fd >= 0); 168e66f31c5Sopenharmony_ci assert(w->fd < (int) loop->nwatchers); 169e66f31c5Sopenharmony_ci 170e66f31c5Sopenharmony_ci pc.events = w->pevents; 171e66f31c5Sopenharmony_ci pc.fd = w->fd; 172e66f31c5Sopenharmony_ci 173e66f31c5Sopenharmony_ci add_failed = 0; 174e66f31c5Sopenharmony_ci if (w->events == 0) { 175e66f31c5Sopenharmony_ci pc.cmd = PS_ADD; 176e66f31c5Sopenharmony_ci if (pollset_ctl(loop->backend_fd, &pc, 1)) { 177e66f31c5Sopenharmony_ci if (errno != EINVAL) { 178e66f31c5Sopenharmony_ci assert(0 && "Failed to add file descriptor (pc.fd) to pollset"); 179e66f31c5Sopenharmony_ci abort(); 180e66f31c5Sopenharmony_ci } 181e66f31c5Sopenharmony_ci /* Check if the fd is already in the pollset */ 182e66f31c5Sopenharmony_ci pqry.fd = pc.fd; 183e66f31c5Sopenharmony_ci rc = pollset_query(loop->backend_fd, &pqry); 184e66f31c5Sopenharmony_ci switch (rc) { 185e66f31c5Sopenharmony_ci case -1: 186e66f31c5Sopenharmony_ci assert(0 && "Failed to query pollset for file descriptor"); 187e66f31c5Sopenharmony_ci abort(); 188e66f31c5Sopenharmony_ci case 0: 189e66f31c5Sopenharmony_ci assert(0 && "Pollset does not contain file descriptor"); 190e66f31c5Sopenharmony_ci abort(); 191e66f31c5Sopenharmony_ci } 192e66f31c5Sopenharmony_ci /* If we got here then the pollset already contained the file descriptor even though 193e66f31c5Sopenharmony_ci * we didn't think it should. This probably shouldn't happen, but we can continue. */ 194e66f31c5Sopenharmony_ci add_failed = 1; 195e66f31c5Sopenharmony_ci } 196e66f31c5Sopenharmony_ci } 197e66f31c5Sopenharmony_ci if (w->events != 0 || add_failed) { 198e66f31c5Sopenharmony_ci /* Modify, potentially removing events -- need to delete then add. 199e66f31c5Sopenharmony_ci * Could maybe mod if we knew for sure no events are removed, but 200e66f31c5Sopenharmony_ci * content of w->events is handled above as not reliable (falls back) 201e66f31c5Sopenharmony_ci * so may require a pollset_query() which would have to be pretty cheap 202e66f31c5Sopenharmony_ci * compared to a PS_DELETE to be worth optimizing. Alternatively, could 203e66f31c5Sopenharmony_ci * lazily remove events, squelching them in the mean time. */ 204e66f31c5Sopenharmony_ci pc.cmd = PS_DELETE; 205e66f31c5Sopenharmony_ci if (pollset_ctl(loop->backend_fd, &pc, 1)) { 206e66f31c5Sopenharmony_ci assert(0 && "Failed to delete file descriptor (pc.fd) from pollset"); 207e66f31c5Sopenharmony_ci abort(); 208e66f31c5Sopenharmony_ci } 209e66f31c5Sopenharmony_ci pc.cmd = PS_ADD; 210e66f31c5Sopenharmony_ci if (pollset_ctl(loop->backend_fd, &pc, 1)) { 211e66f31c5Sopenharmony_ci assert(0 && "Failed to add file descriptor (pc.fd) to pollset"); 212e66f31c5Sopenharmony_ci abort(); 213e66f31c5Sopenharmony_ci } 214e66f31c5Sopenharmony_ci } 215e66f31c5Sopenharmony_ci 216e66f31c5Sopenharmony_ci w->events = w->pevents; 217e66f31c5Sopenharmony_ci } 218e66f31c5Sopenharmony_ci 219e66f31c5Sopenharmony_ci assert(timeout >= -1); 220e66f31c5Sopenharmony_ci base = loop->time; 221e66f31c5Sopenharmony_ci count = 48; /* Benchmarks suggest this gives the best throughput. */ 222e66f31c5Sopenharmony_ci 223e66f31c5Sopenharmony_ci if (lfields->flags & UV_METRICS_IDLE_TIME) { 224e66f31c5Sopenharmony_ci reset_timeout = 1; 225e66f31c5Sopenharmony_ci user_timeout = timeout; 226e66f31c5Sopenharmony_ci timeout = 0; 227e66f31c5Sopenharmony_ci } else { 228e66f31c5Sopenharmony_ci reset_timeout = 0; 229e66f31c5Sopenharmony_ci } 230e66f31c5Sopenharmony_ci 231e66f31c5Sopenharmony_ci for (;;) { 232e66f31c5Sopenharmony_ci /* Only need to set the provider_entry_time if timeout != 0. The function 233e66f31c5Sopenharmony_ci * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME. 234e66f31c5Sopenharmony_ci */ 235e66f31c5Sopenharmony_ci if (timeout != 0) 236e66f31c5Sopenharmony_ci uv__metrics_set_provider_entry_time(loop); 237e66f31c5Sopenharmony_ci 238e66f31c5Sopenharmony_ci /* Store the current timeout in a location that's globally accessible so 239e66f31c5Sopenharmony_ci * other locations like uv__work_done() can determine whether the queue 240e66f31c5Sopenharmony_ci * of events in the callback were waiting when poll was called. 241e66f31c5Sopenharmony_ci */ 242e66f31c5Sopenharmony_ci lfields->current_timeout = timeout; 243e66f31c5Sopenharmony_ci 244e66f31c5Sopenharmony_ci nfds = pollset_poll(loop->backend_fd, 245e66f31c5Sopenharmony_ci events, 246e66f31c5Sopenharmony_ci ARRAY_SIZE(events), 247e66f31c5Sopenharmony_ci timeout); 248e66f31c5Sopenharmony_ci 249e66f31c5Sopenharmony_ci /* Update loop->time unconditionally. It's tempting to skip the update when 250e66f31c5Sopenharmony_ci * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the 251e66f31c5Sopenharmony_ci * operating system didn't reschedule our process while in the syscall. 252e66f31c5Sopenharmony_ci */ 253e66f31c5Sopenharmony_ci SAVE_ERRNO(uv__update_time(loop)); 254e66f31c5Sopenharmony_ci 255e66f31c5Sopenharmony_ci if (nfds == 0) { 256e66f31c5Sopenharmony_ci if (reset_timeout != 0) { 257e66f31c5Sopenharmony_ci timeout = user_timeout; 258e66f31c5Sopenharmony_ci reset_timeout = 0; 259e66f31c5Sopenharmony_ci if (timeout == -1) 260e66f31c5Sopenharmony_ci continue; 261e66f31c5Sopenharmony_ci if (timeout > 0) 262e66f31c5Sopenharmony_ci goto update_timeout; 263e66f31c5Sopenharmony_ci } 264e66f31c5Sopenharmony_ci 265e66f31c5Sopenharmony_ci assert(timeout != -1); 266e66f31c5Sopenharmony_ci return; 267e66f31c5Sopenharmony_ci } 268e66f31c5Sopenharmony_ci 269e66f31c5Sopenharmony_ci if (nfds == -1) { 270e66f31c5Sopenharmony_ci if (errno != EINTR) { 271e66f31c5Sopenharmony_ci abort(); 272e66f31c5Sopenharmony_ci } 273e66f31c5Sopenharmony_ci 274e66f31c5Sopenharmony_ci if (reset_timeout != 0) { 275e66f31c5Sopenharmony_ci timeout = user_timeout; 276e66f31c5Sopenharmony_ci reset_timeout = 0; 277e66f31c5Sopenharmony_ci } 278e66f31c5Sopenharmony_ci 279e66f31c5Sopenharmony_ci if (timeout == -1) 280e66f31c5Sopenharmony_ci continue; 281e66f31c5Sopenharmony_ci 282e66f31c5Sopenharmony_ci if (timeout == 0) 283e66f31c5Sopenharmony_ci return; 284e66f31c5Sopenharmony_ci 285e66f31c5Sopenharmony_ci /* Interrupted by a signal. Update timeout and poll again. */ 286e66f31c5Sopenharmony_ci goto update_timeout; 287e66f31c5Sopenharmony_ci } 288e66f31c5Sopenharmony_ci 289e66f31c5Sopenharmony_ci have_signals = 0; 290e66f31c5Sopenharmony_ci nevents = 0; 291e66f31c5Sopenharmony_ci 292e66f31c5Sopenharmony_ci assert(loop->watchers != NULL); 293e66f31c5Sopenharmony_ci loop->watchers[loop->nwatchers] = (void*) events; 294e66f31c5Sopenharmony_ci loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; 295e66f31c5Sopenharmony_ci 296e66f31c5Sopenharmony_ci for (i = 0; i < nfds; i++) { 297e66f31c5Sopenharmony_ci pe = events + i; 298e66f31c5Sopenharmony_ci pc.cmd = PS_DELETE; 299e66f31c5Sopenharmony_ci pc.fd = pe->fd; 300e66f31c5Sopenharmony_ci 301e66f31c5Sopenharmony_ci /* Skip invalidated events, see uv__platform_invalidate_fd */ 302e66f31c5Sopenharmony_ci if (pc.fd == -1) 303e66f31c5Sopenharmony_ci continue; 304e66f31c5Sopenharmony_ci 305e66f31c5Sopenharmony_ci assert(pc.fd >= 0); 306e66f31c5Sopenharmony_ci assert((unsigned) pc.fd < loop->nwatchers); 307e66f31c5Sopenharmony_ci 308e66f31c5Sopenharmony_ci w = loop->watchers[pc.fd]; 309e66f31c5Sopenharmony_ci 310e66f31c5Sopenharmony_ci if (w == NULL) { 311e66f31c5Sopenharmony_ci /* File descriptor that we've stopped watching, disarm it. 312e66f31c5Sopenharmony_ci * 313e66f31c5Sopenharmony_ci * Ignore all errors because we may be racing with another thread 314e66f31c5Sopenharmony_ci * when the file descriptor is closed. 315e66f31c5Sopenharmony_ci */ 316e66f31c5Sopenharmony_ci pollset_ctl(loop->backend_fd, &pc, 1); 317e66f31c5Sopenharmony_ci continue; 318e66f31c5Sopenharmony_ci } 319e66f31c5Sopenharmony_ci 320e66f31c5Sopenharmony_ci /* Run signal watchers last. This also affects child process watchers 321e66f31c5Sopenharmony_ci * because those are implemented in terms of signal watchers. 322e66f31c5Sopenharmony_ci */ 323e66f31c5Sopenharmony_ci if (w == &loop->signal_io_watcher) { 324e66f31c5Sopenharmony_ci have_signals = 1; 325e66f31c5Sopenharmony_ci } else { 326e66f31c5Sopenharmony_ci uv__metrics_update_idle_time(loop); 327e66f31c5Sopenharmony_ci w->cb(loop, w, pe->revents); 328e66f31c5Sopenharmony_ci } 329e66f31c5Sopenharmony_ci 330e66f31c5Sopenharmony_ci nevents++; 331e66f31c5Sopenharmony_ci } 332e66f31c5Sopenharmony_ci 333e66f31c5Sopenharmony_ci uv__metrics_inc_events(loop, nevents); 334e66f31c5Sopenharmony_ci if (reset_timeout != 0) { 335e66f31c5Sopenharmony_ci timeout = user_timeout; 336e66f31c5Sopenharmony_ci reset_timeout = 0; 337e66f31c5Sopenharmony_ci uv__metrics_inc_events_waiting(loop, nevents); 338e66f31c5Sopenharmony_ci } 339e66f31c5Sopenharmony_ci 340e66f31c5Sopenharmony_ci if (have_signals != 0) { 341e66f31c5Sopenharmony_ci uv__metrics_update_idle_time(loop); 342e66f31c5Sopenharmony_ci loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); 343e66f31c5Sopenharmony_ci } 344e66f31c5Sopenharmony_ci 345e66f31c5Sopenharmony_ci loop->watchers[loop->nwatchers] = NULL; 346e66f31c5Sopenharmony_ci loop->watchers[loop->nwatchers + 1] = NULL; 347e66f31c5Sopenharmony_ci 348e66f31c5Sopenharmony_ci if (have_signals != 0) 349e66f31c5Sopenharmony_ci return; /* Event loop should cycle now so don't poll again. */ 350e66f31c5Sopenharmony_ci 351e66f31c5Sopenharmony_ci if (nevents != 0) { 352e66f31c5Sopenharmony_ci if (nfds == ARRAY_SIZE(events) && --count != 0) { 353e66f31c5Sopenharmony_ci /* Poll for more events but don't block this time. */ 354e66f31c5Sopenharmony_ci timeout = 0; 355e66f31c5Sopenharmony_ci continue; 356e66f31c5Sopenharmony_ci } 357e66f31c5Sopenharmony_ci return; 358e66f31c5Sopenharmony_ci } 359e66f31c5Sopenharmony_ci 360e66f31c5Sopenharmony_ci if (timeout == 0) 361e66f31c5Sopenharmony_ci return; 362e66f31c5Sopenharmony_ci 363e66f31c5Sopenharmony_ci if (timeout == -1) 364e66f31c5Sopenharmony_ci continue; 365e66f31c5Sopenharmony_ci 366e66f31c5Sopenharmony_ciupdate_timeout: 367e66f31c5Sopenharmony_ci assert(timeout > 0); 368e66f31c5Sopenharmony_ci 369e66f31c5Sopenharmony_ci diff = loop->time - base; 370e66f31c5Sopenharmony_ci if (diff >= (uint64_t) timeout) 371e66f31c5Sopenharmony_ci return; 372e66f31c5Sopenharmony_ci 373e66f31c5Sopenharmony_ci timeout -= diff; 374e66f31c5Sopenharmony_ci } 375e66f31c5Sopenharmony_ci} 376e66f31c5Sopenharmony_ci 377e66f31c5Sopenharmony_ci 378e66f31c5Sopenharmony_ciuint64_t uv_get_free_memory(void) { 379e66f31c5Sopenharmony_ci perfstat_memory_total_t mem_total; 380e66f31c5Sopenharmony_ci int result = perfstat_memory_total(NULL, &mem_total, sizeof(mem_total), 1); 381e66f31c5Sopenharmony_ci if (result == -1) { 382e66f31c5Sopenharmony_ci return 0; 383e66f31c5Sopenharmony_ci } 384e66f31c5Sopenharmony_ci return mem_total.real_free * 4096; 385e66f31c5Sopenharmony_ci} 386e66f31c5Sopenharmony_ci 387e66f31c5Sopenharmony_ci 388e66f31c5Sopenharmony_ciuint64_t uv_get_total_memory(void) { 389e66f31c5Sopenharmony_ci perfstat_memory_total_t mem_total; 390e66f31c5Sopenharmony_ci int result = perfstat_memory_total(NULL, &mem_total, sizeof(mem_total), 1); 391e66f31c5Sopenharmony_ci if (result == -1) { 392e66f31c5Sopenharmony_ci return 0; 393e66f31c5Sopenharmony_ci } 394e66f31c5Sopenharmony_ci return mem_total.real_total * 4096; 395e66f31c5Sopenharmony_ci} 396e66f31c5Sopenharmony_ci 397e66f31c5Sopenharmony_ci 398e66f31c5Sopenharmony_ciuint64_t uv_get_constrained_memory(void) { 399e66f31c5Sopenharmony_ci return 0; /* Memory constraints are unknown. */ 400e66f31c5Sopenharmony_ci} 401e66f31c5Sopenharmony_ci 402e66f31c5Sopenharmony_ci 403e66f31c5Sopenharmony_ciuint64_t uv_get_available_memory(void) { 404e66f31c5Sopenharmony_ci return uv_get_free_memory(); 405e66f31c5Sopenharmony_ci} 406e66f31c5Sopenharmony_ci 407e66f31c5Sopenharmony_ci 408e66f31c5Sopenharmony_civoid uv_loadavg(double avg[3]) { 409e66f31c5Sopenharmony_ci perfstat_cpu_total_t ps_total; 410e66f31c5Sopenharmony_ci int result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1); 411e66f31c5Sopenharmony_ci if (result == -1) { 412e66f31c5Sopenharmony_ci avg[0] = 0.; avg[1] = 0.; avg[2] = 0.; 413e66f31c5Sopenharmony_ci return; 414e66f31c5Sopenharmony_ci } 415e66f31c5Sopenharmony_ci avg[0] = ps_total.loadavg[0] / (double)(1 << SBITS); 416e66f31c5Sopenharmony_ci avg[1] = ps_total.loadavg[1] / (double)(1 << SBITS); 417e66f31c5Sopenharmony_ci avg[2] = ps_total.loadavg[2] / (double)(1 << SBITS); 418e66f31c5Sopenharmony_ci} 419e66f31c5Sopenharmony_ci 420e66f31c5Sopenharmony_ci 421e66f31c5Sopenharmony_ci#ifdef HAVE_SYS_AHAFS_EVPRODS_H 422e66f31c5Sopenharmony_cistatic char* uv__rawname(const char* cp, char (*dst)[FILENAME_MAX+1]) { 423e66f31c5Sopenharmony_ci char* dp; 424e66f31c5Sopenharmony_ci 425e66f31c5Sopenharmony_ci dp = rindex(cp, '/'); 426e66f31c5Sopenharmony_ci if (dp == 0) 427e66f31c5Sopenharmony_ci return 0; 428e66f31c5Sopenharmony_ci 429e66f31c5Sopenharmony_ci snprintf(*dst, sizeof(*dst), "%.*s/r%s", (int) (dp - cp), cp, dp + 1); 430e66f31c5Sopenharmony_ci return *dst; 431e66f31c5Sopenharmony_ci} 432e66f31c5Sopenharmony_ci 433e66f31c5Sopenharmony_ci 434e66f31c5Sopenharmony_ci/* 435e66f31c5Sopenharmony_ci * Determine whether given pathname is a directory 436e66f31c5Sopenharmony_ci * Returns 0 if the path is a directory, -1 if not 437e66f31c5Sopenharmony_ci * 438e66f31c5Sopenharmony_ci * Note: Opportunity here for more detailed error information but 439e66f31c5Sopenharmony_ci * that requires changing callers of this function as well 440e66f31c5Sopenharmony_ci */ 441e66f31c5Sopenharmony_cistatic int uv__path_is_a_directory(char* filename) { 442e66f31c5Sopenharmony_ci struct stat statbuf; 443e66f31c5Sopenharmony_ci 444e66f31c5Sopenharmony_ci if (uv__stat(filename, &statbuf) < 0) 445e66f31c5Sopenharmony_ci return -1; /* failed: not a directory, assume it is a file */ 446e66f31c5Sopenharmony_ci 447e66f31c5Sopenharmony_ci if (statbuf.st_type == VDIR) 448e66f31c5Sopenharmony_ci return 0; 449e66f31c5Sopenharmony_ci 450e66f31c5Sopenharmony_ci return -1; 451e66f31c5Sopenharmony_ci} 452e66f31c5Sopenharmony_ci 453e66f31c5Sopenharmony_ci 454e66f31c5Sopenharmony_ci/* 455e66f31c5Sopenharmony_ci * Check whether AHAFS is mounted. 456e66f31c5Sopenharmony_ci * Returns 0 if AHAFS is mounted, or an error code < 0 on failure 457e66f31c5Sopenharmony_ci */ 458e66f31c5Sopenharmony_cistatic int uv__is_ahafs_mounted(void){ 459e66f31c5Sopenharmony_ci char rawbuf[FILENAME_MAX+1]; 460e66f31c5Sopenharmony_ci int rv, i = 2; 461e66f31c5Sopenharmony_ci struct vmount *p; 462e66f31c5Sopenharmony_ci int size_multiplier = 10; 463e66f31c5Sopenharmony_ci size_t siz = sizeof(struct vmount)*size_multiplier; 464e66f31c5Sopenharmony_ci struct vmount *vmt; 465e66f31c5Sopenharmony_ci const char *dev = "/aha"; 466e66f31c5Sopenharmony_ci char *obj, *stub; 467e66f31c5Sopenharmony_ci 468e66f31c5Sopenharmony_ci p = uv__malloc(siz); 469e66f31c5Sopenharmony_ci if (p == NULL) 470e66f31c5Sopenharmony_ci return UV__ERR(errno); 471e66f31c5Sopenharmony_ci 472e66f31c5Sopenharmony_ci /* Retrieve all mounted filesystems */ 473e66f31c5Sopenharmony_ci rv = mntctl(MCTL_QUERY, siz, (char*)p); 474e66f31c5Sopenharmony_ci if (rv < 0) 475e66f31c5Sopenharmony_ci return UV__ERR(errno); 476e66f31c5Sopenharmony_ci if (rv == 0) { 477e66f31c5Sopenharmony_ci /* buffer was not large enough, reallocate to correct size */ 478e66f31c5Sopenharmony_ci siz = *(int*)p; 479e66f31c5Sopenharmony_ci uv__free(p); 480e66f31c5Sopenharmony_ci p = uv__malloc(siz); 481e66f31c5Sopenharmony_ci if (p == NULL) 482e66f31c5Sopenharmony_ci return UV__ERR(errno); 483e66f31c5Sopenharmony_ci rv = mntctl(MCTL_QUERY, siz, (char*)p); 484e66f31c5Sopenharmony_ci if (rv < 0) 485e66f31c5Sopenharmony_ci return UV__ERR(errno); 486e66f31c5Sopenharmony_ci } 487e66f31c5Sopenharmony_ci 488e66f31c5Sopenharmony_ci /* Look for dev in filesystems mount info */ 489e66f31c5Sopenharmony_ci for(vmt = p, i = 0; i < rv; i++) { 490e66f31c5Sopenharmony_ci obj = vmt2dataptr(vmt, VMT_OBJECT); /* device */ 491e66f31c5Sopenharmony_ci stub = vmt2dataptr(vmt, VMT_STUB); /* mount point */ 492e66f31c5Sopenharmony_ci 493e66f31c5Sopenharmony_ci if (EQ(obj, dev) || EQ(uv__rawname(obj, &rawbuf), dev) || EQ(stub, dev)) { 494e66f31c5Sopenharmony_ci uv__free(p); /* Found a match */ 495e66f31c5Sopenharmony_ci return 0; 496e66f31c5Sopenharmony_ci } 497e66f31c5Sopenharmony_ci vmt = (struct vmount *) ((char *) vmt + vmt->vmt_length); 498e66f31c5Sopenharmony_ci } 499e66f31c5Sopenharmony_ci 500e66f31c5Sopenharmony_ci /* /aha is required for monitoring filesystem changes */ 501e66f31c5Sopenharmony_ci return -1; 502e66f31c5Sopenharmony_ci} 503e66f31c5Sopenharmony_ci 504e66f31c5Sopenharmony_ci/* 505e66f31c5Sopenharmony_ci * Recursive call to mkdir() to create intermediate folders, if any 506e66f31c5Sopenharmony_ci * Returns code from mkdir call 507e66f31c5Sopenharmony_ci */ 508e66f31c5Sopenharmony_cistatic int uv__makedir_p(const char *dir) { 509e66f31c5Sopenharmony_ci char tmp[256]; 510e66f31c5Sopenharmony_ci char *p = NULL; 511e66f31c5Sopenharmony_ci size_t len; 512e66f31c5Sopenharmony_ci int err; 513e66f31c5Sopenharmony_ci 514e66f31c5Sopenharmony_ci /* TODO(bnoordhuis) Check uv__strscpy() return value. */ 515e66f31c5Sopenharmony_ci uv__strscpy(tmp, dir, sizeof(tmp)); 516e66f31c5Sopenharmony_ci len = strlen(tmp); 517e66f31c5Sopenharmony_ci if (tmp[len - 1] == '/') 518e66f31c5Sopenharmony_ci tmp[len - 1] = 0; 519e66f31c5Sopenharmony_ci for (p = tmp + 1; *p; p++) { 520e66f31c5Sopenharmony_ci if (*p == '/') { 521e66f31c5Sopenharmony_ci *p = 0; 522e66f31c5Sopenharmony_ci err = mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 523e66f31c5Sopenharmony_ci if (err != 0 && errno != EEXIST) 524e66f31c5Sopenharmony_ci return err; 525e66f31c5Sopenharmony_ci *p = '/'; 526e66f31c5Sopenharmony_ci } 527e66f31c5Sopenharmony_ci } 528e66f31c5Sopenharmony_ci return mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 529e66f31c5Sopenharmony_ci} 530e66f31c5Sopenharmony_ci 531e66f31c5Sopenharmony_ci/* 532e66f31c5Sopenharmony_ci * Creates necessary subdirectories in the AIX Event Infrastructure 533e66f31c5Sopenharmony_ci * file system for monitoring the object specified. 534e66f31c5Sopenharmony_ci * Returns code from mkdir call 535e66f31c5Sopenharmony_ci */ 536e66f31c5Sopenharmony_cistatic int uv__make_subdirs_p(const char *filename) { 537e66f31c5Sopenharmony_ci char cmd[2048]; 538e66f31c5Sopenharmony_ci char *p; 539e66f31c5Sopenharmony_ci int rc = 0; 540e66f31c5Sopenharmony_ci 541e66f31c5Sopenharmony_ci /* Strip off the monitor file name */ 542e66f31c5Sopenharmony_ci p = strrchr(filename, '/'); 543e66f31c5Sopenharmony_ci 544e66f31c5Sopenharmony_ci if (p == NULL) 545e66f31c5Sopenharmony_ci return 0; 546e66f31c5Sopenharmony_ci 547e66f31c5Sopenharmony_ci if (uv__path_is_a_directory((char*)filename) == 0) { 548e66f31c5Sopenharmony_ci sprintf(cmd, "/aha/fs/modDir.monFactory"); 549e66f31c5Sopenharmony_ci } else { 550e66f31c5Sopenharmony_ci sprintf(cmd, "/aha/fs/modFile.monFactory"); 551e66f31c5Sopenharmony_ci } 552e66f31c5Sopenharmony_ci 553e66f31c5Sopenharmony_ci strncat(cmd, filename, (p - filename)); 554e66f31c5Sopenharmony_ci rc = uv__makedir_p(cmd); 555e66f31c5Sopenharmony_ci 556e66f31c5Sopenharmony_ci if (rc == -1 && errno != EEXIST){ 557e66f31c5Sopenharmony_ci return UV__ERR(errno); 558e66f31c5Sopenharmony_ci } 559e66f31c5Sopenharmony_ci 560e66f31c5Sopenharmony_ci return rc; 561e66f31c5Sopenharmony_ci} 562e66f31c5Sopenharmony_ci 563e66f31c5Sopenharmony_ci 564e66f31c5Sopenharmony_ci/* 565e66f31c5Sopenharmony_ci * Checks if /aha is mounted, then proceeds to set up the monitoring 566e66f31c5Sopenharmony_ci * objects for the specified file. 567e66f31c5Sopenharmony_ci * Returns 0 on success, or an error code < 0 on failure 568e66f31c5Sopenharmony_ci */ 569e66f31c5Sopenharmony_cistatic int uv__setup_ahafs(const char* filename, int *fd) { 570e66f31c5Sopenharmony_ci int rc = 0; 571e66f31c5Sopenharmony_ci char mon_file_write_string[RDWR_BUF_SIZE]; 572e66f31c5Sopenharmony_ci char mon_file[PATH_MAX]; 573e66f31c5Sopenharmony_ci int file_is_directory = 0; /* -1 == NO, 0 == YES */ 574e66f31c5Sopenharmony_ci 575e66f31c5Sopenharmony_ci /* Create monitor file name for object */ 576e66f31c5Sopenharmony_ci file_is_directory = uv__path_is_a_directory((char*)filename); 577e66f31c5Sopenharmony_ci 578e66f31c5Sopenharmony_ci if (file_is_directory == 0) 579e66f31c5Sopenharmony_ci sprintf(mon_file, "/aha/fs/modDir.monFactory"); 580e66f31c5Sopenharmony_ci else 581e66f31c5Sopenharmony_ci sprintf(mon_file, "/aha/fs/modFile.monFactory"); 582e66f31c5Sopenharmony_ci 583e66f31c5Sopenharmony_ci if ((strlen(mon_file) + strlen(filename) + 5) > PATH_MAX) 584e66f31c5Sopenharmony_ci return UV_ENAMETOOLONG; 585e66f31c5Sopenharmony_ci 586e66f31c5Sopenharmony_ci /* Make the necessary subdirectories for the monitor file */ 587e66f31c5Sopenharmony_ci rc = uv__make_subdirs_p(filename); 588e66f31c5Sopenharmony_ci if (rc == -1 && errno != EEXIST) 589e66f31c5Sopenharmony_ci return rc; 590e66f31c5Sopenharmony_ci 591e66f31c5Sopenharmony_ci strcat(mon_file, filename); 592e66f31c5Sopenharmony_ci strcat(mon_file, ".mon"); 593e66f31c5Sopenharmony_ci 594e66f31c5Sopenharmony_ci *fd = 0; errno = 0; 595e66f31c5Sopenharmony_ci 596e66f31c5Sopenharmony_ci /* Open the monitor file, creating it if necessary */ 597e66f31c5Sopenharmony_ci *fd = open(mon_file, O_CREAT|O_RDWR); 598e66f31c5Sopenharmony_ci if (*fd < 0) 599e66f31c5Sopenharmony_ci return UV__ERR(errno); 600e66f31c5Sopenharmony_ci 601e66f31c5Sopenharmony_ci /* Write out the monitoring specifications. 602e66f31c5Sopenharmony_ci * In this case, we are monitoring for a state change event type 603e66f31c5Sopenharmony_ci * CHANGED=YES 604e66f31c5Sopenharmony_ci * We will be waiting in select call, rather than a read: 605e66f31c5Sopenharmony_ci * WAIT_TYPE=WAIT_IN_SELECT 606e66f31c5Sopenharmony_ci * We only want minimal information for files: 607e66f31c5Sopenharmony_ci * INFO_LVL=1 608e66f31c5Sopenharmony_ci * For directories, we want more information to track what file 609e66f31c5Sopenharmony_ci * caused the change 610e66f31c5Sopenharmony_ci * INFO_LVL=2 611e66f31c5Sopenharmony_ci */ 612e66f31c5Sopenharmony_ci 613e66f31c5Sopenharmony_ci if (file_is_directory == 0) 614e66f31c5Sopenharmony_ci sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=2"); 615e66f31c5Sopenharmony_ci else 616e66f31c5Sopenharmony_ci sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=1"); 617e66f31c5Sopenharmony_ci 618e66f31c5Sopenharmony_ci rc = write(*fd, mon_file_write_string, strlen(mon_file_write_string)+1); 619e66f31c5Sopenharmony_ci if (rc < 0 && errno != EBUSY) 620e66f31c5Sopenharmony_ci return UV__ERR(errno); 621e66f31c5Sopenharmony_ci 622e66f31c5Sopenharmony_ci return 0; 623e66f31c5Sopenharmony_ci} 624e66f31c5Sopenharmony_ci 625e66f31c5Sopenharmony_ci/* 626e66f31c5Sopenharmony_ci * Skips a specified number of lines in the buffer passed in. 627e66f31c5Sopenharmony_ci * Walks the buffer pointed to by p and attempts to skip n lines. 628e66f31c5Sopenharmony_ci * Returns the total number of lines skipped 629e66f31c5Sopenharmony_ci */ 630e66f31c5Sopenharmony_cistatic int uv__skip_lines(char **p, int n) { 631e66f31c5Sopenharmony_ci int lines = 0; 632e66f31c5Sopenharmony_ci 633e66f31c5Sopenharmony_ci while(n > 0) { 634e66f31c5Sopenharmony_ci *p = strchr(*p, '\n'); 635e66f31c5Sopenharmony_ci if (!p) 636e66f31c5Sopenharmony_ci return lines; 637e66f31c5Sopenharmony_ci 638e66f31c5Sopenharmony_ci (*p)++; 639e66f31c5Sopenharmony_ci n--; 640e66f31c5Sopenharmony_ci lines++; 641e66f31c5Sopenharmony_ci } 642e66f31c5Sopenharmony_ci return lines; 643e66f31c5Sopenharmony_ci} 644e66f31c5Sopenharmony_ci 645e66f31c5Sopenharmony_ci 646e66f31c5Sopenharmony_ci/* 647e66f31c5Sopenharmony_ci * Parse the event occurrence data to figure out what event just occurred 648e66f31c5Sopenharmony_ci * and take proper action. 649e66f31c5Sopenharmony_ci * 650e66f31c5Sopenharmony_ci * The buf is a pointer to the buffer containing the event occurrence data 651e66f31c5Sopenharmony_ci * Returns 0 on success, -1 if unrecoverable error in parsing 652e66f31c5Sopenharmony_ci * 653e66f31c5Sopenharmony_ci */ 654e66f31c5Sopenharmony_cistatic int uv__parse_data(char *buf, int *events, uv_fs_event_t* handle) { 655e66f31c5Sopenharmony_ci int evp_rc, i; 656e66f31c5Sopenharmony_ci char *p; 657e66f31c5Sopenharmony_ci char filename[PATH_MAX]; /* To be used when handling directories */ 658e66f31c5Sopenharmony_ci 659e66f31c5Sopenharmony_ci p = buf; 660e66f31c5Sopenharmony_ci *events = 0; 661e66f31c5Sopenharmony_ci 662e66f31c5Sopenharmony_ci /* Clean the filename buffer*/ 663e66f31c5Sopenharmony_ci for(i = 0; i < PATH_MAX; i++) { 664e66f31c5Sopenharmony_ci filename[i] = 0; 665e66f31c5Sopenharmony_ci } 666e66f31c5Sopenharmony_ci i = 0; 667e66f31c5Sopenharmony_ci 668e66f31c5Sopenharmony_ci /* Check for BUF_WRAP */ 669e66f31c5Sopenharmony_ci if (strncmp(buf, "BUF_WRAP", strlen("BUF_WRAP")) == 0) { 670e66f31c5Sopenharmony_ci assert(0 && "Buffer wrap detected, Some event occurrences lost!"); 671e66f31c5Sopenharmony_ci return 0; 672e66f31c5Sopenharmony_ci } 673e66f31c5Sopenharmony_ci 674e66f31c5Sopenharmony_ci /* Since we are using the default buffer size (4K), and have specified 675e66f31c5Sopenharmony_ci * INFO_LVL=1, we won't see any EVENT_OVERFLOW conditions. Applications 676e66f31c5Sopenharmony_ci * should check for this keyword if they are using an INFO_LVL of 2 or 677e66f31c5Sopenharmony_ci * higher, and have a buffer size of <= 4K 678e66f31c5Sopenharmony_ci */ 679e66f31c5Sopenharmony_ci 680e66f31c5Sopenharmony_ci /* Skip to RC_FROM_EVPROD */ 681e66f31c5Sopenharmony_ci if (uv__skip_lines(&p, 9) != 9) 682e66f31c5Sopenharmony_ci return -1; 683e66f31c5Sopenharmony_ci 684e66f31c5Sopenharmony_ci if (sscanf(p, "RC_FROM_EVPROD=%d\nEND_EVENT_DATA", &evp_rc) == 1) { 685e66f31c5Sopenharmony_ci if (uv__path_is_a_directory(handle->path) == 0) { /* Directory */ 686e66f31c5Sopenharmony_ci if (evp_rc == AHAFS_MODDIR_UNMOUNT || evp_rc == AHAFS_MODDIR_REMOVE_SELF) { 687e66f31c5Sopenharmony_ci /* The directory is no longer available for monitoring */ 688e66f31c5Sopenharmony_ci *events = UV_RENAME; 689e66f31c5Sopenharmony_ci handle->dir_filename = NULL; 690e66f31c5Sopenharmony_ci } else { 691e66f31c5Sopenharmony_ci /* A file was added/removed inside the directory */ 692e66f31c5Sopenharmony_ci *events = UV_CHANGE; 693e66f31c5Sopenharmony_ci 694e66f31c5Sopenharmony_ci /* Get the EVPROD_INFO */ 695e66f31c5Sopenharmony_ci if (uv__skip_lines(&p, 1) != 1) 696e66f31c5Sopenharmony_ci return -1; 697e66f31c5Sopenharmony_ci 698e66f31c5Sopenharmony_ci /* Scan out the name of the file that triggered the event*/ 699e66f31c5Sopenharmony_ci if (sscanf(p, "BEGIN_EVPROD_INFO\n%sEND_EVPROD_INFO", filename) == 1) { 700e66f31c5Sopenharmony_ci handle->dir_filename = uv__strdup((const char*)&filename); 701e66f31c5Sopenharmony_ci } else 702e66f31c5Sopenharmony_ci return -1; 703e66f31c5Sopenharmony_ci } 704e66f31c5Sopenharmony_ci } else { /* Regular File */ 705e66f31c5Sopenharmony_ci if (evp_rc == AHAFS_MODFILE_RENAME) 706e66f31c5Sopenharmony_ci *events = UV_RENAME; 707e66f31c5Sopenharmony_ci else 708e66f31c5Sopenharmony_ci *events = UV_CHANGE; 709e66f31c5Sopenharmony_ci } 710e66f31c5Sopenharmony_ci } 711e66f31c5Sopenharmony_ci else 712e66f31c5Sopenharmony_ci return -1; 713e66f31c5Sopenharmony_ci 714e66f31c5Sopenharmony_ci return 0; 715e66f31c5Sopenharmony_ci} 716e66f31c5Sopenharmony_ci 717e66f31c5Sopenharmony_ci 718e66f31c5Sopenharmony_ci/* This is the internal callback */ 719e66f31c5Sopenharmony_cistatic void uv__ahafs_event(uv_loop_t* loop, uv__io_t* event_watch, unsigned int fflags) { 720e66f31c5Sopenharmony_ci char result_data[RDWR_BUF_SIZE]; 721e66f31c5Sopenharmony_ci int bytes, rc = 0; 722e66f31c5Sopenharmony_ci uv_fs_event_t* handle; 723e66f31c5Sopenharmony_ci int events = 0; 724e66f31c5Sopenharmony_ci char fname[PATH_MAX]; 725e66f31c5Sopenharmony_ci char *p; 726e66f31c5Sopenharmony_ci 727e66f31c5Sopenharmony_ci handle = container_of(event_watch, uv_fs_event_t, event_watcher); 728e66f31c5Sopenharmony_ci 729e66f31c5Sopenharmony_ci /* At this point, we assume that polling has been done on the 730e66f31c5Sopenharmony_ci * file descriptor, so we can just read the AHAFS event occurrence 731e66f31c5Sopenharmony_ci * data and parse its results without having to block anything 732e66f31c5Sopenharmony_ci */ 733e66f31c5Sopenharmony_ci bytes = pread(event_watch->fd, result_data, RDWR_BUF_SIZE, 0); 734e66f31c5Sopenharmony_ci 735e66f31c5Sopenharmony_ci assert((bytes >= 0) && "uv__ahafs_event - Error reading monitor file"); 736e66f31c5Sopenharmony_ci 737e66f31c5Sopenharmony_ci /* In file / directory move cases, AIX Event infrastructure 738e66f31c5Sopenharmony_ci * produces a second event with no data. 739e66f31c5Sopenharmony_ci * Ignore it and return gracefully. 740e66f31c5Sopenharmony_ci */ 741e66f31c5Sopenharmony_ci if(bytes == 0) 742e66f31c5Sopenharmony_ci return; 743e66f31c5Sopenharmony_ci 744e66f31c5Sopenharmony_ci /* Parse the data */ 745e66f31c5Sopenharmony_ci if(bytes > 0) 746e66f31c5Sopenharmony_ci rc = uv__parse_data(result_data, &events, handle); 747e66f31c5Sopenharmony_ci 748e66f31c5Sopenharmony_ci /* Unrecoverable error */ 749e66f31c5Sopenharmony_ci if (rc == -1) 750e66f31c5Sopenharmony_ci return; 751e66f31c5Sopenharmony_ci 752e66f31c5Sopenharmony_ci /* For directory changes, the name of the files that triggered the change 753e66f31c5Sopenharmony_ci * are never absolute pathnames 754e66f31c5Sopenharmony_ci */ 755e66f31c5Sopenharmony_ci if (uv__path_is_a_directory(handle->path) == 0) { 756e66f31c5Sopenharmony_ci p = handle->dir_filename; 757e66f31c5Sopenharmony_ci } else { 758e66f31c5Sopenharmony_ci p = strrchr(handle->path, '/'); 759e66f31c5Sopenharmony_ci if (p == NULL) 760e66f31c5Sopenharmony_ci p = handle->path; 761e66f31c5Sopenharmony_ci else 762e66f31c5Sopenharmony_ci p++; 763e66f31c5Sopenharmony_ci } 764e66f31c5Sopenharmony_ci 765e66f31c5Sopenharmony_ci /* TODO(bnoordhuis) Check uv__strscpy() return value. */ 766e66f31c5Sopenharmony_ci uv__strscpy(fname, p, sizeof(fname)); 767e66f31c5Sopenharmony_ci 768e66f31c5Sopenharmony_ci handle->cb(handle, fname, events, 0); 769e66f31c5Sopenharmony_ci} 770e66f31c5Sopenharmony_ci#endif 771e66f31c5Sopenharmony_ci 772e66f31c5Sopenharmony_ci 773e66f31c5Sopenharmony_ciint uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { 774e66f31c5Sopenharmony_ci#ifdef HAVE_SYS_AHAFS_EVPRODS_H 775e66f31c5Sopenharmony_ci uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); 776e66f31c5Sopenharmony_ci return 0; 777e66f31c5Sopenharmony_ci#else 778e66f31c5Sopenharmony_ci return UV_ENOSYS; 779e66f31c5Sopenharmony_ci#endif 780e66f31c5Sopenharmony_ci} 781e66f31c5Sopenharmony_ci 782e66f31c5Sopenharmony_ci 783e66f31c5Sopenharmony_ciint uv_fs_event_start(uv_fs_event_t* handle, 784e66f31c5Sopenharmony_ci uv_fs_event_cb cb, 785e66f31c5Sopenharmony_ci const char* filename, 786e66f31c5Sopenharmony_ci unsigned int flags) { 787e66f31c5Sopenharmony_ci#ifdef HAVE_SYS_AHAFS_EVPRODS_H 788e66f31c5Sopenharmony_ci int fd, rc, str_offset = 0; 789e66f31c5Sopenharmony_ci char cwd[PATH_MAX]; 790e66f31c5Sopenharmony_ci char absolute_path[PATH_MAX]; 791e66f31c5Sopenharmony_ci char readlink_cwd[PATH_MAX]; 792e66f31c5Sopenharmony_ci struct timeval zt; 793e66f31c5Sopenharmony_ci fd_set pollfd; 794e66f31c5Sopenharmony_ci 795e66f31c5Sopenharmony_ci 796e66f31c5Sopenharmony_ci /* Figure out whether filename is absolute or not */ 797e66f31c5Sopenharmony_ci if (filename[0] == '\0') { 798e66f31c5Sopenharmony_ci /* Missing a pathname */ 799e66f31c5Sopenharmony_ci return UV_ENOENT; 800e66f31c5Sopenharmony_ci } 801e66f31c5Sopenharmony_ci else if (filename[0] == '/') { 802e66f31c5Sopenharmony_ci /* We have absolute pathname */ 803e66f31c5Sopenharmony_ci /* TODO(bnoordhuis) Check uv__strscpy() return value. */ 804e66f31c5Sopenharmony_ci uv__strscpy(absolute_path, filename, sizeof(absolute_path)); 805e66f31c5Sopenharmony_ci } else { 806e66f31c5Sopenharmony_ci /* We have a relative pathname, compose the absolute pathname */ 807e66f31c5Sopenharmony_ci snprintf(cwd, sizeof(cwd), "/proc/%lu/cwd", (unsigned long) getpid()); 808e66f31c5Sopenharmony_ci rc = readlink(cwd, readlink_cwd, sizeof(readlink_cwd) - 1); 809e66f31c5Sopenharmony_ci if (rc < 0) 810e66f31c5Sopenharmony_ci return rc; 811e66f31c5Sopenharmony_ci /* readlink does not null terminate our string */ 812e66f31c5Sopenharmony_ci readlink_cwd[rc] = '\0'; 813e66f31c5Sopenharmony_ci 814e66f31c5Sopenharmony_ci if (filename[0] == '.' && filename[1] == '/') 815e66f31c5Sopenharmony_ci str_offset = 2; 816e66f31c5Sopenharmony_ci 817e66f31c5Sopenharmony_ci snprintf(absolute_path, sizeof(absolute_path), "%s%s", readlink_cwd, 818e66f31c5Sopenharmony_ci filename + str_offset); 819e66f31c5Sopenharmony_ci } 820e66f31c5Sopenharmony_ci 821e66f31c5Sopenharmony_ci if (uv__is_ahafs_mounted() < 0) /* /aha checks failed */ 822e66f31c5Sopenharmony_ci return UV_ENOSYS; 823e66f31c5Sopenharmony_ci 824e66f31c5Sopenharmony_ci /* Setup ahafs */ 825e66f31c5Sopenharmony_ci rc = uv__setup_ahafs((const char *)absolute_path, &fd); 826e66f31c5Sopenharmony_ci if (rc != 0) 827e66f31c5Sopenharmony_ci return rc; 828e66f31c5Sopenharmony_ci 829e66f31c5Sopenharmony_ci /* Setup/Initialize all the libuv routines */ 830e66f31c5Sopenharmony_ci uv__handle_start(handle); 831e66f31c5Sopenharmony_ci uv__io_init(&handle->event_watcher, uv__ahafs_event, fd); 832e66f31c5Sopenharmony_ci handle->path = uv__strdup(filename); 833e66f31c5Sopenharmony_ci handle->cb = cb; 834e66f31c5Sopenharmony_ci handle->dir_filename = NULL; 835e66f31c5Sopenharmony_ci 836e66f31c5Sopenharmony_ci uv__io_start(handle->loop, &handle->event_watcher, POLLIN); 837e66f31c5Sopenharmony_ci 838e66f31c5Sopenharmony_ci /* AHAFS wants someone to poll for it to start mointoring. 839e66f31c5Sopenharmony_ci * so kick-start it so that we don't miss an event in the 840e66f31c5Sopenharmony_ci * eventuality of an event that occurs in the current loop. */ 841e66f31c5Sopenharmony_ci do { 842e66f31c5Sopenharmony_ci memset(&zt, 0, sizeof(zt)); 843e66f31c5Sopenharmony_ci FD_ZERO(&pollfd); 844e66f31c5Sopenharmony_ci FD_SET(fd, &pollfd); 845e66f31c5Sopenharmony_ci rc = select(fd + 1, &pollfd, NULL, NULL, &zt); 846e66f31c5Sopenharmony_ci } while (rc == -1 && errno == EINTR); 847e66f31c5Sopenharmony_ci return 0; 848e66f31c5Sopenharmony_ci#else 849e66f31c5Sopenharmony_ci return UV_ENOSYS; 850e66f31c5Sopenharmony_ci#endif 851e66f31c5Sopenharmony_ci} 852e66f31c5Sopenharmony_ci 853e66f31c5Sopenharmony_ci 854e66f31c5Sopenharmony_ciint uv_fs_event_stop(uv_fs_event_t* handle) { 855e66f31c5Sopenharmony_ci#ifdef HAVE_SYS_AHAFS_EVPRODS_H 856e66f31c5Sopenharmony_ci if (!uv__is_active(handle)) 857e66f31c5Sopenharmony_ci return 0; 858e66f31c5Sopenharmony_ci 859e66f31c5Sopenharmony_ci uv__io_close(handle->loop, &handle->event_watcher); 860e66f31c5Sopenharmony_ci uv__handle_stop(handle); 861e66f31c5Sopenharmony_ci 862e66f31c5Sopenharmony_ci if (uv__path_is_a_directory(handle->path) == 0) { 863e66f31c5Sopenharmony_ci uv__free(handle->dir_filename); 864e66f31c5Sopenharmony_ci handle->dir_filename = NULL; 865e66f31c5Sopenharmony_ci } 866e66f31c5Sopenharmony_ci 867e66f31c5Sopenharmony_ci uv__free(handle->path); 868e66f31c5Sopenharmony_ci handle->path = NULL; 869e66f31c5Sopenharmony_ci uv__close(handle->event_watcher.fd); 870e66f31c5Sopenharmony_ci handle->event_watcher.fd = -1; 871e66f31c5Sopenharmony_ci 872e66f31c5Sopenharmony_ci return 0; 873e66f31c5Sopenharmony_ci#else 874e66f31c5Sopenharmony_ci return UV_ENOSYS; 875e66f31c5Sopenharmony_ci#endif 876e66f31c5Sopenharmony_ci} 877e66f31c5Sopenharmony_ci 878e66f31c5Sopenharmony_ci 879e66f31c5Sopenharmony_civoid uv__fs_event_close(uv_fs_event_t* handle) { 880e66f31c5Sopenharmony_ci#ifdef HAVE_SYS_AHAFS_EVPRODS_H 881e66f31c5Sopenharmony_ci uv_fs_event_stop(handle); 882e66f31c5Sopenharmony_ci#else 883e66f31c5Sopenharmony_ci UNREACHABLE(); 884e66f31c5Sopenharmony_ci#endif 885e66f31c5Sopenharmony_ci} 886e66f31c5Sopenharmony_ci 887e66f31c5Sopenharmony_ci 888e66f31c5Sopenharmony_cichar** uv_setup_args(int argc, char** argv) { 889e66f31c5Sopenharmony_ci char exepath[UV__PATH_MAX]; 890e66f31c5Sopenharmony_ci char** new_argv; 891e66f31c5Sopenharmony_ci size_t size; 892e66f31c5Sopenharmony_ci char* s; 893e66f31c5Sopenharmony_ci int i; 894e66f31c5Sopenharmony_ci 895e66f31c5Sopenharmony_ci if (argc <= 0) 896e66f31c5Sopenharmony_ci return argv; 897e66f31c5Sopenharmony_ci 898e66f31c5Sopenharmony_ci /* Save the original pointer to argv. 899e66f31c5Sopenharmony_ci * AIX uses argv to read the process name. 900e66f31c5Sopenharmony_ci * (Not the memory pointed to by argv[0..n] as on Linux.) 901e66f31c5Sopenharmony_ci */ 902e66f31c5Sopenharmony_ci process_argv = argv; 903e66f31c5Sopenharmony_ci process_argc = argc; 904e66f31c5Sopenharmony_ci 905e66f31c5Sopenharmony_ci /* Use argv[0] to determine value for uv_exepath(). */ 906e66f31c5Sopenharmony_ci size = sizeof(exepath); 907e66f31c5Sopenharmony_ci if (uv__search_path(argv[0], exepath, &size) == 0) { 908e66f31c5Sopenharmony_ci uv_once(&process_title_mutex_once, init_process_title_mutex_once); 909e66f31c5Sopenharmony_ci uv_mutex_lock(&process_title_mutex); 910e66f31c5Sopenharmony_ci original_exepath = uv__strdup(exepath); 911e66f31c5Sopenharmony_ci uv_mutex_unlock(&process_title_mutex); 912e66f31c5Sopenharmony_ci } 913e66f31c5Sopenharmony_ci 914e66f31c5Sopenharmony_ci /* Calculate how much memory we need for the argv strings. */ 915e66f31c5Sopenharmony_ci size = 0; 916e66f31c5Sopenharmony_ci for (i = 0; i < argc; i++) 917e66f31c5Sopenharmony_ci size += strlen(argv[i]) + 1; 918e66f31c5Sopenharmony_ci 919e66f31c5Sopenharmony_ci /* Add space for the argv pointers. */ 920e66f31c5Sopenharmony_ci size += (argc + 1) * sizeof(char*); 921e66f31c5Sopenharmony_ci 922e66f31c5Sopenharmony_ci new_argv = uv__malloc(size); 923e66f31c5Sopenharmony_ci if (new_argv == NULL) 924e66f31c5Sopenharmony_ci return argv; 925e66f31c5Sopenharmony_ci args_mem = new_argv; 926e66f31c5Sopenharmony_ci 927e66f31c5Sopenharmony_ci /* Copy over the strings and set up the pointer table. */ 928e66f31c5Sopenharmony_ci s = (char*) &new_argv[argc + 1]; 929e66f31c5Sopenharmony_ci for (i = 0; i < argc; i++) { 930e66f31c5Sopenharmony_ci size = strlen(argv[i]) + 1; 931e66f31c5Sopenharmony_ci memcpy(s, argv[i], size); 932e66f31c5Sopenharmony_ci new_argv[i] = s; 933e66f31c5Sopenharmony_ci s += size; 934e66f31c5Sopenharmony_ci } 935e66f31c5Sopenharmony_ci new_argv[i] = NULL; 936e66f31c5Sopenharmony_ci 937e66f31c5Sopenharmony_ci return new_argv; 938e66f31c5Sopenharmony_ci} 939e66f31c5Sopenharmony_ci 940e66f31c5Sopenharmony_ci 941e66f31c5Sopenharmony_ciint uv_set_process_title(const char* title) { 942e66f31c5Sopenharmony_ci char* new_title; 943e66f31c5Sopenharmony_ci 944e66f31c5Sopenharmony_ci /* If uv_setup_args wasn't called or failed, we can't continue. */ 945e66f31c5Sopenharmony_ci if (process_argv == NULL || args_mem == NULL) 946e66f31c5Sopenharmony_ci return UV_ENOBUFS; 947e66f31c5Sopenharmony_ci 948e66f31c5Sopenharmony_ci /* We cannot free this pointer when libuv shuts down, 949e66f31c5Sopenharmony_ci * the process may still be using it. 950e66f31c5Sopenharmony_ci */ 951e66f31c5Sopenharmony_ci new_title = uv__strdup(title); 952e66f31c5Sopenharmony_ci if (new_title == NULL) 953e66f31c5Sopenharmony_ci return UV_ENOMEM; 954e66f31c5Sopenharmony_ci 955e66f31c5Sopenharmony_ci uv_once(&process_title_mutex_once, init_process_title_mutex_once); 956e66f31c5Sopenharmony_ci uv_mutex_lock(&process_title_mutex); 957e66f31c5Sopenharmony_ci 958e66f31c5Sopenharmony_ci /* If this is the first time this is set, 959e66f31c5Sopenharmony_ci * don't free and set argv[1] to NULL. 960e66f31c5Sopenharmony_ci */ 961e66f31c5Sopenharmony_ci if (process_title_ptr != NULL) 962e66f31c5Sopenharmony_ci uv__free(process_title_ptr); 963e66f31c5Sopenharmony_ci 964e66f31c5Sopenharmony_ci process_title_ptr = new_title; 965e66f31c5Sopenharmony_ci 966e66f31c5Sopenharmony_ci process_argv[0] = process_title_ptr; 967e66f31c5Sopenharmony_ci if (process_argc > 1) 968e66f31c5Sopenharmony_ci process_argv[1] = NULL; 969e66f31c5Sopenharmony_ci 970e66f31c5Sopenharmony_ci uv_mutex_unlock(&process_title_mutex); 971e66f31c5Sopenharmony_ci 972e66f31c5Sopenharmony_ci return 0; 973e66f31c5Sopenharmony_ci} 974e66f31c5Sopenharmony_ci 975e66f31c5Sopenharmony_ci 976e66f31c5Sopenharmony_ciint uv_get_process_title(char* buffer, size_t size) { 977e66f31c5Sopenharmony_ci size_t len; 978e66f31c5Sopenharmony_ci if (buffer == NULL || size == 0) 979e66f31c5Sopenharmony_ci return UV_EINVAL; 980e66f31c5Sopenharmony_ci 981e66f31c5Sopenharmony_ci /* If uv_setup_args wasn't called, we can't continue. */ 982e66f31c5Sopenharmony_ci if (process_argv == NULL) 983e66f31c5Sopenharmony_ci return UV_ENOBUFS; 984e66f31c5Sopenharmony_ci 985e66f31c5Sopenharmony_ci uv_once(&process_title_mutex_once, init_process_title_mutex_once); 986e66f31c5Sopenharmony_ci uv_mutex_lock(&process_title_mutex); 987e66f31c5Sopenharmony_ci 988e66f31c5Sopenharmony_ci len = strlen(process_argv[0]); 989e66f31c5Sopenharmony_ci if (size <= len) { 990e66f31c5Sopenharmony_ci uv_mutex_unlock(&process_title_mutex); 991e66f31c5Sopenharmony_ci return UV_ENOBUFS; 992e66f31c5Sopenharmony_ci } 993e66f31c5Sopenharmony_ci 994e66f31c5Sopenharmony_ci memcpy(buffer, process_argv[0], len); 995e66f31c5Sopenharmony_ci buffer[len] = '\0'; 996e66f31c5Sopenharmony_ci 997e66f31c5Sopenharmony_ci uv_mutex_unlock(&process_title_mutex); 998e66f31c5Sopenharmony_ci 999e66f31c5Sopenharmony_ci return 0; 1000e66f31c5Sopenharmony_ci} 1001e66f31c5Sopenharmony_ci 1002e66f31c5Sopenharmony_ci 1003e66f31c5Sopenharmony_civoid uv__process_title_cleanup(void) { 1004e66f31c5Sopenharmony_ci uv__free(args_mem); /* Keep valgrind happy. */ 1005e66f31c5Sopenharmony_ci args_mem = NULL; 1006e66f31c5Sopenharmony_ci} 1007e66f31c5Sopenharmony_ci 1008e66f31c5Sopenharmony_ci 1009e66f31c5Sopenharmony_ciint uv_resident_set_memory(size_t* rss) { 1010e66f31c5Sopenharmony_ci char pp[64]; 1011e66f31c5Sopenharmony_ci psinfo_t psinfo; 1012e66f31c5Sopenharmony_ci int err; 1013e66f31c5Sopenharmony_ci int fd; 1014e66f31c5Sopenharmony_ci 1015e66f31c5Sopenharmony_ci snprintf(pp, sizeof(pp), "/proc/%lu/psinfo", (unsigned long) getpid()); 1016e66f31c5Sopenharmony_ci 1017e66f31c5Sopenharmony_ci fd = open(pp, O_RDONLY); 1018e66f31c5Sopenharmony_ci if (fd == -1) 1019e66f31c5Sopenharmony_ci return UV__ERR(errno); 1020e66f31c5Sopenharmony_ci 1021e66f31c5Sopenharmony_ci /* FIXME(bnoordhuis) Handle EINTR. */ 1022e66f31c5Sopenharmony_ci err = UV_EINVAL; 1023e66f31c5Sopenharmony_ci if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) { 1024e66f31c5Sopenharmony_ci *rss = (size_t)psinfo.pr_rssize * 1024; 1025e66f31c5Sopenharmony_ci err = 0; 1026e66f31c5Sopenharmony_ci } 1027e66f31c5Sopenharmony_ci uv__close(fd); 1028e66f31c5Sopenharmony_ci 1029e66f31c5Sopenharmony_ci return err; 1030e66f31c5Sopenharmony_ci} 1031e66f31c5Sopenharmony_ci 1032e66f31c5Sopenharmony_ci 1033e66f31c5Sopenharmony_ciint uv_uptime(double* uptime) { 1034e66f31c5Sopenharmony_ci struct utmp *utmp_buf; 1035e66f31c5Sopenharmony_ci size_t entries = 0; 1036e66f31c5Sopenharmony_ci time_t boot_time; 1037e66f31c5Sopenharmony_ci 1038e66f31c5Sopenharmony_ci boot_time = 0; 1039e66f31c5Sopenharmony_ci utmpname(UTMP_FILE); 1040e66f31c5Sopenharmony_ci 1041e66f31c5Sopenharmony_ci setutent(); 1042e66f31c5Sopenharmony_ci 1043e66f31c5Sopenharmony_ci while ((utmp_buf = getutent()) != NULL) { 1044e66f31c5Sopenharmony_ci if (utmp_buf->ut_user[0] && utmp_buf->ut_type == USER_PROCESS) 1045e66f31c5Sopenharmony_ci ++entries; 1046e66f31c5Sopenharmony_ci if (utmp_buf->ut_type == BOOT_TIME) 1047e66f31c5Sopenharmony_ci boot_time = utmp_buf->ut_time; 1048e66f31c5Sopenharmony_ci } 1049e66f31c5Sopenharmony_ci 1050e66f31c5Sopenharmony_ci endutent(); 1051e66f31c5Sopenharmony_ci 1052e66f31c5Sopenharmony_ci if (boot_time == 0) 1053e66f31c5Sopenharmony_ci return UV_ENOSYS; 1054e66f31c5Sopenharmony_ci 1055e66f31c5Sopenharmony_ci *uptime = time(NULL) - boot_time; 1056e66f31c5Sopenharmony_ci return 0; 1057e66f31c5Sopenharmony_ci} 1058e66f31c5Sopenharmony_ci 1059e66f31c5Sopenharmony_ci 1060e66f31c5Sopenharmony_ciint uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 1061e66f31c5Sopenharmony_ci uv_cpu_info_t* cpu_info; 1062e66f31c5Sopenharmony_ci perfstat_cpu_total_t ps_total; 1063e66f31c5Sopenharmony_ci perfstat_cpu_t* ps_cpus; 1064e66f31c5Sopenharmony_ci perfstat_id_t cpu_id; 1065e66f31c5Sopenharmony_ci int result, ncpus, idx = 0; 1066e66f31c5Sopenharmony_ci 1067e66f31c5Sopenharmony_ci result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1); 1068e66f31c5Sopenharmony_ci if (result == -1) { 1069e66f31c5Sopenharmony_ci return UV_ENOSYS; 1070e66f31c5Sopenharmony_ci } 1071e66f31c5Sopenharmony_ci 1072e66f31c5Sopenharmony_ci ncpus = result = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0); 1073e66f31c5Sopenharmony_ci if (result == -1) { 1074e66f31c5Sopenharmony_ci return UV_ENOSYS; 1075e66f31c5Sopenharmony_ci } 1076e66f31c5Sopenharmony_ci 1077e66f31c5Sopenharmony_ci ps_cpus = (perfstat_cpu_t*) uv__malloc(ncpus * sizeof(perfstat_cpu_t)); 1078e66f31c5Sopenharmony_ci if (!ps_cpus) { 1079e66f31c5Sopenharmony_ci return UV_ENOMEM; 1080e66f31c5Sopenharmony_ci } 1081e66f31c5Sopenharmony_ci 1082e66f31c5Sopenharmony_ci /* TODO(bnoordhuis) Check uv__strscpy() return value. */ 1083e66f31c5Sopenharmony_ci uv__strscpy(cpu_id.name, FIRST_CPU, sizeof(cpu_id.name)); 1084e66f31c5Sopenharmony_ci result = perfstat_cpu(&cpu_id, ps_cpus, sizeof(perfstat_cpu_t), ncpus); 1085e66f31c5Sopenharmony_ci if (result == -1) { 1086e66f31c5Sopenharmony_ci uv__free(ps_cpus); 1087e66f31c5Sopenharmony_ci return UV_ENOSYS; 1088e66f31c5Sopenharmony_ci } 1089e66f31c5Sopenharmony_ci 1090e66f31c5Sopenharmony_ci *cpu_infos = (uv_cpu_info_t*) uv__malloc(ncpus * sizeof(uv_cpu_info_t)); 1091e66f31c5Sopenharmony_ci if (!*cpu_infos) { 1092e66f31c5Sopenharmony_ci uv__free(ps_cpus); 1093e66f31c5Sopenharmony_ci return UV_ENOMEM; 1094e66f31c5Sopenharmony_ci } 1095e66f31c5Sopenharmony_ci 1096e66f31c5Sopenharmony_ci *count = ncpus; 1097e66f31c5Sopenharmony_ci 1098e66f31c5Sopenharmony_ci cpu_info = *cpu_infos; 1099e66f31c5Sopenharmony_ci while (idx < ncpus) { 1100e66f31c5Sopenharmony_ci cpu_info->speed = (int)(ps_total.processorHZ / 1000000); 1101e66f31c5Sopenharmony_ci cpu_info->model = uv__strdup(ps_total.description); 1102e66f31c5Sopenharmony_ci cpu_info->cpu_times.user = ps_cpus[idx].user; 1103e66f31c5Sopenharmony_ci cpu_info->cpu_times.sys = ps_cpus[idx].sys; 1104e66f31c5Sopenharmony_ci cpu_info->cpu_times.idle = ps_cpus[idx].idle; 1105e66f31c5Sopenharmony_ci cpu_info->cpu_times.irq = ps_cpus[idx].wait; 1106e66f31c5Sopenharmony_ci cpu_info->cpu_times.nice = 0; 1107e66f31c5Sopenharmony_ci cpu_info++; 1108e66f31c5Sopenharmony_ci idx++; 1109e66f31c5Sopenharmony_ci } 1110e66f31c5Sopenharmony_ci 1111e66f31c5Sopenharmony_ci uv__free(ps_cpus); 1112e66f31c5Sopenharmony_ci return 0; 1113e66f31c5Sopenharmony_ci} 1114e66f31c5Sopenharmony_ci 1115e66f31c5Sopenharmony_ci 1116e66f31c5Sopenharmony_ciint uv_interface_addresses(uv_interface_address_t** addresses, int* count) { 1117e66f31c5Sopenharmony_ci uv_interface_address_t* address; 1118e66f31c5Sopenharmony_ci int sockfd, sock6fd, inet6, i, r, size = 1; 1119e66f31c5Sopenharmony_ci struct ifconf ifc; 1120e66f31c5Sopenharmony_ci struct ifreq *ifr, *p, flg; 1121e66f31c5Sopenharmony_ci struct in6_ifreq if6; 1122e66f31c5Sopenharmony_ci struct sockaddr_dl* sa_addr; 1123e66f31c5Sopenharmony_ci 1124e66f31c5Sopenharmony_ci ifc.ifc_req = NULL; 1125e66f31c5Sopenharmony_ci sock6fd = -1; 1126e66f31c5Sopenharmony_ci r = 0; 1127e66f31c5Sopenharmony_ci *count = 0; 1128e66f31c5Sopenharmony_ci *addresses = NULL; 1129e66f31c5Sopenharmony_ci 1130e66f31c5Sopenharmony_ci if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) { 1131e66f31c5Sopenharmony_ci r = UV__ERR(errno); 1132e66f31c5Sopenharmony_ci goto cleanup; 1133e66f31c5Sopenharmony_ci } 1134e66f31c5Sopenharmony_ci 1135e66f31c5Sopenharmony_ci if (0 > (sock6fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP))) { 1136e66f31c5Sopenharmony_ci r = UV__ERR(errno); 1137e66f31c5Sopenharmony_ci goto cleanup; 1138e66f31c5Sopenharmony_ci } 1139e66f31c5Sopenharmony_ci 1140e66f31c5Sopenharmony_ci if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) { 1141e66f31c5Sopenharmony_ci r = UV__ERR(errno); 1142e66f31c5Sopenharmony_ci goto cleanup; 1143e66f31c5Sopenharmony_ci } 1144e66f31c5Sopenharmony_ci 1145e66f31c5Sopenharmony_ci ifc.ifc_req = (struct ifreq*)uv__malloc(size); 1146e66f31c5Sopenharmony_ci if (ifc.ifc_req == NULL) { 1147e66f31c5Sopenharmony_ci r = UV_ENOMEM; 1148e66f31c5Sopenharmony_ci goto cleanup; 1149e66f31c5Sopenharmony_ci } 1150e66f31c5Sopenharmony_ci ifc.ifc_len = size; 1151e66f31c5Sopenharmony_ci if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) { 1152e66f31c5Sopenharmony_ci r = UV__ERR(errno); 1153e66f31c5Sopenharmony_ci goto cleanup; 1154e66f31c5Sopenharmony_ci } 1155e66f31c5Sopenharmony_ci 1156e66f31c5Sopenharmony_ci#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p)) 1157e66f31c5Sopenharmony_ci 1158e66f31c5Sopenharmony_ci /* Count all up and running ipv4/ipv6 addresses */ 1159e66f31c5Sopenharmony_ci ifr = ifc.ifc_req; 1160e66f31c5Sopenharmony_ci while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { 1161e66f31c5Sopenharmony_ci p = ifr; 1162e66f31c5Sopenharmony_ci ifr = (struct ifreq*) 1163e66f31c5Sopenharmony_ci ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); 1164e66f31c5Sopenharmony_ci 1165e66f31c5Sopenharmony_ci if (!(p->ifr_addr.sa_family == AF_INET6 || 1166e66f31c5Sopenharmony_ci p->ifr_addr.sa_family == AF_INET)) 1167e66f31c5Sopenharmony_ci continue; 1168e66f31c5Sopenharmony_ci 1169e66f31c5Sopenharmony_ci memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); 1170e66f31c5Sopenharmony_ci if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { 1171e66f31c5Sopenharmony_ci r = UV__ERR(errno); 1172e66f31c5Sopenharmony_ci goto cleanup; 1173e66f31c5Sopenharmony_ci } 1174e66f31c5Sopenharmony_ci 1175e66f31c5Sopenharmony_ci if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) 1176e66f31c5Sopenharmony_ci continue; 1177e66f31c5Sopenharmony_ci 1178e66f31c5Sopenharmony_ci (*count)++; 1179e66f31c5Sopenharmony_ci } 1180e66f31c5Sopenharmony_ci 1181e66f31c5Sopenharmony_ci if (*count == 0) 1182e66f31c5Sopenharmony_ci goto cleanup; 1183e66f31c5Sopenharmony_ci 1184e66f31c5Sopenharmony_ci /* Alloc the return interface structs */ 1185e66f31c5Sopenharmony_ci *addresses = uv__calloc(*count, sizeof(**addresses)); 1186e66f31c5Sopenharmony_ci if (!(*addresses)) { 1187e66f31c5Sopenharmony_ci r = UV_ENOMEM; 1188e66f31c5Sopenharmony_ci goto cleanup; 1189e66f31c5Sopenharmony_ci } 1190e66f31c5Sopenharmony_ci address = *addresses; 1191e66f31c5Sopenharmony_ci 1192e66f31c5Sopenharmony_ci ifr = ifc.ifc_req; 1193e66f31c5Sopenharmony_ci while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { 1194e66f31c5Sopenharmony_ci p = ifr; 1195e66f31c5Sopenharmony_ci ifr = (struct ifreq*) 1196e66f31c5Sopenharmony_ci ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); 1197e66f31c5Sopenharmony_ci 1198e66f31c5Sopenharmony_ci if (!(p->ifr_addr.sa_family == AF_INET6 || 1199e66f31c5Sopenharmony_ci p->ifr_addr.sa_family == AF_INET)) 1200e66f31c5Sopenharmony_ci continue; 1201e66f31c5Sopenharmony_ci 1202e66f31c5Sopenharmony_ci inet6 = (p->ifr_addr.sa_family == AF_INET6); 1203e66f31c5Sopenharmony_ci 1204e66f31c5Sopenharmony_ci memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); 1205e66f31c5Sopenharmony_ci if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) 1206e66f31c5Sopenharmony_ci goto syserror; 1207e66f31c5Sopenharmony_ci 1208e66f31c5Sopenharmony_ci if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) 1209e66f31c5Sopenharmony_ci continue; 1210e66f31c5Sopenharmony_ci 1211e66f31c5Sopenharmony_ci /* All conditions above must match count loop */ 1212e66f31c5Sopenharmony_ci 1213e66f31c5Sopenharmony_ci address->name = uv__strdup(p->ifr_name); 1214e66f31c5Sopenharmony_ci 1215e66f31c5Sopenharmony_ci if (inet6) 1216e66f31c5Sopenharmony_ci address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr); 1217e66f31c5Sopenharmony_ci else 1218e66f31c5Sopenharmony_ci address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr); 1219e66f31c5Sopenharmony_ci 1220e66f31c5Sopenharmony_ci if (inet6) { 1221e66f31c5Sopenharmony_ci memset(&if6, 0, sizeof(if6)); 1222e66f31c5Sopenharmony_ci r = uv__strscpy(if6.ifr_name, p->ifr_name, sizeof(if6.ifr_name)); 1223e66f31c5Sopenharmony_ci if (r == UV_E2BIG) 1224e66f31c5Sopenharmony_ci goto cleanup; 1225e66f31c5Sopenharmony_ci r = 0; 1226e66f31c5Sopenharmony_ci memcpy(&if6.ifr_Addr, &p->ifr_addr, sizeof(if6.ifr_Addr)); 1227e66f31c5Sopenharmony_ci if (ioctl(sock6fd, SIOCGIFNETMASK6, &if6) == -1) 1228e66f31c5Sopenharmony_ci goto syserror; 1229e66f31c5Sopenharmony_ci address->netmask.netmask6 = *((struct sockaddr_in6*) &if6.ifr_Addr); 1230e66f31c5Sopenharmony_ci /* Explicitly set family as the ioctl call appears to return it as 0. */ 1231e66f31c5Sopenharmony_ci address->netmask.netmask6.sin6_family = AF_INET6; 1232e66f31c5Sopenharmony_ci } else { 1233e66f31c5Sopenharmony_ci if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) 1234e66f31c5Sopenharmony_ci goto syserror; 1235e66f31c5Sopenharmony_ci address->netmask.netmask4 = *((struct sockaddr_in*) &p->ifr_addr); 1236e66f31c5Sopenharmony_ci /* Explicitly set family as the ioctl call appears to return it as 0. */ 1237e66f31c5Sopenharmony_ci address->netmask.netmask4.sin_family = AF_INET; 1238e66f31c5Sopenharmony_ci } 1239e66f31c5Sopenharmony_ci 1240e66f31c5Sopenharmony_ci address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0; 1241e66f31c5Sopenharmony_ci 1242e66f31c5Sopenharmony_ci address++; 1243e66f31c5Sopenharmony_ci } 1244e66f31c5Sopenharmony_ci 1245e66f31c5Sopenharmony_ci /* Fill in physical addresses. */ 1246e66f31c5Sopenharmony_ci ifr = ifc.ifc_req; 1247e66f31c5Sopenharmony_ci while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { 1248e66f31c5Sopenharmony_ci p = ifr; 1249e66f31c5Sopenharmony_ci ifr = (struct ifreq*) 1250e66f31c5Sopenharmony_ci ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); 1251e66f31c5Sopenharmony_ci 1252e66f31c5Sopenharmony_ci if (p->ifr_addr.sa_family != AF_LINK) 1253e66f31c5Sopenharmony_ci continue; 1254e66f31c5Sopenharmony_ci 1255e66f31c5Sopenharmony_ci address = *addresses; 1256e66f31c5Sopenharmony_ci for (i = 0; i < *count; i++) { 1257e66f31c5Sopenharmony_ci if (strcmp(address->name, p->ifr_name) == 0) { 1258e66f31c5Sopenharmony_ci sa_addr = (struct sockaddr_dl*) &p->ifr_addr; 1259e66f31c5Sopenharmony_ci memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); 1260e66f31c5Sopenharmony_ci } 1261e66f31c5Sopenharmony_ci address++; 1262e66f31c5Sopenharmony_ci } 1263e66f31c5Sopenharmony_ci } 1264e66f31c5Sopenharmony_ci 1265e66f31c5Sopenharmony_ci#undef ADDR_SIZE 1266e66f31c5Sopenharmony_ci goto cleanup; 1267e66f31c5Sopenharmony_ci 1268e66f31c5Sopenharmony_cisyserror: 1269e66f31c5Sopenharmony_ci uv_free_interface_addresses(*addresses, *count); 1270e66f31c5Sopenharmony_ci *addresses = NULL; 1271e66f31c5Sopenharmony_ci *count = 0; 1272e66f31c5Sopenharmony_ci r = UV_ENOSYS; 1273e66f31c5Sopenharmony_ci 1274e66f31c5Sopenharmony_cicleanup: 1275e66f31c5Sopenharmony_ci if (sockfd != -1) 1276e66f31c5Sopenharmony_ci uv__close(sockfd); 1277e66f31c5Sopenharmony_ci if (sock6fd != -1) 1278e66f31c5Sopenharmony_ci uv__close(sock6fd); 1279e66f31c5Sopenharmony_ci uv__free(ifc.ifc_req); 1280e66f31c5Sopenharmony_ci return r; 1281e66f31c5Sopenharmony_ci} 1282e66f31c5Sopenharmony_ci 1283e66f31c5Sopenharmony_ci 1284e66f31c5Sopenharmony_civoid uv_free_interface_addresses(uv_interface_address_t* addresses, 1285e66f31c5Sopenharmony_ci int count) { 1286e66f31c5Sopenharmony_ci int i; 1287e66f31c5Sopenharmony_ci 1288e66f31c5Sopenharmony_ci for (i = 0; i < count; ++i) { 1289e66f31c5Sopenharmony_ci uv__free(addresses[i].name); 1290e66f31c5Sopenharmony_ci } 1291e66f31c5Sopenharmony_ci 1292e66f31c5Sopenharmony_ci uv__free(addresses); 1293e66f31c5Sopenharmony_ci} 1294e66f31c5Sopenharmony_ci 1295e66f31c5Sopenharmony_ci 1296e66f31c5Sopenharmony_civoid uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { 1297e66f31c5Sopenharmony_ci struct pollfd* events; 1298e66f31c5Sopenharmony_ci uintptr_t i; 1299e66f31c5Sopenharmony_ci uintptr_t nfds; 1300e66f31c5Sopenharmony_ci struct poll_ctl pc; 1301e66f31c5Sopenharmony_ci 1302e66f31c5Sopenharmony_ci assert(loop->watchers != NULL); 1303e66f31c5Sopenharmony_ci assert(fd >= 0); 1304e66f31c5Sopenharmony_ci 1305e66f31c5Sopenharmony_ci events = (struct pollfd*) loop->watchers[loop->nwatchers]; 1306e66f31c5Sopenharmony_ci nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; 1307e66f31c5Sopenharmony_ci 1308e66f31c5Sopenharmony_ci if (events != NULL) 1309e66f31c5Sopenharmony_ci /* Invalidate events with same file descriptor */ 1310e66f31c5Sopenharmony_ci for (i = 0; i < nfds; i++) 1311e66f31c5Sopenharmony_ci if ((int) events[i].fd == fd) 1312e66f31c5Sopenharmony_ci events[i].fd = -1; 1313e66f31c5Sopenharmony_ci 1314e66f31c5Sopenharmony_ci /* Remove the file descriptor from the poll set */ 1315e66f31c5Sopenharmony_ci pc.events = 0; 1316e66f31c5Sopenharmony_ci pc.cmd = PS_DELETE; 1317e66f31c5Sopenharmony_ci pc.fd = fd; 1318e66f31c5Sopenharmony_ci if(loop->backend_fd >= 0) 1319e66f31c5Sopenharmony_ci pollset_ctl(loop->backend_fd, &pc, 1); 1320e66f31c5Sopenharmony_ci} 1321