vx32

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

commit 6914d302fb3800c4704594ea7402e6f69845dc06
parent bd21de03ccb49344d258b1e0d6c63ee79e0b5956
Author: Jesus Galan Lopez (yiyus) <yiyu.jgl@gmail.com>
Date:   Wed, 30 Jun 2010 23:07:31 +0200

new plimit (inside sched), separated cpuload

Diffstat:
src/9vx/Makefrag | 2+-
src/9vx/a/portfns.h | 2++
src/9vx/load.c | 37+++++++++++++++++++++++++++++++++++++
src/9vx/main.c | 15++++++++-------
src/9vx/plimit-bsd.c | 144-------------------------------------------------------------------------------
src/9vx/plimit-darwin.c | 153-------------------------------------------------------------------------------
src/9vx/plimit-linux.c | 160-------------------------------------------------------------------------------
src/9vx/sched.c | 21+++++++++++++++++++++
8 files changed, 69 insertions(+), 465 deletions(-)

diff --git a/src/9vx/Makefrag b/src/9vx/Makefrag @@ -32,7 +32,6 @@ all: 9vx/9vx PLAN9_OBJS = \ $(addprefix 9vx/, \ bootcode.o \ - plimit-$(OS).o \ conf.o \ devaudio.o \ devaudio-$(PLAN9AUDIO).o \ @@ -45,6 +44,7 @@ PLAN9_OBJS = \ fossil.o \ kprocdev.o \ label.o \ + load.o \ main.o \ mmu.o \ sched.o \ diff --git a/src/9vx/a/portfns.h b/src/9vx/a/portfns.h @@ -410,3 +410,5 @@ void uartecho(char*, int); void vx32sysr1(void); void vxnewproc(Proc*); void mmusize(int); +void plimitproc(void*); +void ploadproc(void*); diff --git a/src/9vx/load.c b/src/9vx/load.c @@ -0,0 +1,37 @@ +#include "u.h" +#include <sys/times.h> +#include "lib.h" +#include "mem.h" +#include "dat.h" + +/* + * CPU load + */ +void +ploadproc(void *v) +{ + double load; + vlong hz; + struct tms t; + clock_t now, last; + clock_t used, lastused; + + hz = sysconf(_SC_CLK_TCK); + last = 0; + lastused = 0; + load = 0; + + for(;;){ + usleep(1000000); + now = times(&t); + used = t.tms_utime + t.tms_stime; + load = (double)(used - lastused) / (now - last); + machp[0]->load = load * 100 * hz; +/* +iprint("XXX Load: %d%%\n", (int)(load * 100)); +*/ + lastused = used; + last = now; + } +} + diff --git a/src/9vx/main.c b/src/9vx/main.c @@ -47,6 +47,7 @@ extern Dev audiodevtab; int doabort = 1; // for now int abortonfault; +int nocpuload; char* argv0; char* conffile = "9vx"; char* defaultroot = "local!#Z/usr/local/9vx"; @@ -112,6 +113,9 @@ main(int argc, char **argv) case 'K': tracekdev++; break; + case 'L': + nocpuload++; + break; case 'M': tracemmu++; break; @@ -213,13 +217,6 @@ main(int argc, char **argv) #endif /* - * After fork to deal with the correct pid. - * The cpu limiter will run in a new process. - */ - if(cpulimit != 0) - plimit(getpid(), cpulimit); - - /* * Have to do this after fork; on OS X child does * not inherit sigaltstack. */ @@ -243,6 +240,10 @@ main(int argc, char **argv) makekprocdev(&fsdevtab); makekprocdev(&drawdevtab); makekprocdev(&audiodevtab); + if(nocpuload == 0) + kproc("pload", &ploadproc, nil); + if(cpulimit > 0 && cpulimit < 100) + kproc("plimit", &plimitproc, &cpulimit); } bootinit(); pageinit(); diff --git a/src/9vx/plimit-bsd.c b/src/9vx/plimit-bsd.c @@ -1,144 +0,0 @@ -/* - * 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 @@ -1,153 +0,0 @@ -/* - * 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 @@ -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/sched.c b/src/9vx/sched.c @@ -162,6 +162,27 @@ runproc(void) } /* + * Limit CPU usage going to sleep while holding the run lock + */ +void +plimitproc(void *v) +{ + int lim; + uint sleeping, working; + + lim = *((int*)v); + sleeping = 100000 * (100 - lim) / 100; + working = 100000 * lim / 100; + + for(;;){ + usleep(working); + plock(&run); + usleep(sleeping); + punlock(&run); + } +} + +/* * Host OS process sleep and wakeup. */ static pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER;