Permalink
Browse files

uv: add uv_wait()

  • Loading branch information...
1 parent 43a2b29 commit bac102a181dd5dc277630559159dd8fa61e2fb63 @indutny committed Sep 21, 2012
View
@@ -58,9 +58,11 @@ if __name__ == '__main__':
# There's a bug with windows which doesn't allow this feature.
if sys.platform != 'win32':
- args.extend(['--generator-output', output_dir])
- args.extend(['-Goutput_dir=' + output_dir])
- args.extend('-f make'.split())
+ if '-f' not in args:
+ args.extend('-f make'.split())
+ if 'ninja' not in args:
+ args.extend(['-Goutput_dir=' + output_dir])
+ args.extend(['--generator-output', output_dir])
(major, minor), is_clang = compiler_version()
args.append('-Dgcc_version=%d' % (10 * major + minor))
args.append('-Dclang=%d' % int(is_clang))
@@ -598,6 +598,8 @@ void ev_loop_fork (EV_P);
unsigned int ev_backend (EV_P); /* backend in use by loop */
+int ev_backend_fd (EV_P); /* backend fd in use by loop */
+
void ev_now_update (EV_P); /* update event loop time */
#if EV_WALK_ENABLE
View
@@ -241,6 +241,11 @@ UV_EXTERN int uv_run(uv_loop_t*);
UV_EXTERN int uv_run_once(uv_loop_t*);
/*
+ * Block until event will happen (with dequeing it), or until timeout.
+ */
+UV_EXTERN void uv_wait(uv_loop_t*, unsigned int timeout);
+
+/*
* Manually modify the event loop's reference count. Useful if the user wants
* to have a handle or timeout that doesn't keep the loop alive.
*/
View
@@ -227,7 +227,7 @@ void uv_loop_delete(uv_loop_t* loop) {
}
-static unsigned int uv__poll_timeout(uv_loop_t* loop) {
+unsigned int uv__poll_timeout(uv_loop_t* loop) {
if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop))
return 0;
@@ -82,3 +82,8 @@ int uv_fs_event_init(uv_loop_t* loop,
void uv__fs_event_close(uv_fs_event_t* handle) {
assert(0 && "implement me");
}
+
+
+void uv_wait(uv_loop_t* loop, unsigned int timeout) {
+ assert(0 && "implement me");
+}
View
@@ -1621,6 +1621,12 @@ ev_backend (EV_P)
return backend;
}
+int
+ev_backend_fd (EV_P)
+{
+ return backend_fd;
+}
+
#if EV_FEATURE_API
unsigned int
ev_iteration (EV_P)
@@ -122,6 +122,7 @@ void uv__io_feed(uv_loop_t* loop, uv__io_t* handle, int event);
int uv__io_active(uv__io_t* handle);
/* loop */
+unsigned int uv__poll_timeout(uv_loop_t* loop);
int uv__loop_init(uv_loop_t* loop, int default_loop);
void uv__loop_delete(uv_loop_t* loop);
void uv__run_idle(uv_loop_t* loop);
View
@@ -29,6 +29,7 @@
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/event.h>
+#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
@@ -120,3 +121,19 @@ void uv__fs_event_close(uv_fs_event_t* handle) {
close(handle->fd);
handle->fd = -1;
}
+
+
+void uv_wait(uv_loop_t* loop, unsigned int timeout) {
+ struct timespec ts;
+ unsigned int poll_timeout;
+
+ poll_timeout = uv__poll_timeout(loop);
+ if (timeout != 0 && poll_timeout > timeout) {
+ poll_timeout = timeout;
+ }
+
+ ts.tv_sec = poll_timeout / 1000;
+ ts.tv_nsec = (poll_timeout - ts.tv_sec * 1000) * 1000000;
+
+ kevent(ev_backend_fd(loop->ev), NULL, 0, NULL, 0, &ts);
+}
@@ -63,6 +63,11 @@ static struct {
size_t len;
} process_title;
+static void read_models(unsigned int numcpus, uv_cpu_info_t* ci);
+static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci);
+static void read_times(unsigned int numcpus, uv_cpu_info_t* ci);
+static unsigned long read_cpufreq(unsigned int cpunum);
+
/*
* There's probably some way to get time from Linux than gettimeofday(). What
@@ -301,81 +306,163 @@ uv_err_t uv_uptime(double* uptime) {
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 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);
- }
+ unsigned int numcpus;
+ uv_cpu_info_t* ci;
- *cpu_infos = (uv_cpu_info_t*)malloc(numcpus * sizeof(uv_cpu_info_t));
- if (!(*cpu_infos)) {
- return uv__new_artificial_error(UV_ENOMEM);
- }
+ *cpu_infos = NULL;
+ *count = 0;
+
+ numcpus = sysconf(_SC_NPROCESSORS_ONLN);
+ assert(numcpus != (unsigned int) -1);
+ assert(numcpus != 0);
+ ci = calloc(numcpus, sizeof(*ci));
+ if (ci == NULL)
+ return uv__new_sys_error(ENOMEM);
+
+ read_speeds(numcpus, ci);
+ read_models(numcpus, ci);
+ read_times(numcpus, ci);
+
+ *cpu_infos = ci;
*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 %lu %lu %lu %lu %*s %lu",
- &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++;
+ return uv_ok_;
+}
+
+
+static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci) {
+ unsigned int num;
+
+ for (num = 0; num < numcpus; num++)
+ ci[num].speed = read_cpufreq(num) / 1000;
+}
+
+
+static void read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
+#if defined(__i386__) || defined(__x86_64__)
+ static const char marker[] = "model name\t: ";
+#elif defined(__arm__)
+ static const char marker[] = "Processor\t: ";
+#elif defined(__mips__)
+ static const char marker[] = "cpu model\t\t: ";
+#else
+# warning uv_cpu_info() is not supported on this architecture.
+ static const char marker[] = "(dummy)";
+#endif
+ unsigned int num;
+ char buf[1024];
+ char* model;
+ FILE* fp;
+
+ fp = fopen("/proc/cpuinfo", "r");
+ if (fp == NULL)
+ return;
+
+ num = 0;
+
+ while (fgets(buf, sizeof(buf), fp)) {
+ if (num >= numcpus)
+ break;
+
+ if (strncmp(buf, marker, sizeof(marker) - 1))
+ continue;
+
+ model = buf + sizeof(marker) - 1;
+ model = strndup(model, strlen(model) - 1); /* strip newline */
+ ci[num++].model = model;
+ }
+ fclose(fp);
+}
+
+
+static void read_times(unsigned int numcpus, uv_cpu_info_t* ci) {
+ unsigned long clock_ticks;
+ struct uv_cpu_times_s ts;
+ unsigned long user;
+ unsigned long nice;
+ unsigned long sys;
+ unsigned long idle;
+ unsigned long dummy;
+ unsigned long irq;
+ unsigned int num;
+ unsigned int len;
+ char buf[1024];
+ FILE* fp;
+
+ clock_ticks = sysconf(_SC_CLK_TCK);
+ assert(clock_ticks != (unsigned long) -1);
+ assert(clock_ticks != 0);
+
+ fp = fopen("/proc/stat", "r");
+ if (fp == NULL)
+ return;
+
+ if (!fgets(buf, sizeof(buf), fp))
+ abort();
+
+ num = 0;
+
+ while (fgets(buf, sizeof(buf), fp)) {
+ if (num >= numcpus)
+ break;
+
+ if (strncmp(buf, "cpu", 3))
+ break;
+
+ /* skip "cpu<num> " marker */
+ {
+ unsigned int n = num;
+ for (len = sizeof("cpu0"); n /= 10; len++);
+ assert(sscanf(buf, "cpu%u ", &n) == 1 && n == num);
}
- fclose(fpStat);
+
+ /* Line contains user, nice, system, idle, iowait, irq, softirq, steal,
+ * guest, guest_nice but we're only interested in the first four + irq.
+ *
+ * Don't use %*s to skip fields or %ll to read straight into the uint64_t
+ * fields, they're not allowed in C89 mode.
+ */
+ if (6 != sscanf(buf + len,
+ "%lu %lu %lu %lu %lu %lu",
+ &user,
+ &nice,
+ &sys,
+ &idle,
+ &dummy,
+ &irq))
+ abort();
+
+ ts.user = clock_ticks * user;
+ ts.nice = clock_ticks * nice;
+ ts.sys = clock_ticks * sys;
+ ts.idle = clock_ticks * idle;
+ ts.irq = clock_ticks * irq;
+ ci[num++].cpu_times = ts;
}
+ fclose(fp);
+}
- return uv_ok_;
+
+static unsigned long read_cpufreq(unsigned int cpunum) {
+ unsigned long val;
+ char buf[1024];
+ FILE* fp;
+
+ snprintf(buf,
+ sizeof(buf),
+ "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_cur_freq",
+ cpunum);
+
+ fp = fopen(buf, "r");
+ if (fp == NULL)
+ return 0;
+
+ val = 0;
+ fscanf(fp, "%lu", &val);
+ fclose(fp);
+
+ return val;
}
@@ -472,3 +559,16 @@ void uv_free_interface_addresses(uv_interface_address_t* addresses,
free(addresses);
}
+
+
+void uv_wait(uv_loop_t* loop, unsigned int timeout) {
+ struct timespec ts;
+ unsigned int poll_timeout;
+
+ poll_timeout = uv__poll_timeout(loop);
+ if (timeout != 0 && poll_timeout > timeout) {
+ poll_timeout = timeout;
+ }
+
+ epoll_wait(ev_backend_fd(loop->ev), NULL, 0, poll_timeout);
+}
Oops, something went wrong.

0 comments on commit bac102a

Please sign in to comment.