uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK); unsigned int multiplier = ((uint64_t)1000L / ticks); unsigned int cur = 0; uv_cpu_info_t* cpu_info; u_int64_t* cp_times; char model[512]; u_int64_t cpuspeed; int numcpus; size_t size; int i; size = sizeof(model); if (sysctlbyname("machdep.cpu_brand", &model, &size, NULL, 0) == -1 && sysctlbyname("hw.model", &model, &size, NULL, 0) == -1) { return uv__new_sys_error(errno); } size = sizeof(numcpus); if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0) == -1) { return uv__new_sys_error(errno); } *count = numcpus; /* Only i386 and amd64 have machdep.tsc_freq */ size = sizeof(cpuspeed); if (sysctlbyname("machdep.tsc_freq", &cpuspeed, &size, NULL, 0) == -1) { cpuspeed = 0; } size = numcpus * CPUSTATES * sizeof(*cp_times); cp_times = malloc(size); if (cp_times == NULL) { return uv__new_artificial_error(UV_ENOMEM); } if (sysctlbyname("kern.cp_time", cp_times, &size, NULL, 0) == -1) { return uv__new_sys_error(errno); } *cpu_infos = malloc(numcpus * sizeof(**cpu_infos)); if (!(*cpu_infos)) { free(cp_times); free(*cpu_infos); return uv__new_artificial_error(UV_ENOMEM); } for (i = 0; i < numcpus; i++) { cpu_info = &(*cpu_infos)[i]; cpu_info->cpu_times.user = (uint64_t)(cp_times[CP_USER+cur]) * multiplier; cpu_info->cpu_times.nice = (uint64_t)(cp_times[CP_NICE+cur]) * multiplier; cpu_info->cpu_times.sys = (uint64_t)(cp_times[CP_SYS+cur]) * multiplier; cpu_info->cpu_times.idle = (uint64_t)(cp_times[CP_IDLE+cur]) * multiplier; cpu_info->cpu_times.irq = (uint64_t)(cp_times[CP_INTR+cur]) * multiplier; cpu_info->model = strdup(model); cpu_info->speed = (int)(cpuspeed/(uint64_t) 1e6); cur += CPUSTATES; } free(cp_times); return uv_ok_; }
uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { unsigned int numcpus; uv_cpu_info_t* ci; *cpu_infos = NULL; *count = 0; numcpus = sysconf(_SC_NPROCESSORS_ONLN); assert(numcpus != (unsigned int)-1); assert(numcpus != 0); ci = calloc(numcpus, sizeof(*ci)); if (ci == NULL) return uv__new_sys_error(ENOMEM); if (read_models(numcpus, ci)) { SAVE_ERRNO(uv_free_cpu_info(ci, numcpus)); return uv__new_sys_error(errno); } if (read_times(numcpus, ci)) { SAVE_ERRNO(uv_free_cpu_info(ci, numcpus)); return uv__new_sys_error(errno); } /* read_models() on x86 also reads the CPU speed from /proc/cpuinfo. * We don't check for errors here. Worst case, the field is left zero. */ if (ci[0].speed == 0) read_speeds(numcpus, ci); *cpu_infos = ci; *count = numcpus; return uv_ok_; }
uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK), multiplier = ((uint64_t)1000L / ticks), cpuspeed; uint64_t info[CPUSTATES]; char model[512]; int numcpus = 1; static int which[] = {CTL_HW,HW_MODEL,0}; size_t size; int i; uv_cpu_info_t* cpu_info; size = sizeof(model); if (sysctl(which, 2, &model, &size, NULL, 0) < 0) { return uv__new_sys_error(errno); } which[1] = HW_NCPU; size = sizeof(numcpus); if (sysctl(which, 2, &numcpus, &size, NULL, 0) < 0) { return uv__new_sys_error(errno); } *cpu_infos = (uv_cpu_info_t*)malloc(numcpus * sizeof(uv_cpu_info_t)); if (!(*cpu_infos)) { return uv__new_artificial_error(UV_ENOMEM); } *count = numcpus; which[1] = HW_CPUSPEED; size = sizeof(cpuspeed); if (sysctl(which, 2, &cpuspeed, &size, NULL, 0) < 0) { free(*cpu_infos); return uv__new_sys_error(errno); } size = sizeof(info); which[0] = CTL_KERN; which[1] = KERN_CPTIME2; for (i = 0; i < numcpus; i++) { which[2] = i; size = sizeof(info); if (sysctl(which, 3, &info, &size, NULL, 0) < 0) { free(*cpu_infos); return uv__new_sys_error(errno); } cpu_info = &(*cpu_infos)[i]; cpu_info->cpu_times.user = (uint64_t)(info[CP_USER]) * multiplier; cpu_info->cpu_times.nice = (uint64_t)(info[CP_NICE]) * multiplier; cpu_info->cpu_times.sys = (uint64_t)(info[CP_SYS]) * multiplier; cpu_info->cpu_times.idle = (uint64_t)(info[CP_IDLE]) * multiplier; cpu_info->cpu_times.irq = (uint64_t)(info[CP_INTR]) * multiplier; cpu_info->model = strdup(model); cpu_info->speed = cpuspeed; } return uv_ok_; }
static uv_err_t uv__kill(HANDLE process_handle, int signum) { DWORD status; uv_err_t err; if (signum == SIGTERM || signum == SIGKILL || signum == SIGINT) { /* Kill the process. On Windows, killed processes normally return 1. */ if (TerminateProcess(process_handle, 1)) { err = uv_ok_; } else { err = uv__new_sys_error(GetLastError()); } } else if (signum == 0) { /* Health check: is the process still alive? */ if (GetExitCodeProcess(process_handle, &status)) { if (status == STILL_ACTIVE) { err = uv_ok_; } else { err = uv__new_artificial_error(UV_ESRCH); } } else { err = uv__new_sys_error(GetLastError()); } } else { err = uv__new_artificial_error(UV_ENOSYS); } return err; }
uv_err_t uv_resident_set_memory(size_t* rss) { char buf[1024]; const char* s; ssize_t n; long val; int fd; int i; do fd = open("/proc/self/stat", O_RDONLY); while (fd == -1 && errno == EINTR); if (fd == -1) return uv__new_sys_error(errno); do n = read(fd, buf, sizeof(buf) - 1); while (n == -1 && errno == EINTR); SAVE_ERRNO(close(fd)); if (n == -1) return uv__new_sys_error(errno); buf[n] = '\0'; s = strchr(buf, ' '); if (s == NULL) goto err; s += 1; if (*s != '(') goto err; s = strchr(s, ')'); if (s == NULL) goto err; for (i = 1; i <= 22; i++) { s = strchr(s + 1, ' '); if (s == NULL) goto err; } errno = 0; val = strtol(s, NULL, 10); if (errno != 0) goto err; if (val < 0) goto err; *rss = val * getpagesize(); return uv_ok_; err: return uv__new_artificial_error(UV_EINVAL); }
uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK), multiplier = ((uint64_t)1000L / ticks); char model[512]; uint64_t cpuspeed; size_t size; unsigned int i; natural_t numcpus; mach_msg_type_number_t msg_type; processor_cpu_load_info_data_t *info; uv_cpu_info_t* cpu_info; size = sizeof(model); if (sysctlbyname("machdep.cpu.brand_string", &model, &size, NULL, 0) < 0 && sysctlbyname("hw.model", &model, &size, NULL, 0) < 0) { return uv__new_sys_error(errno); } size = sizeof(cpuspeed); if (sysctlbyname("hw.cpufrequency", &cpuspeed, &size, NULL, 0) < 0) { return uv__new_sys_error(errno); } if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numcpus, (processor_info_array_t*)&info, &msg_type) != KERN_SUCCESS) { return uv__new_sys_error(errno); } *cpu_infos = (uv_cpu_info_t*)malloc(numcpus * sizeof(uv_cpu_info_t)); if (!(*cpu_infos)) { return uv__new_artificial_error(UV_ENOMEM); } *count = numcpus; for (i = 0; i < numcpus; i++) { cpu_info = &(*cpu_infos)[i]; cpu_info->cpu_times.user = (uint64_t)(info[i].cpu_ticks[0]) * multiplier; cpu_info->cpu_times.nice = (uint64_t)(info[i].cpu_ticks[3]) * multiplier; cpu_info->cpu_times.sys = (uint64_t)(info[i].cpu_ticks[1]) * multiplier; cpu_info->cpu_times.idle = (uint64_t)(info[i].cpu_ticks[2]) * multiplier; cpu_info->cpu_times.irq = 0; cpu_info->model = strdup(model); cpu_info->speed = cpuspeed/1000000; } vm_deallocate(mach_task_self(), (vm_address_t)info, msg_type); return uv_ok_; }
uv_err_t uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access, char* name, size_t nameSize) { HANDLE pipeHandle; int errorno; uv_err_t err; char* ptr = (char*)handle; for (;;) { uv_unique_pipe_name(ptr, name, nameSize); pipeHandle = CreateNamedPipeA(name, access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 65536, 65536, 0, NULL); if (pipeHandle != INVALID_HANDLE_VALUE) { /* No name collisions. We're done. */ break; } errorno = GetLastError(); if (errorno != ERROR_PIPE_BUSY && errorno != ERROR_ACCESS_DENIED) { err = uv__new_sys_error(errorno); goto error; } /* Pipe name collision. Increment the pointer and try again. */ ptr++; } if (CreateIoCompletionPort(pipeHandle, loop->iocp, (ULONG_PTR)handle, 0) == NULL) { err = uv__new_sys_error(GetLastError()); goto error; } uv_pipe_connection_init(handle); handle->handle = pipeHandle; return uv_ok_; error: if (pipeHandle != INVALID_HANDLE_VALUE) { CloseHandle(pipeHandle); } return err; }
uv_err_t uv_dlclose(uv_lib_t library) { if (!FreeLibrary(library)) { return uv__new_sys_error(GetLastError()); } return uv_ok_; }
uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { unsigned int numcpus; uv_cpu_info_t* ci; *cpu_infos = NULL; *count = 0; numcpus = sysconf(_SC_NPROCESSORS_ONLN); assert(numcpus != (unsigned int) -1); assert(numcpus != 0); ci = calloc(numcpus, sizeof(*ci)); if (ci == NULL) return uv__new_sys_error(ENOMEM); read_models(numcpus, ci); read_times(numcpus, ci); /* read_models() on x86 also reads the CPU speed from /proc/cpuinfo */ if (ci[0].speed == 0) read_speeds(numcpus, ci); *cpu_infos = ci; *count = numcpus; return uv_ok_; }
uv_err_t uv_resident_set_memory(size_t* rss) { kvm_t *kd = NULL; struct kinfo_proc *kinfo = NULL; pid_t pid; int nprocs; size_t page_size = getpagesize(); pid = getpid(); kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open"); if (kd == NULL) goto error; kinfo = kvm_getprocs(kd, KERN_PROC_PID, pid, &nprocs); if (kinfo == NULL) goto error; #ifdef __DragonFly__ *rss = kinfo->kp_vm_rssize * page_size; #else *rss = kinfo->ki_rssize * page_size; #endif kvm_close(kd); return uv_ok_; error: if (kd) kvm_close(kd); return uv__new_sys_error(errno); }
uv_err_t uv_chdir(const char* dir) { if (chdir(dir) == 0) { return uv_ok_; } else { return uv__new_sys_error(errno); } }
uv_err_t uv_resident_set_memory(size_t* rss) { kvm_t *kd = NULL; struct kinfo_proc *kinfo = NULL; pid_t pid; int nprocs, max_size = sizeof(struct kinfo_proc); size_t page_size = getpagesize(); pid = getpid(); kd = kvm_open(NULL, _PATH_MEM, NULL, O_RDONLY, "kvm_open"); if (kd == NULL) goto error; kinfo = kvm_getprocs(kd, KERN_PROC_PID, pid, max_size, &nprocs); if (kinfo == NULL) goto error; *rss = kinfo->p_vm_rssize * page_size; kvm_close(kd); return uv_ok_; error: if (kd) kvm_close(kd); return uv__new_sys_error(errno); }
static uv_err_t uv_utf8_to_utf16_alloc(const char* s, WCHAR** ws_ptr) { int ws_len, r; WCHAR* ws; ws_len = MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0); if (ws_len <= 0) { return uv__new_sys_error(GetLastError()); } ws = (WCHAR*) malloc(ws_len * sizeof(WCHAR)); if (ws == NULL) { return uv__new_artificial_error(UV_ENOMEM); } r = MultiByteToWideChar(CP_UTF8, 0, s, -1, ws, ws_len); assert(r == ws_len); *ws_ptr = ws; return uv_ok_; }
uv_err_t uv_set_process_title(const char* title) { uv_err_t err; int length; wchar_t* title_w = NULL; uv__once_init(); /* Find out how big the buffer for the wide-char title must be */ length = uv_utf8_to_utf16(title, NULL, 0); if (!length) { err = uv__new_sys_error(GetLastError()); goto done; } /* Convert to wide-char string */ title_w = (wchar_t*)malloc(sizeof(wchar_t) * length); if (!title_w) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } length = uv_utf8_to_utf16(title, title_w, length); if (!length) { err = uv__new_sys_error(GetLastError()); goto done; }; /* If the title must be truncated insert a \0 terminator there */ if (length > MAX_TITLE_LENGTH) { title_w[MAX_TITLE_LENGTH - 1] = L'\0'; } if (!SetConsoleTitleW(title_w)) { err = uv__new_sys_error(GetLastError()); goto done; } EnterCriticalSection(&process_title_lock); free(process_title); process_title = strdup(title); LeaveCriticalSection(&process_title_lock); err = uv_ok_; done: free(title_w); return err; }
uv_err_t uv_interface_addresses(uv_interface_address_t** addresses, int* count) { struct ifaddrs *addrs; struct ifaddrs *ent; uv_interface_address_t* address; if (getifaddrs(&addrs) != 0) { return uv__new_sys_error(errno); } *count = 0; /* Count the number of interfaces */ for (ent = addrs; ent != NULL; ent = ent->ifa_next) { if (!(ent->ifa_flags & IFF_UP && ent->ifa_flags & IFF_RUNNING) || (ent->ifa_addr == NULL) || (ent->ifa_addr->sa_family != PF_INET)) { continue; } (*count)++; } *addresses = malloc(*count * sizeof(**addresses)); if (!(*addresses)) { return uv__new_artificial_error(UV_ENOMEM); } address = *addresses; for (ent = addrs; ent != NULL; ent = ent->ifa_next) { if (!(ent->ifa_flags & IFF_UP && ent->ifa_flags & IFF_RUNNING)) { continue; } if (ent->ifa_addr == NULL) { continue; } if (ent->ifa_addr->sa_family != PF_INET) { continue; } address->name = strdup(ent->ifa_name); if (ent->ifa_addr->sa_family == AF_INET6) { address->address.address6 = *((struct sockaddr_in6 *)ent->ifa_addr); } else { address->address.address4 = *((struct sockaddr_in *)ent->ifa_addr); } address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK) ? 1 : 0; address++; } freeifaddrs(addrs); return uv_ok_; }
uv_err_t uv_kill(int pid, int signum) { int r = kill(pid, signum); if (r) { return uv__new_sys_error(errno); } else { return uv_ok_; } }
uv_err_t uv_uptime(double* uptime) { #ifdef CLOCK_MONOTONIC struct timespec now; if (0 == clock_gettime(CLOCK_MONOTONIC, &now)) { *uptime = now.tv_sec; *uptime += (double)now.tv_nsec / 1000000000.0; return uv_ok_; } return uv__new_sys_error(errno); #else struct sysinfo info; if (sysinfo(&info) < 0) { return uv__new_sys_error(errno); } *uptime = (double)info.uptime; return uv_ok_; #endif }
uv_err_t uv_dlsym(uv_lib_t library, const char* name, void** ptr) { FARPROC proc = GetProcAddress(library, name); if (proc == NULL) { return uv__new_sys_error(GetLastError()); } *ptr = (void*) proc; return uv_ok_; }
uv_err_t uv_dlopen(const char* filename, uv_lib_t* library) { wchar_t filename_w[32768]; HMODULE handle; if (!uv_utf8_to_utf16(filename, filename_w, sizeof(filename_w) / sizeof(wchar_t))) { return uv__new_sys_error(GetLastError()); } handle = LoadLibraryW(filename_w); if (handle == NULL) { return uv__new_sys_error(GetLastError()); } *library = handle; return uv_ok_; }
uv_err_t uv_cwd(char* buffer, size_t size) { DWORD utf16_len; WCHAR utf16_buffer[MAX_PATH]; int r; if (buffer == NULL || size == 0) { return uv__new_artificial_error(UV_EINVAL); } utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer); if (utf16_len == 0) { return uv__new_sys_error(GetLastError()); } else if (utf16_len > MAX_PATH) { /* This should be impossible; however the CRT has a code path to deal */ /* with this scenario, so I added a check anyway. */ return uv__new_artificial_error(UV_EIO); } /* utf16_len contains the length, *not* including the terminating null. */ utf16_buffer[utf16_len] = L'\0'; /* The returned directory should not have a trailing slash, unless it */ /* points at a drive root, like c:\. Remove it if needed.*/ if (utf16_buffer[utf16_len - 1] == L'\\' && !(utf16_len == 3 && utf16_buffer[1] == L':')) { utf16_len--; utf16_buffer[utf16_len] = L'\0'; } /* Convert to UTF-8 */ r = WideCharToMultiByte(CP_UTF8, 0, utf16_buffer, -1, buffer, size > INT_MAX ? INT_MAX : (int) size, NULL, NULL); if (r == 0) { return uv__new_sys_error(GetLastError()); } return uv_ok_; }
uv_err_t uv_resident_set_memory(size_t* rss) { psinfo_t psinfo; uv_err_t err; int fd; fd = open("/proc/self/psinfo", O_RDONLY); if (fd == -1) return uv__new_sys_error(errno); err = uv_ok_; if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) *rss = (size_t)psinfo.pr_rssize * 1024; else err = uv__new_sys_error(EINVAL); close(fd); return err; }
static uv_err_t uv__kill(HANDLE process_handle, int signum) { switch (signum) { case SIGTERM: case SIGKILL: case SIGINT: { /* Unconditionally terminate the process. On Windows, killed processes */ /* normally return 1. */ DWORD error, status; if (TerminateProcess(process_handle, 1)) return uv_ok_; /* If the process already exited before TerminateProcess was called, */ /* TerminateProcess will fail with ERROR_ACESS_DENIED. */ error = GetLastError(); if (error == ERROR_ACCESS_DENIED && GetExitCodeProcess(process_handle, &status) && status != STILL_ACTIVE) { return uv__new_artificial_error(UV_ESRCH); } return uv__new_sys_error(error); } case 0: { /* Health check: is the process still alive? */ DWORD status; if (!GetExitCodeProcess(process_handle, &status)) return uv__new_sys_error(GetLastError()); if (status != STILL_ACTIVE) return uv__new_artificial_error(UV_ESRCH); return uv_ok_; } default: /* Unsupported signal. */ return uv__new_artificial_error(UV_ENOSYS); } }
uv_err_t uv_cwd(char* buffer, size_t size) { if (!buffer || !size) { return uv__new_artificial_error(UV_EINVAL); } if (getcwd(buffer, size)) { return uv_ok_; } else { return uv__new_sys_error(errno); } }
uv_err_t uv_chdir(const char* dir) { uv_err_t err; wchar_t* utf16Buffer = NULL; size_t utf16Size; if (!dir) { err.code = UV_EINVAL; goto done; } utf16Size = uv_utf8_to_utf16(dir, NULL, 0); if (!utf16Size) { err = uv__new_sys_error(GetLastError()); goto done; } utf16Buffer = (wchar_t*)malloc(sizeof(wchar_t) * utf16Size); if (!utf16Buffer) { err.code = UV_ENOMEM; goto done; } if (!uv_utf8_to_utf16(dir, utf16Buffer, utf16Size)) { err = uv__new_sys_error(GetLastError()); goto done; } if (_wchdir(utf16Buffer) == -1) { err = uv__new_sys_error(_doserrno); goto done; } err = uv_ok_; done: if (utf16Buffer) { free(utf16Buffer); } return err; }
uv_err_t uv_cwd(char* buffer, size_t size) { uv_err_t err; size_t utf8Size; wchar_t* utf16Buffer = NULL; if (!buffer || !size) { err.code = UV_EINVAL; goto done; } utf16Buffer = (wchar_t*)malloc(sizeof(wchar_t) * size); if (!utf16Buffer) { err.code = UV_ENOMEM; goto done; } if (!_wgetcwd(utf16Buffer, size - 1)) { err = uv__new_sys_error(_doserrno); goto done; } utf16Buffer[size - 1] = L'\0'; /* Convert to UTF-8 */ utf8Size = uv_utf16_to_utf8(utf16Buffer, -1, buffer, size); if (utf8Size == 0) { err = uv__new_sys_error(GetLastError()); goto done; } buffer[utf8Size] = '\0'; err = uv_ok_; done: if (utf16Buffer) { free(utf16Buffer); } return err; }
uv_err_t uv_kill(int pid, int signum) { uv_err_t err; HANDLE process_handle = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION, FALSE, pid); if (process_handle == INVALID_HANDLE_VALUE) { return uv__new_sys_error(GetLastError()); } err = uv__kill(process_handle, signum); CloseHandle(process_handle); return err; }
uv_err_t uv_resident_set_memory(size_t* rss) { HANDLE current_process; PROCESS_MEMORY_COUNTERS pmc; current_process = GetCurrentProcess(); if (!GetProcessMemoryInfo(current_process, &pmc, sizeof(pmc))) { return uv__new_sys_error(GetLastError()); } *rss = pmc.WorkingSetSize; return uv_ok_; }
uv_err_t uv_resident_set_memory(size_t* rss) { char pp[64]; psinfo_t psinfo; uv_err_t err; int fd; (void) snprintf(pp, sizeof(pp), "/proc/%lu/psinfo", (unsigned long) getpid()); fd = open(pp, O_RDONLY); if (fd == -1) return uv__new_sys_error(errno); err = uv_ok_; if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) *rss = (size_t)psinfo.pr_rssize * 1024; else err = uv__new_sys_error(EINVAL); close(fd); return err; }
uv_err_t uv_uptime(double* uptime) { time_t now; struct timeval info; size_t size = sizeof(info); static int which[] = {CTL_KERN, KERN_BOOTTIME}; if (sysctl(which, 2, &info, &size, NULL, 0) < 0) { return uv__new_sys_error(errno); } now = time(NULL); *uptime = (double)(now - info.tv_sec); return uv_ok_; }
static uv_err_t uv__signal_register_control_handler() { /* When this function is called, the uv__signal_lock must be held. */ /* If the console control handler has already been hooked, just add a */ /* reference. */ if (uv__signal_control_handler_refs > 0) return uv_ok_; if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE)) return uv__new_sys_error(GetLastError()); uv__signal_control_handler_refs++; return uv_ok_; }