PageRenderTime 28ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/deps/uv/src/unix/freebsd.c

https://bitbucket.org/wwag110465/node
C | 343 lines | 238 code | 80 blank | 25 comment | 27 complexity | 8f696da36ea2d248571135ef250d7693 MD5 | raw file
  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. #include "uv.h"
  21. #include "internal.h"
  22. #include <assert.h>
  23. #include <string.h>
  24. #include <errno.h>
  25. #include <kvm.h>
  26. #include <paths.h>
  27. #include <sys/user.h>
  28. #include <sys/types.h>
  29. #include <sys/resource.h>
  30. #include <sys/sysctl.h>
  31. #include <vm/vm_param.h> /* VM_LOADAVG */
  32. #include <time.h>
  33. #include <stdlib.h>
  34. #include <unistd.h> /* sysconf */
  35. #include <fcntl.h>
  36. #undef NANOSEC
  37. #define NANOSEC ((uint64_t) 1e9)
  38. #ifndef CPUSTATES
  39. # define CPUSTATES 5U
  40. #endif
  41. #ifndef CP_USER
  42. # define CP_USER 0
  43. # define CP_NICE 1
  44. # define CP_SYS 2
  45. # define CP_IDLE 3
  46. # define CP_INTR 4
  47. #endif
  48. static char *process_title;
  49. int uv__platform_loop_init(uv_loop_t* loop, int default_loop) {
  50. return uv__kqueue_init(loop);
  51. }
  52. void uv__platform_loop_delete(uv_loop_t* loop) {
  53. }
  54. uint64_t uv__hrtime(void) {
  55. struct timespec ts;
  56. clock_gettime(CLOCK_MONOTONIC, &ts);
  57. return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec);
  58. }
  59. int uv_exepath(char* buffer, size_t* size) {
  60. int mib[4];
  61. size_t cb;
  62. if (!buffer || !size) {
  63. return -1;
  64. }
  65. #ifdef __DragonFly__
  66. mib[0] = CTL_KERN;
  67. mib[1] = KERN_PROC;
  68. mib[2] = KERN_PROC_ARGS;
  69. mib[3] = getpid();
  70. #else
  71. mib[0] = CTL_KERN;
  72. mib[1] = KERN_PROC;
  73. mib[2] = KERN_PROC_PATHNAME;
  74. mib[3] = -1;
  75. #endif
  76. cb = *size;
  77. if (sysctl(mib, 4, buffer, &cb, NULL, 0) < 0) {
  78. *size = 0;
  79. return -1;
  80. }
  81. *size = strlen(buffer);
  82. return 0;
  83. }
  84. uint64_t uv_get_free_memory(void) {
  85. int freecount;
  86. size_t size = sizeof(freecount);
  87. if(sysctlbyname("vm.stats.vm.v_free_count",
  88. &freecount, &size, NULL, 0) == -1){
  89. return -1;
  90. }
  91. return (uint64_t) freecount * sysconf(_SC_PAGESIZE);
  92. }
  93. uint64_t uv_get_total_memory(void) {
  94. unsigned long info;
  95. int which[] = {CTL_HW, HW_PHYSMEM};
  96. size_t size = sizeof(info);
  97. if (sysctl(which, 2, &info, &size, NULL, 0) < 0) {
  98. return -1;
  99. }
  100. return (uint64_t) info;
  101. }
  102. void uv_loadavg(double avg[3]) {
  103. struct loadavg info;
  104. size_t size = sizeof(info);
  105. int which[] = {CTL_VM, VM_LOADAVG};
  106. if (sysctl(which, 2, &info, &size, NULL, 0) < 0) return;
  107. avg[0] = (double) info.ldavg[0] / info.fscale;
  108. avg[1] = (double) info.ldavg[1] / info.fscale;
  109. avg[2] = (double) info.ldavg[2] / info.fscale;
  110. }
  111. char** uv_setup_args(int argc, char** argv) {
  112. process_title = argc ? strdup(argv[0]) : NULL;
  113. return argv;
  114. }
  115. uv_err_t uv_set_process_title(const char* title) {
  116. int oid[4];
  117. if (process_title) free(process_title);
  118. process_title = strdup(title);
  119. oid[0] = CTL_KERN;
  120. oid[1] = KERN_PROC;
  121. oid[2] = KERN_PROC_ARGS;
  122. oid[3] = getpid();
  123. sysctl(oid,
  124. ARRAY_SIZE(oid),
  125. NULL,
  126. NULL,
  127. process_title,
  128. strlen(process_title) + 1);
  129. return uv_ok_;
  130. }
  131. uv_err_t uv_get_process_title(char* buffer, size_t size) {
  132. if (process_title) {
  133. strncpy(buffer, process_title, size);
  134. } else {
  135. if (size > 0) {
  136. buffer[0] = '\0';
  137. }
  138. }
  139. return uv_ok_;
  140. }
  141. uv_err_t uv_resident_set_memory(size_t* rss) {
  142. kvm_t *kd = NULL;
  143. struct kinfo_proc *kinfo = NULL;
  144. pid_t pid;
  145. int nprocs;
  146. size_t page_size = getpagesize();
  147. pid = getpid();
  148. kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open");
  149. if (kd == NULL) goto error;
  150. kinfo = kvm_getprocs(kd, KERN_PROC_PID, pid, &nprocs);
  151. if (kinfo == NULL) goto error;
  152. #ifdef __DragonFly__
  153. *rss = kinfo->kp_vm_rssize * page_size;
  154. #else
  155. *rss = kinfo->ki_rssize * page_size;
  156. #endif
  157. kvm_close(kd);
  158. return uv_ok_;
  159. error:
  160. if (kd) kvm_close(kd);
  161. return uv__new_sys_error(errno);
  162. }
  163. uv_err_t uv_uptime(double* uptime) {
  164. time_t now;
  165. struct timeval info;
  166. size_t size = sizeof(info);
  167. static int which[] = {CTL_KERN, KERN_BOOTTIME};
  168. if (sysctl(which, 2, &info, &size, NULL, 0) < 0) {
  169. return uv__new_sys_error(errno);
  170. }
  171. now = time(NULL);
  172. *uptime = (double)(now - info.tv_sec);
  173. return uv_ok_;
  174. }
  175. uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
  176. unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK),
  177. multiplier = ((uint64_t)1000L / ticks), cpuspeed, maxcpus,
  178. cur = 0;
  179. uv_cpu_info_t* cpu_info;
  180. const char* maxcpus_key;
  181. const char* cptimes_key;
  182. char model[512];
  183. long* cp_times;
  184. int numcpus;
  185. size_t size;
  186. int i;
  187. #if defined(__DragonFly__)
  188. /* This is not quite correct but DragonFlyBSD doesn't seem to have anything
  189. * comparable to kern.smp.maxcpus or kern.cp_times (kern.cp_time is a total,
  190. * not per CPU). At least this stops uv_cpu_info() from failing completely.
  191. */
  192. maxcpus_key = "hw.ncpu";
  193. cptimes_key = "kern.cp_time";
  194. #else
  195. maxcpus_key = "kern.smp.maxcpus";
  196. cptimes_key = "kern.cp_times";
  197. #endif
  198. size = sizeof(model);
  199. if (sysctlbyname("hw.model", &model, &size, NULL, 0) < 0) {
  200. return uv__new_sys_error(errno);
  201. }
  202. size = sizeof(numcpus);
  203. if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0) < 0) {
  204. return uv__new_sys_error(errno);
  205. }
  206. *cpu_infos = (uv_cpu_info_t*)malloc(numcpus * sizeof(uv_cpu_info_t));
  207. if (!(*cpu_infos)) {
  208. return uv__new_artificial_error(UV_ENOMEM);
  209. }
  210. *count = numcpus;
  211. size = sizeof(cpuspeed);
  212. if (sysctlbyname("hw.clockrate", &cpuspeed, &size, NULL, 0) < 0) {
  213. free(*cpu_infos);
  214. return uv__new_sys_error(errno);
  215. }
  216. /* kern.cp_times on FreeBSD i386 gives an array up to maxcpus instead of ncpu */
  217. size = sizeof(maxcpus);
  218. if (sysctlbyname(maxcpus_key, &maxcpus, &size, NULL, 0) < 0) {
  219. free(*cpu_infos);
  220. return uv__new_sys_error(errno);
  221. }
  222. size = maxcpus * CPUSTATES * sizeof(long);
  223. cp_times = malloc(size);
  224. if (cp_times == NULL) {
  225. free(*cpu_infos);
  226. return uv__new_sys_error(ENOMEM);
  227. }
  228. if (sysctlbyname(cptimes_key, cp_times, &size, NULL, 0) < 0) {
  229. free(cp_times);
  230. free(*cpu_infos);
  231. return uv__new_sys_error(errno);
  232. }
  233. for (i = 0; i < numcpus; i++) {
  234. cpu_info = &(*cpu_infos)[i];
  235. cpu_info->cpu_times.user = (uint64_t)(cp_times[CP_USER+cur]) * multiplier;
  236. cpu_info->cpu_times.nice = (uint64_t)(cp_times[CP_NICE+cur]) * multiplier;
  237. cpu_info->cpu_times.sys = (uint64_t)(cp_times[CP_SYS+cur]) * multiplier;
  238. cpu_info->cpu_times.idle = (uint64_t)(cp_times[CP_IDLE+cur]) * multiplier;
  239. cpu_info->cpu_times.irq = (uint64_t)(cp_times[CP_INTR+cur]) * multiplier;
  240. cpu_info->model = strdup(model);
  241. cpu_info->speed = cpuspeed;
  242. cur+=CPUSTATES;
  243. }
  244. free(cp_times);
  245. return uv_ok_;
  246. }
  247. void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
  248. int i;
  249. for (i = 0; i < count; i++) {
  250. free(cpu_infos[i].model);
  251. }
  252. free(cpu_infos);
  253. }
  254. uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
  255. int* count) {
  256. /* TODO: implement */
  257. *addresses = NULL;
  258. *count = 0;
  259. return uv_ok_;
  260. }
  261. void uv_free_interface_addresses(uv_interface_address_t* addresses,
  262. int count) {
  263. }