new plimit (inside sched), separated cpuload - vx32 - Local 9vx git repository for patches.
       
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
 (DIR) commit 6914d302fb3800c4704594ea7402e6f69845dc06
 (DIR) parent bd21de03ccb49344d258b1e0d6c63ee79e0b5956
 (HTM) 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(-)
       ---
 (DIR) 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 \
 (DIR) 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*);
 (DIR) 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;
       +        }
       +}
       +
 (DIR) 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();
 (DIR) 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;
       -}
 (DIR) 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;
       -}
 (DIR) 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);
       -}
 (DIR) 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;