commit 5220b28ac197e5f8f6ecc35be4be832b5f9e8d05
parent 788314fcd19a0728b05839a35c5b9fd6e9c57f8d
Author: Jesus Galan Lopez (yiyus) <yiyu.jgl@gmail.com>
Date:   Sun, 27 Jun 2010 01:28:49 +0200
plimit for freebsd, i dont know if compiles
--HG--
rename : src/9vx/cpulimit-linux.c => src/9vx/plimit-linux.c
Diffstat:
6 files changed, 459 insertions(+), 162 deletions(-)
diff --git a/src/9vx/Makefrag b/src/9vx/Makefrag
@@ -32,7 +32,7 @@ all: 9vx/9vx
 PLAN9_OBJS = \
 	$(addprefix 9vx/, \
 		bootcode.o \
-		cpulimit-$(OS).o \
+		plimit-$(OS).o \
 		conf.o \
 		devaudio.o \
 		devaudio-$(PLAN9AUDIO).o \
diff --git a/src/9vx/cpulimit-linux.c b/src/9vx/cpulimit-linux.c
@@ -1,160 +0,0 @@
-/*
- * plimit-linux.c - Process limiting support for Linux systems.
- *
- * Copyright (c) 2008 by Devon H. O'Dell <devon.odell@gmail.com>
- * Copyright (c) 2010 by Devon H. O'Dell <devon.odell@gmail.com>
- *
- * This software is released under a 2-clause BSD license.
- */
-
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/param.h>
-#include <sys/mman.h>
-
-#include <fcntl.h>
-#include <limits.h>
-#include <sched.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "u.h"
-
-#define timediff(x, y)						\
-	(((x)->tv_sec - (y)->tv_sec) * 1000000 +		\
-	((x)->tv_usec - (y)->tv_usec))
-
-int pid;
-
-void
-limit(int percent) {
-	struct timespec sleep_slice;
-	struct timespec work_slice;
-	struct timeval last_sample;
-	struct timeval last_start;
-	struct timeval last_end;
-	double last_usage;
-	int last_pstart;
-	double lim;
-	double rat;
-	double cpu;
-	char buf[1024];
-	char stat[MAXPATHLEN];
-	long hz;
-	int c;
-
-	hz = sysconf(_SC_CLK_TCK);
-
-	lim = (double)percent / 100;
-	rat = cpu = -1;
-	last_usage = 0.0;
-	c = last_pstart = -1;
-
-	snprintf(stat, MAXPATHLEN, "/proc/%d/stat", pid);
-
-	memset(&sleep_slice, 0, sizeof(struct timespec));
-	memset(&work_slice, 0, sizeof(struct timespec));
-	memset(&last_sample, 0, sizeof(struct timeval));
-	memset(&last_start, 0, sizeof(struct timeval));
-	memset(&last_end, 0, sizeof(struct timeval));
-
-	while (1) {
-		struct timeval now;
-		int seen_paren;
-		char *tmp;
-		long uj;
-		long sj;
-		long dt;
-		int n;
-		int r;
-		long t;
-
-		t = open(stat, O_RDONLY);
-		if (t < 0)
-			exit(1);
-		tmp = buf;
-		while ((n = read(t, tmp, 1024)) != 0)
-			tmp += n;
-		close(t);
-
-		seen_paren = n = 0;
-		while (buf[n] != ' ' && seen_paren == 0) {
-			if (buf[n] == ')')
-				seen_paren = 1;
-			n++;
-		}
-
-		r = 0;
-		while (r < 13)
-			if (buf[n++] == ' ')
-				r++;
-
-		uj = strtol(&buf[n], &tmp, 10);
-		sj = strtol(tmp, NULL, 10);
-
-		t = (uj + sj) * hz;
-
-		gettimeofday(&now, NULL);
-		if (last_pstart < 0) {
-			last_sample = now;
-			last_pstart = t;
-
-			kill(pid, SIGSTOP);
-			continue;
-		}
-
-		dt = timediff(&now, &last_sample);
-
-		if (last_usage == 0.0)
-			last_usage = ((t - last_pstart) / (dt * hz / 1000000.0));
-		else
-			last_usage = 0.96 * last_usage + 0.96 * ((t - last_pstart) / (dt * hz / 1000000.0));
-
-		last_sample = now;
-		last_pstart = t;
-
-		if (cpu < 0) {
-			cpu = lim;
-			rat = cpu;
-			work_slice.tv_nsec = 100000000 * lim;
-		} else {
-			rat = MIN(rat / cpu * lim, 1);
-			work_slice.tv_nsec = 100000000 * rat;
-		}
-
-		sleep_slice.tv_nsec = 100000000 - work_slice.tv_nsec;
-
-		kill(pid, SIGCONT);
-
-		gettimeofday(&last_start, NULL);
-		nanosleep(&work_slice, NULL);
-		gettimeofday(&last_end, NULL);
-
-		if (sleep_slice.tv_nsec > 0) {
-			kill(pid, SIGSTOP);
-			nanosleep(&sleep_slice, NULL);
-		}
-	}
-}
-
-void
-quit(int sig){
-	kill(pid, SIGCONT);
-	exit(0);
-}
-
-void
-plimit(pid_t p, int lim)
-{
-	if(fork() > 0)
-		return;
-
-	signal(SIGINT, quit);
-	signal(SIGTERM, quit);
-
-	pid = p;
-	limit(lim);
-}
diff --git a/src/9vx/main.c b/src/9vx/main.c
@@ -83,7 +83,7 @@ main(int argc, char **argv)
 	int vetap;
 	char *vedev;
 	char *inifile;
-	
+
 	/* Minimal set up to make print work. */
 	setmach(&mach0);
 	coherence = nop;
diff --git a/src/9vx/plimit-bsd.c b/src/9vx/plimit-bsd.c
@@ -0,0 +1,144 @@
+/*
+ * plimit-bsd.c - Process limiting support for BSD systems.
+ *
+ * Copyright (c) 2008 by Devon H. O'Dell <devon.odell@gmail.com>
+ *
+ * This software is released under a 2-clause BSD license.
+ */
+
+#include <sys/types.h>
+#include <sys/proc.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/timespec.h>
+#include <sys/user.h>
+
+#include <fcntl.h>
+#include <kvm.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "u.h"
+
+#define timediff(x, y)						\
+	(((x)->tv_sec - (y)->tv_sec) * 1000000 +		\
+	((x)->tv_usec - (y)->tv_usec))
+
+void
+plimit(pid_t pid, int percent)
+{
+	pid_t p;
+	double lim;
+
+	lim = (double)percent; // XXX: / 100 ?
+
+	p = rfork(RFPROC|RFNOWAIT|RFCFDG);
+
+	if (p == 0) {
+		struct timespec sleep_slice;
+		struct timespec work_slice;
+		struct timeval last_sample;
+		struct timeval last_start;
+		struct timeval last_end;
+		struct clockinfo ci;
+		double last_usage;
+		int last_pstart;
+		int mibctl[2];
+		size_t len;
+		double rat;
+		double cpu;
+		int c;
+
+		mibctl[0] = CTL_KERN;
+		mibctl[1] = KERN_CLOCKRATE;
+		len = sizeof(ci);
+		sysctl(mibctl, 2, &ci, &len, NULL, 0);
+
+		rat = cpu = -1;
+		last_usage = 0.0;
+		c = last_pstart = -1;
+
+		memset(&sleep_slice, 0, sizeof(struct timespec));
+		memset(&work_slice, 0, sizeof(struct timespec));
+		memset(&last_sample, 0, sizeof(struct timeval));
+		memset(&last_start, 0, sizeof(struct timeval));
+		memset(&last_end, 0, sizeof(struct timeval));
+
+		while (1) {
+			struct kinfo_proc *kp;
+			struct timeval now;
+			struct proc kp_p;
+			kvm_t *kd;
+			long dt;
+			uint64_t mt;
+			int t;
+
+			kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
+			if (!kd) {
+				return;
+			}
+
+			kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &t);
+			if (!kp) {
+				return;
+			}
+
+			if (kvm_read(kd, (ulong)kp->ki_paddr, &kp_p, sizeof (struct proc)) == -1) {
+				return;
+			}
+
+			mt = kp_p.p_rux.rux_tu + kp_p.p_crux.rux_tu;
+
+			kvm_close(kd);
+
+			gettimeofday(&now, NULL);
+			if (last_pstart < 0) {
+				last_sample = now;
+				last_pstart = mt;
+
+				kill(pid, SIGSTOP);
+				continue;
+			}
+
+			dt = timediff(&now, &last_sample);
+
+			if (last_usage == 0.0) {
+				last_usage = ((mt - last_pstart) / (dt * ci.hz / 1000000.0));
+			} else {
+				last_usage = 0.96 * last_usage + 0.96 * ((mt - last_pstart) / (dt * ci.hz / 1000000.0));
+			}
+
+			last_sample = now;
+			last_pstart = mt;
+
+			if (cpu < 0) {
+				cpu = lim;
+				rat = lim;
+				work_slice.tv_nsec = 100000000 * lim;
+			} else {
+				rat = MIN(rat / cpu * lim, 1);
+				work_slice.tv_nsec = 100000000 * rat;
+			}
+
+			sleep_slice.tv_nsec = 100000000 - work_slice.tv_nsec;
+
+			kill(pid, SIGCONT);
+
+			gettimeofday(&last_start, NULL);
+			nanosleep(&work_slice, NULL);
+			gettimeofday(&last_end, NULL);
+
+			if (sleep_slice.tv_nsec > 0) {
+				kill(pid, SIGSTOP);
+				nanosleep(&sleep_slice, NULL);
+			}
+		}
+	} else {
+		return;
+	}
+
+	return;
+}
diff --git a/src/9vx/plimit-darwin.c b/src/9vx/plimit-darwin.c
@@ -0,0 +1,153 @@
+/*
+ * plimit-bsd.c - Process limiting support for Darwin.
+ *
+ * Copyright (c) 2008 by Devon H. O'Dell <devon.odell@gmail.com>
+ *
+ * This software is released under a 2-clause BSD license.
+ */
+
+#warning "Darwin has no rfork; we'll have to figure out how to do this."
+
+#if 0
+#include <sys/types.h>
+#include <sys/proc.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/timespec.h>
+#include <sys/user.h>
+
+#include <fcntl.h>
+#include <kvm.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "u.h"
+
+
+#define timediff(x, y)						\
+	(((x)->tv_sec - (y)->tv_sec) * 1000000 +		\
+	((x)->tv_usec - (y)->tv_usec))
+#endif
+
+void
+plimit(pid_t pid, int percent)
+{
+
+fprintf(fileno(stderr), "there is no darwin support in plimit");
+/*
+	pid_t p;
+	double lim;
+
+	lim = (double)percent; // XXX: / 100 ?
+
+	p = rfork(RFPROC|RFNOWAIT|RFCFDG);
+
+	if (p == 0) {
+		struct timespec sleep_slice;
+		struct timespec work_slice;
+		struct timeval last_sample;
+		struct timeval last_start;
+		struct timeval last_end;
+		struct clockinfo ci;
+		double last_usage;
+		int last_pstart;
+		int mibctl[2];
+		size_t len;
+		double rat;
+		double cpu;
+		int c;
+
+		mibctl[0] = CTL_KERN;
+		mibctl[1] = KERN_CLOCKRATE;
+		len = sizeof(ci);
+		sysctl(mibctl, 2, &ci, &len, NULL, 0);
+
+		rat = cpu = -1;
+		last_usage = 0.0;
+		c = last_pstart = -1;
+
+		memset(&sleep_slice, 0, sizeof(struct timespec));
+		memset(&work_slice, 0, sizeof(struct timespec));
+		memset(&last_sample, 0, sizeof(struct timeval));
+		memset(&last_start, 0, sizeof(struct timeval));
+		memset(&last_end, 0, sizeof(struct timeval));
+
+		while (1) {
+			struct kinfo_proc *kp;
+			struct timeval now;
+			struct proc kp_p;
+			kvm_t *kd;
+			long dt;
+			uint64_t mt;
+			int t;
+
+			kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
+			if (!kd) {
+				return;
+			}
+
+			kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &t);
+			if (!kp) {
+				return;
+			}
+
+			if (kvm_read(kd, (ulong)kp->ki_paddr, &kp_p, sizeof (struct proc)) == -1) {
+				return;
+			}
+
+			mt = kp_p.p_rux.rux_tu + kp_p.p_crux.rux_tu;
+
+			kvm_close(kd);
+
+			gettimeofday(&now, NULL);
+			if (last_pstart < 0) {
+				last_sample = now;
+				last_pstart = mt;
+
+				kill(pid, SIGSTOP);
+				continue;
+			}
+
+			dt = timediff(&now, &last_sample);
+
+			if (last_usage == 0.0) {
+				last_usage = ((mt - last_pstart) / (dt * ci.hz / 1000000.0));
+			} else {
+				last_usage = 0.96 * last_usage + 0.96 * ((mt - last_pstart) / (dt * ci.hz / 1000000.0));
+			}
+
+			last_sample = now;
+			last_pstart = mt;
+
+			if (cpu < 0) {
+				cpu = lim;
+				rat = lim;
+				work_slice.tv_nsec = 100000000 * lim;
+			} else {
+				rat = MIN(rat / cpu * lim, 1);
+				work_slice.tv_nsec = 100000000 * rat;
+			}
+
+			sleep_slice.tv_nsec = 100000000 - work_slice.tv_nsec;
+
+			kill(pid, SIGCONT);
+
+			gettimeofday(&last_start, NULL);
+			nanosleep(&work_slice, NULL);
+			gettimeofday(&last_end, NULL);
+
+			if (sleep_slice.tv_nsec > 0) {
+				kill(pid, SIGSTOP);
+				nanosleep(&sleep_slice, NULL);
+			}
+		}
+	} else {
+		return;
+	}
+*/
+
+	return;
+}
diff --git a/src/9vx/plimit-linux.c b/src/9vx/plimit-linux.c
@@ -0,0 +1,160 @@
+/*
+ * plimit-linux.c - Process limiting support for Linux systems.
+ *
+ * Copyright (c) 2008 by Devon H. O'Dell <devon.odell@gmail.com>
+ * Copyright (c) 2010 by Devon H. O'Dell <devon.odell@gmail.com>
+ *
+ * This software is released under a 2-clause BSD license.
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/mman.h>
+
+#include <fcntl.h>
+#include <limits.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "u.h"
+
+#define timediff(x, y)						\
+	(((x)->tv_sec - (y)->tv_sec) * 1000000 +		\
+	((x)->tv_usec - (y)->tv_usec))
+
+int pid;
+
+void
+limit(int percent) {
+	struct timespec sleep_slice;
+	struct timespec work_slice;
+	struct timeval last_sample;
+	struct timeval last_start;
+	struct timeval last_end;
+	double last_usage;
+	int last_pstart;
+	double lim;
+	double rat;
+	double cpu;
+	char buf[1024];
+	char stat[MAXPATHLEN];
+	long hz;
+	int c;
+
+	hz = sysconf(_SC_CLK_TCK);
+
+	lim = (double)percent / 100;
+	rat = cpu = -1;
+	last_usage = 0.0;
+	c = last_pstart = -1;
+
+	snprintf(stat, MAXPATHLEN, "/proc/%d/stat", pid);
+
+	memset(&sleep_slice, 0, sizeof(struct timespec));
+	memset(&work_slice, 0, sizeof(struct timespec));
+	memset(&last_sample, 0, sizeof(struct timeval));
+	memset(&last_start, 0, sizeof(struct timeval));
+	memset(&last_end, 0, sizeof(struct timeval));
+
+	while (1) {
+		struct timeval now;
+		int seen_paren;
+		char *tmp;
+		long uj;
+		long sj;
+		long dt;
+		int n;
+		int r;
+		long t;
+
+		t = open(stat, O_RDONLY);
+		if (t < 0)
+			exit(1);
+		tmp = buf;
+		while ((n = read(t, tmp, 1024)) != 0)
+			tmp += n;
+		close(t);
+
+		seen_paren = n = 0;
+		while (buf[n] != ' ' && seen_paren == 0) {
+			if (buf[n] == ')')
+				seen_paren = 1;
+			n++;
+		}
+
+		r = 0;
+		while (r < 13)
+			if (buf[n++] == ' ')
+				r++;
+
+		uj = strtol(&buf[n], &tmp, 10);
+		sj = strtol(tmp, NULL, 10);
+
+		t = (uj + sj) * hz;
+
+		gettimeofday(&now, NULL);
+		if (last_pstart < 0) {
+			last_sample = now;
+			last_pstart = t;
+
+			kill(pid, SIGSTOP);
+			continue;
+		}
+
+		dt = timediff(&now, &last_sample);
+
+		if (last_usage == 0.0)
+			last_usage = ((t - last_pstart) / (dt * hz / 1000000.0));
+		else
+			last_usage = 0.96 * last_usage + 0.96 * ((t - last_pstart) / (dt * hz / 1000000.0));
+
+		last_sample = now;
+		last_pstart = t;
+
+		if (cpu < 0) {
+			cpu = lim;
+			rat = cpu;
+			work_slice.tv_nsec = 100000000 * lim;
+		} else {
+			rat = MIN(rat / cpu * lim, 1);
+			work_slice.tv_nsec = 100000000 * rat;
+		}
+
+		sleep_slice.tv_nsec = 100000000 - work_slice.tv_nsec;
+
+		kill(pid, SIGCONT);
+
+		gettimeofday(&last_start, NULL);
+		nanosleep(&work_slice, NULL);
+		gettimeofday(&last_end, NULL);
+
+		if (sleep_slice.tv_nsec > 0) {
+			kill(pid, SIGSTOP);
+			nanosleep(&sleep_slice, NULL);
+		}
+	}
+}
+
+void
+quit(int sig){
+	kill(pid, SIGCONT);
+	exit(0);
+}
+
+void
+plimit(pid_t p, int lim)
+{
+	if(fork() > 0)
+		return;
+
+	signal(SIGINT, quit);
+	signal(SIGTERM, quit);
+
+	pid = p;
+	limit(lim);
+}