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