--- //depot/projects/smpng/sys/compat/linprocfs/linprocfs.c 2007/05/19 15:31:43 +++ //depot/user/jhb/lock/compat/linprocfs/linprocfs.c 2007/05/19 16:26:17 @@ -374,19 +374,26 @@ static int linprocfs_dostat(PFS_FILL_ARGS) { + long cp_time[CPUSTATES]; + long *cp; int i; + read_cpu_time(cp_time); sbuf_printf(sb, "cpu %ld %ld %ld %ld\n", T2J(cp_time[CP_USER]), T2J(cp_time[CP_NICE]), T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/), T2J(cp_time[CP_IDLE])); - for (i = 0; i < mp_ncpus; ++i) + for (i = 0; i <= mp_maxid; ++i) { + if (CPU_ABSENT(i)) + continue; + cp = &cp_times[CPUSTATES * i]; sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i, - T2J(cp_time[CP_USER]) / mp_ncpus, - T2J(cp_time[CP_NICE]) / mp_ncpus, - T2J(cp_time[CP_SYS]) / mp_ncpus, - T2J(cp_time[CP_IDLE]) / mp_ncpus); + T2J(cp[CP_USER]), + T2J(cp[CP_NICE]), + T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/), + T2J(cp[CP_IDLE])); + } sbuf_printf(sb, "disk 0 0 0 0\n" "page %u %u\n" @@ -410,9 +417,11 @@ static int linprocfs_douptime(PFS_FILL_ARGS) { + long cp_time[CPUSTATES]; struct timeval tv; getmicrouptime(&tv); + read_cpu_time(cp_time); sbuf_printf(sb, "%lld.%02ld %ld.%02ld\n", (long long)tv.tv_sec, tv.tv_usec / 10000, T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100); --- //depot/projects/smpng/sys/kern/kern_clock.c 2007/03/09 22:52:10 +++ //depot/user/jhb/lock/kern/kern_clock.c 2007/03/09 23:26:17 @@ -80,35 +80,115 @@ static void initclocks(void *dummy); SYSINIT(clocks, SI_SUB_CLOCKS, SI_ORDER_FIRST, initclocks, NULL) -/* Some of these don't belong here, but it's easiest to concentrate them. */ -long cp_time[CPUSTATES]; +/* Some of these don't belong here, but it's easiest to concentrate them. */ +long cp_times[CPUSTATES * MAXCPU]; static int sysctl_kern_cp_time(SYSCTL_HANDLER_ARGS) { - int error; + long cp_time[CPUSTATES]; #ifdef SCTL_MASK32 int i; unsigned int cp_time32[CPUSTATES]; +#endif + + if (!req->oldptr) { +#ifdef SCTL_MASK32 + if (req->flags & SCTL_MASK32) + return SYSCTL_OUT(req, 0, sizeof(cp_time32)); +#endif + return SYSCTL_OUT(req, 0, sizeof(cp_time)); + } + read_cpu_time(cp_time); + +#ifdef SCTL_MASK32 if (req->flags & SCTL_MASK32) { - if (!req->oldptr) - return SYSCTL_OUT(req, 0, sizeof(cp_time32)); for (i = 0; i < CPUSTATES; i++) cp_time32[i] = (unsigned int)cp_time[i]; - error = SYSCTL_OUT(req, cp_time32, sizeof(cp_time32)); - } else + return (SYSCTL_OUT(req, cp_time32, sizeof(cp_time32))); + } +#endif + return (SYSCTL_OUT(req, cp_time, sizeof(cp_time))); +} + +SYSCTL_PROC(_kern, OID_AUTO, cp_time, CTLTYPE_LONG|CTLFLAG_RD, + 0,0, sysctl_kern_cp_time, "LU", "System CPU time statistics"); + +static int +sysctl_kern_pcpu_time(SYSCTL_HANDLER_ARGS) +{ + long zero; + int error, i, j; +#ifdef SCTL_MASK32 + unsigned int cp_time32[CPUSTATES], zero32; +#endif + + if (!req->oldptr) { +#ifdef SCTL_MASK32 + if (req->flags & SCTL_MASK32) + return (SYSCTL_OUT(req, 0, sizeof(cp_time32) * + (mp_maxid + 1))); +#endif + return (SYSCTL_OUT(req, 0, sizeof(long) * CPUSTATES * + (mp_maxid + 1))); + } + + error = 0; + zero = 0; +#ifdef SCTL_MASK32 + zero32 = 0; +#endif + for (i = 0; error == 0 && i <= mp_maxid; i++) { + + /* + * If there isn't a CPU for this ID, just output an + * array of zero ticks. + */ + if (CPU_ABSENT(i)) { + for (j = 0; error == 0 && j < CPUSTATES; j++) { +#ifdef SCTL_MASK32 + if (req->flags & SCTL_MASK32) + error = SYSCTL_OUT(req, &zero32, + sizeof(zero32)); + else +#endif + error = SYSCTL_OUT(req, &zero, + sizeof(zero)); + } + continue; + } + +#ifdef SCTL_MASK32 + if (req->flags & SCTL_MASK32) { + for (j = 0; j < CPUSTATES; j++) + cp_time32[j] = cp_times[CPUSTATES * i + j]; + error = SYSCTL_OUT(req, cp_time32, sizeof(cp_time32)); + } else #endif - { - if (!req->oldptr) - return SYSCTL_OUT(req, 0, sizeof(cp_time)); - error = SYSCTL_OUT(req, cp_time, sizeof(cp_time)); + error = SYSCTL_OUT(req, &cp_times[CPUSTATES * i], + sizeof(long) * CPUSTATES); } - return error; + return (error); } -SYSCTL_PROC(_kern, OID_AUTO, cp_time, CTLTYPE_LONG|CTLFLAG_RD, - 0,0, sysctl_kern_cp_time, "LU", "CPU time statistics"); +SYSCTL_PROC(_kern, OID_AUTO, pcpu_time, CTLTYPE_LONG|CTLFLAG_RD, + 0,0, sysctl_kern_pcpu_time, "LU", "Per-CPU time statistics"); + +void +read_cpu_time(long *cp_time) +{ + int i, j; + + /* Sum up global cp_time[]. */ + bzero(cp_time, sizeof(long) * CPUSTATES); + for (i = 0; i <= mp_maxid; i++) { + if (CPU_ABSENT(i)) + continue; + for (j = 0; j < CPUSTATES; j++) + cp_time[j] += cp_times[i * CPUSTATES + j]; + } +} #ifdef SW_WATCHDOG #include @@ -407,12 +487,12 @@ struct vmspace *vm; struct thread *td; struct proc *p; - long rss; + long *cp_time, rss; td = curthread; p = td->td_proc; + cp_time = &cp_times[PCPU_GET(cpuid) * CPUSTATES]; - mtx_lock_spin_flags(&sched_lock, MTX_QUIET); if (usermode) { /* * Charge the time as appropriate. @@ -459,6 +539,7 @@ CTR4(KTR_SCHED, "statclock: %p(%s) prio %d stathz %d", td, td->td_proc->p_comm, td->td_priority, (stathz)?stathz:hz); + mtx_lock_spin_flags(&sched_lock, MTX_QUIET); sched_clock(td); /* Update resource usage integrals and maximums. */ --- //depot/projects/smpng/sys/sys/resource.h 2005/11/21 20:05:51 +++ //depot/user/jhb/lock/sys/resource.h 2006/11/16 16:59:04 @@ -156,7 +156,9 @@ #ifdef _KERNEL extern struct loadavg averunnable; -extern long cp_time[CPUSTATES]; +extern long cp_times[CPUSTATES * MAXCPU]; + +void read_cpu_time(long cp_time[CPUSTATES]); #else