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