11cb0ef41Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 21cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 31cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to 41cb0ef41Sopenharmony_ci * deal in the Software without restriction, including without limitation the 51cb0ef41Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 61cb0ef41Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 71cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions: 81cb0ef41Sopenharmony_ci * 91cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 101cb0ef41Sopenharmony_ci * all copies or substantial portions of the Software. 111cb0ef41Sopenharmony_ci * 121cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 131cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 141cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 151cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 161cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 171cb0ef41Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 181cb0ef41Sopenharmony_ci * IN THE SOFTWARE. 191cb0ef41Sopenharmony_ci */ 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci#include "uv.h" 221cb0ef41Sopenharmony_ci#include "internal.h" 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci#include <assert.h> 251cb0ef41Sopenharmony_ci#include <string.h> 261cb0ef41Sopenharmony_ci#include <errno.h> 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci#include <kvm.h> 291cb0ef41Sopenharmony_ci#include <paths.h> 301cb0ef41Sopenharmony_ci#include <unistd.h> 311cb0ef41Sopenharmony_ci#include <time.h> 321cb0ef41Sopenharmony_ci#include <stdlib.h> 331cb0ef41Sopenharmony_ci#include <fcntl.h> 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci#include <sys/resource.h> 361cb0ef41Sopenharmony_ci#include <sys/types.h> 371cb0ef41Sopenharmony_ci#include <sys/sysctl.h> 381cb0ef41Sopenharmony_ci#include <uvm/uvm_extern.h> 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ci#include <unistd.h> 411cb0ef41Sopenharmony_ci#include <time.h> 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ciint uv__platform_loop_init(uv_loop_t* loop) { 451cb0ef41Sopenharmony_ci return uv__kqueue_init(loop); 461cb0ef41Sopenharmony_ci} 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_civoid uv__platform_loop_delete(uv_loop_t* loop) { 501cb0ef41Sopenharmony_ci} 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_civoid uv_loadavg(double avg[3]) { 541cb0ef41Sopenharmony_ci struct loadavg info; 551cb0ef41Sopenharmony_ci size_t size = sizeof(info); 561cb0ef41Sopenharmony_ci int which[] = {CTL_VM, VM_LOADAVG}; 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0) == -1) return; 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci avg[0] = (double) info.ldavg[0] / info.fscale; 611cb0ef41Sopenharmony_ci avg[1] = (double) info.ldavg[1] / info.fscale; 621cb0ef41Sopenharmony_ci avg[2] = (double) info.ldavg[2] / info.fscale; 631cb0ef41Sopenharmony_ci} 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ciint uv_exepath(char* buffer, size_t* size) { 671cb0ef41Sopenharmony_ci /* Intermediate buffer, retrieving partial path name does not work 681cb0ef41Sopenharmony_ci * As of NetBSD-8(beta), vnode->path translator does not handle files 691cb0ef41Sopenharmony_ci * with longer names than 31 characters. 701cb0ef41Sopenharmony_ci */ 711cb0ef41Sopenharmony_ci char int_buf[PATH_MAX]; 721cb0ef41Sopenharmony_ci size_t int_size; 731cb0ef41Sopenharmony_ci int mib[4]; 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci if (buffer == NULL || size == NULL || *size == 0) 761cb0ef41Sopenharmony_ci return UV_EINVAL; 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ci mib[0] = CTL_KERN; 791cb0ef41Sopenharmony_ci mib[1] = KERN_PROC_ARGS; 801cb0ef41Sopenharmony_ci mib[2] = -1; 811cb0ef41Sopenharmony_ci mib[3] = KERN_PROC_PATHNAME; 821cb0ef41Sopenharmony_ci int_size = ARRAY_SIZE(int_buf); 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ci if (sysctl(mib, 4, int_buf, &int_size, NULL, 0)) 851cb0ef41Sopenharmony_ci return UV__ERR(errno); 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci /* Copy string from the intermediate buffer to outer one with appropriate 881cb0ef41Sopenharmony_ci * length. 891cb0ef41Sopenharmony_ci */ 901cb0ef41Sopenharmony_ci /* TODO(bnoordhuis) Check uv__strscpy() return value. */ 911cb0ef41Sopenharmony_ci uv__strscpy(buffer, int_buf, *size); 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci /* Set new size. */ 941cb0ef41Sopenharmony_ci *size = strlen(buffer); 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci return 0; 971cb0ef41Sopenharmony_ci} 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ciuint64_t uv_get_free_memory(void) { 1011cb0ef41Sopenharmony_ci struct uvmexp info; 1021cb0ef41Sopenharmony_ci size_t size = sizeof(info); 1031cb0ef41Sopenharmony_ci int which[] = {CTL_VM, VM_UVMEXP}; 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) 1061cb0ef41Sopenharmony_ci return UV__ERR(errno); 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ci return (uint64_t) info.free * sysconf(_SC_PAGESIZE); 1091cb0ef41Sopenharmony_ci} 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ciuint64_t uv_get_total_memory(void) { 1131cb0ef41Sopenharmony_ci#if defined(HW_PHYSMEM64) 1141cb0ef41Sopenharmony_ci uint64_t info; 1151cb0ef41Sopenharmony_ci int which[] = {CTL_HW, HW_PHYSMEM64}; 1161cb0ef41Sopenharmony_ci#else 1171cb0ef41Sopenharmony_ci unsigned int info; 1181cb0ef41Sopenharmony_ci int which[] = {CTL_HW, HW_PHYSMEM}; 1191cb0ef41Sopenharmony_ci#endif 1201cb0ef41Sopenharmony_ci size_t size = sizeof(info); 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) 1231cb0ef41Sopenharmony_ci return UV__ERR(errno); 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci return (uint64_t) info; 1261cb0ef41Sopenharmony_ci} 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ciuint64_t uv_get_constrained_memory(void) { 1301cb0ef41Sopenharmony_ci return 0; /* Memory constraints are unknown. */ 1311cb0ef41Sopenharmony_ci} 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ciint uv_resident_set_memory(size_t* rss) { 1351cb0ef41Sopenharmony_ci kvm_t *kd = NULL; 1361cb0ef41Sopenharmony_ci struct kinfo_proc2 *kinfo = NULL; 1371cb0ef41Sopenharmony_ci pid_t pid; 1381cb0ef41Sopenharmony_ci int nprocs; 1391cb0ef41Sopenharmony_ci int max_size = sizeof(struct kinfo_proc2); 1401cb0ef41Sopenharmony_ci int page_size; 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ci page_size = getpagesize(); 1431cb0ef41Sopenharmony_ci pid = getpid(); 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, "kvm_open"); 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci if (kd == NULL) goto error; 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_ci kinfo = kvm_getproc2(kd, KERN_PROC_PID, pid, max_size, &nprocs); 1501cb0ef41Sopenharmony_ci if (kinfo == NULL) goto error; 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci *rss = kinfo->p_vm_rssize * page_size; 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci kvm_close(kd); 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci return 0; 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_cierror: 1591cb0ef41Sopenharmony_ci if (kd) kvm_close(kd); 1601cb0ef41Sopenharmony_ci return UV_EPERM; 1611cb0ef41Sopenharmony_ci} 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ciint uv_uptime(double* uptime) { 1651cb0ef41Sopenharmony_ci time_t now; 1661cb0ef41Sopenharmony_ci struct timeval info; 1671cb0ef41Sopenharmony_ci size_t size = sizeof(info); 1681cb0ef41Sopenharmony_ci static int which[] = {CTL_KERN, KERN_BOOTTIME}; 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) 1711cb0ef41Sopenharmony_ci return UV__ERR(errno); 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_ci now = time(NULL); 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci *uptime = (double)(now - info.tv_sec); 1761cb0ef41Sopenharmony_ci return 0; 1771cb0ef41Sopenharmony_ci} 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_ciint uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 1811cb0ef41Sopenharmony_ci unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK); 1821cb0ef41Sopenharmony_ci unsigned int multiplier = ((uint64_t)1000L / ticks); 1831cb0ef41Sopenharmony_ci unsigned int cur = 0; 1841cb0ef41Sopenharmony_ci uv_cpu_info_t* cpu_info; 1851cb0ef41Sopenharmony_ci u_int64_t* cp_times; 1861cb0ef41Sopenharmony_ci char model[512]; 1871cb0ef41Sopenharmony_ci u_int64_t cpuspeed; 1881cb0ef41Sopenharmony_ci int numcpus; 1891cb0ef41Sopenharmony_ci size_t size; 1901cb0ef41Sopenharmony_ci int i; 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci size = sizeof(model); 1931cb0ef41Sopenharmony_ci if (sysctlbyname("machdep.cpu_brand", &model, &size, NULL, 0) && 1941cb0ef41Sopenharmony_ci sysctlbyname("hw.model", &model, &size, NULL, 0)) { 1951cb0ef41Sopenharmony_ci return UV__ERR(errno); 1961cb0ef41Sopenharmony_ci } 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci size = sizeof(numcpus); 1991cb0ef41Sopenharmony_ci if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0)) 2001cb0ef41Sopenharmony_ci return UV__ERR(errno); 2011cb0ef41Sopenharmony_ci *count = numcpus; 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci /* Only i386 and amd64 have machdep.tsc_freq */ 2041cb0ef41Sopenharmony_ci size = sizeof(cpuspeed); 2051cb0ef41Sopenharmony_ci if (sysctlbyname("machdep.tsc_freq", &cpuspeed, &size, NULL, 0)) 2061cb0ef41Sopenharmony_ci cpuspeed = 0; 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci size = numcpus * CPUSTATES * sizeof(*cp_times); 2091cb0ef41Sopenharmony_ci cp_times = uv__malloc(size); 2101cb0ef41Sopenharmony_ci if (cp_times == NULL) 2111cb0ef41Sopenharmony_ci return UV_ENOMEM; 2121cb0ef41Sopenharmony_ci 2131cb0ef41Sopenharmony_ci if (sysctlbyname("kern.cp_time", cp_times, &size, NULL, 0)) 2141cb0ef41Sopenharmony_ci return UV__ERR(errno); 2151cb0ef41Sopenharmony_ci 2161cb0ef41Sopenharmony_ci *cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos)); 2171cb0ef41Sopenharmony_ci if (!(*cpu_infos)) { 2181cb0ef41Sopenharmony_ci uv__free(cp_times); 2191cb0ef41Sopenharmony_ci uv__free(*cpu_infos); 2201cb0ef41Sopenharmony_ci return UV_ENOMEM; 2211cb0ef41Sopenharmony_ci } 2221cb0ef41Sopenharmony_ci 2231cb0ef41Sopenharmony_ci for (i = 0; i < numcpus; i++) { 2241cb0ef41Sopenharmony_ci cpu_info = &(*cpu_infos)[i]; 2251cb0ef41Sopenharmony_ci cpu_info->cpu_times.user = (uint64_t)(cp_times[CP_USER+cur]) * multiplier; 2261cb0ef41Sopenharmony_ci cpu_info->cpu_times.nice = (uint64_t)(cp_times[CP_NICE+cur]) * multiplier; 2271cb0ef41Sopenharmony_ci cpu_info->cpu_times.sys = (uint64_t)(cp_times[CP_SYS+cur]) * multiplier; 2281cb0ef41Sopenharmony_ci cpu_info->cpu_times.idle = (uint64_t)(cp_times[CP_IDLE+cur]) * multiplier; 2291cb0ef41Sopenharmony_ci cpu_info->cpu_times.irq = (uint64_t)(cp_times[CP_INTR+cur]) * multiplier; 2301cb0ef41Sopenharmony_ci cpu_info->model = uv__strdup(model); 2311cb0ef41Sopenharmony_ci cpu_info->speed = (int)(cpuspeed/(uint64_t) 1e6); 2321cb0ef41Sopenharmony_ci cur += CPUSTATES; 2331cb0ef41Sopenharmony_ci } 2341cb0ef41Sopenharmony_ci uv__free(cp_times); 2351cb0ef41Sopenharmony_ci return 0; 2361cb0ef41Sopenharmony_ci} 2371cb0ef41Sopenharmony_ci 2381cb0ef41Sopenharmony_ciint uv__random_sysctl(void* buf, size_t len) { 2391cb0ef41Sopenharmony_ci static int name[] = {CTL_KERN, KERN_ARND}; 2401cb0ef41Sopenharmony_ci size_t count, req; 2411cb0ef41Sopenharmony_ci unsigned char* p; 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ci p = buf; 2441cb0ef41Sopenharmony_ci while (len) { 2451cb0ef41Sopenharmony_ci req = len < 32 ? len : 32; 2461cb0ef41Sopenharmony_ci count = req; 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_ci if (sysctl(name, ARRAY_SIZE(name), p, &count, NULL, 0) == -1) 2491cb0ef41Sopenharmony_ci return UV__ERR(errno); 2501cb0ef41Sopenharmony_ci 2511cb0ef41Sopenharmony_ci if (count != req) 2521cb0ef41Sopenharmony_ci return UV_EIO; /* Can't happen. */ 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ci p += count; 2551cb0ef41Sopenharmony_ci len -= count; 2561cb0ef41Sopenharmony_ci } 2571cb0ef41Sopenharmony_ci 2581cb0ef41Sopenharmony_ci return 0; 2591cb0ef41Sopenharmony_ci} 260