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