linux-core.c
Go to the documentation of this file.
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2  * Permission is hereby granted, free of charge, to any person obtaining a copy
3  * of this software and associated documentation files (the "Software"), to
4  * deal in the Software without restriction, including without limitation the
5  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
6  * sell copies of the Software, and to permit persons to whom the Software is
7  * furnished to do so, subject to the following conditions:
8  *
9  * The above copyright notice and this permission notice shall be included in
10  * all copies or substantial portions of the Software.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
18  * IN THE SOFTWARE.
19  */
20 
21 /* We lean on the fact that POLL{IN,OUT,ERR,HUP} correspond with their
22  * EPOLL* counterparts. We use the POLL* variants in this file because that
23  * is what libuv uses elsewhere.
24  */
25 
26 #include "uv.h"
27 #include "internal.h"
28 
29 #include <inttypes.h>
30 #include <stdint.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <assert.h>
35 #include <errno.h>
36 
37 #include <net/if.h>
38 #include <sys/epoll.h>
39 #include <sys/param.h>
40 #include <sys/prctl.h>
41 #include <sys/sysinfo.h>
42 #include <unistd.h>
43 #include <fcntl.h>
44 #include <time.h>
45 
46 #define HAVE_IFADDRS_H 1
47 
48 #ifdef __UCLIBC__
49 # if __UCLIBC_MAJOR__ < 0 && __UCLIBC_MINOR__ < 9 && __UCLIBC_SUBLEVEL__ < 32
50 # undef HAVE_IFADDRS_H
51 # endif
52 #endif
53 
54 #ifdef HAVE_IFADDRS_H
55 # if defined(__ANDROID__)
56 # include "uv/android-ifaddrs.h"
57 # else
58 # include <ifaddrs.h>
59 # endif
60 # include <sys/socket.h>
61 # include <net/ethernet.h>
62 # include <netpacket/packet.h>
63 #endif /* HAVE_IFADDRS_H */
64 
65 /* Available from 2.6.32 onwards. */
66 #ifndef CLOCK_MONOTONIC_COARSE
67 # define CLOCK_MONOTONIC_COARSE 6
68 #endif
69 
70 /* This is rather annoying: CLOCK_BOOTTIME lives in <linux/time.h> but we can't
71  * include that file because it conflicts with <time.h>. We'll just have to
72  * define it ourselves.
73  */
74 #ifndef CLOCK_BOOTTIME
75 # define CLOCK_BOOTTIME 7
76 #endif
77 
78 static int read_models(unsigned int numcpus, uv_cpu_info_t* ci);
79 static int read_times(FILE* statfile_fp,
80  unsigned int numcpus,
81  uv_cpu_info_t* ci);
82 static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci);
83 static uint64_t read_cpufreq(unsigned int cpunum);
84 
85 
87  int fd;
88 
89  /* It was reported that EPOLL_CLOEXEC is not defined on Android API < 21,
90  * a.k.a. Lollipop. Since EPOLL_CLOEXEC is an alias for O_CLOEXEC on all
91  * architectures, we just use that instead.
92  */
93 #if defined(__ANDROID_API__) && __ANDROID_API__ < 21
94  fd = -1;
95  errno = ENOSYS;
96 #else
97  fd = epoll_create1(O_CLOEXEC);
98 #endif
99 
100  /* epoll_create1() can fail either because it's not implemented (old kernel)
101  * or because it doesn't understand the O_CLOEXEC flag.
102  */
103  if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) {
104  fd = epoll_create(256);
105 
106  if (fd != -1)
107  uv__cloexec(fd, 1);
108  }
109 
110  loop->backend_fd = fd;
111  loop->inotify_fd = -1;
112  loop->inotify_watchers = NULL;
113 
114  if (fd == -1)
115  return UV__ERR(errno);
116 
117  return 0;
118 }
119 
120 
122  int err;
123  void* old_watchers;
124 
125  old_watchers = loop->inotify_watchers;
126 
127  uv__close(loop->backend_fd);
128  loop->backend_fd = -1;
130 
132  if (err)
133  return err;
134 
135  return uv__inotify_fork(loop, old_watchers);
136 }
137 
138 
140  if (loop->inotify_fd == -1) return;
141  uv__io_stop(loop, &loop->inotify_read_watcher, POLLIN);
142  uv__close(loop->inotify_fd);
143  loop->inotify_fd = -1;
144 }
145 
146 
148  struct epoll_event* events;
149  struct epoll_event dummy;
150  uintptr_t i;
151  uintptr_t nfds;
152 
153  assert(loop->watchers != NULL);
154  assert(fd >= 0);
155 
156  events = (struct epoll_event*) loop->watchers[loop->nwatchers];
157  nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
158  if (events != NULL)
159  /* Invalidate events with same file descriptor */
160  for (i = 0; i < nfds; i++)
161  if (events[i].data.fd == fd)
162  events[i].data.fd = -1;
163 
164  /* Remove the file descriptor from the epoll.
165  * This avoids a problem where the same file description remains open
166  * in another process, causing repeated junk epoll events.
167  *
168  * We pass in a dummy epoll_event, to work around a bug in old kernels.
169  */
170  if (loop->backend_fd >= 0) {
171  /* Work around a bug in kernels 3.10 to 3.19 where passing a struct that
172  * has the EPOLLWAKEUP flag set generates spurious audit syslog warnings.
173  */
174  memset(&dummy, 0, sizeof(dummy));
175  epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &dummy);
176  }
177 }
178 
179 
181  struct epoll_event e;
182  int rc;
183 
184  memset(&e, 0, sizeof(e));
185  e.events = POLLIN;
186  e.data.fd = -1;
187 
188  rc = 0;
189  if (epoll_ctl(loop->backend_fd, EPOLL_CTL_ADD, fd, &e))
190  if (errno != EEXIST)
191  rc = UV__ERR(errno);
192 
193  if (rc == 0)
194  if (epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &e))
195  abort();
196 
197  return rc;
198 }
199 
200 
202  /* A bug in kernels < 2.6.37 makes timeouts larger than ~30 minutes
203  * effectively infinite on 32 bits architectures. To avoid blocking
204  * indefinitely, we cap the timeout and poll again if necessary.
205  *
206  * Note that "30 minutes" is a simplification because it depends on
207  * the value of CONFIG_HZ. The magic constant assumes CONFIG_HZ=1200,
208  * that being the largest value I have seen in the wild (and only once.)
209  */
210  static const int max_safe_timeout = 1789569;
211  static int no_epoll_pwait;
212  static int no_epoll_wait;
213  struct epoll_event events[1024];
214  struct epoll_event* pe;
215  struct epoll_event e;
216  int real_timeout;
217  QUEUE* q;
218  uv__io_t* w;
219  sigset_t sigset;
220  uint64_t sigmask;
221  uint64_t base;
222  int have_signals;
223  int nevents;
224  int count;
225  int nfds;
226  int fd;
227  int op;
228  int i;
229 
230  if (loop->nfds == 0) {
231  assert(QUEUE_EMPTY(&loop->watcher_queue));
232  return;
233  }
234 
235  memset(&e, 0, sizeof(e));
236 
237  while (!QUEUE_EMPTY(&loop->watcher_queue)) {
238  q = QUEUE_HEAD(&loop->watcher_queue);
239  QUEUE_REMOVE(q);
240  QUEUE_INIT(q);
241 
242  w = QUEUE_DATA(q, uv__io_t, watcher_queue);
243  assert(w->pevents != 0);
244  assert(w->fd >= 0);
245  assert(w->fd < (int) loop->nwatchers);
246 
247  e.events = w->pevents;
248  e.data.fd = w->fd;
249 
250  if (w->events == 0)
251  op = EPOLL_CTL_ADD;
252  else
253  op = EPOLL_CTL_MOD;
254 
255  /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching
256  * events, skip the syscall and squelch the events after epoll_wait().
257  */
258  if (epoll_ctl(loop->backend_fd, op, w->fd, &e)) {
259  if (errno != EEXIST)
260  abort();
261 
262  assert(op == EPOLL_CTL_ADD);
263 
264  /* We've reactivated a file descriptor that's been watched before. */
265  if (epoll_ctl(loop->backend_fd, EPOLL_CTL_MOD, w->fd, &e))
266  abort();
267  }
268 
269  w->events = w->pevents;
270  }
271 
272  sigmask = 0;
273  if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
274  sigemptyset(&sigset);
275  sigaddset(&sigset, SIGPROF);
276  sigmask |= 1 << (SIGPROF - 1);
277  }
278 
279  assert(timeout >= -1);
280  base = loop->time;
281  count = 48; /* Benchmarks suggest this gives the best throughput. */
282  real_timeout = timeout;
283 
284  for (;;) {
285  /* See the comment for max_safe_timeout for an explanation of why
286  * this is necessary. Executive summary: kernel bug workaround.
287  */
288  if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)
289  timeout = max_safe_timeout;
290 
291  if (sigmask != 0 && no_epoll_pwait != 0)
292  if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))
293  abort();
294 
295  if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) {
296 #if defined(__ANDROID_API__) && __ANDROID_API__ < 21
297  nfds = -1;
298  errno = ENOSYS;
299 #else
300  nfds = epoll_pwait(loop->backend_fd,
301  events,
303  timeout,
304  &sigset);
305 #endif
306  if (nfds == -1 && errno == ENOSYS)
307  no_epoll_pwait = 1;
308  } else {
309  nfds = epoll_wait(loop->backend_fd,
310  events,
312  timeout);
313  if (nfds == -1 && errno == ENOSYS)
314  no_epoll_wait = 1;
315  }
316 
317  if (sigmask != 0 && no_epoll_pwait != 0)
318  if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL))
319  abort();
320 
321  /* Update loop->time unconditionally. It's tempting to skip the update when
322  * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
323  * operating system didn't reschedule our process while in the syscall.
324  */
325  SAVE_ERRNO(uv__update_time(loop));
326 
327  if (nfds == 0) {
328  assert(timeout != -1);
329 
330  if (timeout == 0)
331  return;
332 
333  /* We may have been inside the system call for longer than |timeout|
334  * milliseconds so we need to update the timestamp to avoid drift.
335  */
336  goto update_timeout;
337  }
338 
339  if (nfds == -1) {
340  if (errno == ENOSYS) {
341  /* epoll_wait() or epoll_pwait() failed, try the other system call. */
342  assert(no_epoll_wait == 0 || no_epoll_pwait == 0);
343  continue;
344  }
345 
346  if (errno != EINTR)
347  abort();
348 
349  if (timeout == -1)
350  continue;
351 
352  if (timeout == 0)
353  return;
354 
355  /* Interrupted by a signal. Update timeout and poll again. */
356  goto update_timeout;
357  }
358 
359  have_signals = 0;
360  nevents = 0;
361 
362  {
363  /* Squelch a -Waddress-of-packed-member warning with gcc >= 9. */
364  union {
365  struct epoll_event* events;
366  uv__io_t* watchers;
367  } x;
368 
369  x.events = events;
370  assert(loop->watchers != NULL);
371  loop->watchers[loop->nwatchers] = x.watchers;
372  loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
373  }
374 
375  for (i = 0; i < nfds; i++) {
376  pe = events + i;
377  fd = pe->data.fd;
378 
379  /* Skip invalidated events, see uv__platform_invalidate_fd */
380  if (fd == -1)
381  continue;
382 
383  assert(fd >= 0);
384  assert((unsigned) fd < loop->nwatchers);
385 
386  w = loop->watchers[fd];
387 
388  if (w == NULL) {
389  /* File descriptor that we've stopped watching, disarm it.
390  *
391  * Ignore all errors because we may be racing with another thread
392  * when the file descriptor is closed.
393  */
394  epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, pe);
395  continue;
396  }
397 
398  /* Give users only events they're interested in. Prevents spurious
399  * callbacks when previous callback invocation in this loop has stopped
400  * the current watcher. Also, filters out events that users has not
401  * requested us to watch.
402  */
403  pe->events &= w->pevents | POLLERR | POLLHUP;
404 
405  /* Work around an epoll quirk where it sometimes reports just the
406  * EPOLLERR or EPOLLHUP event. In order to force the event loop to
407  * move forward, we merge in the read/write events that the watcher
408  * is interested in; uv__read() and uv__write() will then deal with
409  * the error or hangup in the usual fashion.
410  *
411  * Note to self: happens when epoll reports EPOLLIN|EPOLLHUP, the user
412  * reads the available data, calls uv_read_stop(), then sometime later
413  * calls uv_read_start() again. By then, libuv has forgotten about the
414  * hangup and the kernel won't report EPOLLIN again because there's
415  * nothing left to read. If anything, libuv is to blame here. The
416  * current hack is just a quick bandaid; to properly fix it, libuv
417  * needs to remember the error/hangup event. We should get that for
418  * free when we switch over to edge-triggered I/O.
419  */
420  if (pe->events == POLLERR || pe->events == POLLHUP)
421  pe->events |=
422  w->pevents & (POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
423 
424  if (pe->events != 0) {
425  /* Run signal watchers last. This also affects child process watchers
426  * because those are implemented in terms of signal watchers.
427  */
428  if (w == &loop->signal_io_watcher)
429  have_signals = 1;
430  else
431  w->cb(loop, w, pe->events);
432 
433  nevents++;
434  }
435  }
436 
437  if (have_signals != 0)
438  loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
439 
440  loop->watchers[loop->nwatchers] = NULL;
441  loop->watchers[loop->nwatchers + 1] = NULL;
442 
443  if (have_signals != 0)
444  return; /* Event loop should cycle now so don't poll again. */
445 
446  if (nevents != 0) {
447  if (nfds == ARRAY_SIZE(events) && --count != 0) {
448  /* Poll for more events but don't block this time. */
449  timeout = 0;
450  continue;
451  }
452  return;
453  }
454 
455  if (timeout == 0)
456  return;
457 
458  if (timeout == -1)
459  continue;
460 
461 update_timeout:
462  assert(timeout > 0);
463 
464  real_timeout -= (loop->time - base);
465  if (real_timeout <= 0)
466  return;
467 
468  timeout = real_timeout;
469  }
470 }
471 
472 
474  static clock_t fast_clock_id = -1;
475  struct timespec t;
476  clock_t clock_id;
477 
478  /* Prefer CLOCK_MONOTONIC_COARSE if available but only when it has
479  * millisecond granularity or better. CLOCK_MONOTONIC_COARSE is
480  * serviced entirely from the vDSO, whereas CLOCK_MONOTONIC may
481  * decide to make a costly system call.
482  */
483  /* TODO(bnoordhuis) Use CLOCK_MONOTONIC_COARSE for UV_CLOCK_PRECISE
484  * when it has microsecond granularity or better (unlikely).
485  */
486  if (type == UV_CLOCK_FAST && fast_clock_id == -1) {
487  if (clock_getres(CLOCK_MONOTONIC_COARSE, &t) == 0 &&
488  t.tv_nsec <= 1 * 1000 * 1000) {
489  fast_clock_id = CLOCK_MONOTONIC_COARSE;
490  } else {
491  fast_clock_id = CLOCK_MONOTONIC;
492  }
493  }
494 
495  clock_id = CLOCK_MONOTONIC;
496  if (type == UV_CLOCK_FAST)
497  clock_id = fast_clock_id;
498 
499  if (clock_gettime(clock_id, &t))
500  return 0; /* Not really possible. */
501 
502  return t.tv_sec * (uint64_t) 1e9 + t.tv_nsec;
503 }
504 
505 
506 int uv_resident_set_memory(size_t* rss) {
507  char buf[1024];
508  const char* s;
509  ssize_t n;
510  long val;
511  int fd;
512  int i;
513 
514  do
515  fd = open("/proc/self/stat", O_RDONLY);
516  while (fd == -1 && errno == EINTR);
517 
518  if (fd == -1)
519  return UV__ERR(errno);
520 
521  do
522  n = read(fd, buf, sizeof(buf) - 1);
523  while (n == -1 && errno == EINTR);
524 
525  uv__close(fd);
526  if (n == -1)
527  return UV__ERR(errno);
528  buf[n] = '\0';
529 
530  s = strchr(buf, ' ');
531  if (s == NULL)
532  goto err;
533 
534  s += 1;
535  if (*s != '(')
536  goto err;
537 
538  s = strchr(s, ')');
539  if (s == NULL)
540  goto err;
541 
542  for (i = 1; i <= 22; i++) {
543  s = strchr(s + 1, ' ');
544  if (s == NULL)
545  goto err;
546  }
547 
548  errno = 0;
549  val = strtol(s, NULL, 10);
550  if (errno != 0)
551  goto err;
552  if (val < 0)
553  goto err;
554 
555  *rss = val * getpagesize();
556  return 0;
557 
558 err:
559  return UV_EINVAL;
560 }
561 
562 
563 int uv_uptime(double* uptime) {
564  static volatile int no_clock_boottime;
565  struct timespec now;
566  int r;
567 
568  /* Try CLOCK_BOOTTIME first, fall back to CLOCK_MONOTONIC if not available
569  * (pre-2.6.39 kernels). CLOCK_MONOTONIC doesn't increase when the system
570  * is suspended.
571  */
572  if (no_clock_boottime) {
573  retry: r = clock_gettime(CLOCK_MONOTONIC, &now);
574  }
575  else if ((r = clock_gettime(CLOCK_BOOTTIME, &now)) && errno == EINVAL) {
576  no_clock_boottime = 1;
577  goto retry;
578  }
579 
580  if (r)
581  return UV__ERR(errno);
582 
583  *uptime = now.tv_sec;
584  return 0;
585 }
586 
587 
588 static int uv__cpu_num(FILE* statfile_fp, unsigned int* numcpus) {
589  unsigned int num;
590  char buf[1024];
591 
592  if (!fgets(buf, sizeof(buf), statfile_fp))
593  return UV_EIO;
594 
595  num = 0;
596  while (fgets(buf, sizeof(buf), statfile_fp)) {
597  if (strncmp(buf, "cpu", 3))
598  break;
599  num++;
600  }
601 
602  if (num == 0)
603  return UV_EIO;
604 
605  *numcpus = num;
606  return 0;
607 }
608 
609 
610 int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
611  unsigned int numcpus;
612  uv_cpu_info_t* ci;
613  int err;
614  FILE* statfile_fp;
615 
616  *cpu_infos = NULL;
617  *count = 0;
618 
619  statfile_fp = uv__open_file("/proc/stat");
620  if (statfile_fp == NULL)
621  return UV__ERR(errno);
622 
623  err = uv__cpu_num(statfile_fp, &numcpus);
624  if (err < 0)
625  goto out;
626 
627  err = UV_ENOMEM;
628  ci = uv__calloc(numcpus, sizeof(*ci));
629  if (ci == NULL)
630  goto out;
631 
632  err = read_models(numcpus, ci);
633  if (err == 0)
634  err = read_times(statfile_fp, numcpus, ci);
635 
636  if (err) {
637  uv_free_cpu_info(ci, numcpus);
638  goto out;
639  }
640 
641  /* read_models() on x86 also reads the CPU speed from /proc/cpuinfo.
642  * We don't check for errors here. Worst case, the field is left zero.
643  */
644  if (ci[0].speed == 0)
645  read_speeds(numcpus, ci);
646 
647  *cpu_infos = ci;
648  *count = numcpus;
649  err = 0;
650 
651 out:
652 
653  if (fclose(statfile_fp))
654  if (errno != EINTR && errno != EINPROGRESS)
655  abort();
656 
657  return err;
658 }
659 
660 
661 static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci) {
662  unsigned int num;
663 
664  for (num = 0; num < numcpus; num++)
665  ci[num].speed = read_cpufreq(num) / 1000;
666 }
667 
668 
669 /* Also reads the CPU frequency on x86. The other architectures only have
670  * a BogoMIPS field, which may not be very accurate.
671  *
672  * Note: Simply returns on error, uv_cpu_info() takes care of the cleanup.
673  */
674 static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
675  static const char model_marker[] = "model name\t: ";
676  static const char speed_marker[] = "cpu MHz\t\t: ";
677  const char* inferred_model;
678  unsigned int model_idx;
679  unsigned int speed_idx;
680  char buf[1024];
681  char* model;
682  FILE* fp;
683 
684  /* Most are unused on non-ARM, non-MIPS and non-x86 architectures. */
685  (void) &model_marker;
686  (void) &speed_marker;
687  (void) &speed_idx;
688  (void) &model;
689  (void) &buf;
690  (void) &fp;
691 
692  model_idx = 0;
693  speed_idx = 0;
694 
695 #if defined(__arm__) || \
696  defined(__i386__) || \
697  defined(__mips__) || \
698  defined(__x86_64__)
699  fp = uv__open_file("/proc/cpuinfo");
700  if (fp == NULL)
701  return UV__ERR(errno);
702 
703  while (fgets(buf, sizeof(buf), fp)) {
704  if (model_idx < numcpus) {
705  if (strncmp(buf, model_marker, sizeof(model_marker) - 1) == 0) {
706  model = buf + sizeof(model_marker) - 1;
707  model = uv__strndup(model, strlen(model) - 1); /* Strip newline. */
708  if (model == NULL) {
709  fclose(fp);
710  return UV_ENOMEM;
711  }
712  ci[model_idx++].model = model;
713  continue;
714  }
715  }
716 #if defined(__arm__) || defined(__mips__)
717  if (model_idx < numcpus) {
718 #if defined(__arm__)
719  /* Fallback for pre-3.8 kernels. */
720  static const char model_marker[] = "Processor\t: ";
721 #else /* defined(__mips__) */
722  static const char model_marker[] = "cpu model\t\t: ";
723 #endif
724  if (strncmp(buf, model_marker, sizeof(model_marker) - 1) == 0) {
725  model = buf + sizeof(model_marker) - 1;
726  model = uv__strndup(model, strlen(model) - 1); /* Strip newline. */
727  if (model == NULL) {
728  fclose(fp);
729  return UV_ENOMEM;
730  }
731  ci[model_idx++].model = model;
732  continue;
733  }
734  }
735 #else /* !__arm__ && !__mips__ */
736  if (speed_idx < numcpus) {
737  if (strncmp(buf, speed_marker, sizeof(speed_marker) - 1) == 0) {
738  ci[speed_idx++].speed = atoi(buf + sizeof(speed_marker) - 1);
739  continue;
740  }
741  }
742 #endif /* __arm__ || __mips__ */
743  }
744 
745  fclose(fp);
746 #endif /* __arm__ || __i386__ || __mips__ || __x86_64__ */
747 
748  /* Now we want to make sure that all the models contain *something* because
749  * it's not safe to leave them as null. Copy the last entry unless there
750  * isn't one, in that case we simply put "unknown" into everything.
751  */
752  inferred_model = "unknown";
753  if (model_idx > 0)
754  inferred_model = ci[model_idx - 1].model;
755 
756  while (model_idx < numcpus) {
757  model = uv__strndup(inferred_model, strlen(inferred_model));
758  if (model == NULL)
759  return UV_ENOMEM;
760  ci[model_idx++].model = model;
761  }
762 
763  return 0;
764 }
765 
766 
767 static int read_times(FILE* statfile_fp,
768  unsigned int numcpus,
769  uv_cpu_info_t* ci) {
770  struct uv_cpu_times_s ts;
771  uint64_t clock_ticks;
772  uint64_t user;
773  uint64_t nice;
774  uint64_t sys;
775  uint64_t idle;
776  uint64_t dummy;
777  uint64_t irq;
778  uint64_t num;
779  uint64_t len;
780  char buf[1024];
781 
782  clock_ticks = sysconf(_SC_CLK_TCK);
783  assert(clock_ticks != (uint64_t) -1);
784  assert(clock_ticks != 0);
785 
786  rewind(statfile_fp);
787 
788  if (!fgets(buf, sizeof(buf), statfile_fp))
789  abort();
790 
791  num = 0;
792 
793  while (fgets(buf, sizeof(buf), statfile_fp)) {
794  if (num >= numcpus)
795  break;
796 
797  if (strncmp(buf, "cpu", 3))
798  break;
799 
800  /* skip "cpu<num> " marker */
801  {
802  unsigned int n;
803  int r = sscanf(buf, "cpu%u ", &n);
804  assert(r == 1);
805  (void) r; /* silence build warning */
806  for (len = sizeof("cpu0"); n /= 10; len++);
807  }
808 
809  /* Line contains user, nice, system, idle, iowait, irq, softirq, steal,
810  * guest, guest_nice but we're only interested in the first four + irq.
811  *
812  * Don't use %*s to skip fields or %ll to read straight into the uint64_t
813  * fields, they're not allowed in C89 mode.
814  */
815  if (6 != sscanf(buf + len,
816  "%" PRIu64 " %" PRIu64 " %" PRIu64
817  "%" PRIu64 " %" PRIu64 " %" PRIu64,
818  &user,
819  &nice,
820  &sys,
821  &idle,
822  &dummy,
823  &irq))
824  abort();
825 
826  ts.user = clock_ticks * user;
827  ts.nice = clock_ticks * nice;
828  ts.sys = clock_ticks * sys;
829  ts.idle = clock_ticks * idle;
830  ts.irq = clock_ticks * irq;
831  ci[num++].cpu_times = ts;
832  }
833  assert(num == numcpus);
834 
835  return 0;
836 }
837 
838 
839 static uint64_t read_cpufreq(unsigned int cpunum) {
840  uint64_t val;
841  char buf[1024];
842  FILE* fp;
843 
844  snprintf(buf,
845  sizeof(buf),
846  "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_cur_freq",
847  cpunum);
848 
849  fp = uv__open_file(buf);
850  if (fp == NULL)
851  return 0;
852 
853  if (fscanf(fp, "%" PRIu64, &val) != 1)
854  val = 0;
855 
856  fclose(fp);
857 
858  return val;
859 }
860 
861 
862 static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
863  if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
864  return 1;
865  if (ent->ifa_addr == NULL)
866  return 1;
867  /*
868  * On Linux getifaddrs returns information related to the raw underlying
869  * devices. We're not interested in this information yet.
870  */
871  if (ent->ifa_addr->sa_family == PF_PACKET)
872  return exclude_type;
873  return !exclude_type;
874 }
875 
877 #ifndef HAVE_IFADDRS_H
878  *count = 0;
879  *addresses = NULL;
880  return UV_ENOSYS;
881 #else
882  struct ifaddrs *addrs, *ent;
883  uv_interface_address_t* address;
884  int i;
885  struct sockaddr_ll *sll;
886 
887  *count = 0;
888  *addresses = NULL;
889 
890  if (getifaddrs(&addrs))
891  return UV__ERR(errno);
892 
893  /* Count the number of interfaces */
894  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
896  continue;
897 
898  (*count)++;
899  }
900 
901  if (*count == 0) {
902  freeifaddrs(addrs);
903  return 0;
904  }
905 
906  /* Make sure the memory is initiallized to zero using calloc() */
907  *addresses = uv__calloc(*count, sizeof(**addresses));
908  if (!(*addresses)) {
909  freeifaddrs(addrs);
910  return UV_ENOMEM;
911  }
912 
913  address = *addresses;
914 
915  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
917  continue;
918 
919  address->name = uv__strdup(ent->ifa_name);
920 
921  if (ent->ifa_addr->sa_family == AF_INET6) {
922  address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
923  } else {
924  address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr);
925  }
926 
927  if (ent->ifa_netmask->sa_family == AF_INET6) {
928  address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask);
929  } else {
930  address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask);
931  }
932 
933  address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK);
934 
935  address++;
936  }
937 
938  /* Fill in physical addresses for each interface */
939  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
941  continue;
942 
943  address = *addresses;
944 
945  for (i = 0; i < (*count); i++) {
946  size_t namelen = strlen(ent->ifa_name);
947  /* Alias interface share the same physical address */
948  if (strncmp(address->name, ent->ifa_name, namelen) == 0 &&
949  (address->name[namelen] == 0 || address->name[namelen] == ':')) {
950  sll = (struct sockaddr_ll*)ent->ifa_addr;
951  memcpy(address->phys_addr, sll->sll_addr, sizeof(address->phys_addr));
952  }
953  address++;
954  }
955  }
956 
957  freeifaddrs(addrs);
958 
959  return 0;
960 #endif
961 }
962 
963 
965  int count) {
966  int i;
967 
968  for (i = 0; i < count; i++) {
969  uv__free(addresses[i].name);
970  }
971 
972  uv__free(addresses);
973 }
974 
975 
976 void uv__set_process_title(const char* title) {
977 #if defined(PR_SET_NAME)
978  prctl(PR_SET_NAME, title); /* Only copies first 16 characters. */
979 #endif
980 }
981 
982 
983 static uint64_t uv__read_proc_meminfo(const char* what) {
984  uint64_t rc;
985  ssize_t n;
986  char* p;
987  int fd;
988  char buf[4096]; /* Large enough to hold all of /proc/meminfo. */
989 
990  rc = 0;
991  fd = uv__open_cloexec("/proc/meminfo", O_RDONLY);
992 
993  if (fd < 0)
994  return 0;
995 
996  n = read(fd, buf, sizeof(buf) - 1);
997 
998  if (n <= 0)
999  goto out;
1000 
1001  buf[n] = '\0';
1002  p = strstr(buf, what);
1003 
1004  if (p == NULL)
1005  goto out;
1006 
1007  p += strlen(what);
1008 
1009  if (1 != sscanf(p, "%" PRIu64 " kB", &rc))
1010  goto out;
1011 
1012  rc *= 1024;
1013 
1014 out:
1015 
1016  if (uv__close_nocheckstdio(fd))
1017  abort();
1018 
1019  return rc;
1020 }
1021 
1022 
1024  struct sysinfo info;
1025  uint64_t rc;
1026 
1027  rc = uv__read_proc_meminfo("MemFree:");
1028 
1029  if (rc != 0)
1030  return rc;
1031 
1032  if (0 == sysinfo(&info))
1033  return (uint64_t) info.freeram * info.mem_unit;
1034 
1035  return 0;
1036 }
1037 
1038 
1040  struct sysinfo info;
1041  uint64_t rc;
1042 
1043  rc = uv__read_proc_meminfo("MemTotal:");
1044 
1045  if (rc != 0)
1046  return rc;
1047 
1048  if (0 == sysinfo(&info))
1049  return (uint64_t) info.totalram * info.mem_unit;
1050 
1051  return 0;
1052 }
1053 
1054 
1055 static uint64_t uv__read_cgroups_uint64(const char* cgroup, const char* param) {
1056  char filename[256];
1057  uint64_t rc;
1058  int fd;
1059  ssize_t n;
1060  char buf[32]; /* Large enough to hold an encoded uint64_t. */
1061 
1062  snprintf(filename, 256, "/sys/fs/cgroup/%s/%s", cgroup, param);
1063 
1064  rc = 0;
1065  fd = uv__open_cloexec(filename, O_RDONLY);
1066 
1067  if (fd < 0)
1068  return 0;
1069 
1070  n = read(fd, buf, sizeof(buf) - 1);
1071 
1072  if (n > 0) {
1073  buf[n] = '\0';
1074  sscanf(buf, "%" PRIu64, &rc);
1075  }
1076 
1077  if (uv__close_nocheckstdio(fd))
1078  abort();
1079 
1080  return rc;
1081 }
1082 
1083 
1085  /*
1086  * This might return 0 if there was a problem getting the memory limit from
1087  * cgroups. This is OK because a return value of 0 signifies that the memory
1088  * limit is unknown.
1089  */
1090  return uv__read_cgroups_uint64("memory", "memory.limit_in_bytes");
1091 }
EPOLL_CTL_ADD
#define EPOLL_CTL_ADD
Definition: os390-syscalls.h:32
async_greeter_server_with_graceful_shutdown.loop
loop
Definition: async_greeter_server_with_graceful_shutdown.py:59
uv_cpu_times_s::irq
uint64_t irq
Definition: uv.h:1076
uv__open_file
FILE * uv__open_file(const char *path)
Definition: unix/core.c:461
filename
const char * filename
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:135
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
now
static double now(void)
Definition: test/core/fling/client.cc:130
idle
static uv_idle_t idle
Definition: test-poll-oob.c:37
ARRAY_SIZE
#define ARRAY_SIZE(array)
Definition: bloaty.cc:101
AF_INET6
#define AF_INET6
Definition: ares_setup.h:208
uv_cpu_info_s
Definition: uv.h:1079
memset
return memset(p, 0, total)
read_speeds
static void read_speeds(unsigned int numcpus, uv_cpu_info_t *ci)
Definition: linux-core.c:661
uv_free_cpu_info
UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t *cpu_infos, int count)
Definition: uv-common.c:816
uv_free_interface_addresses
void uv_free_interface_addresses(uv_interface_address_t *addresses, int count)
Definition: linux-core.c:964
uv__close_nocheckstdio
int uv__close_nocheckstdio(int fd)
Definition: unix/core.c:538
string.h
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
EPOLL_CTL_MOD
#define EPOLL_CTL_MOD
Definition: os390-syscalls.h:34
error_ref_leak.err
err
Definition: error_ref_leak.py:35
QUEUE_HEAD
#define QUEUE_HEAD(q)
Definition: queue.h:42
UV__EXCLUDE_IFPHYS
@ UV__EXCLUDE_IFPHYS
Definition: third_party/libuv/src/unix/internal.h:146
android-ifaddrs.h
uv__open_cloexec
int uv__open_cloexec(const char *path, int flags)
Definition: unix/core.c:991
CLOCK_BOOTTIME
#define CLOCK_BOOTTIME
Definition: linux-core.c:75
setup.name
name
Definition: setup.py:542
uv__cpu_num
static int uv__cpu_num(FILE *statfile_fp, unsigned int *numcpus)
Definition: linux-core.c:588
UV__POLLPRI
#define UV__POLLPRI
Definition: third_party/libuv/src/unix/internal.h:126
xds_manager.p
p
Definition: xds_manager.py:60
QUEUE_DATA
#define QUEUE_DATA(ptr, type, field)
Definition: queue.h:30
uv__io_s::fd
int fd
Definition: unix.h:100
uv_uptime
int uv_uptime(double *uptime)
Definition: linux-core.c:563
uv__io_poll
void uv__io_poll(uv_loop_t *loop, int timeout)
Definition: linux-core.c:201
uv_cpu_info_s::cpu_times
struct uv_cpu_times_s cpu_times
Definition: uv.h:1082
uv_clocktype_t
uv_clocktype_t
Definition: third_party/libuv/src/unix/internal.h:150
uv_interface_address_s::netmask
union uv_interface_address_s::@401 netmask
uv__platform_loop_delete
void uv__platform_loop_delete(uv_loop_t *loop)
Definition: linux-core.c:139
epoll_create1
uv__os390_epoll * epoll_create1(int flags)
Definition: os390-syscalls.c:215
uv__io_s::events
unsigned int events
Definition: unix.h:99
retry
void retry(grpc_end2end_test_config config)
Definition: retry.cc:319
uv_interface_address_s::name
char * name
Definition: uv.h:1086
QUEUE_INIT
#define QUEUE_INIT(q)
Definition: queue.h:45
uv_cpu_times_s::nice
uint64_t nice
Definition: uv.h:1073
memcpy
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
uv__platform_loop_init
int uv__platform_loop_init(uv_loop_t *loop)
Definition: linux-core.c:86
read_models
static int read_models(unsigned int numcpus, uv_cpu_info_t *ci)
Definition: linux-core.c:674
ssize_t
intptr_t ssize_t
Definition: win.h:27
uv_get_constrained_memory
uint64_t uv_get_constrained_memory(void)
Definition: linux-core.c:1084
sockaddr_in6
Definition: ares_ipv6.h:25
read_times
static int read_times(FILE *statfile_fp, unsigned int numcpus, uv_cpu_info_t *ci)
Definition: linux-core.c:767
CLOCK_MONOTONIC_COARSE
#define CLOCK_MONOTONIC_COARSE
Definition: linux-core.c:67
uv__cloexec
#define uv__cloexec
Definition: third_party/libuv/src/unix/internal.h:173
ifaddrs::ifa_netmask
struct sockaddr * ifa_netmask
Definition: android-ifaddrs.h:34
ifaddrs::ifa_addr
struct sockaddr * ifa_addr
Definition: android-ifaddrs.h:33
uv__inotify_fork
int uv__inotify_fork(uv_loop_t *loop, void *old_watchers)
Definition: linux-inotify.c:86
uv__io_check_fd
int uv__io_check_fd(uv_loop_t *loop, int fd)
Definition: linux-core.c:180
uv__strdup
char * uv__strdup(const char *s)
Definition: uv-common.c:55
ifaddrs::ifa_name
char * ifa_name
Definition: android-ifaddrs.h:31
uv_get_free_memory
uint64_t uv_get_free_memory(void)
Definition: linux-core.c:1023
uv__hrtime
uint64_t uv__hrtime(uv_clocktype_t type)
Definition: linux-core.c:473
uv_cpu_times_s
Definition: uv.h:1071
uv__read_proc_meminfo
static uint64_t uv__read_proc_meminfo(const char *what)
Definition: linux-core.c:983
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
uv__set_process_title
void uv__set_process_title(const char *title)
Definition: linux-core.c:976
epoll_event::fd
int fd
Definition: os390-syscalls.h:42
uv__calloc
void * uv__calloc(size_t count, size_t size)
Definition: uv-common.c:92
uv__free
void uv__free(void *ptr)
Definition: uv-common.c:81
uv_resident_set_memory
int uv_resident_set_memory(size_t *rss)
Definition: linux-core.c:506
x
int x
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3610
UV__ERR
#define UV__ERR(x)
Definition: errno.h:29
read_cpufreq
static uint64_t read_cpufreq(unsigned int cpunum)
Definition: linux-core.c:839
gen_synthetic_protos.base
base
Definition: gen_synthetic_protos.py:31
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
uintptr_t
_W64 unsigned int uintptr_t
Definition: stdint-msvc2008.h:119
uv__io_fork
int uv__io_fork(uv_loop_t *loop)
Definition: linux-core.c:121
epoll_wait
int epoll_wait(uv__os390_epoll *lst, struct epoll_event *events, int maxevents, int timeout)
Definition: os390-syscalls.c:284
QUEUE_REMOVE
#define QUEUE_REMOVE(q)
Definition: queue.h:101
uv_cpu_times_s::user
uint64_t user
Definition: uv.h:1072
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
stdint.h
QUEUE_EMPTY
#define QUEUE_EMPTY(q)
Definition: queue.h:39
uv_cpu_info_s::model
char * model
Definition: uv.h:1080
UV_CLOCK_FAST
@ UV_CLOCK_FAST
Definition: third_party/libuv/src/unix/internal.h:152
uv_interface_addresses
int uv_interface_addresses(uv_interface_address_t **addresses, int *count)
Definition: linux-core.c:876
UV__EXCLUDE_IFADDR
@ UV__EXCLUDE_IFADDR
Definition: third_party/libuv/src/unix/internal.h:147
uv_interface_address_s
Definition: uv.h:1085
uv.h
uv__read_cgroups_uint64
static uint64_t uv__read_cgroups_uint64(const char *cgroup, const char *param)
Definition: linux-core.c:1055
internal.h
read
int read(izstream &zs, T *x, Items items)
Definition: bloaty/third_party/zlib/contrib/iostream2/zstream.h:115
UV__POLLRDHUP
#define UV__POLLRDHUP
Definition: third_party/libuv/src/unix/internal.h:120
benchmark.FILE
FILE
Definition: benchmark.py:21
count
int * count
Definition: bloaty/third_party/googletest/googlemock/test/gmock_stress_test.cc:96
uv__io_s::cb
uv__io_cb cb
Definition: unix.h:95
uv_interface_address_s::address4
struct sockaddr_in address4
Definition: uv.h:1090
grpc::fclose
fclose(creds_file)
epoll_event
Definition: os390-syscalls.h:40
uv_interface_address_s::netmask6
struct sockaddr_in6 netmask6
Definition: uv.h:1095
UV_LOOP_BLOCK_SIGPROF
@ UV_LOOP_BLOCK_SIGPROF
Definition: third_party/libuv/src/unix/internal.h:141
fix_build_deps.r
r
Definition: fix_build_deps.py:491
ifaddrs::ifa_flags
unsigned int ifa_flags
Definition: android-ifaddrs.h:32
SAVE_ERRNO
#define SAVE_ERRNO(block)
Definition: third_party/libuv/src/unix/internal.h:94
epoll_ctl
int epoll_ctl(uv__os390_epoll *lst, int op, int fd, struct epoll_event *event)
Definition: os390-syscalls.c:238
xds_manager.num
num
Definition: xds_manager.py:56
EPOLL_CTL_DEL
#define EPOLL_CTL_DEL
Definition: os390-syscalls.h:33
uv__ifaddr_exclude
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type)
Definition: linux-core.c:862
uv__platform_invalidate_fd
void uv__platform_invalidate_fd(uv_loop_t *loop, int fd)
Definition: linux-core.c:147
absl::ABSL_NAMESPACE_BEGIN::dummy
int dummy
Definition: function_type_benchmark.cc:28
uv_interface_address_s::is_internal
int is_internal
Definition: uv.h:1088
uv__io_s::pevents
unsigned int pevents
Definition: unix.h:98
uv_get_total_memory
uint64_t uv_get_total_memory(void)
Definition: linux-core.c:1039
uv__io_stop
void uv__io_stop(uv_loop_t *loop, uv__io_t *w, unsigned int events)
Definition: unix/core.c:898
ifaddrs
Definition: android-ifaddrs.h:29
uv__strndup
char * uv__strndup(const char *s, size_t n)
Definition: uv-common.c:63
open
#define open
Definition: test-fs.c:46
uv_interface_address_s::address
union uv_interface_address_s::@400 address
epoll_event::events
int events
Definition: os390-syscalls.h:41
uv_interface_address_s::phys_addr
char phys_addr[6]
Definition: uv.h:1087
ifaddrs::ifa_next
struct ifaddrs * ifa_next
Definition: android-ifaddrs.h:30
uv_interface_address_s::netmask4
struct sockaddr_in netmask4
Definition: uv.h:1094
uv_loop_s
Definition: uv.h:1767
uv_cpu_info
int uv_cpu_info(uv_cpu_info_t **cpu_infos, int *count)
Definition: linux-core.c:610
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
freeifaddrs
void freeifaddrs(struct ifaddrs *ifa)
Definition: android-ifaddrs.c:704
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
getifaddrs
__BEGIN_DECLS int getifaddrs(struct ifaddrs **ifap)
Definition: android-ifaddrs.c:655
uv__io_s
Definition: unix.h:94
int32_t
signed int int32_t
Definition: stdint-msvc2008.h:77
uv_cpu_info_s::speed
int speed
Definition: uv.h:1081
uv_cpu_times_s::sys
uint64_t sys
Definition: uv.h:1074
op
static grpc_op * op
Definition: test/core/fling/client.cc:47
timeout
uv_timer_t timeout
Definition: libuv/docs/code/uvwget/main.c:9
errno.h
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
uv_interface_address_s::address6
struct sockaddr_in6 address6
Definition: uv.h:1091
QUEUE
void * QUEUE[2]
Definition: queue.h:21
uv_cpu_times_s::idle
uint64_t idle
Definition: uv.h:1075
uv__close
int uv__close(int fd)
Definition: unix/core.c:557


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:00:28