1e66f31c5Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2e66f31c5Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 3e66f31c5Sopenharmony_ci * of this software and associated documentation files (the "Software"), to 4e66f31c5Sopenharmony_ci * deal in the Software without restriction, including without limitation the 5e66f31c5Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 6e66f31c5Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 7e66f31c5Sopenharmony_ci * furnished to do so, subject to the following conditions: 8e66f31c5Sopenharmony_ci * 9e66f31c5Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 10e66f31c5Sopenharmony_ci * all copies or substantial portions of the Software. 11e66f31c5Sopenharmony_ci * 12e66f31c5Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13e66f31c5Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14e66f31c5Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15e66f31c5Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16e66f31c5Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17e66f31c5Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 18e66f31c5Sopenharmony_ci * IN THE SOFTWARE. 19e66f31c5Sopenharmony_ci */ 20e66f31c5Sopenharmony_ci 21e66f31c5Sopenharmony_ci#include "uv.h" 22e66f31c5Sopenharmony_ci#include "internal.h" 23e66f31c5Sopenharmony_ci 24e66f31c5Sopenharmony_ci#include <stdio.h> 25e66f31c5Sopenharmony_ci#include <stdint.h> 26e66f31c5Sopenharmony_ci#include <stdlib.h> 27e66f31c5Sopenharmony_ci#include <string.h> 28e66f31c5Sopenharmony_ci#include <assert.h> 29e66f31c5Sopenharmony_ci#include <errno.h> 30e66f31c5Sopenharmony_ci 31e66f31c5Sopenharmony_ci#ifndef SUNOS_NO_IFADDRS 32e66f31c5Sopenharmony_ci# include <ifaddrs.h> 33e66f31c5Sopenharmony_ci#endif 34e66f31c5Sopenharmony_ci#include <net/if.h> 35e66f31c5Sopenharmony_ci#include <net/if_dl.h> 36e66f31c5Sopenharmony_ci#include <net/if_arp.h> 37e66f31c5Sopenharmony_ci#include <sys/sockio.h> 38e66f31c5Sopenharmony_ci 39e66f31c5Sopenharmony_ci#include <sys/loadavg.h> 40e66f31c5Sopenharmony_ci#include <sys/time.h> 41e66f31c5Sopenharmony_ci#include <unistd.h> 42e66f31c5Sopenharmony_ci#include <kstat.h> 43e66f31c5Sopenharmony_ci#include <fcntl.h> 44e66f31c5Sopenharmony_ci 45e66f31c5Sopenharmony_ci#include <sys/port.h> 46e66f31c5Sopenharmony_ci#include <port.h> 47e66f31c5Sopenharmony_ci 48e66f31c5Sopenharmony_ci#define PORT_FIRED 0x69 49e66f31c5Sopenharmony_ci#define PORT_UNUSED 0x0 50e66f31c5Sopenharmony_ci#define PORT_LOADED 0x99 51e66f31c5Sopenharmony_ci#define PORT_DELETED -1 52e66f31c5Sopenharmony_ci 53e66f31c5Sopenharmony_ci#if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64) 54e66f31c5Sopenharmony_ci#define PROCFS_FILE_OFFSET_BITS_HACK 1 55e66f31c5Sopenharmony_ci#undef _FILE_OFFSET_BITS 56e66f31c5Sopenharmony_ci#else 57e66f31c5Sopenharmony_ci#define PROCFS_FILE_OFFSET_BITS_HACK 0 58e66f31c5Sopenharmony_ci#endif 59e66f31c5Sopenharmony_ci 60e66f31c5Sopenharmony_ci#include <procfs.h> 61e66f31c5Sopenharmony_ci 62e66f31c5Sopenharmony_ci#if (PROCFS_FILE_OFFSET_BITS_HACK - 0 == 1) 63e66f31c5Sopenharmony_ci#define _FILE_OFFSET_BITS 64 64e66f31c5Sopenharmony_ci#endif 65e66f31c5Sopenharmony_ci 66e66f31c5Sopenharmony_ci 67e66f31c5Sopenharmony_ciint uv__platform_loop_init(uv_loop_t* loop) { 68e66f31c5Sopenharmony_ci int err; 69e66f31c5Sopenharmony_ci int fd; 70e66f31c5Sopenharmony_ci 71e66f31c5Sopenharmony_ci loop->fs_fd = -1; 72e66f31c5Sopenharmony_ci loop->backend_fd = -1; 73e66f31c5Sopenharmony_ci 74e66f31c5Sopenharmony_ci fd = port_create(); 75e66f31c5Sopenharmony_ci if (fd == -1) 76e66f31c5Sopenharmony_ci return UV__ERR(errno); 77e66f31c5Sopenharmony_ci 78e66f31c5Sopenharmony_ci err = uv__cloexec(fd, 1); 79e66f31c5Sopenharmony_ci if (err) { 80e66f31c5Sopenharmony_ci uv__close(fd); 81e66f31c5Sopenharmony_ci return err; 82e66f31c5Sopenharmony_ci } 83e66f31c5Sopenharmony_ci loop->backend_fd = fd; 84e66f31c5Sopenharmony_ci 85e66f31c5Sopenharmony_ci return 0; 86e66f31c5Sopenharmony_ci} 87e66f31c5Sopenharmony_ci 88e66f31c5Sopenharmony_ci 89e66f31c5Sopenharmony_civoid uv__platform_loop_delete(uv_loop_t* loop) { 90e66f31c5Sopenharmony_ci if (loop->fs_fd != -1) { 91e66f31c5Sopenharmony_ci uv__close(loop->fs_fd); 92e66f31c5Sopenharmony_ci loop->fs_fd = -1; 93e66f31c5Sopenharmony_ci } 94e66f31c5Sopenharmony_ci 95e66f31c5Sopenharmony_ci if (loop->backend_fd != -1) { 96e66f31c5Sopenharmony_ci uv__close(loop->backend_fd); 97e66f31c5Sopenharmony_ci loop->backend_fd = -1; 98e66f31c5Sopenharmony_ci } 99e66f31c5Sopenharmony_ci} 100e66f31c5Sopenharmony_ci 101e66f31c5Sopenharmony_ci 102e66f31c5Sopenharmony_ciint uv__io_fork(uv_loop_t* loop) { 103e66f31c5Sopenharmony_ci#if defined(PORT_SOURCE_FILE) 104e66f31c5Sopenharmony_ci if (loop->fs_fd != -1) { 105e66f31c5Sopenharmony_ci /* stop the watcher before we blow away its fileno */ 106e66f31c5Sopenharmony_ci uv__io_stop(loop, &loop->fs_event_watcher, POLLIN); 107e66f31c5Sopenharmony_ci } 108e66f31c5Sopenharmony_ci#endif 109e66f31c5Sopenharmony_ci uv__platform_loop_delete(loop); 110e66f31c5Sopenharmony_ci return uv__platform_loop_init(loop); 111e66f31c5Sopenharmony_ci} 112e66f31c5Sopenharmony_ci 113e66f31c5Sopenharmony_ci 114e66f31c5Sopenharmony_civoid uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { 115e66f31c5Sopenharmony_ci struct port_event* events; 116e66f31c5Sopenharmony_ci uintptr_t i; 117e66f31c5Sopenharmony_ci uintptr_t nfds; 118e66f31c5Sopenharmony_ci 119e66f31c5Sopenharmony_ci assert(loop->watchers != NULL); 120e66f31c5Sopenharmony_ci assert(fd >= 0); 121e66f31c5Sopenharmony_ci 122e66f31c5Sopenharmony_ci events = (struct port_event*) loop->watchers[loop->nwatchers]; 123e66f31c5Sopenharmony_ci nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; 124e66f31c5Sopenharmony_ci if (events == NULL) 125e66f31c5Sopenharmony_ci return; 126e66f31c5Sopenharmony_ci 127e66f31c5Sopenharmony_ci /* Invalidate events with same file descriptor */ 128e66f31c5Sopenharmony_ci for (i = 0; i < nfds; i++) 129e66f31c5Sopenharmony_ci if ((int) events[i].portev_object == fd) 130e66f31c5Sopenharmony_ci events[i].portev_object = -1; 131e66f31c5Sopenharmony_ci} 132e66f31c5Sopenharmony_ci 133e66f31c5Sopenharmony_ci 134e66f31c5Sopenharmony_ciint uv__io_check_fd(uv_loop_t* loop, int fd) { 135e66f31c5Sopenharmony_ci if (port_associate(loop->backend_fd, PORT_SOURCE_FD, fd, POLLIN, 0)) 136e66f31c5Sopenharmony_ci return UV__ERR(errno); 137e66f31c5Sopenharmony_ci 138e66f31c5Sopenharmony_ci if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd)) { 139e66f31c5Sopenharmony_ci perror("(libuv) port_dissociate()"); 140e66f31c5Sopenharmony_ci abort(); 141e66f31c5Sopenharmony_ci } 142e66f31c5Sopenharmony_ci 143e66f31c5Sopenharmony_ci return 0; 144e66f31c5Sopenharmony_ci} 145e66f31c5Sopenharmony_ci 146e66f31c5Sopenharmony_ci 147e66f31c5Sopenharmony_civoid uv__io_poll(uv_loop_t* loop, int timeout) { 148e66f31c5Sopenharmony_ci struct port_event events[1024]; 149e66f31c5Sopenharmony_ci struct port_event* pe; 150e66f31c5Sopenharmony_ci struct timespec spec; 151e66f31c5Sopenharmony_ci struct uv__queue* q; 152e66f31c5Sopenharmony_ci uv__io_t* w; 153e66f31c5Sopenharmony_ci sigset_t* pset; 154e66f31c5Sopenharmony_ci sigset_t set; 155e66f31c5Sopenharmony_ci uint64_t base; 156e66f31c5Sopenharmony_ci uint64_t diff; 157e66f31c5Sopenharmony_ci unsigned int nfds; 158e66f31c5Sopenharmony_ci unsigned int i; 159e66f31c5Sopenharmony_ci int saved_errno; 160e66f31c5Sopenharmony_ci int have_signals; 161e66f31c5Sopenharmony_ci int nevents; 162e66f31c5Sopenharmony_ci int count; 163e66f31c5Sopenharmony_ci int err; 164e66f31c5Sopenharmony_ci int fd; 165e66f31c5Sopenharmony_ci int user_timeout; 166e66f31c5Sopenharmony_ci int reset_timeout; 167e66f31c5Sopenharmony_ci 168e66f31c5Sopenharmony_ci if (loop->nfds == 0) { 169e66f31c5Sopenharmony_ci assert(uv__queue_empty(&loop->watcher_queue)); 170e66f31c5Sopenharmony_ci return; 171e66f31c5Sopenharmony_ci } 172e66f31c5Sopenharmony_ci 173e66f31c5Sopenharmony_ci while (!uv__queue_empty(&loop->watcher_queue)) { 174e66f31c5Sopenharmony_ci q = uv__queue_head(&loop->watcher_queue); 175e66f31c5Sopenharmony_ci uv__queue_remove(q); 176e66f31c5Sopenharmony_ci uv__queue_init(q); 177e66f31c5Sopenharmony_ci 178e66f31c5Sopenharmony_ci w = uv__queue_data(q, uv__io_t, watcher_queue); 179e66f31c5Sopenharmony_ci assert(w->pevents != 0); 180e66f31c5Sopenharmony_ci 181e66f31c5Sopenharmony_ci if (port_associate(loop->backend_fd, 182e66f31c5Sopenharmony_ci PORT_SOURCE_FD, 183e66f31c5Sopenharmony_ci w->fd, 184e66f31c5Sopenharmony_ci w->pevents, 185e66f31c5Sopenharmony_ci 0)) { 186e66f31c5Sopenharmony_ci perror("(libuv) port_associate()"); 187e66f31c5Sopenharmony_ci abort(); 188e66f31c5Sopenharmony_ci } 189e66f31c5Sopenharmony_ci 190e66f31c5Sopenharmony_ci w->events = w->pevents; 191e66f31c5Sopenharmony_ci } 192e66f31c5Sopenharmony_ci 193e66f31c5Sopenharmony_ci pset = NULL; 194e66f31c5Sopenharmony_ci if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { 195e66f31c5Sopenharmony_ci pset = &set; 196e66f31c5Sopenharmony_ci sigemptyset(pset); 197e66f31c5Sopenharmony_ci sigaddset(pset, SIGPROF); 198e66f31c5Sopenharmony_ci } 199e66f31c5Sopenharmony_ci 200e66f31c5Sopenharmony_ci assert(timeout >= -1); 201e66f31c5Sopenharmony_ci base = loop->time; 202e66f31c5Sopenharmony_ci count = 48; /* Benchmarks suggest this gives the best throughput. */ 203e66f31c5Sopenharmony_ci 204e66f31c5Sopenharmony_ci if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) { 205e66f31c5Sopenharmony_ci reset_timeout = 1; 206e66f31c5Sopenharmony_ci user_timeout = timeout; 207e66f31c5Sopenharmony_ci timeout = 0; 208e66f31c5Sopenharmony_ci } else { 209e66f31c5Sopenharmony_ci reset_timeout = 0; 210e66f31c5Sopenharmony_ci } 211e66f31c5Sopenharmony_ci 212e66f31c5Sopenharmony_ci for (;;) { 213e66f31c5Sopenharmony_ci /* Only need to set the provider_entry_time if timeout != 0. The function 214e66f31c5Sopenharmony_ci * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME. 215e66f31c5Sopenharmony_ci */ 216e66f31c5Sopenharmony_ci if (timeout != 0) 217e66f31c5Sopenharmony_ci uv__metrics_set_provider_entry_time(loop); 218e66f31c5Sopenharmony_ci 219e66f31c5Sopenharmony_ci if (timeout != -1) { 220e66f31c5Sopenharmony_ci spec.tv_sec = timeout / 1000; 221e66f31c5Sopenharmony_ci spec.tv_nsec = (timeout % 1000) * 1000000; 222e66f31c5Sopenharmony_ci } 223e66f31c5Sopenharmony_ci 224e66f31c5Sopenharmony_ci /* Work around a kernel bug where nfds is not updated. */ 225e66f31c5Sopenharmony_ci events[0].portev_source = 0; 226e66f31c5Sopenharmony_ci 227e66f31c5Sopenharmony_ci nfds = 1; 228e66f31c5Sopenharmony_ci saved_errno = 0; 229e66f31c5Sopenharmony_ci 230e66f31c5Sopenharmony_ci if (pset != NULL) 231e66f31c5Sopenharmony_ci pthread_sigmask(SIG_BLOCK, pset, NULL); 232e66f31c5Sopenharmony_ci 233e66f31c5Sopenharmony_ci err = port_getn(loop->backend_fd, 234e66f31c5Sopenharmony_ci events, 235e66f31c5Sopenharmony_ci ARRAY_SIZE(events), 236e66f31c5Sopenharmony_ci &nfds, 237e66f31c5Sopenharmony_ci timeout == -1 ? NULL : &spec); 238e66f31c5Sopenharmony_ci 239e66f31c5Sopenharmony_ci if (pset != NULL) 240e66f31c5Sopenharmony_ci pthread_sigmask(SIG_UNBLOCK, pset, NULL); 241e66f31c5Sopenharmony_ci 242e66f31c5Sopenharmony_ci if (err) { 243e66f31c5Sopenharmony_ci /* Work around another kernel bug: port_getn() may return events even 244e66f31c5Sopenharmony_ci * on error. 245e66f31c5Sopenharmony_ci */ 246e66f31c5Sopenharmony_ci if (errno == EINTR || errno == ETIME) { 247e66f31c5Sopenharmony_ci saved_errno = errno; 248e66f31c5Sopenharmony_ci } else { 249e66f31c5Sopenharmony_ci perror("(libuv) port_getn()"); 250e66f31c5Sopenharmony_ci abort(); 251e66f31c5Sopenharmony_ci } 252e66f31c5Sopenharmony_ci } 253e66f31c5Sopenharmony_ci 254e66f31c5Sopenharmony_ci /* Update loop->time unconditionally. It's tempting to skip the update when 255e66f31c5Sopenharmony_ci * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the 256e66f31c5Sopenharmony_ci * operating system didn't reschedule our process while in the syscall. 257e66f31c5Sopenharmony_ci */ 258e66f31c5Sopenharmony_ci SAVE_ERRNO(uv__update_time(loop)); 259e66f31c5Sopenharmony_ci 260e66f31c5Sopenharmony_ci if (events[0].portev_source == 0) { 261e66f31c5Sopenharmony_ci if (reset_timeout != 0) { 262e66f31c5Sopenharmony_ci timeout = user_timeout; 263e66f31c5Sopenharmony_ci reset_timeout = 0; 264e66f31c5Sopenharmony_ci } 265e66f31c5Sopenharmony_ci 266e66f31c5Sopenharmony_ci if (timeout == 0) 267e66f31c5Sopenharmony_ci return; 268e66f31c5Sopenharmony_ci 269e66f31c5Sopenharmony_ci if (timeout == -1) 270e66f31c5Sopenharmony_ci continue; 271e66f31c5Sopenharmony_ci 272e66f31c5Sopenharmony_ci goto update_timeout; 273e66f31c5Sopenharmony_ci } 274e66f31c5Sopenharmony_ci 275e66f31c5Sopenharmony_ci if (nfds == 0) { 276e66f31c5Sopenharmony_ci assert(timeout != -1); 277e66f31c5Sopenharmony_ci return; 278e66f31c5Sopenharmony_ci } 279e66f31c5Sopenharmony_ci 280e66f31c5Sopenharmony_ci have_signals = 0; 281e66f31c5Sopenharmony_ci nevents = 0; 282e66f31c5Sopenharmony_ci 283e66f31c5Sopenharmony_ci assert(loop->watchers != NULL); 284e66f31c5Sopenharmony_ci loop->watchers[loop->nwatchers] = (void*) events; 285e66f31c5Sopenharmony_ci loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; 286e66f31c5Sopenharmony_ci for (i = 0; i < nfds; i++) { 287e66f31c5Sopenharmony_ci pe = events + i; 288e66f31c5Sopenharmony_ci fd = pe->portev_object; 289e66f31c5Sopenharmony_ci 290e66f31c5Sopenharmony_ci /* Skip invalidated events, see uv__platform_invalidate_fd */ 291e66f31c5Sopenharmony_ci if (fd == -1) 292e66f31c5Sopenharmony_ci continue; 293e66f31c5Sopenharmony_ci 294e66f31c5Sopenharmony_ci assert(fd >= 0); 295e66f31c5Sopenharmony_ci assert((unsigned) fd < loop->nwatchers); 296e66f31c5Sopenharmony_ci 297e66f31c5Sopenharmony_ci w = loop->watchers[fd]; 298e66f31c5Sopenharmony_ci 299e66f31c5Sopenharmony_ci /* File descriptor that we've stopped watching, ignore. */ 300e66f31c5Sopenharmony_ci if (w == NULL) 301e66f31c5Sopenharmony_ci continue; 302e66f31c5Sopenharmony_ci 303e66f31c5Sopenharmony_ci /* Run signal watchers last. This also affects child process watchers 304e66f31c5Sopenharmony_ci * because those are implemented in terms of signal watchers. 305e66f31c5Sopenharmony_ci */ 306e66f31c5Sopenharmony_ci if (w == &loop->signal_io_watcher) { 307e66f31c5Sopenharmony_ci have_signals = 1; 308e66f31c5Sopenharmony_ci } else { 309e66f31c5Sopenharmony_ci uv__metrics_update_idle_time(loop); 310e66f31c5Sopenharmony_ci w->cb(loop, w, pe->portev_events); 311e66f31c5Sopenharmony_ci } 312e66f31c5Sopenharmony_ci 313e66f31c5Sopenharmony_ci nevents++; 314e66f31c5Sopenharmony_ci 315e66f31c5Sopenharmony_ci if (w != loop->watchers[fd]) 316e66f31c5Sopenharmony_ci continue; /* Disabled by callback. */ 317e66f31c5Sopenharmony_ci 318e66f31c5Sopenharmony_ci /* Events Ports operates in oneshot mode, rearm timer on next run. */ 319e66f31c5Sopenharmony_ci if (w->pevents != 0 && uv__queue_empty(&w->watcher_queue)) 320e66f31c5Sopenharmony_ci uv__queue_insert_tail(&loop->watcher_queue, &w->watcher_queue); 321e66f31c5Sopenharmony_ci } 322e66f31c5Sopenharmony_ci 323e66f31c5Sopenharmony_ci uv__metrics_inc_events(loop, nevents); 324e66f31c5Sopenharmony_ci if (reset_timeout != 0) { 325e66f31c5Sopenharmony_ci timeout = user_timeout; 326e66f31c5Sopenharmony_ci reset_timeout = 0; 327e66f31c5Sopenharmony_ci uv__metrics_inc_events_waiting(loop, nevents); 328e66f31c5Sopenharmony_ci } 329e66f31c5Sopenharmony_ci 330e66f31c5Sopenharmony_ci if (have_signals != 0) { 331e66f31c5Sopenharmony_ci uv__metrics_update_idle_time(loop); 332e66f31c5Sopenharmony_ci loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); 333e66f31c5Sopenharmony_ci } 334e66f31c5Sopenharmony_ci 335e66f31c5Sopenharmony_ci loop->watchers[loop->nwatchers] = NULL; 336e66f31c5Sopenharmony_ci loop->watchers[loop->nwatchers + 1] = NULL; 337e66f31c5Sopenharmony_ci 338e66f31c5Sopenharmony_ci if (have_signals != 0) 339e66f31c5Sopenharmony_ci return; /* Event loop should cycle now so don't poll again. */ 340e66f31c5Sopenharmony_ci 341e66f31c5Sopenharmony_ci if (nevents != 0) { 342e66f31c5Sopenharmony_ci if (nfds == ARRAY_SIZE(events) && --count != 0) { 343e66f31c5Sopenharmony_ci /* Poll for more events but don't block this time. */ 344e66f31c5Sopenharmony_ci timeout = 0; 345e66f31c5Sopenharmony_ci continue; 346e66f31c5Sopenharmony_ci } 347e66f31c5Sopenharmony_ci return; 348e66f31c5Sopenharmony_ci } 349e66f31c5Sopenharmony_ci 350e66f31c5Sopenharmony_ci if (saved_errno == ETIME) { 351e66f31c5Sopenharmony_ci assert(timeout != -1); 352e66f31c5Sopenharmony_ci return; 353e66f31c5Sopenharmony_ci } 354e66f31c5Sopenharmony_ci 355e66f31c5Sopenharmony_ci if (timeout == 0) 356e66f31c5Sopenharmony_ci return; 357e66f31c5Sopenharmony_ci 358e66f31c5Sopenharmony_ci if (timeout == -1) 359e66f31c5Sopenharmony_ci continue; 360e66f31c5Sopenharmony_ci 361e66f31c5Sopenharmony_ciupdate_timeout: 362e66f31c5Sopenharmony_ci assert(timeout > 0); 363e66f31c5Sopenharmony_ci 364e66f31c5Sopenharmony_ci diff = loop->time - base; 365e66f31c5Sopenharmony_ci if (diff >= (uint64_t) timeout) 366e66f31c5Sopenharmony_ci return; 367e66f31c5Sopenharmony_ci 368e66f31c5Sopenharmony_ci timeout -= diff; 369e66f31c5Sopenharmony_ci } 370e66f31c5Sopenharmony_ci} 371e66f31c5Sopenharmony_ci 372e66f31c5Sopenharmony_ci 373e66f31c5Sopenharmony_ciuint64_t uv__hrtime(uv_clocktype_t type) { 374e66f31c5Sopenharmony_ci return gethrtime(); 375e66f31c5Sopenharmony_ci} 376e66f31c5Sopenharmony_ci 377e66f31c5Sopenharmony_ci 378e66f31c5Sopenharmony_ci/* 379e66f31c5Sopenharmony_ci * We could use a static buffer for the path manipulations that we need outside 380e66f31c5Sopenharmony_ci * of the function, but this function could be called by multiple consumers and 381e66f31c5Sopenharmony_ci * we don't want to potentially create a race condition in the use of snprintf. 382e66f31c5Sopenharmony_ci */ 383e66f31c5Sopenharmony_ciint uv_exepath(char* buffer, size_t* size) { 384e66f31c5Sopenharmony_ci ssize_t res; 385e66f31c5Sopenharmony_ci char buf[128]; 386e66f31c5Sopenharmony_ci 387e66f31c5Sopenharmony_ci if (buffer == NULL || size == NULL || *size == 0) 388e66f31c5Sopenharmony_ci return UV_EINVAL; 389e66f31c5Sopenharmony_ci 390e66f31c5Sopenharmony_ci snprintf(buf, sizeof(buf), "/proc/%lu/path/a.out", (unsigned long) getpid()); 391e66f31c5Sopenharmony_ci 392e66f31c5Sopenharmony_ci res = *size - 1; 393e66f31c5Sopenharmony_ci if (res > 0) 394e66f31c5Sopenharmony_ci res = readlink(buf, buffer, res); 395e66f31c5Sopenharmony_ci 396e66f31c5Sopenharmony_ci if (res == -1) 397e66f31c5Sopenharmony_ci return UV__ERR(errno); 398e66f31c5Sopenharmony_ci 399e66f31c5Sopenharmony_ci buffer[res] = '\0'; 400e66f31c5Sopenharmony_ci *size = res; 401e66f31c5Sopenharmony_ci return 0; 402e66f31c5Sopenharmony_ci} 403e66f31c5Sopenharmony_ci 404e66f31c5Sopenharmony_ci 405e66f31c5Sopenharmony_ciuint64_t uv_get_free_memory(void) { 406e66f31c5Sopenharmony_ci return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES); 407e66f31c5Sopenharmony_ci} 408e66f31c5Sopenharmony_ci 409e66f31c5Sopenharmony_ci 410e66f31c5Sopenharmony_ciuint64_t uv_get_total_memory(void) { 411e66f31c5Sopenharmony_ci return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES); 412e66f31c5Sopenharmony_ci} 413e66f31c5Sopenharmony_ci 414e66f31c5Sopenharmony_ci 415e66f31c5Sopenharmony_ciuint64_t uv_get_constrained_memory(void) { 416e66f31c5Sopenharmony_ci return 0; /* Memory constraints are unknown. */ 417e66f31c5Sopenharmony_ci} 418e66f31c5Sopenharmony_ci 419e66f31c5Sopenharmony_ci 420e66f31c5Sopenharmony_ciuint64_t uv_get_available_memory(void) { 421e66f31c5Sopenharmony_ci return uv_get_free_memory(); 422e66f31c5Sopenharmony_ci} 423e66f31c5Sopenharmony_ci 424e66f31c5Sopenharmony_ci 425e66f31c5Sopenharmony_civoid uv_loadavg(double avg[3]) { 426e66f31c5Sopenharmony_ci (void) getloadavg(avg, 3); 427e66f31c5Sopenharmony_ci} 428e66f31c5Sopenharmony_ci 429e66f31c5Sopenharmony_ci 430e66f31c5Sopenharmony_ci#if defined(PORT_SOURCE_FILE) 431e66f31c5Sopenharmony_ci 432e66f31c5Sopenharmony_cistatic int uv__fs_event_rearm(uv_fs_event_t *handle) { 433e66f31c5Sopenharmony_ci if (handle->fd == PORT_DELETED) 434e66f31c5Sopenharmony_ci return UV_EBADF; 435e66f31c5Sopenharmony_ci 436e66f31c5Sopenharmony_ci if (port_associate(handle->loop->fs_fd, 437e66f31c5Sopenharmony_ci PORT_SOURCE_FILE, 438e66f31c5Sopenharmony_ci (uintptr_t) &handle->fo, 439e66f31c5Sopenharmony_ci FILE_ATTRIB | FILE_MODIFIED, 440e66f31c5Sopenharmony_ci handle) == -1) { 441e66f31c5Sopenharmony_ci return UV__ERR(errno); 442e66f31c5Sopenharmony_ci } 443e66f31c5Sopenharmony_ci handle->fd = PORT_LOADED; 444e66f31c5Sopenharmony_ci 445e66f31c5Sopenharmony_ci return 0; 446e66f31c5Sopenharmony_ci} 447e66f31c5Sopenharmony_ci 448e66f31c5Sopenharmony_ci 449e66f31c5Sopenharmony_cistatic void uv__fs_event_read(uv_loop_t* loop, 450e66f31c5Sopenharmony_ci uv__io_t* w, 451e66f31c5Sopenharmony_ci unsigned int revents) { 452e66f31c5Sopenharmony_ci uv_fs_event_t *handle = NULL; 453e66f31c5Sopenharmony_ci timespec_t timeout; 454e66f31c5Sopenharmony_ci port_event_t pe; 455e66f31c5Sopenharmony_ci int events; 456e66f31c5Sopenharmony_ci int r; 457e66f31c5Sopenharmony_ci 458e66f31c5Sopenharmony_ci (void) w; 459e66f31c5Sopenharmony_ci (void) revents; 460e66f31c5Sopenharmony_ci 461e66f31c5Sopenharmony_ci do { 462e66f31c5Sopenharmony_ci uint_t n = 1; 463e66f31c5Sopenharmony_ci 464e66f31c5Sopenharmony_ci /* 465e66f31c5Sopenharmony_ci * Note that our use of port_getn() here (and not port_get()) is deliberate: 466e66f31c5Sopenharmony_ci * there is a bug in event ports (Sun bug 6456558) whereby a zeroed timeout 467e66f31c5Sopenharmony_ci * causes port_get() to return success instead of ETIME when there aren't 468e66f31c5Sopenharmony_ci * actually any events (!); by using port_getn() in lieu of port_get(), 469e66f31c5Sopenharmony_ci * we can at least workaround the bug by checking for zero returned events 470e66f31c5Sopenharmony_ci * and treating it as we would ETIME. 471e66f31c5Sopenharmony_ci */ 472e66f31c5Sopenharmony_ci do { 473e66f31c5Sopenharmony_ci memset(&timeout, 0, sizeof timeout); 474e66f31c5Sopenharmony_ci r = port_getn(loop->fs_fd, &pe, 1, &n, &timeout); 475e66f31c5Sopenharmony_ci } 476e66f31c5Sopenharmony_ci while (r == -1 && errno == EINTR); 477e66f31c5Sopenharmony_ci 478e66f31c5Sopenharmony_ci if ((r == -1 && errno == ETIME) || n == 0) 479e66f31c5Sopenharmony_ci break; 480e66f31c5Sopenharmony_ci 481e66f31c5Sopenharmony_ci handle = (uv_fs_event_t*) pe.portev_user; 482e66f31c5Sopenharmony_ci assert((r == 0) && "unexpected port_get() error"); 483e66f31c5Sopenharmony_ci 484e66f31c5Sopenharmony_ci if (uv__is_closing(handle)) { 485e66f31c5Sopenharmony_ci uv__handle_stop(handle); 486e66f31c5Sopenharmony_ci uv__make_close_pending((uv_handle_t*) handle); 487e66f31c5Sopenharmony_ci break; 488e66f31c5Sopenharmony_ci } 489e66f31c5Sopenharmony_ci 490e66f31c5Sopenharmony_ci events = 0; 491e66f31c5Sopenharmony_ci if (pe.portev_events & (FILE_ATTRIB | FILE_MODIFIED)) 492e66f31c5Sopenharmony_ci events |= UV_CHANGE; 493e66f31c5Sopenharmony_ci if (pe.portev_events & ~(FILE_ATTRIB | FILE_MODIFIED)) 494e66f31c5Sopenharmony_ci events |= UV_RENAME; 495e66f31c5Sopenharmony_ci assert(events != 0); 496e66f31c5Sopenharmony_ci handle->fd = PORT_FIRED; 497e66f31c5Sopenharmony_ci handle->cb(handle, NULL, events, 0); 498e66f31c5Sopenharmony_ci 499e66f31c5Sopenharmony_ci if (handle->fd != PORT_DELETED) { 500e66f31c5Sopenharmony_ci r = uv__fs_event_rearm(handle); 501e66f31c5Sopenharmony_ci if (r != 0) 502e66f31c5Sopenharmony_ci handle->cb(handle, NULL, 0, r); 503e66f31c5Sopenharmony_ci } 504e66f31c5Sopenharmony_ci } 505e66f31c5Sopenharmony_ci while (handle->fd != PORT_DELETED); 506e66f31c5Sopenharmony_ci} 507e66f31c5Sopenharmony_ci 508e66f31c5Sopenharmony_ci 509e66f31c5Sopenharmony_ciint uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { 510e66f31c5Sopenharmony_ci uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); 511e66f31c5Sopenharmony_ci return 0; 512e66f31c5Sopenharmony_ci} 513e66f31c5Sopenharmony_ci 514e66f31c5Sopenharmony_ci 515e66f31c5Sopenharmony_ciint uv_fs_event_start(uv_fs_event_t* handle, 516e66f31c5Sopenharmony_ci uv_fs_event_cb cb, 517e66f31c5Sopenharmony_ci const char* path, 518e66f31c5Sopenharmony_ci unsigned int flags) { 519e66f31c5Sopenharmony_ci int portfd; 520e66f31c5Sopenharmony_ci int first_run; 521e66f31c5Sopenharmony_ci int err; 522e66f31c5Sopenharmony_ci 523e66f31c5Sopenharmony_ci if (uv__is_active(handle)) 524e66f31c5Sopenharmony_ci return UV_EINVAL; 525e66f31c5Sopenharmony_ci 526e66f31c5Sopenharmony_ci first_run = 0; 527e66f31c5Sopenharmony_ci if (handle->loop->fs_fd == -1) { 528e66f31c5Sopenharmony_ci portfd = port_create(); 529e66f31c5Sopenharmony_ci if (portfd == -1) 530e66f31c5Sopenharmony_ci return UV__ERR(errno); 531e66f31c5Sopenharmony_ci handle->loop->fs_fd = portfd; 532e66f31c5Sopenharmony_ci first_run = 1; 533e66f31c5Sopenharmony_ci } 534e66f31c5Sopenharmony_ci 535e66f31c5Sopenharmony_ci uv__handle_start(handle); 536e66f31c5Sopenharmony_ci handle->path = uv__strdup(path); 537e66f31c5Sopenharmony_ci handle->fd = PORT_UNUSED; 538e66f31c5Sopenharmony_ci handle->cb = cb; 539e66f31c5Sopenharmony_ci 540e66f31c5Sopenharmony_ci memset(&handle->fo, 0, sizeof handle->fo); 541e66f31c5Sopenharmony_ci handle->fo.fo_name = handle->path; 542e66f31c5Sopenharmony_ci err = uv__fs_event_rearm(handle); 543e66f31c5Sopenharmony_ci if (err != 0) { 544e66f31c5Sopenharmony_ci uv_fs_event_stop(handle); 545e66f31c5Sopenharmony_ci return err; 546e66f31c5Sopenharmony_ci } 547e66f31c5Sopenharmony_ci 548e66f31c5Sopenharmony_ci if (first_run) { 549e66f31c5Sopenharmony_ci uv__io_init(&handle->loop->fs_event_watcher, uv__fs_event_read, portfd); 550e66f31c5Sopenharmony_ci uv__io_start(handle->loop, &handle->loop->fs_event_watcher, POLLIN); 551e66f31c5Sopenharmony_ci } 552e66f31c5Sopenharmony_ci 553e66f31c5Sopenharmony_ci return 0; 554e66f31c5Sopenharmony_ci} 555e66f31c5Sopenharmony_ci 556e66f31c5Sopenharmony_ci 557e66f31c5Sopenharmony_cistatic int uv__fs_event_stop(uv_fs_event_t* handle) { 558e66f31c5Sopenharmony_ci int ret = 0; 559e66f31c5Sopenharmony_ci 560e66f31c5Sopenharmony_ci if (!uv__is_active(handle)) 561e66f31c5Sopenharmony_ci return 0; 562e66f31c5Sopenharmony_ci 563e66f31c5Sopenharmony_ci if (handle->fd == PORT_LOADED) { 564e66f31c5Sopenharmony_ci ret = port_dissociate(handle->loop->fs_fd, 565e66f31c5Sopenharmony_ci PORT_SOURCE_FILE, 566e66f31c5Sopenharmony_ci (uintptr_t) &handle->fo); 567e66f31c5Sopenharmony_ci } 568e66f31c5Sopenharmony_ci 569e66f31c5Sopenharmony_ci handle->fd = PORT_DELETED; 570e66f31c5Sopenharmony_ci uv__free(handle->path); 571e66f31c5Sopenharmony_ci handle->path = NULL; 572e66f31c5Sopenharmony_ci handle->fo.fo_name = NULL; 573e66f31c5Sopenharmony_ci if (ret == 0) 574e66f31c5Sopenharmony_ci uv__handle_stop(handle); 575e66f31c5Sopenharmony_ci 576e66f31c5Sopenharmony_ci return ret; 577e66f31c5Sopenharmony_ci} 578e66f31c5Sopenharmony_ci 579e66f31c5Sopenharmony_ciint uv_fs_event_stop(uv_fs_event_t* handle) { 580e66f31c5Sopenharmony_ci (void) uv__fs_event_stop(handle); 581e66f31c5Sopenharmony_ci return 0; 582e66f31c5Sopenharmony_ci} 583e66f31c5Sopenharmony_ci 584e66f31c5Sopenharmony_civoid uv__fs_event_close(uv_fs_event_t* handle) { 585e66f31c5Sopenharmony_ci /* 586e66f31c5Sopenharmony_ci * If we were unable to dissociate the port here, then it is most likely 587e66f31c5Sopenharmony_ci * that there is a pending queued event. When this happens, we don't want 588e66f31c5Sopenharmony_ci * to complete the close as it will free the underlying memory for the 589e66f31c5Sopenharmony_ci * handle, causing a use-after-free problem when the event is processed. 590e66f31c5Sopenharmony_ci * We defer the final cleanup until after the event is consumed in 591e66f31c5Sopenharmony_ci * uv__fs_event_read(). 592e66f31c5Sopenharmony_ci */ 593e66f31c5Sopenharmony_ci if (uv__fs_event_stop(handle) == 0) 594e66f31c5Sopenharmony_ci uv__make_close_pending((uv_handle_t*) handle); 595e66f31c5Sopenharmony_ci} 596e66f31c5Sopenharmony_ci 597e66f31c5Sopenharmony_ci#else /* !defined(PORT_SOURCE_FILE) */ 598e66f31c5Sopenharmony_ci 599e66f31c5Sopenharmony_ciint uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { 600e66f31c5Sopenharmony_ci return UV_ENOSYS; 601e66f31c5Sopenharmony_ci} 602e66f31c5Sopenharmony_ci 603e66f31c5Sopenharmony_ci 604e66f31c5Sopenharmony_ciint uv_fs_event_start(uv_fs_event_t* handle, 605e66f31c5Sopenharmony_ci uv_fs_event_cb cb, 606e66f31c5Sopenharmony_ci const char* filename, 607e66f31c5Sopenharmony_ci unsigned int flags) { 608e66f31c5Sopenharmony_ci return UV_ENOSYS; 609e66f31c5Sopenharmony_ci} 610e66f31c5Sopenharmony_ci 611e66f31c5Sopenharmony_ci 612e66f31c5Sopenharmony_ciint uv_fs_event_stop(uv_fs_event_t* handle) { 613e66f31c5Sopenharmony_ci return UV_ENOSYS; 614e66f31c5Sopenharmony_ci} 615e66f31c5Sopenharmony_ci 616e66f31c5Sopenharmony_ci 617e66f31c5Sopenharmony_civoid uv__fs_event_close(uv_fs_event_t* handle) { 618e66f31c5Sopenharmony_ci UNREACHABLE(); 619e66f31c5Sopenharmony_ci} 620e66f31c5Sopenharmony_ci 621e66f31c5Sopenharmony_ci#endif /* defined(PORT_SOURCE_FILE) */ 622e66f31c5Sopenharmony_ci 623e66f31c5Sopenharmony_ci 624e66f31c5Sopenharmony_ciint uv_resident_set_memory(size_t* rss) { 625e66f31c5Sopenharmony_ci psinfo_t psinfo; 626e66f31c5Sopenharmony_ci int err; 627e66f31c5Sopenharmony_ci int fd; 628e66f31c5Sopenharmony_ci 629e66f31c5Sopenharmony_ci fd = open("/proc/self/psinfo", O_RDONLY); 630e66f31c5Sopenharmony_ci if (fd == -1) 631e66f31c5Sopenharmony_ci return UV__ERR(errno); 632e66f31c5Sopenharmony_ci 633e66f31c5Sopenharmony_ci /* FIXME(bnoordhuis) Handle EINTR. */ 634e66f31c5Sopenharmony_ci err = UV_EINVAL; 635e66f31c5Sopenharmony_ci if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) { 636e66f31c5Sopenharmony_ci *rss = (size_t)psinfo.pr_rssize * 1024; 637e66f31c5Sopenharmony_ci err = 0; 638e66f31c5Sopenharmony_ci } 639e66f31c5Sopenharmony_ci uv__close(fd); 640e66f31c5Sopenharmony_ci 641e66f31c5Sopenharmony_ci return err; 642e66f31c5Sopenharmony_ci} 643e66f31c5Sopenharmony_ci 644e66f31c5Sopenharmony_ci 645e66f31c5Sopenharmony_ciint uv_uptime(double* uptime) { 646e66f31c5Sopenharmony_ci kstat_ctl_t *kc; 647e66f31c5Sopenharmony_ci kstat_t *ksp; 648e66f31c5Sopenharmony_ci kstat_named_t *knp; 649e66f31c5Sopenharmony_ci 650e66f31c5Sopenharmony_ci long hz = sysconf(_SC_CLK_TCK); 651e66f31c5Sopenharmony_ci 652e66f31c5Sopenharmony_ci kc = kstat_open(); 653e66f31c5Sopenharmony_ci if (kc == NULL) 654e66f31c5Sopenharmony_ci return UV_EPERM; 655e66f31c5Sopenharmony_ci 656e66f31c5Sopenharmony_ci ksp = kstat_lookup(kc, (char*) "unix", 0, (char*) "system_misc"); 657e66f31c5Sopenharmony_ci if (kstat_read(kc, ksp, NULL) == -1) { 658e66f31c5Sopenharmony_ci *uptime = -1; 659e66f31c5Sopenharmony_ci } else { 660e66f31c5Sopenharmony_ci knp = (kstat_named_t*) kstat_data_lookup(ksp, (char*) "clk_intr"); 661e66f31c5Sopenharmony_ci *uptime = knp->value.ul / hz; 662e66f31c5Sopenharmony_ci } 663e66f31c5Sopenharmony_ci kstat_close(kc); 664e66f31c5Sopenharmony_ci 665e66f31c5Sopenharmony_ci return 0; 666e66f31c5Sopenharmony_ci} 667e66f31c5Sopenharmony_ci 668e66f31c5Sopenharmony_ci 669e66f31c5Sopenharmony_ciint uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 670e66f31c5Sopenharmony_ci int lookup_instance; 671e66f31c5Sopenharmony_ci kstat_ctl_t *kc; 672e66f31c5Sopenharmony_ci kstat_t *ksp; 673e66f31c5Sopenharmony_ci kstat_named_t *knp; 674e66f31c5Sopenharmony_ci uv_cpu_info_t* cpu_info; 675e66f31c5Sopenharmony_ci 676e66f31c5Sopenharmony_ci kc = kstat_open(); 677e66f31c5Sopenharmony_ci if (kc == NULL) 678e66f31c5Sopenharmony_ci return UV_EPERM; 679e66f31c5Sopenharmony_ci 680e66f31c5Sopenharmony_ci /* Get count of cpus */ 681e66f31c5Sopenharmony_ci lookup_instance = 0; 682e66f31c5Sopenharmony_ci while ((ksp = kstat_lookup(kc, (char*) "cpu_info", lookup_instance, NULL))) { 683e66f31c5Sopenharmony_ci lookup_instance++; 684e66f31c5Sopenharmony_ci } 685e66f31c5Sopenharmony_ci 686e66f31c5Sopenharmony_ci *cpu_infos = uv__malloc(lookup_instance * sizeof(**cpu_infos)); 687e66f31c5Sopenharmony_ci if (!(*cpu_infos)) { 688e66f31c5Sopenharmony_ci kstat_close(kc); 689e66f31c5Sopenharmony_ci return UV_ENOMEM; 690e66f31c5Sopenharmony_ci } 691e66f31c5Sopenharmony_ci 692e66f31c5Sopenharmony_ci *count = lookup_instance; 693e66f31c5Sopenharmony_ci 694e66f31c5Sopenharmony_ci cpu_info = *cpu_infos; 695e66f31c5Sopenharmony_ci lookup_instance = 0; 696e66f31c5Sopenharmony_ci while ((ksp = kstat_lookup(kc, (char*) "cpu_info", lookup_instance, NULL))) { 697e66f31c5Sopenharmony_ci if (kstat_read(kc, ksp, NULL) == -1) { 698e66f31c5Sopenharmony_ci cpu_info->speed = 0; 699e66f31c5Sopenharmony_ci cpu_info->model = NULL; 700e66f31c5Sopenharmony_ci } else { 701e66f31c5Sopenharmony_ci knp = kstat_data_lookup(ksp, (char*) "clock_MHz"); 702e66f31c5Sopenharmony_ci assert(knp->data_type == KSTAT_DATA_INT32 || 703e66f31c5Sopenharmony_ci knp->data_type == KSTAT_DATA_INT64); 704e66f31c5Sopenharmony_ci cpu_info->speed = (knp->data_type == KSTAT_DATA_INT32) ? knp->value.i32 705e66f31c5Sopenharmony_ci : knp->value.i64; 706e66f31c5Sopenharmony_ci 707e66f31c5Sopenharmony_ci knp = kstat_data_lookup(ksp, (char*) "brand"); 708e66f31c5Sopenharmony_ci assert(knp->data_type == KSTAT_DATA_STRING); 709e66f31c5Sopenharmony_ci cpu_info->model = uv__strdup(KSTAT_NAMED_STR_PTR(knp)); 710e66f31c5Sopenharmony_ci } 711e66f31c5Sopenharmony_ci 712e66f31c5Sopenharmony_ci lookup_instance++; 713e66f31c5Sopenharmony_ci cpu_info++; 714e66f31c5Sopenharmony_ci } 715e66f31c5Sopenharmony_ci 716e66f31c5Sopenharmony_ci cpu_info = *cpu_infos; 717e66f31c5Sopenharmony_ci lookup_instance = 0; 718e66f31c5Sopenharmony_ci for (;;) { 719e66f31c5Sopenharmony_ci ksp = kstat_lookup(kc, (char*) "cpu", lookup_instance, (char*) "sys"); 720e66f31c5Sopenharmony_ci 721e66f31c5Sopenharmony_ci if (ksp == NULL) 722e66f31c5Sopenharmony_ci break; 723e66f31c5Sopenharmony_ci 724e66f31c5Sopenharmony_ci if (kstat_read(kc, ksp, NULL) == -1) { 725e66f31c5Sopenharmony_ci cpu_info->cpu_times.user = 0; 726e66f31c5Sopenharmony_ci cpu_info->cpu_times.nice = 0; 727e66f31c5Sopenharmony_ci cpu_info->cpu_times.sys = 0; 728e66f31c5Sopenharmony_ci cpu_info->cpu_times.idle = 0; 729e66f31c5Sopenharmony_ci cpu_info->cpu_times.irq = 0; 730e66f31c5Sopenharmony_ci } else { 731e66f31c5Sopenharmony_ci knp = kstat_data_lookup(ksp, (char*) "cpu_ticks_user"); 732e66f31c5Sopenharmony_ci assert(knp->data_type == KSTAT_DATA_UINT64); 733e66f31c5Sopenharmony_ci cpu_info->cpu_times.user = knp->value.ui64; 734e66f31c5Sopenharmony_ci 735e66f31c5Sopenharmony_ci knp = kstat_data_lookup(ksp, (char*) "cpu_ticks_kernel"); 736e66f31c5Sopenharmony_ci assert(knp->data_type == KSTAT_DATA_UINT64); 737e66f31c5Sopenharmony_ci cpu_info->cpu_times.sys = knp->value.ui64; 738e66f31c5Sopenharmony_ci 739e66f31c5Sopenharmony_ci knp = kstat_data_lookup(ksp, (char*) "cpu_ticks_idle"); 740e66f31c5Sopenharmony_ci assert(knp->data_type == KSTAT_DATA_UINT64); 741e66f31c5Sopenharmony_ci cpu_info->cpu_times.idle = knp->value.ui64; 742e66f31c5Sopenharmony_ci 743e66f31c5Sopenharmony_ci knp = kstat_data_lookup(ksp, (char*) "intr"); 744e66f31c5Sopenharmony_ci assert(knp->data_type == KSTAT_DATA_UINT64); 745e66f31c5Sopenharmony_ci cpu_info->cpu_times.irq = knp->value.ui64; 746e66f31c5Sopenharmony_ci cpu_info->cpu_times.nice = 0; 747e66f31c5Sopenharmony_ci } 748e66f31c5Sopenharmony_ci 749e66f31c5Sopenharmony_ci lookup_instance++; 750e66f31c5Sopenharmony_ci cpu_info++; 751e66f31c5Sopenharmony_ci } 752e66f31c5Sopenharmony_ci 753e66f31c5Sopenharmony_ci kstat_close(kc); 754e66f31c5Sopenharmony_ci 755e66f31c5Sopenharmony_ci return 0; 756e66f31c5Sopenharmony_ci} 757e66f31c5Sopenharmony_ci 758e66f31c5Sopenharmony_ci 759e66f31c5Sopenharmony_ci#ifdef SUNOS_NO_IFADDRS 760e66f31c5Sopenharmony_ciint uv_interface_addresses(uv_interface_address_t** addresses, int* count) { 761e66f31c5Sopenharmony_ci *count = 0; 762e66f31c5Sopenharmony_ci *addresses = NULL; 763e66f31c5Sopenharmony_ci return UV_ENOSYS; 764e66f31c5Sopenharmony_ci} 765e66f31c5Sopenharmony_ci#else /* SUNOS_NO_IFADDRS */ 766e66f31c5Sopenharmony_ci/* 767e66f31c5Sopenharmony_ci * Inspired By: 768e66f31c5Sopenharmony_ci * https://blogs.oracle.com/paulie/entry/retrieving_mac_address_in_solaris 769e66f31c5Sopenharmony_ci * http://www.pauliesworld.org/project/getmac.c 770e66f31c5Sopenharmony_ci */ 771e66f31c5Sopenharmony_cistatic int uv__set_phys_addr(uv_interface_address_t* address, 772e66f31c5Sopenharmony_ci struct ifaddrs* ent) { 773e66f31c5Sopenharmony_ci 774e66f31c5Sopenharmony_ci struct sockaddr_dl* sa_addr; 775e66f31c5Sopenharmony_ci int sockfd; 776e66f31c5Sopenharmony_ci size_t i; 777e66f31c5Sopenharmony_ci struct arpreq arpreq; 778e66f31c5Sopenharmony_ci 779e66f31c5Sopenharmony_ci /* This appears to only work as root */ 780e66f31c5Sopenharmony_ci sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); 781e66f31c5Sopenharmony_ci memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); 782e66f31c5Sopenharmony_ci for (i = 0; i < sizeof(address->phys_addr); i++) { 783e66f31c5Sopenharmony_ci /* Check that all bytes of phys_addr are zero. */ 784e66f31c5Sopenharmony_ci if (address->phys_addr[i] != 0) 785e66f31c5Sopenharmony_ci return 0; 786e66f31c5Sopenharmony_ci } 787e66f31c5Sopenharmony_ci memset(&arpreq, 0, sizeof(arpreq)); 788e66f31c5Sopenharmony_ci if (address->address.address4.sin_family == AF_INET) { 789e66f31c5Sopenharmony_ci struct sockaddr_in* sin = ((struct sockaddr_in*)&arpreq.arp_pa); 790e66f31c5Sopenharmony_ci sin->sin_addr.s_addr = address->address.address4.sin_addr.s_addr; 791e66f31c5Sopenharmony_ci } else if (address->address.address4.sin_family == AF_INET6) { 792e66f31c5Sopenharmony_ci struct sockaddr_in6* sin = ((struct sockaddr_in6*)&arpreq.arp_pa); 793e66f31c5Sopenharmony_ci memcpy(sin->sin6_addr.s6_addr, 794e66f31c5Sopenharmony_ci address->address.address6.sin6_addr.s6_addr, 795e66f31c5Sopenharmony_ci sizeof(address->address.address6.sin6_addr.s6_addr)); 796e66f31c5Sopenharmony_ci } else { 797e66f31c5Sopenharmony_ci return 0; 798e66f31c5Sopenharmony_ci } 799e66f31c5Sopenharmony_ci 800e66f31c5Sopenharmony_ci sockfd = socket(AF_INET, SOCK_DGRAM, 0); 801e66f31c5Sopenharmony_ci if (sockfd < 0) 802e66f31c5Sopenharmony_ci return UV__ERR(errno); 803e66f31c5Sopenharmony_ci 804e66f31c5Sopenharmony_ci if (ioctl(sockfd, SIOCGARP, (char*)&arpreq) == -1) { 805e66f31c5Sopenharmony_ci uv__close(sockfd); 806e66f31c5Sopenharmony_ci return UV__ERR(errno); 807e66f31c5Sopenharmony_ci } 808e66f31c5Sopenharmony_ci memcpy(address->phys_addr, arpreq.arp_ha.sa_data, sizeof(address->phys_addr)); 809e66f31c5Sopenharmony_ci uv__close(sockfd); 810e66f31c5Sopenharmony_ci return 0; 811e66f31c5Sopenharmony_ci} 812e66f31c5Sopenharmony_ci 813e66f31c5Sopenharmony_ci 814e66f31c5Sopenharmony_cistatic int uv__ifaddr_exclude(struct ifaddrs *ent) { 815e66f31c5Sopenharmony_ci if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) 816e66f31c5Sopenharmony_ci return 1; 817e66f31c5Sopenharmony_ci if (ent->ifa_addr == NULL) 818e66f31c5Sopenharmony_ci return 1; 819e66f31c5Sopenharmony_ci if (ent->ifa_addr->sa_family != AF_INET && 820e66f31c5Sopenharmony_ci ent->ifa_addr->sa_family != AF_INET6) 821e66f31c5Sopenharmony_ci return 1; 822e66f31c5Sopenharmony_ci return 0; 823e66f31c5Sopenharmony_ci} 824e66f31c5Sopenharmony_ci 825e66f31c5Sopenharmony_ciint uv_interface_addresses(uv_interface_address_t** addresses, int* count) { 826e66f31c5Sopenharmony_ci uv_interface_address_t* address; 827e66f31c5Sopenharmony_ci struct ifaddrs* addrs; 828e66f31c5Sopenharmony_ci struct ifaddrs* ent; 829e66f31c5Sopenharmony_ci 830e66f31c5Sopenharmony_ci *count = 0; 831e66f31c5Sopenharmony_ci *addresses = NULL; 832e66f31c5Sopenharmony_ci 833e66f31c5Sopenharmony_ci if (getifaddrs(&addrs)) 834e66f31c5Sopenharmony_ci return UV__ERR(errno); 835e66f31c5Sopenharmony_ci 836e66f31c5Sopenharmony_ci /* Count the number of interfaces */ 837e66f31c5Sopenharmony_ci for (ent = addrs; ent != NULL; ent = ent->ifa_next) { 838e66f31c5Sopenharmony_ci if (uv__ifaddr_exclude(ent)) 839e66f31c5Sopenharmony_ci continue; 840e66f31c5Sopenharmony_ci (*count)++; 841e66f31c5Sopenharmony_ci } 842e66f31c5Sopenharmony_ci 843e66f31c5Sopenharmony_ci if (*count == 0) { 844e66f31c5Sopenharmony_ci freeifaddrs(addrs); 845e66f31c5Sopenharmony_ci return 0; 846e66f31c5Sopenharmony_ci } 847e66f31c5Sopenharmony_ci 848e66f31c5Sopenharmony_ci *addresses = uv__malloc(*count * sizeof(**addresses)); 849e66f31c5Sopenharmony_ci if (!(*addresses)) { 850e66f31c5Sopenharmony_ci freeifaddrs(addrs); 851e66f31c5Sopenharmony_ci return UV_ENOMEM; 852e66f31c5Sopenharmony_ci } 853e66f31c5Sopenharmony_ci 854e66f31c5Sopenharmony_ci address = *addresses; 855e66f31c5Sopenharmony_ci 856e66f31c5Sopenharmony_ci for (ent = addrs; ent != NULL; ent = ent->ifa_next) { 857e66f31c5Sopenharmony_ci if (uv__ifaddr_exclude(ent)) 858e66f31c5Sopenharmony_ci continue; 859e66f31c5Sopenharmony_ci 860e66f31c5Sopenharmony_ci address->name = uv__strdup(ent->ifa_name); 861e66f31c5Sopenharmony_ci 862e66f31c5Sopenharmony_ci if (ent->ifa_addr->sa_family == AF_INET6) { 863e66f31c5Sopenharmony_ci address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); 864e66f31c5Sopenharmony_ci } else { 865e66f31c5Sopenharmony_ci address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); 866e66f31c5Sopenharmony_ci } 867e66f31c5Sopenharmony_ci 868e66f31c5Sopenharmony_ci if (ent->ifa_netmask->sa_family == AF_INET6) { 869e66f31c5Sopenharmony_ci address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); 870e66f31c5Sopenharmony_ci } else { 871e66f31c5Sopenharmony_ci address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); 872e66f31c5Sopenharmony_ci } 873e66f31c5Sopenharmony_ci 874e66f31c5Sopenharmony_ci address->is_internal = !!((ent->ifa_flags & IFF_PRIVATE) || 875e66f31c5Sopenharmony_ci (ent->ifa_flags & IFF_LOOPBACK)); 876e66f31c5Sopenharmony_ci 877e66f31c5Sopenharmony_ci uv__set_phys_addr(address, ent); 878e66f31c5Sopenharmony_ci address++; 879e66f31c5Sopenharmony_ci } 880e66f31c5Sopenharmony_ci 881e66f31c5Sopenharmony_ci freeifaddrs(addrs); 882e66f31c5Sopenharmony_ci 883e66f31c5Sopenharmony_ci return 0; 884e66f31c5Sopenharmony_ci} 885e66f31c5Sopenharmony_ci#endif /* SUNOS_NO_IFADDRS */ 886e66f31c5Sopenharmony_ci 887e66f31c5Sopenharmony_civoid uv_free_interface_addresses(uv_interface_address_t* addresses, 888e66f31c5Sopenharmony_ci int count) { 889e66f31c5Sopenharmony_ci int i; 890e66f31c5Sopenharmony_ci 891e66f31c5Sopenharmony_ci for (i = 0; i < count; i++) { 892e66f31c5Sopenharmony_ci uv__free(addresses[i].name); 893e66f31c5Sopenharmony_ci } 894e66f31c5Sopenharmony_ci 895e66f31c5Sopenharmony_ci uv__free(addresses); 896e66f31c5Sopenharmony_ci} 897e66f31c5Sopenharmony_ci 898e66f31c5Sopenharmony_ci 899e66f31c5Sopenharmony_ci#if !defined(_POSIX_VERSION) || _POSIX_VERSION < 200809L 900e66f31c5Sopenharmony_cisize_t strnlen(const char* s, size_t maxlen) { 901e66f31c5Sopenharmony_ci const char* end; 902e66f31c5Sopenharmony_ci end = memchr(s, '\0', maxlen); 903e66f31c5Sopenharmony_ci if (end == NULL) 904e66f31c5Sopenharmony_ci return maxlen; 905e66f31c5Sopenharmony_ci return end - s; 906e66f31c5Sopenharmony_ci} 907e66f31c5Sopenharmony_ci#endif 908