platform api
This commit is contained in:
parent
12cc4f7d3d
commit
3d189de699
43
include/uv.h
43
include/uv.h
@ -177,6 +177,8 @@ typedef struct uv_async_s uv_async_t;
|
||||
typedef struct uv_getaddrinfo_s uv_getaddrinfo_t;
|
||||
typedef struct uv_process_s uv_process_t;
|
||||
typedef struct uv_counters_s uv_counters_t;
|
||||
typedef struct uv_cpu_info_s uv_cpu_info_t;
|
||||
typedef struct uv_interface_address_s uv_interface_address_t;
|
||||
/* Request types */
|
||||
typedef struct uv_req_s uv_req_t;
|
||||
typedef struct uv_shutdown_s uv_shutdown_t;
|
||||
@ -1036,7 +1038,48 @@ UV_EXTERN int uv_queue_work(uv_loop_t* loop, uv_work_t* req,
|
||||
uv_work_cb work_cb, uv_after_work_cb after_work_cb);
|
||||
|
||||
|
||||
struct uv_cpu_info_s {
|
||||
char* model;
|
||||
int speed;
|
||||
struct uv_cpu_times_s {
|
||||
uint64_t user;
|
||||
uint64_t nice;
|
||||
uint64_t sys;
|
||||
uint64_t idle;
|
||||
uint64_t irq;
|
||||
} cpu_times;
|
||||
};
|
||||
|
||||
struct uv_interface_address_s {
|
||||
char* name;
|
||||
int is_internal;
|
||||
union {
|
||||
struct sockaddr_in address4;
|
||||
struct sockaddr_in6 address6;
|
||||
} address;
|
||||
};
|
||||
|
||||
UV_EXTERN char** uv_setup_args(int argc, char** argv);
|
||||
UV_EXTERN uv_err_t uv_get_process_title(char* buffer, size_t size);
|
||||
UV_EXTERN uv_err_t uv_set_process_title(const char* title);
|
||||
UV_EXTERN uv_err_t uv_resident_set_memory(size_t* rss);
|
||||
UV_EXTERN uv_err_t uv_uptime(double* uptime);
|
||||
|
||||
/*
|
||||
* This allocates cpu_infos array, and sets count. The array
|
||||
* is freed using uv_free_cpu_info().
|
||||
*/
|
||||
UV_EXTERN uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
|
||||
UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);
|
||||
|
||||
/*
|
||||
* This allocates addresses array, and sets count. The array
|
||||
* is freed using uv_free_interface_addresses().
|
||||
*/
|
||||
UV_EXTERN uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
|
||||
int* count);
|
||||
UV_EXTERN void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||
int count);
|
||||
|
||||
/*
|
||||
* File System Methods.
|
||||
|
||||
@ -25,6 +25,9 @@
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <ifaddrs.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_time.h>
|
||||
@ -34,6 +37,9 @@
|
||||
#include <unistd.h> /* sysconf */
|
||||
|
||||
|
||||
static char *process_title;
|
||||
|
||||
|
||||
uint64_t uv_hrtime() {
|
||||
uint64_t time;
|
||||
Nanoseconds enano;
|
||||
@ -71,6 +77,7 @@ int uv_exepath(char* buffer, size_t* size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv_get_free_memory(void) {
|
||||
vm_statistics_data_t info;
|
||||
mach_msg_type_number_t count = sizeof(info) / sizeof(integer_t);
|
||||
@ -83,6 +90,7 @@ uint64_t uv_get_free_memory(void) {
|
||||
return (uint64_t) info.free_count * sysconf(_SC_PAGESIZE);
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv_get_total_memory(void) {
|
||||
uint64_t info;
|
||||
int which[] = {CTL_HW, HW_MEMSIZE};
|
||||
@ -95,6 +103,7 @@ uint64_t uv_get_total_memory(void) {
|
||||
return (uint64_t) info;
|
||||
}
|
||||
|
||||
|
||||
void uv_loadavg(double avg[3]) {
|
||||
struct loadavg info;
|
||||
size_t size = sizeof(info);
|
||||
@ -106,3 +115,206 @@ void uv_loadavg(double avg[3]) {
|
||||
avg[1] = (double) info.ldavg[1] / info.fscale;
|
||||
avg[2] = (double) info.ldavg[2] / info.fscale;
|
||||
}
|
||||
|
||||
|
||||
char** uv_setup_args(int argc, char** argv) {
|
||||
process_title = argc ? strdup(argv[0]) : NULL;
|
||||
return argv;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_set_process_title(const char* title) {
|
||||
/* TODO implement me */
|
||||
return uv__new_artificial_error(UV_ENOSYS);
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_get_process_title(char* buffer, size_t size) {
|
||||
if (process_title) {
|
||||
strncpy(buffer, process_title, size);
|
||||
} else {
|
||||
if (size > 0) {
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_resident_set_memory(size_t* rss) {
|
||||
struct task_basic_info t_info;
|
||||
mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
|
||||
|
||||
int r = task_info(mach_task_self(),
|
||||
TASK_BASIC_INFO,
|
||||
(task_info_t)&t_info,
|
||||
&t_info_count);
|
||||
|
||||
if (r != KERN_SUCCESS) {
|
||||
return uv__new_sys_error(errno);
|
||||
}
|
||||
|
||||
*rss = t_info.resident_size;
|
||||
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
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_;
|
||||
}
|
||||
|
||||
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("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_;
|
||||
}
|
||||
|
||||
|
||||
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
free(cpu_infos[i].model);
|
||||
}
|
||||
|
||||
free(cpu_infos);
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
|
||||
int* count) {
|
||||
struct ifaddrs *addrs, *ent;
|
||||
char ip[INET6_ADDRSTRLEN];
|
||||
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 == AF_LINK)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
*addresses = (uv_interface_address_t*)
|
||||
malloc(*count * sizeof(uv_interface_address_t));
|
||||
if (!(*addresses)) {
|
||||
return uv__new_artificial_error(UV_ENOMEM);
|
||||
}
|
||||
|
||||
address = *addresses;
|
||||
|
||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||
bzero(&ip, sizeof (ip));
|
||||
if (!(ent->ifa_flags & IFF_UP && ent->ifa_flags & IFF_RUNNING)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ent->ifa_addr == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* On Mac OS X getifaddrs returns information related to Mac Addresses for
|
||||
* various devices, such as firewire, etc. These are not relevant here.
|
||||
*/
|
||||
if (ent->ifa_addr->sa_family == AF_LINK) {
|
||||
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_;
|
||||
}
|
||||
|
||||
|
||||
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||
int count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
free(addresses[i].name);
|
||||
}
|
||||
|
||||
free(addresses);
|
||||
}
|
||||
|
||||
@ -35,6 +35,9 @@
|
||||
#define NANOSEC 1000000000
|
||||
|
||||
|
||||
static char *process_title;
|
||||
|
||||
|
||||
uint64_t uv_hrtime(void) {
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
@ -72,6 +75,7 @@ int uv_exepath(char* buffer, size_t* size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv_get_free_memory(void) {
|
||||
int freecount;
|
||||
size_t size = sizeof(freecount);
|
||||
@ -84,6 +88,7 @@ uint64_t uv_get_free_memory(void) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv_get_total_memory(void) {
|
||||
unsigned long info;
|
||||
int which[] = {CTL_HW, HW_PHYSMEM};
|
||||
@ -97,6 +102,7 @@ uint64_t uv_get_total_memory(void) {
|
||||
return (uint64_t) info;
|
||||
}
|
||||
|
||||
|
||||
void uv_loadavg(double avg[3]) {
|
||||
struct loadavg info;
|
||||
size_t size = sizeof(info);
|
||||
@ -108,3 +114,161 @@ void uv_loadavg(double avg[3]) {
|
||||
avg[1] = (double) info.ldavg[1] / info.fscale;
|
||||
avg[2] = (double) info.ldavg[2] / info.fscale;
|
||||
}
|
||||
|
||||
|
||||
char** uv_setup_args(int argc, char** argv) {
|
||||
process_title = argc ? strdup(argv[0]) : NULL;
|
||||
return argv;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_set_process_title(const char* title) {
|
||||
if (process_title) free(process_title);
|
||||
process_title = strdup(title);
|
||||
setproctitle(title);
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_get_process_title(char* buffer, size_t size) {
|
||||
if (process_title) {
|
||||
strncpy(buffer, process_title, size);
|
||||
} else {
|
||||
if (size > 0) {
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
*rss = kinfo->ki_rssize * page_size;
|
||||
|
||||
kvm_close(kd);
|
||||
|
||||
return uv_ok_;
|
||||
|
||||
error:
|
||||
if (kd) kvm_close(kd);
|
||||
return uv__new_sys_error(errno);
|
||||
}
|
||||
|
||||
|
||||
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_;
|
||||
}
|
||||
|
||||
|
||||
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, maxcpus,
|
||||
cur = 0;
|
||||
char model[512];
|
||||
int numcpus;
|
||||
size_t size;
|
||||
uv_cpu_info_t* cpu_info;
|
||||
|
||||
size = sizeof(model);
|
||||
if (sysctlbyname("hw.model", &model, &size, NULL, 0) < 0) {
|
||||
return uv__new_sys_error(errno);
|
||||
}
|
||||
size = sizeof(numcpus);
|
||||
if (sysctlbyname("hw.ncpu", &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;
|
||||
|
||||
size = sizeof(cpuspeed);
|
||||
if (sysctlbyname("hw.clockrate", &cpuspeed, &size, NULL, 0) < 0) {
|
||||
free(*cpu_infos);
|
||||
return uv__new_sys_error(errno);
|
||||
}
|
||||
// kern.cp_times on FreeBSD i386 gives an array up to maxcpus instead of ncpu
|
||||
size = sizeof(maxcpus);
|
||||
if (sysctlbyname("kern.smp.maxcpus", &maxcpus, &size, NULL, 0) < 0) {
|
||||
free(*cpu_infos);
|
||||
return uv__new_sys_error(errno);
|
||||
}
|
||||
size = maxcpus * CPUSTATES * sizeof(long);
|
||||
long cp_times[size];
|
||||
if (sysctlbyname("kern.cp_times", &cp_times, &size, NULL, 0) < 0) {
|
||||
free(*cpu_infos);
|
||||
return uv__new_sys_error(errno);
|
||||
}
|
||||
|
||||
for (int 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 = cpuspeed;
|
||||
|
||||
cur+=CPUSTATES;
|
||||
}
|
||||
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
free(cpu_infos[i].brand);
|
||||
}
|
||||
|
||||
free(cpu_infos);
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
|
||||
int* count) {
|
||||
/* TODO: implement */
|
||||
*addresses = NULL;
|
||||
*count = 0;
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||
int count) {
|
||||
}
|
||||
|
||||
363
src/unix/linux.c
363
src/unix/linux.c
@ -22,12 +22,16 @@
|
||||
#include "internal.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <ifaddrs.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
@ -36,6 +40,14 @@
|
||||
#define NANOSEC 1000000000
|
||||
|
||||
|
||||
static char buf[MAXPATHLEN + 1];
|
||||
|
||||
static struct {
|
||||
char *str;
|
||||
size_t len;
|
||||
} process_title;
|
||||
|
||||
|
||||
/* Don't look aghast, this is exactly how glibc's basename() works. */
|
||||
static char* basename_r(const char* path) {
|
||||
char* s = strrchr(path, '/');
|
||||
@ -209,3 +221,354 @@ void uv__fs_event_destroy(uv_fs_event_t* handle) {
|
||||
free(handle->filename);
|
||||
handle->filename = NULL;
|
||||
}
|
||||
|
||||
|
||||
char** uv_setup_args(int argc, char** argv) {
|
||||
char **new_argv;
|
||||
char **new_env;
|
||||
size_t size;
|
||||
int envc;
|
||||
char *s;
|
||||
int i;
|
||||
|
||||
for (envc = 0; environ[envc]; envc++);
|
||||
|
||||
s = envc ? environ[envc - 1] : argv[argc - 1];
|
||||
|
||||
process_title.str = argv[0];
|
||||
process_title.len = s + strlen(s) + 1 - argv[0];
|
||||
|
||||
size = process_title.len;
|
||||
size += (argc + 1) * sizeof(char **);
|
||||
size += (envc + 1) * sizeof(char **);
|
||||
|
||||
if ((s = (char *) malloc(size)) == NULL) {
|
||||
process_title.str = NULL;
|
||||
process_title.len = 0;
|
||||
return argv;
|
||||
}
|
||||
|
||||
new_argv = (char **) s;
|
||||
new_env = new_argv + argc + 1;
|
||||
s = (char *) (new_env + envc + 1);
|
||||
memcpy(s, process_title.str, process_title.len);
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
new_argv[i] = s + (argv[i] - argv[0]);
|
||||
new_argv[argc] = NULL;
|
||||
|
||||
s += environ[0] - argv[0];
|
||||
|
||||
for (i = 0; i < envc; i++)
|
||||
new_env[i] = s + (environ[i] - environ[0]);
|
||||
new_env[envc] = NULL;
|
||||
|
||||
environ = new_env;
|
||||
return new_argv;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_set_process_title(const char* title) {
|
||||
/* No need to terminate, last char is always '\0'. */
|
||||
if (process_title.len)
|
||||
strncpy(process_title.str, title, process_title.len - 1);
|
||||
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_get_process_title(char* buffer, size_t size) {
|
||||
if (process_title.str) {
|
||||
strncpy(buffer, process_title.str, size);
|
||||
} else {
|
||||
if (size > 0) {
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_resident_set_memory(size_t* rss) {
|
||||
FILE* f;
|
||||
int itmp;
|
||||
char ctmp;
|
||||
size_t page_size = getpagesize();
|
||||
char *cbuf;
|
||||
int foundExeEnd;
|
||||
|
||||
f = fopen("/proc/self/stat", "r");
|
||||
if (!f) return uv__new_sys_error(errno);
|
||||
|
||||
/* PID */
|
||||
if (fscanf(f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* Exec file */
|
||||
cbuf = buf;
|
||||
foundExeEnd = 0;
|
||||
if (fscanf (f, "%c", cbuf++) == 0) goto error;
|
||||
while (1) {
|
||||
if (fscanf(f, "%c", cbuf) == 0) goto error;
|
||||
if (*cbuf == ')') {
|
||||
foundExeEnd = 1;
|
||||
} else if (foundExeEnd && *cbuf == ' ') {
|
||||
*cbuf = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
cbuf++;
|
||||
}
|
||||
/* State */
|
||||
if (fscanf (f, "%c ", &ctmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* Parent process */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* Process group */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* Session id */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* TTY */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* TTY owner process group */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* Flags */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* Minor faults (no memory page) */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* Minor faults, children */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* Major faults (memory page faults) */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* Major faults, children */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* utime */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* stime */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* utime, children */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* stime, children */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* jiffies remaining in current time slice */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* 'nice' value */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* jiffies until next timeout */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* jiffies until next SIGALRM */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* start time (jiffies since system boot) */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
|
||||
/* Virtual memory size */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
|
||||
/* Resident set size */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
*rss = (size_t) itmp * page_size;
|
||||
|
||||
/* rlim */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* Start of text */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* End of text */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
/* Start of stack */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */
|
||||
|
||||
fclose (f);
|
||||
return uv_ok_;
|
||||
|
||||
error:
|
||||
fclose (f);
|
||||
return uv__new_sys_error(errno);
|
||||
}
|
||||
|
||||
|
||||
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_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;
|
||||
int numcpus = 0, i = 0;
|
||||
unsigned long long ticks_user, ticks_sys, ticks_idle, ticks_nice, ticks_intr;
|
||||
char line[512], speedPath[256], model[512];
|
||||
FILE *fpStat = fopen("/proc/stat", "r");
|
||||
FILE *fpModel = fopen("/proc/cpuinfo", "r");
|
||||
FILE *fpSpeed;
|
||||
uv_cpu_info_t* cpu_info;
|
||||
|
||||
if (fpModel) {
|
||||
while (fgets(line, 511, fpModel) != NULL) {
|
||||
if (strncmp(line, "model name", 10) == 0) {
|
||||
numcpus++;
|
||||
if (numcpus == 1) {
|
||||
char *p = strchr(line, ':') + 2;
|
||||
strcpy(model, p);
|
||||
model[strlen(model)-1] = 0;
|
||||
}
|
||||
} else if (strncmp(line, "cpu MHz", 7) == 0) {
|
||||
if (numcpus == 1) {
|
||||
sscanf(line, "%*s %*s : %u", &cpuspeed);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(fpModel);
|
||||
}
|
||||
|
||||
*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;
|
||||
|
||||
cpu_info = *cpu_infos;
|
||||
|
||||
if (fpStat) {
|
||||
while (fgets(line, 511, fpStat) != NULL) {
|
||||
if (strncmp(line, "cpu ", 4) == 0) {
|
||||
continue;
|
||||
} else if (strncmp(line, "cpu", 3) != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
sscanf(line, "%*s %llu %llu %llu %llu %*llu %llu",
|
||||
&ticks_user, &ticks_nice, &ticks_sys, &ticks_idle, &ticks_intr);
|
||||
snprintf(speedPath, sizeof(speedPath),
|
||||
"/sys/devices/system/cpu/cpu%u/cpufreq/cpuinfo_max_freq", i);
|
||||
|
||||
fpSpeed = fopen(speedPath, "r");
|
||||
|
||||
if (fpSpeed) {
|
||||
if (fgets(line, 511, fpSpeed) != NULL) {
|
||||
sscanf(line, "%u", &cpuspeed);
|
||||
cpuspeed /= 1000;
|
||||
}
|
||||
fclose(fpSpeed);
|
||||
}
|
||||
|
||||
cpu_info->cpu_times.user = ticks_user * multiplier;
|
||||
cpu_info->cpu_times.nice = ticks_nice * multiplier;
|
||||
cpu_info->cpu_times.sys = ticks_sys * multiplier;
|
||||
cpu_info->cpu_times.idle = ticks_idle * multiplier;
|
||||
cpu_info->cpu_times.irq = ticks_intr * multiplier;
|
||||
|
||||
cpu_info->model = strdup(model);
|
||||
cpu_info->speed = cpuspeed;
|
||||
|
||||
cpu_info++;
|
||||
}
|
||||
fclose(fpStat);
|
||||
}
|
||||
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
free(cpu_infos[i].model);
|
||||
}
|
||||
|
||||
free(cpu_infos);
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
|
||||
int* count) {
|
||||
struct ifaddrs *addrs, *ent;
|
||||
char ip[INET6_ADDRSTRLEN];
|
||||
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_PACKET)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
*addresses = (uv_interface_address_t*)
|
||||
malloc(*count * sizeof(uv_interface_address_t));
|
||||
if (!(*addresses)) {
|
||||
return uv__new_artificial_error(UV_ENOMEM);
|
||||
}
|
||||
|
||||
address = *addresses;
|
||||
|
||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||
bzero(&ip, sizeof (ip));
|
||||
if (!(ent->ifa_flags & IFF_UP && ent->ifa_flags & IFF_RUNNING)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ent->ifa_addr == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* On Linux getifaddrs returns information related to the raw underlying
|
||||
* devices. We're not interested in this information.
|
||||
*/
|
||||
if (ent->ifa_addr->sa_family == PF_PACKET) {
|
||||
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_;
|
||||
}
|
||||
|
||||
|
||||
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||
int count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
free(addresses[i].name);
|
||||
}
|
||||
|
||||
free(addresses);
|
||||
}
|
||||
|
||||
@ -33,12 +33,16 @@
|
||||
#define NANOSEC 1000000000
|
||||
|
||||
|
||||
static char *process_title;
|
||||
|
||||
|
||||
uint64_t uv_hrtime(void) {
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return (ts.tv_sec * NANOSEC + ts.tv_nsec);
|
||||
}
|
||||
|
||||
|
||||
void uv_loadavg(double avg[3]) {
|
||||
struct loadavg info;
|
||||
size_t size = sizeof(info);
|
||||
@ -51,6 +55,7 @@ void uv_loadavg(double avg[3]) {
|
||||
avg[2] = (double) info.ldavg[2] / info.fscale;
|
||||
}
|
||||
|
||||
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
int mib[4];
|
||||
char **argsbuf = NULL;
|
||||
@ -98,6 +103,7 @@ out:
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv_get_free_memory(void) {
|
||||
struct uvmexp info;
|
||||
size_t size = sizeof(info);
|
||||
@ -110,6 +116,7 @@ uint64_t uv_get_free_memory(void) {
|
||||
return (uint64_t) info.free * sysconf(_SC_PAGESIZE);
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv_get_total_memory(void) {
|
||||
uint64_t info;
|
||||
int which[] = {CTL_HW, HW_PHYSMEM64};
|
||||
@ -121,3 +128,160 @@ uint64_t uv_get_total_memory(void) {
|
||||
|
||||
return (uint64_t) info;
|
||||
}
|
||||
|
||||
|
||||
char** uv_setup_args(int argc, char** argv) {
|
||||
process_title = argc ? strdup(argv[0]) : NULL;
|
||||
return argv;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_set_process_title(const char* title) {
|
||||
if (process_title) free(process_title);
|
||||
process_title = strdup(title);
|
||||
setproctitle(title);
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_get_process_title(char* buffer, size_t size) {
|
||||
if (process_title) {
|
||||
strncpy(buffer, process_title, size);
|
||||
} else {
|
||||
if (size > 0) {
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_resident_set_memory(size_t* rss) {
|
||||
kvm_t *kd = NULL;
|
||||
struct kinfo_proc2 *kinfo = NULL;
|
||||
pid_t pid;
|
||||
int nprocs, max_size = sizeof(struct kinfo_proc2);
|
||||
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_getproc2(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);
|
||||
}
|
||||
|
||||
|
||||
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_;
|
||||
}
|
||||
|
||||
|
||||
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, NULL};
|
||||
size_t size;
|
||||
uv_cpu_info_t* cpu_info;
|
||||
|
||||
size = sizeof(model);
|
||||
if (sysctl(which, 2, &model, &size, NULL, 0) < 0) {
|
||||
return -1;
|
||||
}
|
||||
which[1] = HW_NCPU;
|
||||
size = sizeof(numcpus);
|
||||
if (sysctl(which, 2, &numcpus, &size, NULL, 0) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*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 (int 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_;
|
||||
}
|
||||
|
||||
|
||||
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
free(cpu_infos[i].brand);
|
||||
}
|
||||
|
||||
free(cpu_infos);
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
|
||||
int* count) {
|
||||
/* TODO: implement */
|
||||
*addresses = NULL;
|
||||
*count = 0;
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||
int count) {
|
||||
}
|
||||
|
||||
267
src/unix/sunos.c
267
src/unix/sunos.c
@ -28,6 +28,11 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef SUNOS_HAVE_IFADDRS
|
||||
# include <ifaddrs.h>
|
||||
#endif
|
||||
#include <net/if.h>
|
||||
|
||||
#include <sys/loadavg.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
@ -38,6 +43,19 @@
|
||||
# include <port.h>
|
||||
#endif
|
||||
|
||||
#if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64)
|
||||
#define PROCFS_FILE_OFFSET_BITS_HACK 1
|
||||
#undef _FILE_OFFSET_BITS
|
||||
#else
|
||||
#define PROCFS_FILE_OFFSET_BITS_HACK 0
|
||||
#endif
|
||||
|
||||
#include <procfs.h>
|
||||
|
||||
#if (PROCFS_FILE_OFFSET_BITS_HACK - 0 == 1)
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#endif
|
||||
|
||||
|
||||
uint64_t uv_hrtime() {
|
||||
return (gethrtime());
|
||||
@ -198,3 +216,252 @@ void uv__fs_event_destroy(uv_fs_event_t* handle) {
|
||||
}
|
||||
|
||||
#endif /* HAVE_PORTS_FS */
|
||||
|
||||
|
||||
char** uv_setup_args(int argc, char** argv) {
|
||||
return argv;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_set_process_title(const char* title) {
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_get_process_title(char* buffer, size_t size) {
|
||||
if (size > 0) {
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_resident_set_memory(size_t* rss) {
|
||||
pid_t pid = getpid();
|
||||
psinfo_t psinfo;
|
||||
char pidpath[1024];
|
||||
FILE *f;
|
||||
|
||||
sprintf(pidpath, "/proc/%d/psinfo", (int)pid);
|
||||
|
||||
f = fopen(pidpath, "r");
|
||||
if (!f) return uv__new_sys_error(errno);
|
||||
|
||||
if (fread(&psinfo, sizeof(psinfo_t), 1, f) != 1) {
|
||||
fclose (f);
|
||||
return uv__new_sys_error(errno);
|
||||
}
|
||||
|
||||
/* XXX correct? */
|
||||
|
||||
*rss = (size_t) psinfo.pr_rssize * 1024;
|
||||
|
||||
fclose (f);
|
||||
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_uptime(double* uptime) {
|
||||
kstat_ctl_t *kc;
|
||||
kstat_t *ksp;
|
||||
kstat_named_t *knp;
|
||||
|
||||
long hz = sysconf(_SC_CLK_TCK);
|
||||
|
||||
if ((kc = kstat_open()) == NULL)
|
||||
return uv__new_sys_error(errno);
|
||||
|
||||
ksp = kstat_lookup(kc, (char *)"unix", 0, (char *)"system_misc");
|
||||
|
||||
if (kstat_read(kc, ksp, NULL) == -1) {
|
||||
*uptime = -1;
|
||||
} else {
|
||||
knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"clk_intr");
|
||||
*uptime = knp->value.ul / hz;
|
||||
}
|
||||
|
||||
kstat_close(kc);
|
||||
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
int lookup_instance;
|
||||
kstat_ctl_t *kc;
|
||||
kstat_t *ksp;
|
||||
kstat_named_t *knp;
|
||||
uv_cpu_info_t* cpu_info;
|
||||
|
||||
if ((kc = kstat_open()) == NULL) {
|
||||
return uv__new_sys_error(errno);
|
||||
}
|
||||
|
||||
/* Get count of cpus */
|
||||
lookup_instance = 0;
|
||||
while ((ksp = kstat_lookup(kc, (char *)"cpu_info", lookup_instance, NULL))) {
|
||||
lookup_instance++;
|
||||
}
|
||||
|
||||
*cpu_infos = (uv_cpu_info_t*)
|
||||
malloc(lookup_instance * sizeof(uv_cpu_info_t));
|
||||
if (!(*cpu_infos)) {
|
||||
return uv__new_artificial_error(UV_ENOMEM);
|
||||
}
|
||||
|
||||
*count = lookup_instance;
|
||||
|
||||
cpu_info = *cpu_infos;
|
||||
lookup_instance = 0;
|
||||
while ((ksp = kstat_lookup(kc, (char *)"cpu_info", lookup_instance, NULL))) {
|
||||
if (kstat_read(kc, ksp, NULL) == -1) {
|
||||
/*
|
||||
* It is deeply annoying, but some kstats can return errors
|
||||
* under otherwise routine conditions. (ACPI is one
|
||||
* offender; there are surely others.) To prevent these
|
||||
* fouled kstats from completely ruining our day, we assign
|
||||
* an "error" member to the return value that consists of
|
||||
* the strerror().
|
||||
*/
|
||||
cpu_info->speed = 0;
|
||||
cpu_info->model = NULL;
|
||||
} else {
|
||||
knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"clock_MHz");
|
||||
assert(knp->data_type == KSTAT_DATA_INT32);
|
||||
cpu_info->speed = knp->value.i32;
|
||||
|
||||
knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"brand");
|
||||
assert(knp->data_type == KSTAT_DATA_STRING);
|
||||
cpu_info->model = KSTAT_NAMED_STR_PTR(knp);
|
||||
}
|
||||
|
||||
lookup_instance++;
|
||||
cpu_info++;
|
||||
}
|
||||
|
||||
cpu_info = *cpu_infos;
|
||||
lookup_instance = 0;
|
||||
while ((ksp = kstat_lookup(kc, (char *)"cpu", lookup_instance, (char *)"sys"))){
|
||||
|
||||
if (kstat_read(kc, ksp, NULL) == -1) {
|
||||
cpu_info->cpu_times.user = 0;
|
||||
cpu_info->cpu_times.nice = 0;
|
||||
cpu_info->cpu_times.sys = 0;
|
||||
cpu_info->cpu_times.idle = 0;
|
||||
cpu_info->cpu_times.irq = 0;
|
||||
} else {
|
||||
knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"cpu_ticks_user");
|
||||
assert(knp->data_type == KSTAT_DATA_UINT64);
|
||||
cpu_info->cpu_times.user = knp->value.ui64;
|
||||
|
||||
knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"cpu_ticks_kernel");
|
||||
assert(knp->data_type == KSTAT_DATA_UINT64);
|
||||
cpu_info->cpu_times.sys = knp->value.ui64;
|
||||
|
||||
knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"cpu_ticks_idle");
|
||||
assert(knp->data_type == KSTAT_DATA_UINT64);
|
||||
cpu_info->cpu_times.idle = knp->value.ui64;
|
||||
|
||||
knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"intr");
|
||||
assert(knp->data_type == KSTAT_DATA_UINT64);
|
||||
cpu_info->cpu_times.irq = knp->value.ui64;
|
||||
cpu_info->cpu_times.nice = 0;
|
||||
}
|
||||
|
||||
lookup_instance++;
|
||||
cpu_info++;
|
||||
}
|
||||
|
||||
kstat_close(kc);
|
||||
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
free(cpu_infos[i].model);
|
||||
}
|
||||
|
||||
free(cpu_infos);
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
|
||||
int* count) {
|
||||
#ifndef SUNOS_HAVE_IFADDRS
|
||||
return uv__new_artificial_error(UV_ENOSYS);
|
||||
#else
|
||||
struct ifaddrs *addrs, *ent;
|
||||
char ip[INET6_ADDRSTRLEN];
|
||||
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_PACKET)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
*addresses = (uv_interface_address_t*)
|
||||
malloc(*count * sizeof(uv_interface_address_t));
|
||||
if (!(*addresses)) {
|
||||
return uv__new_artificial_error(UV_ENOMEM);
|
||||
}
|
||||
|
||||
address = *addresses;
|
||||
|
||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||
bzero(&ip, sizeof (ip));
|
||||
if (!(ent->ifa_flags & IFF_UP && ent->ifa_flags & IFF_RUNNING)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ent->ifa_addr == NULL) {
|
||||
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_PRIVATE || ent->ifa_flags &
|
||||
IFF_LOOPBACK ? 1 : 0;
|
||||
|
||||
address++;
|
||||
}
|
||||
|
||||
freeifaddrs(addrs);
|
||||
|
||||
return uv_ok_;
|
||||
#endif /* SUNOS_HAVE_IFADDRS */
|
||||
}
|
||||
|
||||
|
||||
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||
int count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
free(addresses[i].name);
|
||||
}
|
||||
|
||||
free(addresses);
|
||||
}
|
||||
|
||||
330
src/win/util.c
330
src/win/util.c
@ -22,11 +22,30 @@
|
||||
#include <assert.h>
|
||||
#include <direct.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "uv.h"
|
||||
#include "internal.h"
|
||||
#include "tlhelp32.h"
|
||||
#include "psapi.h"
|
||||
#include "iphlpapi.h"
|
||||
|
||||
|
||||
/*
|
||||
* Max title length; the only thing MSDN tells us about the maximum length
|
||||
* of the console title is that it is smaller than 64K. However in practice
|
||||
* it is much smaller, and there is no way to figure out what the exact length
|
||||
* of the title is or can be, at least not on XP. To make it even more
|
||||
* annoying, GetConsoleTitle failes when the buffer to be read into is bigger
|
||||
* than the actual maximum length. So we make a conservative guess here;
|
||||
* just don't put the novel you're writing in the title, unless the plot
|
||||
* survives truncation.
|
||||
*/
|
||||
#define MAX_TITLE_LENGTH 8192
|
||||
|
||||
|
||||
static char *process_title;
|
||||
|
||||
|
||||
int uv_utf16_to_utf8(const wchar_t* utf16Buffer, size_t utf16Size,
|
||||
@ -236,3 +255,314 @@ int uv_parent_pid() {
|
||||
CloseHandle(handle);
|
||||
return parent_pid;
|
||||
}
|
||||
|
||||
|
||||
char** uv_setup_args(int argc, char** argv) {
|
||||
return argv;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_set_process_title(const char* title) {
|
||||
uv_err_t err;
|
||||
int length;
|
||||
wchar_t* title_w = NULL;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
free(process_title);
|
||||
process_title = strdup(title);
|
||||
|
||||
err = uv_ok_;
|
||||
|
||||
done:
|
||||
free(title_w);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int uv__get_process_title() {
|
||||
wchar_t title_w[MAX_TITLE_LENGTH];
|
||||
int length;
|
||||
|
||||
if (!GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Find out what the size of the buffer is that we need */
|
||||
length = uv_utf16_to_utf8(title_w, -1, NULL, 0);
|
||||
if (!length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(!process_title);
|
||||
process_title = (char*)malloc(length);
|
||||
if (!process_title) {
|
||||
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
|
||||
}
|
||||
|
||||
/* Do utf16 -> utf8 conversion here */
|
||||
if (!uv_utf16_to_utf8(title_w, -1, process_title, length)) {
|
||||
free(process_title);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_get_process_title(char* buffer, size_t size) {
|
||||
/*
|
||||
* If the process_title was never read before nor explicitly set,
|
||||
* we must query it with getConsoleTitleW
|
||||
*/
|
||||
if (!process_title && uv__get_process_title() == -1) {
|
||||
return uv__new_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
assert(process_title);
|
||||
strncpy(buffer, process_title, size);
|
||||
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
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_uptime(double* uptime) {
|
||||
*uptime = (double)GetTickCount()/1000.0;
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
uv_err_t err;
|
||||
char key[128];
|
||||
HKEY processor_key = NULL;
|
||||
DWORD cpu_speed = 0;
|
||||
DWORD cpu_speed_length = sizeof(cpu_speed);
|
||||
char cpu_brand[256];
|
||||
DWORD cpu_brand_length = sizeof(cpu_brand);
|
||||
SYSTEM_INFO system_info;
|
||||
uv_cpu_info_t* cpu_info;
|
||||
unsigned int i;
|
||||
|
||||
GetSystemInfo(&system_info);
|
||||
|
||||
*cpu_infos = (uv_cpu_info_t*)malloc(system_info.dwNumberOfProcessors *
|
||||
sizeof(uv_cpu_info_t));
|
||||
if (!(*cpu_infos)) {
|
||||
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
|
||||
}
|
||||
|
||||
*count = 0;
|
||||
|
||||
for (i = 0; i < system_info.dwNumberOfProcessors; i++) {
|
||||
_snprintf(key, sizeof(key), "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d", i);
|
||||
|
||||
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_QUERY_VALUE,
|
||||
&processor_key) != ERROR_SUCCESS) {
|
||||
if (i == 0) {
|
||||
err = uv__new_sys_error(GetLastError());
|
||||
goto done;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (RegQueryValueEx(processor_key, "~MHz", NULL, NULL,
|
||||
(LPBYTE)&cpu_speed, &cpu_speed_length)
|
||||
!= ERROR_SUCCESS) {
|
||||
err = uv__new_sys_error(GetLastError());
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (RegQueryValueEx(processor_key, "ProcessorNameString", NULL, NULL,
|
||||
(LPBYTE)&cpu_brand, &cpu_brand_length)
|
||||
!= ERROR_SUCCESS) {
|
||||
err = uv__new_sys_error(GetLastError());
|
||||
goto done;
|
||||
}
|
||||
|
||||
RegCloseKey(processor_key);
|
||||
processor_key = NULL;
|
||||
|
||||
cpu_info = &(*cpu_infos)[i];
|
||||
|
||||
/* $TODO: find times on windows */
|
||||
cpu_info->cpu_times.user = 0;
|
||||
cpu_info->cpu_times.nice = 0;
|
||||
cpu_info->cpu_times.sys = 0;
|
||||
cpu_info->cpu_times.idle = 0;
|
||||
cpu_info->cpu_times.irq = 0;
|
||||
|
||||
cpu_info->model = strdup(cpu_brand);
|
||||
cpu_info->speed = cpu_speed;
|
||||
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
err = uv_ok_;
|
||||
|
||||
done:
|
||||
if (processor_key) {
|
||||
RegCloseKey(processor_key);
|
||||
}
|
||||
|
||||
if (err.code != UV_OK) {
|
||||
free(*cpu_infos);
|
||||
*cpu_infos = NULL;
|
||||
*count = 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
free(cpu_infos[i].model);
|
||||
}
|
||||
|
||||
free(cpu_infos);
|
||||
}
|
||||
|
||||
|
||||
uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
|
||||
int* count) {
|
||||
unsigned long size = 0;
|
||||
IP_ADAPTER_ADDRESSES* adapter_addresses;
|
||||
IP_ADAPTER_ADDRESSES* adapter_address;
|
||||
uv_interface_address_t* address;
|
||||
struct sockaddr* sock_addr;
|
||||
int length;
|
||||
|
||||
if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &size)
|
||||
!= ERROR_BUFFER_OVERFLOW) {
|
||||
return uv__new_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
adapter_addresses = (IP_ADAPTER_ADDRESSES*)malloc(size);
|
||||
if (!adapter_addresses) {
|
||||
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
|
||||
}
|
||||
|
||||
if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapter_addresses, &size)
|
||||
!= ERROR_SUCCESS) {
|
||||
return uv__new_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
/* Count the number of interfaces */
|
||||
*count = 0;
|
||||
|
||||
for (adapter_address = adapter_addresses;
|
||||
adapter_address != NULL;
|
||||
adapter_address = adapter_address->Next) {
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
*addresses = (uv_interface_address_t*)
|
||||
malloc(*count * sizeof(uv_interface_address_t));
|
||||
if (!(*addresses)) {
|
||||
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
|
||||
}
|
||||
|
||||
address = *addresses;
|
||||
|
||||
for (adapter_address = adapter_addresses;
|
||||
adapter_address != NULL;
|
||||
adapter_address = adapter_address->Next,
|
||||
address++) {
|
||||
|
||||
/* Convert FriendlyName to utf8 */
|
||||
length = uv_utf16_to_utf8(adapter_address->FriendlyName, -1, NULL, 0);
|
||||
if (!length) {
|
||||
address->name = NULL;
|
||||
address->address.address4 = uv_addr_ip4_any_;
|
||||
continue;
|
||||
}
|
||||
|
||||
address->name = (char*)malloc(length);
|
||||
if (!address->name) {
|
||||
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
|
||||
}
|
||||
|
||||
if (!uv_utf16_to_utf8(adapter_address->FriendlyName, -1, address->name,
|
||||
length)) {
|
||||
free(address->name);
|
||||
address->name = NULL;
|
||||
address->address.address4 = uv_addr_ip4_any_;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (adapter_address->FirstUnicastAddress) {
|
||||
sock_addr = adapter_address->FirstUnicastAddress->Address.lpSockaddr;
|
||||
if (sock_addr->sa_family == AF_INET6) {
|
||||
address->address.address6 = *((struct sockaddr_in6 *)sock_addr);
|
||||
} else {
|
||||
address->address.address4 = *((struct sockaddr_in *)sock_addr);
|
||||
}
|
||||
}
|
||||
|
||||
address->is_internal =
|
||||
adapter_address->IfType == IF_TYPE_SOFTWARE_LOOPBACK ? 1 : 0;
|
||||
}
|
||||
|
||||
free(adapter_addresses);
|
||||
|
||||
return uv_ok_;
|
||||
}
|
||||
|
||||
|
||||
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||
int count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
free(addresses[i].name);
|
||||
}
|
||||
|
||||
free(addresses);
|
||||
}
|
||||
|
||||
@ -38,6 +38,8 @@ static int maybe_run_test(int argc, char **argv);
|
||||
int main(int argc, char **argv) {
|
||||
platform_init(argc, argv);
|
||||
|
||||
argv = uv_setup_args(argc, argv);
|
||||
|
||||
switch (argc) {
|
||||
case 1: return run_tests(TEST_TIMEOUT, 0);
|
||||
case 2: return maybe_run_test(argc, argv);
|
||||
|
||||
@ -191,8 +191,10 @@ out:
|
||||
}
|
||||
|
||||
/* Show error and output from processes if the test failed. */
|
||||
if (status != 0) {
|
||||
LOGF("\n`%s` failed: %s\n", test, errmsg);
|
||||
if (status != 0 || task->show_output) {
|
||||
if (status != 0) {
|
||||
LOGF("\n`%s` failed: %s\n", test, errmsg);
|
||||
}
|
||||
|
||||
for (i = 0; i < process_count; i++) {
|
||||
switch (process_output_size(&processes[i])) {
|
||||
|
||||
@ -40,6 +40,7 @@ typedef struct {
|
||||
char *process_name;
|
||||
int (*main)();
|
||||
int is_helper;
|
||||
int show_output;
|
||||
} task_entry_t, bench_entry_t;
|
||||
|
||||
|
||||
@ -57,19 +58,22 @@ typedef struct {
|
||||
int run_test_##name();
|
||||
|
||||
#define TEST_ENTRY(name) \
|
||||
{ #name, #name, &run_test_##name, 0 },
|
||||
{ #name, #name, &run_test_##name, 0, 0 },
|
||||
|
||||
#define TEST_OUTPUT_ENTRY(name) \
|
||||
{ #name, #name, &run_test_##name, 0, 1 },
|
||||
|
||||
#define BENCHMARK_DECLARE(name) \
|
||||
int run_benchmark_##name();
|
||||
|
||||
#define BENCHMARK_ENTRY(name) \
|
||||
{ #name, #name, &run_benchmark_##name, 0 },
|
||||
{ #name, #name, &run_benchmark_##name, 0, 0 },
|
||||
|
||||
#define HELPER_DECLARE(name) \
|
||||
int run_helper_##name();
|
||||
|
||||
#define HELPER_ENTRY(task_name, name) \
|
||||
{ #task_name, #name, &run_helper_##name, 1 },
|
||||
{ #task_name, #name, &run_helper_##name, 1, 0 },
|
||||
|
||||
#define TEST_HELPER HELPER_ENTRY
|
||||
#define BENCHMARK_HELPER HELPER_ENTRY
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
TEST_DECLARE (platform_output)
|
||||
TEST_DECLARE (tty)
|
||||
TEST_DECLARE (stdio_over_pipes)
|
||||
TEST_DECLARE (ipc_listen_before_write)
|
||||
@ -77,6 +78,7 @@ TEST_DECLARE (check_ref)
|
||||
TEST_DECLARE (unref_in_prepare_cb)
|
||||
TEST_DECLARE (async)
|
||||
TEST_DECLARE (get_currentexe)
|
||||
TEST_DECLARE (process_title)
|
||||
TEST_DECLARE (cwd_and_chdir)
|
||||
TEST_DECLARE (get_memory)
|
||||
TEST_DECLARE (hrtime)
|
||||
@ -136,6 +138,8 @@ HELPER_DECLARE (pipe_echo_server)
|
||||
|
||||
|
||||
TASK_LIST_START
|
||||
TEST_OUTPUT_ENTRY (platform_output)
|
||||
|
||||
TEST_ENTRY (pipe_connect_bad_name)
|
||||
|
||||
TEST_ENTRY (tty)
|
||||
@ -224,6 +228,8 @@ TASK_LIST_START
|
||||
|
||||
TEST_ENTRY (get_currentexe)
|
||||
|
||||
TEST_ENTRY (process_title)
|
||||
|
||||
TEST_ENTRY (cwd_and_chdir)
|
||||
|
||||
TEST_ENTRY (get_memory)
|
||||
|
||||
83
test/test-platform-output.c
Normal file
83
test/test-platform-output.c
Normal file
@ -0,0 +1,83 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
TEST_IMPL(platform_output) {
|
||||
char buffer[512];
|
||||
size_t rss;
|
||||
double uptime;
|
||||
uv_cpu_info_t* cpus;
|
||||
uv_interface_address_t* interfaces;
|
||||
int count;
|
||||
int i;
|
||||
uv_err_t err;
|
||||
|
||||
err = uv_get_process_title(buffer, sizeof(buffer));
|
||||
ASSERT(UV_OK == err.code);
|
||||
fprintf(stderr, "uv_get_process_title: %s\n", buffer);
|
||||
|
||||
err = uv_resident_set_memory(&rss);
|
||||
ASSERT(UV_OK == err.code);
|
||||
fprintf(stderr, "uv_resident_set_memory: %d\n", rss);
|
||||
|
||||
err = uv_uptime(&uptime);
|
||||
ASSERT(UV_OK == err.code);
|
||||
fprintf(stderr, "uv_uptime: %f\n", uptime);
|
||||
|
||||
err = uv_cpu_info(&cpus, &count);
|
||||
ASSERT(UV_OK == err.code);
|
||||
|
||||
fprintf(stderr, "uv_cpu_info:\n");
|
||||
for (i = 0; i < count; i++) {
|
||||
fprintf(stderr, " model: %s\n", cpus[i].model);
|
||||
fprintf(stderr, " speed: %d\n", cpus[i].speed);
|
||||
fprintf(stderr, " times.sys: %llu\n", cpus[i].cpu_times.sys);
|
||||
fprintf(stderr, " times.user: %llu\n", cpus[i].cpu_times.user);
|
||||
fprintf(stderr, " times.idle: %llu\n", cpus[i].cpu_times.idle);
|
||||
fprintf(stderr, " times.irq: %llu\n", cpus[i].cpu_times.irq);
|
||||
fprintf(stderr, " times.nice: %llu\n", cpus[i].cpu_times.nice);
|
||||
}
|
||||
uv_free_cpu_info(cpus, count);
|
||||
|
||||
err = uv_interface_addresses(&interfaces, &count);
|
||||
ASSERT(UV_OK == err.code);
|
||||
|
||||
fprintf(stderr, "uv_interface_addresses:\n");
|
||||
for (i = 0; i < count; i++) {
|
||||
fprintf(stderr, " name: %s\n", interfaces[i].name);
|
||||
fprintf(stderr, " internal: %d\n", interfaces[i].is_internal);
|
||||
|
||||
if (interfaces[i].address.address4.sin_family == AF_INET) {
|
||||
uv_ip4_name(&interfaces[i].address.address4, buffer, sizeof(buffer));
|
||||
} else if (interfaces[i].address.address4.sin_family == AF_INET6) {
|
||||
uv_ip6_name(&interfaces[i].address.address6, buffer, sizeof(buffer));
|
||||
}
|
||||
|
||||
fprintf(stderr, " address: %s\n", buffer);
|
||||
}
|
||||
uv_free_interface_addresses(interfaces, count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
42
test/test-process-title.c
Normal file
42
test/test-process-title.c
Normal file
@ -0,0 +1,42 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <string.h>
|
||||
|
||||
TEST_IMPL(process_title) {
|
||||
char buffer[512];
|
||||
uv_err_t err;
|
||||
|
||||
err = uv_get_process_title(buffer, sizeof(buffer));
|
||||
ASSERT(UV_OK == err.code);
|
||||
|
||||
err = uv_set_process_title("new title");
|
||||
ASSERT(UV_OK == err.code);
|
||||
|
||||
err = uv_get_process_title(buffer, sizeof(buffer));
|
||||
ASSERT(UV_OK == err.code);
|
||||
|
||||
ASSERT(strcmp(buffer, "new title") == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
4
uv.gyp
4
uv.gyp
@ -157,6 +157,8 @@
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
'-lws2_32.lib',
|
||||
'-lpsapi.lib',
|
||||
'-liphlpapi.lib'
|
||||
],
|
||||
},
|
||||
}, { # Not Windows i.e. POSIX
|
||||
@ -300,6 +302,8 @@
|
||||
'test/test-ping-pong.c',
|
||||
'test/test-pipe-bind-error.c',
|
||||
'test/test-pipe-connect-error.c',
|
||||
'test/test-platform-output.c',
|
||||
'test/test-process-title.c',
|
||||
'test/test-ref.c',
|
||||
'test/test-shutdown-eof.c',
|
||||
'test/test-spawn.c',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user