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