xref: /netbsd-src/external/mit/libuv/dist/src/unix/openbsd.c (revision 0e552da7216834a96e91ad098e59272b41087480)
1*0e552da7Schristos /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2*0e552da7Schristos  * Permission is hereby granted, free of charge, to any person obtaining a copy
3*0e552da7Schristos  * of this software and associated documentation files (the "Software"), to
4*0e552da7Schristos  * deal in the Software without restriction, including without limitation the
5*0e552da7Schristos  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
6*0e552da7Schristos  * sell copies of the Software, and to permit persons to whom the Software is
7*0e552da7Schristos  * furnished to do so, subject to the following conditions:
8*0e552da7Schristos  *
9*0e552da7Schristos  * The above copyright notice and this permission notice shall be included in
10*0e552da7Schristos  * all copies or substantial portions of the Software.
11*0e552da7Schristos  *
12*0e552da7Schristos  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13*0e552da7Schristos  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14*0e552da7Schristos  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15*0e552da7Schristos  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16*0e552da7Schristos  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17*0e552da7Schristos  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
18*0e552da7Schristos  * IN THE SOFTWARE.
19*0e552da7Schristos  */
20*0e552da7Schristos 
21*0e552da7Schristos #include "uv.h"
22*0e552da7Schristos #include "internal.h"
23*0e552da7Schristos 
24*0e552da7Schristos #include <sys/types.h>
25*0e552da7Schristos #include <sys/param.h>
26*0e552da7Schristos #include <sys/resource.h>
27*0e552da7Schristos #include <sys/sched.h>
28*0e552da7Schristos #include <sys/time.h>
29*0e552da7Schristos #include <sys/sysctl.h>
30*0e552da7Schristos 
31*0e552da7Schristos #include <errno.h>
32*0e552da7Schristos #include <fcntl.h>
33*0e552da7Schristos #include <paths.h>
34*0e552da7Schristos #include <stdlib.h>
35*0e552da7Schristos #include <string.h>
36*0e552da7Schristos #include <unistd.h>
37*0e552da7Schristos 
38*0e552da7Schristos 
uv__platform_loop_init(uv_loop_t * loop)39*0e552da7Schristos int uv__platform_loop_init(uv_loop_t* loop) {
40*0e552da7Schristos   return uv__kqueue_init(loop);
41*0e552da7Schristos }
42*0e552da7Schristos 
43*0e552da7Schristos 
uv__platform_loop_delete(uv_loop_t * loop)44*0e552da7Schristos void uv__platform_loop_delete(uv_loop_t* loop) {
45*0e552da7Schristos }
46*0e552da7Schristos 
47*0e552da7Schristos 
uv_loadavg(double avg[3])48*0e552da7Schristos void uv_loadavg(double avg[3]) {
49*0e552da7Schristos   struct loadavg info;
50*0e552da7Schristos   size_t size = sizeof(info);
51*0e552da7Schristos   int which[] = {CTL_VM, VM_LOADAVG};
52*0e552da7Schristos 
53*0e552da7Schristos   if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0) < 0) return;
54*0e552da7Schristos 
55*0e552da7Schristos   avg[0] = (double) info.ldavg[0] / info.fscale;
56*0e552da7Schristos   avg[1] = (double) info.ldavg[1] / info.fscale;
57*0e552da7Schristos   avg[2] = (double) info.ldavg[2] / info.fscale;
58*0e552da7Schristos }
59*0e552da7Schristos 
60*0e552da7Schristos 
uv_exepath(char * buffer,size_t * size)61*0e552da7Schristos int uv_exepath(char* buffer, size_t* size) {
62*0e552da7Schristos   int mib[4];
63*0e552da7Schristos   char **argsbuf = NULL;
64*0e552da7Schristos   size_t argsbuf_size = 100U;
65*0e552da7Schristos   size_t exepath_size;
66*0e552da7Schristos   pid_t mypid;
67*0e552da7Schristos   int err;
68*0e552da7Schristos 
69*0e552da7Schristos   if (buffer == NULL || size == NULL || *size == 0)
70*0e552da7Schristos     return UV_EINVAL;
71*0e552da7Schristos 
72*0e552da7Schristos   mypid = getpid();
73*0e552da7Schristos   for (;;) {
74*0e552da7Schristos     err = UV_ENOMEM;
75*0e552da7Schristos     argsbuf = uv__reallocf(argsbuf, argsbuf_size);
76*0e552da7Schristos     if (argsbuf == NULL)
77*0e552da7Schristos       goto out;
78*0e552da7Schristos     mib[0] = CTL_KERN;
79*0e552da7Schristos     mib[1] = KERN_PROC_ARGS;
80*0e552da7Schristos     mib[2] = mypid;
81*0e552da7Schristos     mib[3] = KERN_PROC_ARGV;
82*0e552da7Schristos     if (sysctl(mib, ARRAY_SIZE(mib), argsbuf, &argsbuf_size, NULL, 0) == 0) {
83*0e552da7Schristos       break;
84*0e552da7Schristos     }
85*0e552da7Schristos     if (errno != ENOMEM) {
86*0e552da7Schristos       err = UV__ERR(errno);
87*0e552da7Schristos       goto out;
88*0e552da7Schristos     }
89*0e552da7Schristos     argsbuf_size *= 2U;
90*0e552da7Schristos   }
91*0e552da7Schristos 
92*0e552da7Schristos   if (argsbuf[0] == NULL) {
93*0e552da7Schristos     err = UV_EINVAL;  /* FIXME(bnoordhuis) More appropriate error. */
94*0e552da7Schristos     goto out;
95*0e552da7Schristos   }
96*0e552da7Schristos 
97*0e552da7Schristos   *size -= 1;
98*0e552da7Schristos   exepath_size = strlen(argsbuf[0]);
99*0e552da7Schristos   if (*size > exepath_size)
100*0e552da7Schristos     *size = exepath_size;
101*0e552da7Schristos 
102*0e552da7Schristos   memcpy(buffer, argsbuf[0], *size);
103*0e552da7Schristos   buffer[*size] = '\0';
104*0e552da7Schristos   err = 0;
105*0e552da7Schristos 
106*0e552da7Schristos out:
107*0e552da7Schristos   uv__free(argsbuf);
108*0e552da7Schristos 
109*0e552da7Schristos   return err;
110*0e552da7Schristos }
111*0e552da7Schristos 
112*0e552da7Schristos 
uv_get_free_memory(void)113*0e552da7Schristos uint64_t uv_get_free_memory(void) {
114*0e552da7Schristos   struct uvmexp info;
115*0e552da7Schristos   size_t size = sizeof(info);
116*0e552da7Schristos   int which[] = {CTL_VM, VM_UVMEXP};
117*0e552da7Schristos 
118*0e552da7Schristos   if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
119*0e552da7Schristos     return UV__ERR(errno);
120*0e552da7Schristos 
121*0e552da7Schristos   return (uint64_t) info.free * sysconf(_SC_PAGESIZE);
122*0e552da7Schristos }
123*0e552da7Schristos 
124*0e552da7Schristos 
uv_get_total_memory(void)125*0e552da7Schristos uint64_t uv_get_total_memory(void) {
126*0e552da7Schristos   uint64_t info;
127*0e552da7Schristos   int which[] = {CTL_HW, HW_PHYSMEM64};
128*0e552da7Schristos   size_t size = sizeof(info);
129*0e552da7Schristos 
130*0e552da7Schristos   if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
131*0e552da7Schristos     return UV__ERR(errno);
132*0e552da7Schristos 
133*0e552da7Schristos   return (uint64_t) info;
134*0e552da7Schristos }
135*0e552da7Schristos 
136*0e552da7Schristos 
uv_get_constrained_memory(void)137*0e552da7Schristos uint64_t uv_get_constrained_memory(void) {
138*0e552da7Schristos   return 0;  /* Memory constraints are unknown. */
139*0e552da7Schristos }
140*0e552da7Schristos 
141*0e552da7Schristos 
uv_resident_set_memory(size_t * rss)142*0e552da7Schristos int uv_resident_set_memory(size_t* rss) {
143*0e552da7Schristos   struct kinfo_proc kinfo;
144*0e552da7Schristos   size_t page_size = getpagesize();
145*0e552da7Schristos   size_t size = sizeof(struct kinfo_proc);
146*0e552da7Schristos   int mib[6];
147*0e552da7Schristos 
148*0e552da7Schristos   mib[0] = CTL_KERN;
149*0e552da7Schristos   mib[1] = KERN_PROC;
150*0e552da7Schristos   mib[2] = KERN_PROC_PID;
151*0e552da7Schristos   mib[3] = getpid();
152*0e552da7Schristos   mib[4] = sizeof(struct kinfo_proc);
153*0e552da7Schristos   mib[5] = 1;
154*0e552da7Schristos 
155*0e552da7Schristos   if (sysctl(mib, ARRAY_SIZE(mib), &kinfo, &size, NULL, 0) < 0)
156*0e552da7Schristos     return UV__ERR(errno);
157*0e552da7Schristos 
158*0e552da7Schristos   *rss = kinfo.p_vm_rssize * page_size;
159*0e552da7Schristos   return 0;
160*0e552da7Schristos }
161*0e552da7Schristos 
162*0e552da7Schristos 
uv_uptime(double * uptime)163*0e552da7Schristos int uv_uptime(double* uptime) {
164*0e552da7Schristos   time_t now;
165*0e552da7Schristos   struct timeval info;
166*0e552da7Schristos   size_t size = sizeof(info);
167*0e552da7Schristos   static int which[] = {CTL_KERN, KERN_BOOTTIME};
168*0e552da7Schristos 
169*0e552da7Schristos   if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
170*0e552da7Schristos     return UV__ERR(errno);
171*0e552da7Schristos 
172*0e552da7Schristos   now = time(NULL);
173*0e552da7Schristos 
174*0e552da7Schristos   *uptime = (double)(now - info.tv_sec);
175*0e552da7Schristos   return 0;
176*0e552da7Schristos }
177*0e552da7Schristos 
178*0e552da7Schristos 
uv_cpu_info(uv_cpu_info_t ** cpu_infos,int * count)179*0e552da7Schristos int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
180*0e552da7Schristos   unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK),
181*0e552da7Schristos                multiplier = ((uint64_t)1000L / ticks), cpuspeed;
182*0e552da7Schristos   uint64_t info[CPUSTATES];
183*0e552da7Schristos   char model[512];
184*0e552da7Schristos   int numcpus = 1;
185*0e552da7Schristos   int which[] = {CTL_HW,HW_MODEL};
186*0e552da7Schristos   int percpu[] = {CTL_KERN,KERN_CPTIME2,0};
187*0e552da7Schristos   size_t size;
188*0e552da7Schristos   int i, j;
189*0e552da7Schristos   uv_cpu_info_t* cpu_info;
190*0e552da7Schristos 
191*0e552da7Schristos   size = sizeof(model);
192*0e552da7Schristos   if (sysctl(which, ARRAY_SIZE(which), &model, &size, NULL, 0))
193*0e552da7Schristos     return UV__ERR(errno);
194*0e552da7Schristos 
195*0e552da7Schristos   which[1] = HW_NCPUONLINE;
196*0e552da7Schristos   size = sizeof(numcpus);
197*0e552da7Schristos   if (sysctl(which, ARRAY_SIZE(which), &numcpus, &size, NULL, 0))
198*0e552da7Schristos     return UV__ERR(errno);
199*0e552da7Schristos 
200*0e552da7Schristos   *cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
201*0e552da7Schristos   if (!(*cpu_infos))
202*0e552da7Schristos     return UV_ENOMEM;
203*0e552da7Schristos 
204*0e552da7Schristos   i = 0;
205*0e552da7Schristos   *count = numcpus;
206*0e552da7Schristos 
207*0e552da7Schristos   which[1] = HW_CPUSPEED;
208*0e552da7Schristos   size = sizeof(cpuspeed);
209*0e552da7Schristos   if (sysctl(which, ARRAY_SIZE(which), &cpuspeed, &size, NULL, 0))
210*0e552da7Schristos     goto error;
211*0e552da7Schristos 
212*0e552da7Schristos   size = sizeof(info);
213*0e552da7Schristos   for (i = 0; i < numcpus; i++) {
214*0e552da7Schristos     percpu[2] = i;
215*0e552da7Schristos     if (sysctl(percpu, ARRAY_SIZE(percpu), &info, &size, NULL, 0))
216*0e552da7Schristos       goto error;
217*0e552da7Schristos 
218*0e552da7Schristos     cpu_info = &(*cpu_infos)[i];
219*0e552da7Schristos 
220*0e552da7Schristos     cpu_info->cpu_times.user = (uint64_t)(info[CP_USER]) * multiplier;
221*0e552da7Schristos     cpu_info->cpu_times.nice = (uint64_t)(info[CP_NICE]) * multiplier;
222*0e552da7Schristos     cpu_info->cpu_times.sys = (uint64_t)(info[CP_SYS]) * multiplier;
223*0e552da7Schristos     cpu_info->cpu_times.idle = (uint64_t)(info[CP_IDLE]) * multiplier;
224*0e552da7Schristos     cpu_info->cpu_times.irq = (uint64_t)(info[CP_INTR]) * multiplier;
225*0e552da7Schristos 
226*0e552da7Schristos     cpu_info->model = uv__strdup(model);
227*0e552da7Schristos     cpu_info->speed = cpuspeed;
228*0e552da7Schristos   }
229*0e552da7Schristos 
230*0e552da7Schristos   return 0;
231*0e552da7Schristos 
232*0e552da7Schristos error:
233*0e552da7Schristos   *count = 0;
234*0e552da7Schristos   for (j = 0; j < i; j++)
235*0e552da7Schristos     uv__free((*cpu_infos)[j].model);
236*0e552da7Schristos 
237*0e552da7Schristos   uv__free(*cpu_infos);
238*0e552da7Schristos   *cpu_infos = NULL;
239*0e552da7Schristos   return UV__ERR(errno);
240*0e552da7Schristos }
241