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 <paths.h> 29e66f31c5Sopenharmony_ci#include <sys/user.h> 30e66f31c5Sopenharmony_ci#include <sys/types.h> 31e66f31c5Sopenharmony_ci#include <sys/resource.h> 32e66f31c5Sopenharmony_ci#include <sys/sysctl.h> 33e66f31c5Sopenharmony_ci#include <vm/vm_param.h> /* VM_LOADAVG */ 34e66f31c5Sopenharmony_ci#include <time.h> 35e66f31c5Sopenharmony_ci#include <stdlib.h> 36e66f31c5Sopenharmony_ci#include <unistd.h> /* sysconf */ 37e66f31c5Sopenharmony_ci#include <fcntl.h> 38e66f31c5Sopenharmony_ci 39e66f31c5Sopenharmony_ci#ifndef CPUSTATES 40e66f31c5Sopenharmony_ci# define CPUSTATES 5U 41e66f31c5Sopenharmony_ci#endif 42e66f31c5Sopenharmony_ci#ifndef CP_USER 43e66f31c5Sopenharmony_ci# define CP_USER 0 44e66f31c5Sopenharmony_ci# define CP_NICE 1 45e66f31c5Sopenharmony_ci# define CP_SYS 2 46e66f31c5Sopenharmony_ci# define CP_IDLE 3 47e66f31c5Sopenharmony_ci# define CP_INTR 4 48e66f31c5Sopenharmony_ci#endif 49e66f31c5Sopenharmony_ci 50e66f31c5Sopenharmony_ci 51e66f31c5Sopenharmony_ciint uv__platform_loop_init(uv_loop_t* loop) { 52e66f31c5Sopenharmony_ci return uv__kqueue_init(loop); 53e66f31c5Sopenharmony_ci} 54e66f31c5Sopenharmony_ci 55e66f31c5Sopenharmony_ci 56e66f31c5Sopenharmony_civoid uv__platform_loop_delete(uv_loop_t* loop) { 57e66f31c5Sopenharmony_ci} 58e66f31c5Sopenharmony_ci 59e66f31c5Sopenharmony_ciint uv_exepath(char* buffer, size_t* size) { 60e66f31c5Sopenharmony_ci char abspath[PATH_MAX * 2 + 1]; 61e66f31c5Sopenharmony_ci int mib[4]; 62e66f31c5Sopenharmony_ci size_t abspath_size; 63e66f31c5Sopenharmony_ci 64e66f31c5Sopenharmony_ci if (buffer == NULL || size == NULL || *size == 0) 65e66f31c5Sopenharmony_ci return UV_EINVAL; 66e66f31c5Sopenharmony_ci 67e66f31c5Sopenharmony_ci mib[0] = CTL_KERN; 68e66f31c5Sopenharmony_ci mib[1] = KERN_PROC; 69e66f31c5Sopenharmony_ci mib[2] = KERN_PROC_PATHNAME; 70e66f31c5Sopenharmony_ci mib[3] = -1; 71e66f31c5Sopenharmony_ci 72e66f31c5Sopenharmony_ci abspath_size = sizeof abspath; 73e66f31c5Sopenharmony_ci if (sysctl(mib, ARRAY_SIZE(mib), abspath, &abspath_size, NULL, 0)) 74e66f31c5Sopenharmony_ci return UV__ERR(errno); 75e66f31c5Sopenharmony_ci 76e66f31c5Sopenharmony_ci assert(abspath_size > 0); 77e66f31c5Sopenharmony_ci abspath_size -= 1; 78e66f31c5Sopenharmony_ci *size -= 1; 79e66f31c5Sopenharmony_ci 80e66f31c5Sopenharmony_ci if (*size > abspath_size) 81e66f31c5Sopenharmony_ci *size = abspath_size; 82e66f31c5Sopenharmony_ci 83e66f31c5Sopenharmony_ci memcpy(buffer, abspath, *size); 84e66f31c5Sopenharmony_ci buffer[*size] = '\0'; 85e66f31c5Sopenharmony_ci 86e66f31c5Sopenharmony_ci return 0; 87e66f31c5Sopenharmony_ci} 88e66f31c5Sopenharmony_ci 89e66f31c5Sopenharmony_ciuint64_t uv_get_free_memory(void) { 90e66f31c5Sopenharmony_ci int freecount; 91e66f31c5Sopenharmony_ci size_t size = sizeof(freecount); 92e66f31c5Sopenharmony_ci 93e66f31c5Sopenharmony_ci if (sysctlbyname("vm.stats.vm.v_free_count", &freecount, &size, NULL, 0)) 94e66f31c5Sopenharmony_ci return 0; 95e66f31c5Sopenharmony_ci 96e66f31c5Sopenharmony_ci return (uint64_t) freecount * sysconf(_SC_PAGESIZE); 97e66f31c5Sopenharmony_ci 98e66f31c5Sopenharmony_ci} 99e66f31c5Sopenharmony_ci 100e66f31c5Sopenharmony_ci 101e66f31c5Sopenharmony_ciuint64_t uv_get_total_memory(void) { 102e66f31c5Sopenharmony_ci unsigned long info; 103e66f31c5Sopenharmony_ci int which[] = {CTL_HW, HW_PHYSMEM}; 104e66f31c5Sopenharmony_ci 105e66f31c5Sopenharmony_ci size_t size = sizeof(info); 106e66f31c5Sopenharmony_ci 107e66f31c5Sopenharmony_ci if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) 108e66f31c5Sopenharmony_ci return 0; 109e66f31c5Sopenharmony_ci 110e66f31c5Sopenharmony_ci return (uint64_t) info; 111e66f31c5Sopenharmony_ci} 112e66f31c5Sopenharmony_ci 113e66f31c5Sopenharmony_ci 114e66f31c5Sopenharmony_ciuint64_t uv_get_constrained_memory(void) { 115e66f31c5Sopenharmony_ci return 0; /* Memory constraints are unknown. */ 116e66f31c5Sopenharmony_ci} 117e66f31c5Sopenharmony_ci 118e66f31c5Sopenharmony_ci 119e66f31c5Sopenharmony_ciuint64_t uv_get_available_memory(void) { 120e66f31c5Sopenharmony_ci return uv_get_free_memory(); 121e66f31c5Sopenharmony_ci} 122e66f31c5Sopenharmony_ci 123e66f31c5Sopenharmony_ci 124e66f31c5Sopenharmony_civoid uv_loadavg(double avg[3]) { 125e66f31c5Sopenharmony_ci struct loadavg info; 126e66f31c5Sopenharmony_ci size_t size = sizeof(info); 127e66f31c5Sopenharmony_ci int which[] = {CTL_VM, VM_LOADAVG}; 128e66f31c5Sopenharmony_ci 129e66f31c5Sopenharmony_ci if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0) < 0) return; 130e66f31c5Sopenharmony_ci 131e66f31c5Sopenharmony_ci avg[0] = (double) info.ldavg[0] / info.fscale; 132e66f31c5Sopenharmony_ci avg[1] = (double) info.ldavg[1] / info.fscale; 133e66f31c5Sopenharmony_ci avg[2] = (double) info.ldavg[2] / info.fscale; 134e66f31c5Sopenharmony_ci} 135e66f31c5Sopenharmony_ci 136e66f31c5Sopenharmony_ci 137e66f31c5Sopenharmony_ciint uv_resident_set_memory(size_t* rss) { 138e66f31c5Sopenharmony_ci struct kinfo_proc kinfo; 139e66f31c5Sopenharmony_ci size_t page_size; 140e66f31c5Sopenharmony_ci size_t kinfo_size; 141e66f31c5Sopenharmony_ci int mib[4]; 142e66f31c5Sopenharmony_ci 143e66f31c5Sopenharmony_ci mib[0] = CTL_KERN; 144e66f31c5Sopenharmony_ci mib[1] = KERN_PROC; 145e66f31c5Sopenharmony_ci mib[2] = KERN_PROC_PID; 146e66f31c5Sopenharmony_ci mib[3] = getpid(); 147e66f31c5Sopenharmony_ci 148e66f31c5Sopenharmony_ci kinfo_size = sizeof(kinfo); 149e66f31c5Sopenharmony_ci 150e66f31c5Sopenharmony_ci if (sysctl(mib, ARRAY_SIZE(mib), &kinfo, &kinfo_size, NULL, 0)) 151e66f31c5Sopenharmony_ci return UV__ERR(errno); 152e66f31c5Sopenharmony_ci 153e66f31c5Sopenharmony_ci page_size = getpagesize(); 154e66f31c5Sopenharmony_ci 155e66f31c5Sopenharmony_ci#ifdef __DragonFly__ 156e66f31c5Sopenharmony_ci *rss = kinfo.kp_vm_rssize * page_size; 157e66f31c5Sopenharmony_ci#else 158e66f31c5Sopenharmony_ci *rss = kinfo.ki_rssize * page_size; 159e66f31c5Sopenharmony_ci#endif 160e66f31c5Sopenharmony_ci 161e66f31c5Sopenharmony_ci return 0; 162e66f31c5Sopenharmony_ci} 163e66f31c5Sopenharmony_ci 164e66f31c5Sopenharmony_ci 165e66f31c5Sopenharmony_ciint uv_uptime(double* uptime) { 166e66f31c5Sopenharmony_ci int r; 167e66f31c5Sopenharmony_ci struct timespec sp; 168e66f31c5Sopenharmony_ci r = clock_gettime(CLOCK_MONOTONIC, &sp); 169e66f31c5Sopenharmony_ci if (r) 170e66f31c5Sopenharmony_ci return UV__ERR(errno); 171e66f31c5Sopenharmony_ci 172e66f31c5Sopenharmony_ci *uptime = sp.tv_sec; 173e66f31c5Sopenharmony_ci return 0; 174e66f31c5Sopenharmony_ci} 175e66f31c5Sopenharmony_ci 176e66f31c5Sopenharmony_ci 177e66f31c5Sopenharmony_ciint uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 178e66f31c5Sopenharmony_ci unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK), 179e66f31c5Sopenharmony_ci multiplier = ((uint64_t)1000L / ticks), cpuspeed, maxcpus, 180e66f31c5Sopenharmony_ci cur = 0; 181e66f31c5Sopenharmony_ci uv_cpu_info_t* cpu_info; 182e66f31c5Sopenharmony_ci const char* maxcpus_key; 183e66f31c5Sopenharmony_ci const char* cptimes_key; 184e66f31c5Sopenharmony_ci const char* model_key; 185e66f31c5Sopenharmony_ci char model[512]; 186e66f31c5Sopenharmony_ci long* cp_times; 187e66f31c5Sopenharmony_ci int numcpus; 188e66f31c5Sopenharmony_ci size_t size; 189e66f31c5Sopenharmony_ci int i; 190e66f31c5Sopenharmony_ci 191e66f31c5Sopenharmony_ci#if defined(__DragonFly__) 192e66f31c5Sopenharmony_ci /* This is not quite correct but DragonFlyBSD doesn't seem to have anything 193e66f31c5Sopenharmony_ci * comparable to kern.smp.maxcpus or kern.cp_times (kern.cp_time is a total, 194e66f31c5Sopenharmony_ci * not per CPU). At least this stops uv_cpu_info() from failing completely. 195e66f31c5Sopenharmony_ci */ 196e66f31c5Sopenharmony_ci maxcpus_key = "hw.ncpu"; 197e66f31c5Sopenharmony_ci cptimes_key = "kern.cp_time"; 198e66f31c5Sopenharmony_ci#else 199e66f31c5Sopenharmony_ci maxcpus_key = "kern.smp.maxcpus"; 200e66f31c5Sopenharmony_ci cptimes_key = "kern.cp_times"; 201e66f31c5Sopenharmony_ci#endif 202e66f31c5Sopenharmony_ci 203e66f31c5Sopenharmony_ci#if defined(__arm__) || defined(__aarch64__) 204e66f31c5Sopenharmony_ci /* The key hw.model and hw.clockrate are not available on FreeBSD ARM. */ 205e66f31c5Sopenharmony_ci model_key = "hw.machine"; 206e66f31c5Sopenharmony_ci cpuspeed = 0; 207e66f31c5Sopenharmony_ci#else 208e66f31c5Sopenharmony_ci model_key = "hw.model"; 209e66f31c5Sopenharmony_ci 210e66f31c5Sopenharmony_ci size = sizeof(cpuspeed); 211e66f31c5Sopenharmony_ci if (sysctlbyname("hw.clockrate", &cpuspeed, &size, NULL, 0)) 212e66f31c5Sopenharmony_ci return -errno; 213e66f31c5Sopenharmony_ci#endif 214e66f31c5Sopenharmony_ci 215e66f31c5Sopenharmony_ci size = sizeof(model); 216e66f31c5Sopenharmony_ci if (sysctlbyname(model_key, &model, &size, NULL, 0)) 217e66f31c5Sopenharmony_ci return UV__ERR(errno); 218e66f31c5Sopenharmony_ci 219e66f31c5Sopenharmony_ci size = sizeof(numcpus); 220e66f31c5Sopenharmony_ci if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0)) 221e66f31c5Sopenharmony_ci return UV__ERR(errno); 222e66f31c5Sopenharmony_ci 223e66f31c5Sopenharmony_ci *cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos)); 224e66f31c5Sopenharmony_ci if (!(*cpu_infos)) 225e66f31c5Sopenharmony_ci return UV_ENOMEM; 226e66f31c5Sopenharmony_ci 227e66f31c5Sopenharmony_ci *count = numcpus; 228e66f31c5Sopenharmony_ci 229e66f31c5Sopenharmony_ci /* kern.cp_times on FreeBSD i386 gives an array up to maxcpus instead of 230e66f31c5Sopenharmony_ci * ncpu. 231e66f31c5Sopenharmony_ci */ 232e66f31c5Sopenharmony_ci size = sizeof(maxcpus); 233e66f31c5Sopenharmony_ci if (sysctlbyname(maxcpus_key, &maxcpus, &size, NULL, 0)) { 234e66f31c5Sopenharmony_ci uv__free(*cpu_infos); 235e66f31c5Sopenharmony_ci return UV__ERR(errno); 236e66f31c5Sopenharmony_ci } 237e66f31c5Sopenharmony_ci 238e66f31c5Sopenharmony_ci size = maxcpus * CPUSTATES * sizeof(long); 239e66f31c5Sopenharmony_ci 240e66f31c5Sopenharmony_ci cp_times = uv__malloc(size); 241e66f31c5Sopenharmony_ci if (cp_times == NULL) { 242e66f31c5Sopenharmony_ci uv__free(*cpu_infos); 243e66f31c5Sopenharmony_ci return UV_ENOMEM; 244e66f31c5Sopenharmony_ci } 245e66f31c5Sopenharmony_ci 246e66f31c5Sopenharmony_ci if (sysctlbyname(cptimes_key, cp_times, &size, NULL, 0)) { 247e66f31c5Sopenharmony_ci uv__free(cp_times); 248e66f31c5Sopenharmony_ci uv__free(*cpu_infos); 249e66f31c5Sopenharmony_ci return UV__ERR(errno); 250e66f31c5Sopenharmony_ci } 251e66f31c5Sopenharmony_ci 252e66f31c5Sopenharmony_ci for (i = 0; i < numcpus; i++) { 253e66f31c5Sopenharmony_ci cpu_info = &(*cpu_infos)[i]; 254e66f31c5Sopenharmony_ci 255e66f31c5Sopenharmony_ci cpu_info->cpu_times.user = (uint64_t)(cp_times[CP_USER+cur]) * multiplier; 256e66f31c5Sopenharmony_ci cpu_info->cpu_times.nice = (uint64_t)(cp_times[CP_NICE+cur]) * multiplier; 257e66f31c5Sopenharmony_ci cpu_info->cpu_times.sys = (uint64_t)(cp_times[CP_SYS+cur]) * multiplier; 258e66f31c5Sopenharmony_ci cpu_info->cpu_times.idle = (uint64_t)(cp_times[CP_IDLE+cur]) * multiplier; 259e66f31c5Sopenharmony_ci cpu_info->cpu_times.irq = (uint64_t)(cp_times[CP_INTR+cur]) * multiplier; 260e66f31c5Sopenharmony_ci 261e66f31c5Sopenharmony_ci cpu_info->model = uv__strdup(model); 262e66f31c5Sopenharmony_ci cpu_info->speed = cpuspeed; 263e66f31c5Sopenharmony_ci 264e66f31c5Sopenharmony_ci cur+=CPUSTATES; 265e66f31c5Sopenharmony_ci } 266e66f31c5Sopenharmony_ci 267e66f31c5Sopenharmony_ci uv__free(cp_times); 268e66f31c5Sopenharmony_ci return 0; 269e66f31c5Sopenharmony_ci} 270e66f31c5Sopenharmony_ci 271e66f31c5Sopenharmony_ci 272e66f31c5Sopenharmony_cissize_t 273e66f31c5Sopenharmony_ciuv__fs_copy_file_range(int fd_in, 274e66f31c5Sopenharmony_ci off_t* off_in, 275e66f31c5Sopenharmony_ci int fd_out, 276e66f31c5Sopenharmony_ci off_t* off_out, 277e66f31c5Sopenharmony_ci size_t len, 278e66f31c5Sopenharmony_ci unsigned int flags) 279e66f31c5Sopenharmony_ci{ 280e66f31c5Sopenharmony_ci#if __FreeBSD__ >= 13 && !defined(__DragonFly__) 281e66f31c5Sopenharmony_ci return copy_file_range(fd_in, off_in, fd_out, off_out, len, flags); 282e66f31c5Sopenharmony_ci#else 283e66f31c5Sopenharmony_ci return errno = ENOSYS, -1; 284e66f31c5Sopenharmony_ci#endif 285e66f31c5Sopenharmony_ci} 286