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 <paths.h> 291cb0ef41Sopenharmony_ci#include <sys/user.h> 301cb0ef41Sopenharmony_ci#include <sys/types.h> 311cb0ef41Sopenharmony_ci#include <sys/resource.h> 321cb0ef41Sopenharmony_ci#include <sys/sysctl.h> 331cb0ef41Sopenharmony_ci#include <vm/vm_param.h> /* VM_LOADAVG */ 341cb0ef41Sopenharmony_ci#include <time.h> 351cb0ef41Sopenharmony_ci#include <stdlib.h> 361cb0ef41Sopenharmony_ci#include <unistd.h> /* sysconf */ 371cb0ef41Sopenharmony_ci#include <fcntl.h> 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci#ifndef CPUSTATES 401cb0ef41Sopenharmony_ci# define CPUSTATES 5U 411cb0ef41Sopenharmony_ci#endif 421cb0ef41Sopenharmony_ci#ifndef CP_USER 431cb0ef41Sopenharmony_ci# define CP_USER 0 441cb0ef41Sopenharmony_ci# define CP_NICE 1 451cb0ef41Sopenharmony_ci# define CP_SYS 2 461cb0ef41Sopenharmony_ci# define CP_IDLE 3 471cb0ef41Sopenharmony_ci# define CP_INTR 4 481cb0ef41Sopenharmony_ci#endif 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ciint uv__platform_loop_init(uv_loop_t* loop) { 521cb0ef41Sopenharmony_ci return uv__kqueue_init(loop); 531cb0ef41Sopenharmony_ci} 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_civoid uv__platform_loop_delete(uv_loop_t* loop) { 571cb0ef41Sopenharmony_ci} 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ciint uv_exepath(char* buffer, size_t* size) { 601cb0ef41Sopenharmony_ci char abspath[PATH_MAX * 2 + 1]; 611cb0ef41Sopenharmony_ci int mib[4]; 621cb0ef41Sopenharmony_ci size_t abspath_size; 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci if (buffer == NULL || size == NULL || *size == 0) 651cb0ef41Sopenharmony_ci return UV_EINVAL; 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci mib[0] = CTL_KERN; 681cb0ef41Sopenharmony_ci mib[1] = KERN_PROC; 691cb0ef41Sopenharmony_ci mib[2] = KERN_PROC_PATHNAME; 701cb0ef41Sopenharmony_ci mib[3] = -1; 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci abspath_size = sizeof abspath; 731cb0ef41Sopenharmony_ci if (sysctl(mib, ARRAY_SIZE(mib), abspath, &abspath_size, NULL, 0)) 741cb0ef41Sopenharmony_ci return UV__ERR(errno); 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci assert(abspath_size > 0); 771cb0ef41Sopenharmony_ci abspath_size -= 1; 781cb0ef41Sopenharmony_ci *size -= 1; 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci if (*size > abspath_size) 811cb0ef41Sopenharmony_ci *size = abspath_size; 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci memcpy(buffer, abspath, *size); 841cb0ef41Sopenharmony_ci buffer[*size] = '\0'; 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_ci return 0; 871cb0ef41Sopenharmony_ci} 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ciuint64_t uv_get_free_memory(void) { 901cb0ef41Sopenharmony_ci int freecount; 911cb0ef41Sopenharmony_ci size_t size = sizeof(freecount); 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci if (sysctlbyname("vm.stats.vm.v_free_count", &freecount, &size, NULL, 0)) 941cb0ef41Sopenharmony_ci return UV__ERR(errno); 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci return (uint64_t) freecount * sysconf(_SC_PAGESIZE); 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci} 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ciuint64_t uv_get_total_memory(void) { 1021cb0ef41Sopenharmony_ci unsigned long info; 1031cb0ef41Sopenharmony_ci int which[] = {CTL_HW, HW_PHYSMEM}; 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci size_t size = sizeof(info); 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ci if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) 1081cb0ef41Sopenharmony_ci return UV__ERR(errno); 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci return (uint64_t) info; 1111cb0ef41Sopenharmony_ci} 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ciuint64_t uv_get_constrained_memory(void) { 1151cb0ef41Sopenharmony_ci return 0; /* Memory constraints are unknown. */ 1161cb0ef41Sopenharmony_ci} 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_civoid uv_loadavg(double avg[3]) { 1201cb0ef41Sopenharmony_ci struct loadavg info; 1211cb0ef41Sopenharmony_ci size_t size = sizeof(info); 1221cb0ef41Sopenharmony_ci int which[] = {CTL_VM, VM_LOADAVG}; 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0) < 0) return; 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_ci avg[0] = (double) info.ldavg[0] / info.fscale; 1271cb0ef41Sopenharmony_ci avg[1] = (double) info.ldavg[1] / info.fscale; 1281cb0ef41Sopenharmony_ci avg[2] = (double) info.ldavg[2] / info.fscale; 1291cb0ef41Sopenharmony_ci} 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ciint uv_resident_set_memory(size_t* rss) { 1331cb0ef41Sopenharmony_ci struct kinfo_proc kinfo; 1341cb0ef41Sopenharmony_ci size_t page_size; 1351cb0ef41Sopenharmony_ci size_t kinfo_size; 1361cb0ef41Sopenharmony_ci int mib[4]; 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci mib[0] = CTL_KERN; 1391cb0ef41Sopenharmony_ci mib[1] = KERN_PROC; 1401cb0ef41Sopenharmony_ci mib[2] = KERN_PROC_PID; 1411cb0ef41Sopenharmony_ci mib[3] = getpid(); 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ci kinfo_size = sizeof(kinfo); 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci if (sysctl(mib, ARRAY_SIZE(mib), &kinfo, &kinfo_size, NULL, 0)) 1461cb0ef41Sopenharmony_ci return UV__ERR(errno); 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ci page_size = getpagesize(); 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci#ifdef __DragonFly__ 1511cb0ef41Sopenharmony_ci *rss = kinfo.kp_vm_rssize * page_size; 1521cb0ef41Sopenharmony_ci#else 1531cb0ef41Sopenharmony_ci *rss = kinfo.ki_rssize * page_size; 1541cb0ef41Sopenharmony_ci#endif 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci return 0; 1571cb0ef41Sopenharmony_ci} 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ciint uv_uptime(double* uptime) { 1611cb0ef41Sopenharmony_ci int r; 1621cb0ef41Sopenharmony_ci struct timespec sp; 1631cb0ef41Sopenharmony_ci r = clock_gettime(CLOCK_MONOTONIC, &sp); 1641cb0ef41Sopenharmony_ci if (r) 1651cb0ef41Sopenharmony_ci return UV__ERR(errno); 1661cb0ef41Sopenharmony_ci 1671cb0ef41Sopenharmony_ci *uptime = sp.tv_sec; 1681cb0ef41Sopenharmony_ci return 0; 1691cb0ef41Sopenharmony_ci} 1701cb0ef41Sopenharmony_ci 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_ciint uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { 1731cb0ef41Sopenharmony_ci unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK), 1741cb0ef41Sopenharmony_ci multiplier = ((uint64_t)1000L / ticks), cpuspeed, maxcpus, 1751cb0ef41Sopenharmony_ci cur = 0; 1761cb0ef41Sopenharmony_ci uv_cpu_info_t* cpu_info; 1771cb0ef41Sopenharmony_ci const char* maxcpus_key; 1781cb0ef41Sopenharmony_ci const char* cptimes_key; 1791cb0ef41Sopenharmony_ci const char* model_key; 1801cb0ef41Sopenharmony_ci char model[512]; 1811cb0ef41Sopenharmony_ci long* cp_times; 1821cb0ef41Sopenharmony_ci int numcpus; 1831cb0ef41Sopenharmony_ci size_t size; 1841cb0ef41Sopenharmony_ci int i; 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci#if defined(__DragonFly__) 1871cb0ef41Sopenharmony_ci /* This is not quite correct but DragonFlyBSD doesn't seem to have anything 1881cb0ef41Sopenharmony_ci * comparable to kern.smp.maxcpus or kern.cp_times (kern.cp_time is a total, 1891cb0ef41Sopenharmony_ci * not per CPU). At least this stops uv_cpu_info() from failing completely. 1901cb0ef41Sopenharmony_ci */ 1911cb0ef41Sopenharmony_ci maxcpus_key = "hw.ncpu"; 1921cb0ef41Sopenharmony_ci cptimes_key = "kern.cp_time"; 1931cb0ef41Sopenharmony_ci#else 1941cb0ef41Sopenharmony_ci maxcpus_key = "kern.smp.maxcpus"; 1951cb0ef41Sopenharmony_ci cptimes_key = "kern.cp_times"; 1961cb0ef41Sopenharmony_ci#endif 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci#if defined(__arm__) || defined(__aarch64__) 1991cb0ef41Sopenharmony_ci /* The key hw.model and hw.clockrate are not available on FreeBSD ARM. */ 2001cb0ef41Sopenharmony_ci model_key = "hw.machine"; 2011cb0ef41Sopenharmony_ci cpuspeed = 0; 2021cb0ef41Sopenharmony_ci#else 2031cb0ef41Sopenharmony_ci model_key = "hw.model"; 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_ci size = sizeof(cpuspeed); 2061cb0ef41Sopenharmony_ci if (sysctlbyname("hw.clockrate", &cpuspeed, &size, NULL, 0)) 2071cb0ef41Sopenharmony_ci return -errno; 2081cb0ef41Sopenharmony_ci#endif 2091cb0ef41Sopenharmony_ci 2101cb0ef41Sopenharmony_ci size = sizeof(model); 2111cb0ef41Sopenharmony_ci if (sysctlbyname(model_key, &model, &size, NULL, 0)) 2121cb0ef41Sopenharmony_ci return UV__ERR(errno); 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci size = sizeof(numcpus); 2151cb0ef41Sopenharmony_ci if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0)) 2161cb0ef41Sopenharmony_ci return UV__ERR(errno); 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_ci *cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos)); 2191cb0ef41Sopenharmony_ci if (!(*cpu_infos)) 2201cb0ef41Sopenharmony_ci return UV_ENOMEM; 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_ci *count = numcpus; 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_ci /* kern.cp_times on FreeBSD i386 gives an array up to maxcpus instead of 2251cb0ef41Sopenharmony_ci * ncpu. 2261cb0ef41Sopenharmony_ci */ 2271cb0ef41Sopenharmony_ci size = sizeof(maxcpus); 2281cb0ef41Sopenharmony_ci if (sysctlbyname(maxcpus_key, &maxcpus, &size, NULL, 0)) { 2291cb0ef41Sopenharmony_ci uv__free(*cpu_infos); 2301cb0ef41Sopenharmony_ci return UV__ERR(errno); 2311cb0ef41Sopenharmony_ci } 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci size = maxcpus * CPUSTATES * sizeof(long); 2341cb0ef41Sopenharmony_ci 2351cb0ef41Sopenharmony_ci cp_times = uv__malloc(size); 2361cb0ef41Sopenharmony_ci if (cp_times == NULL) { 2371cb0ef41Sopenharmony_ci uv__free(*cpu_infos); 2381cb0ef41Sopenharmony_ci return UV_ENOMEM; 2391cb0ef41Sopenharmony_ci } 2401cb0ef41Sopenharmony_ci 2411cb0ef41Sopenharmony_ci if (sysctlbyname(cptimes_key, cp_times, &size, NULL, 0)) { 2421cb0ef41Sopenharmony_ci uv__free(cp_times); 2431cb0ef41Sopenharmony_ci uv__free(*cpu_infos); 2441cb0ef41Sopenharmony_ci return UV__ERR(errno); 2451cb0ef41Sopenharmony_ci } 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci for (i = 0; i < numcpus; i++) { 2481cb0ef41Sopenharmony_ci cpu_info = &(*cpu_infos)[i]; 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ci cpu_info->cpu_times.user = (uint64_t)(cp_times[CP_USER+cur]) * multiplier; 2511cb0ef41Sopenharmony_ci cpu_info->cpu_times.nice = (uint64_t)(cp_times[CP_NICE+cur]) * multiplier; 2521cb0ef41Sopenharmony_ci cpu_info->cpu_times.sys = (uint64_t)(cp_times[CP_SYS+cur]) * multiplier; 2531cb0ef41Sopenharmony_ci cpu_info->cpu_times.idle = (uint64_t)(cp_times[CP_IDLE+cur]) * multiplier; 2541cb0ef41Sopenharmony_ci cpu_info->cpu_times.irq = (uint64_t)(cp_times[CP_INTR+cur]) * multiplier; 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ci cpu_info->model = uv__strdup(model); 2571cb0ef41Sopenharmony_ci cpu_info->speed = cpuspeed; 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci cur+=CPUSTATES; 2601cb0ef41Sopenharmony_ci } 2611cb0ef41Sopenharmony_ci 2621cb0ef41Sopenharmony_ci uv__free(cp_times); 2631cb0ef41Sopenharmony_ci return 0; 2641cb0ef41Sopenharmony_ci} 2651cb0ef41Sopenharmony_ci 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_ciint uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) { 2681cb0ef41Sopenharmony_ci#if __FreeBSD__ >= 11 && !defined(__DragonFly__) 2691cb0ef41Sopenharmony_ci return sendmmsg(fd, 2701cb0ef41Sopenharmony_ci (struct mmsghdr*) mmsg, 2711cb0ef41Sopenharmony_ci vlen, 2721cb0ef41Sopenharmony_ci 0 /* flags */); 2731cb0ef41Sopenharmony_ci#else 2741cb0ef41Sopenharmony_ci return errno = ENOSYS, -1; 2751cb0ef41Sopenharmony_ci#endif 2761cb0ef41Sopenharmony_ci} 2771cb0ef41Sopenharmony_ci 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ciint uv__recvmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) { 2801cb0ef41Sopenharmony_ci#if __FreeBSD__ >= 11 && !defined(__DragonFly__) 2811cb0ef41Sopenharmony_ci return recvmmsg(fd, 2821cb0ef41Sopenharmony_ci (struct mmsghdr*) mmsg, 2831cb0ef41Sopenharmony_ci vlen, 2841cb0ef41Sopenharmony_ci 0 /* flags */, 2851cb0ef41Sopenharmony_ci NULL /* timeout */); 2861cb0ef41Sopenharmony_ci#else 2871cb0ef41Sopenharmony_ci return errno = ENOSYS, -1; 2881cb0ef41Sopenharmony_ci#endif 2891cb0ef41Sopenharmony_ci} 2901cb0ef41Sopenharmony_ci 2911cb0ef41Sopenharmony_cissize_t 2921cb0ef41Sopenharmony_ciuv__fs_copy_file_range(int fd_in, 2931cb0ef41Sopenharmony_ci off_t* off_in, 2941cb0ef41Sopenharmony_ci int fd_out, 2951cb0ef41Sopenharmony_ci off_t* off_out, 2961cb0ef41Sopenharmony_ci size_t len, 2971cb0ef41Sopenharmony_ci unsigned int flags) 2981cb0ef41Sopenharmony_ci{ 2991cb0ef41Sopenharmony_ci#if __FreeBSD__ >= 13 && !defined(__DragonFly__) 3001cb0ef41Sopenharmony_ci return copy_file_range(fd_in, off_in, fd_out, off_out, len, flags); 3011cb0ef41Sopenharmony_ci#else 3021cb0ef41Sopenharmony_ci return errno = ENOSYS, -1; 3031cb0ef41Sopenharmony_ci#endif 3041cb0ef41Sopenharmony_ci} 305