|
160
|
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 <kvm.h>
|
|
|
29 #include <paths.h>
|
|
|
30 #include <unistd.h>
|
|
|
31 #include <time.h>
|
|
|
32 #include <stdlib.h>
|
|
|
33 #include <fcntl.h>
|
|
|
34
|
|
|
35 #include <sys/resource.h>
|
|
|
36 #include <sys/types.h>
|
|
|
37 #include <sys/sysctl.h>
|
|
|
38 #include <uvm/uvm_extern.h>
|
|
|
39
|
|
|
40 #include <unistd.h>
|
|
|
41 #include <time.h>
|
|
|
42
|
|
|
43
|
|
|
44 int uv__platform_loop_init(uv_loop_t* loop) {
|
|
|
45 return uv__kqueue_init(loop);
|
|
|
46 }
|
|
|
47
|
|
|
48
|
|
|
49 void uv__platform_loop_delete(uv_loop_t* loop) {
|
|
|
50 }
|
|
|
51
|
|
|
52
|
|
|
53 void uv_loadavg(double avg[3]) {
|
|
|
54 struct loadavg info;
|
|
|
55 size_t size = sizeof(info);
|
|
|
56 int which[] = {CTL_VM, VM_LOADAVG};
|
|
|
57
|
|
|
58 if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0) == -1) return;
|
|
|
59
|
|
|
60 avg[0] = (double) info.ldavg[0] / info.fscale;
|
|
|
61 avg[1] = (double) info.ldavg[1] / info.fscale;
|
|
|
62 avg[2] = (double) info.ldavg[2] / info.fscale;
|
|
|
63 }
|
|
|
64
|
|
|
65
|
|
|
66 int uv_exepath(char* buffer, size_t* size) {
|
|
|
67 /* Intermediate buffer, retrieving partial path name does not work
|
|
|
68 * As of NetBSD-8(beta), vnode->path translator does not handle files
|
|
|
69 * with longer names than 31 characters.
|
|
|
70 */
|
|
|
71 char int_buf[PATH_MAX];
|
|
|
72 size_t int_size;
|
|
|
73 int mib[4];
|
|
|
74
|
|
|
75 if (buffer == NULL || size == NULL || *size == 0)
|
|
|
76 return UV_EINVAL;
|
|
|
77
|
|
|
78 mib[0] = CTL_KERN;
|
|
|
79 mib[1] = KERN_PROC_ARGS;
|
|
|
80 mib[2] = -1;
|
|
|
81 mib[3] = KERN_PROC_PATHNAME;
|
|
|
82 int_size = ARRAY_SIZE(int_buf);
|
|
|
83
|
|
|
84 if (sysctl(mib, 4, int_buf, &int_size, NULL, 0))
|
|
|
85 return UV__ERR(errno);
|
|
|
86
|
|
|
87 /* Copy string from the intermediate buffer to outer one with appropriate
|
|
|
88 * length.
|
|
|
89 */
|
|
|
90 /* TODO(bnoordhuis) Check uv__strscpy() return value. */
|
|
|
91 uv__strscpy(buffer, int_buf, *size);
|
|
|
92
|
|
|
93 /* Set new size. */
|
|
|
94 *size = strlen(buffer);
|
|
|
95
|
|
|
96 return 0;
|
|
|
97 }
|
|
|
98
|
|
|
99
|
|
|
100 uint64_t uv_get_free_memory(void) {
|
|
|
101 struct uvmexp info;
|
|
|
102 size_t size = sizeof(info);
|
|
|
103 int which[] = {CTL_VM, VM_UVMEXP};
|
|
|
104
|
|
|
105 if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
|
|
|
106 return 0;
|
|
|
107
|
|
|
108 return (uint64_t) info.free * sysconf(_SC_PAGESIZE);
|
|
|
109 }
|
|
|
110
|
|
|
111
|
|
|
112 uint64_t uv_get_total_memory(void) {
|
|
|
113 #if defined(HW_PHYSMEM64)
|
|
|
114 uint64_t info;
|
|
|
115 int which[] = {CTL_HW, HW_PHYSMEM64};
|
|
|
116 #else
|
|
|
117 unsigned int info;
|
|
|
118 int which[] = {CTL_HW, HW_PHYSMEM};
|
|
|
119 #endif
|
|
|
120 size_t size = sizeof(info);
|
|
|
121
|
|
|
122 if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
|
|
|
123 return 0;
|
|
|
124
|
|
|
125 return (uint64_t) info;
|
|
|
126 }
|
|
|
127
|
|
|
128
|
|
|
129 uint64_t uv_get_constrained_memory(void) {
|
|
|
130 return 0; /* Memory constraints are unknown. */
|
|
|
131 }
|
|
|
132
|
|
|
133
|
|
|
134 uint64_t uv_get_available_memory(void) {
|
|
|
135 return uv_get_free_memory();
|
|
|
136 }
|
|
|
137
|
|
|
138
|
|
|
139 int uv_resident_set_memory(size_t* rss) {
|
|
|
140 kvm_t *kd = NULL;
|
|
|
141 struct kinfo_proc2 *kinfo = NULL;
|
|
|
142 pid_t pid;
|
|
|
143 int nprocs;
|
|
|
144 int max_size = sizeof(struct kinfo_proc2);
|
|
|
145 int page_size;
|
|
|
146
|
|
|
147 page_size = getpagesize();
|
|
|
148 pid = getpid();
|
|
|
149
|
|
|
150 kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, "kvm_open");
|
|
|
151
|
|
|
152 if (kd == NULL) goto error;
|
|
|
153
|
|
|
154 kinfo = kvm_getproc2(kd, KERN_PROC_PID, pid, max_size, &nprocs);
|
|
|
155 if (kinfo == NULL) goto error;
|
|
|
156
|
|
|
157 *rss = kinfo->p_vm_rssize * page_size;
|
|
|
158
|
|
|
159 kvm_close(kd);
|
|
|
160
|
|
|
161 return 0;
|
|
|
162
|
|
|
163 error:
|
|
|
164 if (kd) kvm_close(kd);
|
|
|
165 return UV_EPERM;
|
|
|
166 }
|
|
|
167
|
|
|
168
|
|
|
169 int uv_uptime(double* uptime) {
|
|
|
170 time_t now;
|
|
|
171 struct timeval info;
|
|
|
172 size_t size = sizeof(info);
|
|
|
173 static int which[] = {CTL_KERN, KERN_BOOTTIME};
|
|
|
174
|
|
|
175 if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
|
|
|
176 return UV__ERR(errno);
|
|
|
177
|
|
|
178 now = time(NULL);
|
|
|
179
|
|
|
180 *uptime = (double)(now - info.tv_sec);
|
|
|
181 return 0;
|
|
|
182 }
|
|
|
183
|
|
|
184
|
|
|
185 int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
|
|
186 unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK);
|
|
|
187 unsigned int multiplier = ((uint64_t)1000L / ticks);
|
|
|
188 unsigned int cur = 0;
|
|
|
189 uv_cpu_info_t* cpu_info;
|
|
|
190 u_int64_t* cp_times;
|
|
|
191 char model[512];
|
|
|
192 u_int64_t cpuspeed;
|
|
|
193 int numcpus;
|
|
|
194 size_t size;
|
|
|
195 int i;
|
|
|
196
|
|
|
197 size = sizeof(model);
|
|
|
198 if (sysctlbyname("machdep.cpu_brand", &model, &size, NULL, 0) &&
|
|
|
199 sysctlbyname("hw.model", &model, &size, NULL, 0)) {
|
|
|
200 return UV__ERR(errno);
|
|
|
201 }
|
|
|
202
|
|
|
203 size = sizeof(numcpus);
|
|
|
204 if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0))
|
|
|
205 return UV__ERR(errno);
|
|
|
206 *count = numcpus;
|
|
|
207
|
|
|
208 /* Only i386 and amd64 have machdep.tsc_freq */
|
|
|
209 size = sizeof(cpuspeed);
|
|
|
210 if (sysctlbyname("machdep.tsc_freq", &cpuspeed, &size, NULL, 0))
|
|
|
211 cpuspeed = 0;
|
|
|
212
|
|
|
213 size = numcpus * CPUSTATES * sizeof(*cp_times);
|
|
|
214 cp_times = uv__malloc(size);
|
|
|
215 if (cp_times == NULL)
|
|
|
216 return UV_ENOMEM;
|
|
|
217
|
|
|
218 if (sysctlbyname("kern.cp_time", cp_times, &size, NULL, 0))
|
|
|
219 return UV__ERR(errno);
|
|
|
220
|
|
|
221 *cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
|
|
|
222 if (!(*cpu_infos)) {
|
|
|
223 uv__free(cp_times);
|
|
|
224 uv__free(*cpu_infos);
|
|
|
225 return UV_ENOMEM;
|
|
|
226 }
|
|
|
227
|
|
|
228 for (i = 0; i < numcpus; i++) {
|
|
|
229 cpu_info = &(*cpu_infos)[i];
|
|
|
230 cpu_info->cpu_times.user = (uint64_t)(cp_times[CP_USER+cur]) * multiplier;
|
|
|
231 cpu_info->cpu_times.nice = (uint64_t)(cp_times[CP_NICE+cur]) * multiplier;
|
|
|
232 cpu_info->cpu_times.sys = (uint64_t)(cp_times[CP_SYS+cur]) * multiplier;
|
|
|
233 cpu_info->cpu_times.idle = (uint64_t)(cp_times[CP_IDLE+cur]) * multiplier;
|
|
|
234 cpu_info->cpu_times.irq = (uint64_t)(cp_times[CP_INTR+cur]) * multiplier;
|
|
|
235 cpu_info->model = uv__strdup(model);
|
|
|
236 cpu_info->speed = (int)(cpuspeed/(uint64_t) 1e6);
|
|
|
237 cur += CPUSTATES;
|
|
|
238 }
|
|
|
239 uv__free(cp_times);
|
|
|
240 return 0;
|
|
|
241 }
|
|
|
242
|
|
|
243 int uv__random_sysctl(void* buf, size_t len) {
|
|
|
244 static int name[] = {CTL_KERN, KERN_ARND};
|
|
|
245 size_t count, req;
|
|
|
246 unsigned char* p;
|
|
|
247
|
|
|
248 p = buf;
|
|
|
249 while (len) {
|
|
|
250 req = len < 32 ? len : 32;
|
|
|
251 count = req;
|
|
|
252
|
|
|
253 if (sysctl(name, ARRAY_SIZE(name), p, &count, NULL, 0) == -1)
|
|
|
254 return UV__ERR(errno);
|
|
|
255
|
|
|
256 if (count != req)
|
|
|
257 return UV_EIO; /* Can't happen. */
|
|
|
258
|
|
|
259 p += count;
|
|
|
260 len -= count;
|
|
|
261 }
|
|
|
262
|
|
|
263 return 0;
|
|
|
264 }
|