platform api

This commit is contained in:
Igor Zinkovsky 2011-12-13 01:29:27 -08:00
parent 12cc4f7d3d
commit 3d189de699
14 changed files with 1691 additions and 5 deletions

View File

@ -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.

View File

@ -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);
}

View File

@ -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) {
}

View File

@ -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);
}

View File

@ -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) {
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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])) {

View File

@ -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

View File

@ -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)

View 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
View 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
View File

@ -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',