vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

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:
src/9vx/Makefrag | 2+-
src/9vx/cpulimit-linux.c | 160-------------------------------------------------------------------------------
src/9vx/main.c | 2+-
src/9vx/plimit-bsd.c | 144+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/9vx/plimit-darwin.c | 153+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/9vx/plimit-linux.c | 160+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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); +}