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 <assert.h> 25e66f31c5Sopenharmony_ci#include <string.h> 26e66f31c5Sopenharmony_ci#include <errno.h> 27e66f31c5Sopenharmony_ci 28e66f31c5Sopenharmony_ci#include <kvm.h> 29e66f31c5Sopenharmony_ci#include <paths.h> 30e66f31c5Sopenharmony_ci#include <unistd.h> 31e66f31c5Sopenharmony_ci#include <time.h> 32e66f31c5Sopenharmony_ci#include <stdlib.h> 33e66f31c5Sopenharmony_ci#include <fcntl.h> 34e66f31c5Sopenharmony_ci 35e66f31c5Sopenharmony_ci#include <sys/resource.h> 36e66f31c5Sopenharmony_ci#include <sys/types.h> 37e66f31c5Sopenharmony_ci#include <sys/sysctl.h> 38e66f31c5Sopenharmony_ci#include <uvm/uvm_extern.h> 39e66f31c5Sopenharmony_ci 40e66f31c5Sopenharmony_ci#include <unistd.h> 41e66f31c5Sopenharmony_ci#include <time.h> 42e66f31c5Sopenharmony_ci 43e66f31c5Sopenharmony_ci 44e66f31c5Sopenharmony_ciint uv__platform_loop_init(uv_loop_t* loop) { 45e66f31c5Sopenharmony_ci return uv__kqueue_init(loop); 46e66f31c5Sopenharmony_ci} 47e66f31c5Sopenharmony_ci 48e66f31c5Sopenharmony_ci 49e66f31c5Sopenharmony_civoid uv__platform_loop_delete(uv_loop_t* loop) { 50e66f31c5Sopenharmony_ci} 51e66f31c5Sopenharmony_ci 52e66f31c5Sopenharmony_ci 53e66f31c5Sopenharmony_civoid uv_loadavg(double avg[3]) { 54e66f31c5Sopenharmony_ci struct loadavg info; 55e66f31c5Sopenharmony_ci size_t size = sizeof(info); 56e66f31c5Sopenharmony_ci int which[] = {CTL_VM, VM_LOADAVG}; 57e66f31c5Sopenharmony_ci 58e66f31c5Sopenharmony_ci if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0) == -1) return; 59e66f31c5Sopenharmony_ci 60e66f31c5Sopenharmony_ci avg[0] = (double) info.ldavg[0] / info.fscale; 61e66f31c5Sopenharmony_ci avg[1] = (double) info.ldavg[1] / info.fscale; 62e66f31c5Sopenharmony_ci avg[2] = (double) info.ldavg[2] / info.fscale; 63e66f31c5Sopenharmony_ci} 64e66f31c5Sopenharmony_ci 65e66f31c5Sopenharmony_ci 66e66f31c5Sopenharmony_ciint uv_exepath(char* buffer, size_t* size) { 67e66f31c5Sopenharmony_ci /* Intermediate buffer, retrieving partial path name does not work 68e66f31c5Sopenharmony_ci * As of NetBSD-8(beta), vnode->path translator does not handle files 69e66f31c5Sopenharmony_ci * with longer names than 31 characters. 70e66f31c5Sopenharmony_ci */ 71e66f31c5Sopenharmony_ci char int_buf[PATH_MAX]; 72e66f31c5Sopenharmony_ci size_t int_size; 73e66f31c5Sopenharmony_ci int mib[4]; 74e66f31c5Sopenharmony_ci 75e66f31c5Sopenharmony_ci if (buffer == NULL || size == NULL || *size == 0) 76e66f31c5Sopenharmony_ci return UV_EINVAL; 77e66f31c5Sopenharmony_ci 78e66f31c5Sopenharmony_ci mib[0] = CTL_KERN; 79e66f31c5Sopenharmony_ci mib[1] = KERN_PROC_ARGS; 80e66f31c5Sopenharmony_ci mib[2] = -1; 81e66f31c5Sopenharmony_ci mib[3] = KERN_PROC_PATHNAME; 82e66f31c5Sopenharmony_ci int_size = ARRAY_SIZE(int_buf); 83e66f31c5Sopenharmony_ci 84e66f31c5Sopenharmony_ci if (sysctl(mib, 4, int_buf, &int_size, NULL, 0)) 85e66f31c5Sopenharmony_ci return UV__ERR(errno); 86e66f31c5Sopenharmony_ci 87e66f31c5Sopenharmony_ci /* Copy string from the intermediate buffer to outer one with appropriate 88e66f31c5Sopenharmony_ci * length. 89e66f31c5Sopenharmony_ci */ 90e66f31c5Sopenharmony_ci /* TODO(bnoordhuis) Check uv__strscpy() return value. */ 91e66f31c5Sopenharmony_ci uv__strscpy(buffer, int_buf, *size); 92e66f31c5Sopenharmony_ci 93e66f31c5Sopenharmony_ci /* Set new size. */ 94e66f31c5Sopenharmony_ci *size = strlen(buffer); 95e66f31c5Sopenharmony_ci 96e66f31c5Sopenharmony_ci return 0; 97e66f31c5Sopenharmony_ci} 98e66f31c5Sopenharmony_ci 99e66f31c5Sopenharmony_ci 100e66f31c5Sopenharmony_ciuint64_t uv_get_free_memory(void) { 101e66f31c5Sopenharmony_ci struct uvmexp info; 102e66f31c5Sopenharmony_ci size_t size = sizeof(info); 103e66f31c5Sopenharmony_ci int which[] = {CTL_VM, VM_UVMEXP}; 104e66f31c5Sopenharmony_ci 105e66f31c5Sopenharmony_ci if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) 106e66f31c5Sopenharmony_ci return 0; 107e66f31c5Sopenharmony_ci 108e66f31c5Sopenharmony_ci return (uint64_t) info.free * sysconf(_SC_PAGESIZE); 109e66f31c5Sopenharmony_ci} 110e66f31c5Sopenharmony_ci 111e66f31c5Sopenharmony_ci 112e66f31c5Sopenharmony_ciuint64_t uv_get_total_memory(void) { 113e66f31c5Sopenharmony_ci#if defined(HW_PHYSMEM64) 114e66f31c5Sopenharmony_ci uint64_t info; 115e66f31c5Sopenharmony_ci int which[] = {CTL_HW, HW_PHYSMEM64}; 116e66f31c5Sopenharmony_ci#else 117e66f31c5Sopenharmony_ci unsigned int info; 118e66f31c5Sopenharmony_ci int which[] = {CTL_HW, HW_PHYSMEM}; 119e66f31c5Sopenharmony_ci#endif 120e66f31c5Sopenharmony_ci size_t size = sizeof(info); 121e66f31c5Sopenharmony_ci 122e66f31c5Sopenharmony_ci if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) 123e66f31c5Sopenharmony_ci return 0; 124e66f31c5Sopenharmony_ci 125e66f31c5Sopenharmony_ci return (uint64_t) info; 126e66f31c5Sopenharmony_ci} 127e66f31c5Sopenharmony_ci 128e66f31c5Sopenharmony_ci 129e66f31c5Sopenharmony_ciuint64_t uv_get_constrained_memory(void) { 130e66f31c5Sopenharmony_ci return 0; /* Memory constraints are unknown. */ 131e66f31c5Sopenharmony_ci} 132e66f31c5Sopenharmony_ci 133e66f31c5Sopenharmony_ci 134e66f31c5Sopenharmony_ciuint64_t uv_get_available_memory(void) { 135e66f31c5Sopenharmony_ci return uv_get_free_memory(); 136e66f31c5Sopenharmony_ci} 137e66f31c5Sopenharmony_ci 138e66f31c5Sopenharmony_ci 139e66f31c5Sopenharmony_ciint uv_resident_set_memory(size_t* rss) { 140e66f31c5Sopenharmony_ci kvm_t *kd = NULL; 141e66f31c5Sopenharmony_ci struct kinfo_proc2 *kinfo = NULL; 142e66f31c5Sopenharmony_ci pid_t pid; 143e66f31c5Sopenharmony_ci int nprocs; 144e66f31c5Sopenharmony_ci int max_size = sizeof(struct kinfo_proc2); 145e66f31c5Sopenharmony_ci int page_size; 146e66f31c5Sopenharmony_ci 147e66f31c5Sopenharmony_ci page_size = getpagesize(); 148e66f31c5Sopenharmony_ci pid = getpid(); 149e66f31c5Sopenharmony_ci 150e66f31c5Sopenharmony_ci kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, "kvm_open"); 151e66f31c5Sopenharmony_ci 152e66f31c5Sopenharmony_ci if (kd == NULL) goto error; 153e66f31c5Sopenharmony_ci 154e66f31c5Sopenharmony_ci kinfo = kvm_getproc2(kd, KERN_PROC_PID, pid, max_size, &nprocs); 155e66f31c5Sopenharmony_ci if (kinfo == NULL) goto error; 156e66f31c5Sopenharmony_ci 157e66f31c5Sopenharmony_ci *rss = kinfo->p_vm_rssize * page_size; 158e66f31c5Sopenharmony_ci 159e66f31c5Sopenharmony_ci kvm_close(kd); 160e66f31c5Sopenharmony_ci 161e66f31c5Sopenharmony_ci return 0; 162e66f31c5Sopenharmony_ci 163e66f31c5Sopenharmony_cierror: 164e66f31c5Sopenharmony_ci if (kd) kvm_close(kd); 165e66f31c5Sopenharmony_ci return UV_EPERM; 166e66f31c5Sopenharmony_ci} 167e66f31c5Sopenharmony_ci 168e66f31c5Sopenharmony_ci 169e66f31c5Sopenharmony_ciint uv_uptime(double* uptime) { 170e66f31c5Sopenharmony_ci time_t now; 171e66f31c5Sopenharmony_ci struct timeval info; 172e66f31c5Sopenharmony_ci size_t size = sizeof(info); 173e66f31c5Sopenharmony_ci static int which[] = {CTL_KERN, KERN_BOOTTIME}; 174e66f31c5Sopenharmony_ci 175e66f31c5Sopenharmony_ci if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) 176e66f31c5Sopenharmony_ci return UV__ERR(errno); 177e66f31c5Sopenharmony_ci 178e66f31c5Sopenharmony_ci now = time(NULL); 179e66f31c5Sopenharmony_ci 180e66f31c5Sopenharmony_ci *uptime = (double)(now - info.tv_sec); 181e66f31c5Sopenharmony_ci return 0; 182e66f31c5Sopenharmony_ci} 183e66f31c5Sopenharmony_ci 184e66f31c5Sopenharmony_ci 185e66f31c5Sopenharmony_ciint uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 186e66f31c5Sopenharmony_ci unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK); 187e66f31c5Sopenharmony_ci unsigned int multiplier = ((uint64_t)1000L / ticks); 188e66f31c5Sopenharmony_ci unsigned int cur = 0; 189e66f31c5Sopenharmony_ci uv_cpu_info_t* cpu_info; 190e66f31c5Sopenharmony_ci u_int64_t* cp_times; 191e66f31c5Sopenharmony_ci char model[512]; 192e66f31c5Sopenharmony_ci u_int64_t cpuspeed; 193e66f31c5Sopenharmony_ci int numcpus; 194e66f31c5Sopenharmony_ci size_t size; 195e66f31c5Sopenharmony_ci int i; 196e66f31c5Sopenharmony_ci 197e66f31c5Sopenharmony_ci size = sizeof(model); 198e66f31c5Sopenharmony_ci if (sysctlbyname("machdep.cpu_brand", &model, &size, NULL, 0) && 199e66f31c5Sopenharmony_ci sysctlbyname("hw.model", &model, &size, NULL, 0)) { 200e66f31c5Sopenharmony_ci return UV__ERR(errno); 201e66f31c5Sopenharmony_ci } 202e66f31c5Sopenharmony_ci 203e66f31c5Sopenharmony_ci size = sizeof(numcpus); 204e66f31c5Sopenharmony_ci if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0)) 205e66f31c5Sopenharmony_ci return UV__ERR(errno); 206e66f31c5Sopenharmony_ci *count = numcpus; 207e66f31c5Sopenharmony_ci 208e66f31c5Sopenharmony_ci /* Only i386 and amd64 have machdep.tsc_freq */ 209e66f31c5Sopenharmony_ci size = sizeof(cpuspeed); 210e66f31c5Sopenharmony_ci if (sysctlbyname("machdep.tsc_freq", &cpuspeed, &size, NULL, 0)) 211e66f31c5Sopenharmony_ci cpuspeed = 0; 212e66f31c5Sopenharmony_ci 213e66f31c5Sopenharmony_ci size = numcpus * CPUSTATES * sizeof(*cp_times); 214e66f31c5Sopenharmony_ci cp_times = uv__malloc(size); 215e66f31c5Sopenharmony_ci if (cp_times == NULL) 216e66f31c5Sopenharmony_ci return UV_ENOMEM; 217e66f31c5Sopenharmony_ci 218e66f31c5Sopenharmony_ci if (sysctlbyname("kern.cp_time", cp_times, &size, NULL, 0)) 219e66f31c5Sopenharmony_ci return UV__ERR(errno); 220e66f31c5Sopenharmony_ci 221e66f31c5Sopenharmony_ci *cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos)); 222e66f31c5Sopenharmony_ci if (!(*cpu_infos)) { 223e66f31c5Sopenharmony_ci uv__free(cp_times); 224e66f31c5Sopenharmony_ci uv__free(*cpu_infos); 225e66f31c5Sopenharmony_ci return UV_ENOMEM; 226e66f31c5Sopenharmony_ci } 227e66f31c5Sopenharmony_ci 228e66f31c5Sopenharmony_ci for (i = 0; i < numcpus; i++) { 229e66f31c5Sopenharmony_ci cpu_info = &(*cpu_infos)[i]; 230e66f31c5Sopenharmony_ci cpu_info->cpu_times.user = (uint64_t)(cp_times[CP_USER+cur]) * multiplier; 231e66f31c5Sopenharmony_ci cpu_info->cpu_times.nice = (uint64_t)(cp_times[CP_NICE+cur]) * multiplier; 232e66f31c5Sopenharmony_ci cpu_info->cpu_times.sys = (uint64_t)(cp_times[CP_SYS+cur]) * multiplier; 233e66f31c5Sopenharmony_ci cpu_info->cpu_times.idle = (uint64_t)(cp_times[CP_IDLE+cur]) * multiplier; 234e66f31c5Sopenharmony_ci cpu_info->cpu_times.irq = (uint64_t)(cp_times[CP_INTR+cur]) * multiplier; 235e66f31c5Sopenharmony_ci cpu_info->model = uv__strdup(model); 236e66f31c5Sopenharmony_ci cpu_info->speed = (int)(cpuspeed/(uint64_t) 1e6); 237e66f31c5Sopenharmony_ci cur += CPUSTATES; 238e66f31c5Sopenharmony_ci } 239e66f31c5Sopenharmony_ci uv__free(cp_times); 240e66f31c5Sopenharmony_ci return 0; 241e66f31c5Sopenharmony_ci} 242e66f31c5Sopenharmony_ci 243e66f31c5Sopenharmony_ciint uv__random_sysctl(void* buf, size_t len) { 244e66f31c5Sopenharmony_ci static int name[] = {CTL_KERN, KERN_ARND}; 245e66f31c5Sopenharmony_ci size_t count, req; 246e66f31c5Sopenharmony_ci unsigned char* p; 247e66f31c5Sopenharmony_ci 248e66f31c5Sopenharmony_ci p = buf; 249e66f31c5Sopenharmony_ci while (len) { 250e66f31c5Sopenharmony_ci req = len < 32 ? len : 32; 251e66f31c5Sopenharmony_ci count = req; 252e66f31c5Sopenharmony_ci 253e66f31c5Sopenharmony_ci if (sysctl(name, ARRAY_SIZE(name), p, &count, NULL, 0) == -1) 254e66f31c5Sopenharmony_ci return UV__ERR(errno); 255e66f31c5Sopenharmony_ci 256e66f31c5Sopenharmony_ci if (count != req) 257e66f31c5Sopenharmony_ci return UV_EIO; /* Can't happen. */ 258e66f31c5Sopenharmony_ci 259e66f31c5Sopenharmony_ci p += count; 260e66f31c5Sopenharmony_ci len -= count; 261e66f31c5Sopenharmony_ci } 262e66f31c5Sopenharmony_ci 263e66f31c5Sopenharmony_ci return 0; 264e66f31c5Sopenharmony_ci} 265