Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 12 May 2000 22:48:43 -0700 (PDT)
From:      Arun Sharma <adsharma@sharmas.dhs.org>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/18524: Per CPU time keeping on SMP
Message-ID:  <200005130548.WAA00677@sharmas.dhs.org>

next in thread | raw e-mail | index | archive | help

>Number:         18524
>Category:       kern
>Synopsis:       The current kernel doesn't keep stats on a per cpu basis
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri May 12 23:00:04 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     Arun Sharma
>Release:        FreeBSD 4.0-STABLE i386
>Organization:
Myself
>Environment:

	5.0-current

>Description:

	The current kernel doesn't keep stats on a per cpu basis 

>How-To-Repeat:

 	Run 5.0-current.	

>Fix:

	The attached patch creates the right variables within the kernel.
	The kld at http://sharmas.dhs.org/~adsharma/projects/freebsd/sysctl.tar.gz 
        extracts them using a bunch of dynamic sysctls. 
 
Implementation details:

1. On UP,
 
        sys_time is a global and contains the system wide stats
        cpu_time is a global and is essentially the same as sys_time.
 
2. On SMP
 
        sys_time contains the system wide stats
        cpu_time has been changed to a pointer in the per-cpu space.
        On BSP, this pointer points to a static array cpu0_cpu_time
        On APs, this space is kmem_alloc'ed
 
        Perhaps I should wrap cpu_time in a structure (cpu_info ?), which
        could be the right place to store all per CPU info.
 
3. I've taken the liberty of changing CP_* to CPU_*. I hope the new names
   better convey the meaning of the variables and are acceptable.   

4. The machine specific code for Alpha will need some changes - which I
   can implement, but have no way of compiling or testing.
 
5. All the existing utilties which depended on peeking at cp_time will
   break (which is a good thing, IMO - so that they can be changed to use 
   the new sysctl :-) 

6. After the above kld is loaded, the sysctl's will be at kern.stats.*


--- sys/i386/i386/genassym.c	Fri May  5 02:58:01 2000
+++ sys.new/i386/i386/genassym.c	Fri May 12 00:05:22 2000
@@ -197,6 +197,7 @@
 ASSYM(GD_PRV_CADDR2, offsetof(struct globaldata, gd_prv_CADDR2));
 ASSYM(GD_PRV_CADDR3, offsetof(struct globaldata, gd_prv_CADDR3));
 ASSYM(GD_PRV_PADDR1, offsetof(struct globaldata, gd_prv_PADDR1));
+ASSYM(GD_CPU_TIME, offsetof(struct globaldata, gd_cpu_time));
 ASSYM(PS_IDLESTACK, offsetof(struct privatespace, idlestack));
 ASSYM(PS_IDLESTACK_TOP, sizeof(struct privatespace));
 #endif
--- sys/i386/i386/globals.s	Mon Mar 27 23:16:15 2000
+++ sys.new/i386/i386/globals.s	Fri May 12 00:05:55 2000
@@ -110,6 +110,7 @@
 	.globl	gd_ss_eflags, gd_inside_intr
 	.globl  gd_prv_CMAP1, gd_prv_CMAP2, gd_prv_CMAP3, gd_prv_PMAP1
 	.globl  gd_prv_CADDR1, gd_prv_CADDR2, gd_prv_CADDR3, gd_prv_PADDR1
+	.globl  gd_cpu_time
 
 	.set    gd_cpuid,globaldata + GD_CPUID
 	.set    gd_cpu_lockid,globaldata + GD_CPU_LOCKID
@@ -124,6 +125,7 @@
 	.set    gd_prv_CADDR2,globaldata + GD_PRV_CADDR2
 	.set    gd_prv_CADDR3,globaldata + GD_PRV_CADDR3
 	.set    gd_prv_PADDR1,globaldata + GD_PRV_PADDR1
+	.set    gd_cpu_time,globaldata + GD_CPU_TIME
 #endif
 
 #if defined(SMP) || defined(APIC_IO)
--- sys/i386/i386/machdep.c	Fri May  5 02:58:02 2000
+++ sys.new/i386/i386/machdep.c	Fri May 12 00:06:37 2000
@@ -102,6 +102,7 @@
 #ifdef SMP
 #include <machine/smp.h>
 #include <machine/globaldata.h>
+#include <sys/dkstat.h>
 #endif
 #ifdef PERFMON
 #include <machine/perfmon.h>
@@ -131,6 +132,10 @@
 
 static MALLOC_DEFINE(M_MBUF, "mbuf", "mbuf");
 
+#ifdef SMP
+static cpu0_cpu_time[NCPUSTATES];
+#endif
+
 int	_udatasel, _ucodesel;
 u_int	atdevbase;
 
@@ -1986,6 +1991,11 @@
 	proc0.p_addr->u_pcb.pcb_mpnest = 1;
 #endif
 	proc0.p_addr->u_pcb.pcb_ext = 0;
+
+#ifdef SMP
+       /* Setup cpu0's cpu_time */
+       cpu_time = &cpu0_cpu_time;
+#endif  
 }
 
 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
--- sys/i386/i386/mp_machdep.c	Mon Mar 27 23:16:15 2000
+++ sys.new/i386/i386/mp_machdep.c	Fri May 12 22:10:48 2000
@@ -243,6 +243,11 @@
 /** XXX FIXME: what system files declare these??? */
 extern struct region_descriptor r_gdt, r_idt;
 
+extern long sys_time[NCPUSTATES];
+#ifndef SMP
+extern long cpu_time[NCPUSTATES];
+#endif
+
 int	bsp_apic_ready = 0;	/* flags useability of BSP apic */
 int	mp_ncpus;		/* # of CPUs, including BSP */
 int	mp_naps;		/* # of Applications processors */
@@ -1862,6 +1867,10 @@
 		SMPpt[pg + 3] = 0;		/* *prv_CMAP3 */
 		SMPpt[pg + 4] = 0;		/* *prv_PMAP1 */
 
+		/* space for cpu time */
+		gd->gd_cpu_time = (long *) kmem_alloc(kernel_map, sizeof(long)
+                                                      * NCPUSTATES);
+ 
 		/* prime data page for it to use */
 		gd->gd_cpuid = x;
 		gd->gd_cpu_lockid = x << 24;
@@ -2286,8 +2295,6 @@
 int		checkstate_cpustate[NCPU];
 u_long		checkstate_pc[NCPU];
 
-extern long	cp_time[CPUSTATES];
-
 #define PC_TO_INDEX(pc, prof)				\
         ((int)(((u_quad_t)((pc) - (prof)->pr_off) *	\
             (u_quad_t)((prof)->pr_scale)) >> 16) & ~1)
@@ -2336,10 +2343,13 @@
 		if (pscnt > 1)
 			return;
 		p->p_uticks++;
-		if (p->p_nice > NZERO)
-			cp_time[CP_NICE]++;
-		else
-			cp_time[CP_USER]++;
+		if (p->p_nice > NZERO) {
+			cpu_time[CPU_NICE]++;
+			sys_time[CPU_NICE]++;
+		} else {
+			cpu_time[CPU_USER]++;
+			sys_time[CPU_NICE]++;
+		}
 		break;
 	case CHECKSTATE_SYS:
 #ifdef GPROF
@@ -2358,11 +2368,13 @@
 		if (pscnt > 1)
 			return;
 
-		if (!p)
-			cp_time[CP_IDLE]++;
-		else {
+		if (!p) {
+			cpu_time[CPU_IDLE]++;
+			sys_time[CPU_IDLE]++;
+		} else {
 			p->p_sticks++;
-			cp_time[CP_SYS]++;
+			cpu_time[CPU_SYS]++;
+			sys_time[CPU_SYS]++;
 		}
 		break;
 	case CHECKSTATE_INTR:
@@ -2384,7 +2396,8 @@
 			return;
 		if (p)
 			p->p_iticks++;
-		cp_time[CP_INTR]++;
+		cpu_time[CPU_INTR]++;
+		sys_time[CPU_INTR]++;
 	}
 	if (p != NULL) {
 		schedclock(p);
--- sys/i386/include/globaldata.h	Mon Mar 27 23:16:20 2000
+++ sys.new/i386/include/globaldata.h	Fri May 12 00:11:42 2000
@@ -65,6 +65,7 @@
 	caddr_t		gd_prv_CADDR2;
 	caddr_t		gd_prv_CADDR3;
 	unsigned	*gd_prv_PADDR1;
+	long		*gd_cpu_time;
 #endif
 	u_int		gd_astpending;
 };
--- sys/i386/include/globals.h	Mon Mar 27 23:16:21 2000
+++ sys.new/i386/include/globals.h	Fri May 12 00:13:18 2000
@@ -108,6 +108,7 @@
 #define	prv_CADDR2	GLOBAL_RVALUE(prv_CADDR2, caddr_t)
 #define	prv_CADDR3	GLOBAL_RVALUE(prv_CADDR3, caddr_t)
 #define	prv_PADDR1	GLOBAL_RVALUE(prv_PADDR1, unsigned *)
+#define cpu_time        GLOBAL_LVALUE(cpu_time, long *)    
 #endif
 #endif	/*UP kernel*/
 
@@ -125,6 +126,8 @@
 #ifdef USER_LDT
 GLOBAL_FUNC(currentldt)
 #endif
+
+GLOBAL_FUNC(cpu_time)
 
 #ifdef SMP
 GLOBAL_FUNC(cpuid)
--- sys/kern/kern_clock.c	Wed Apr 19 07:57:51 2000
+++ sys.new/kern/kern_clock.c	Fri May 12 22:06:44 2000
@@ -69,11 +69,12 @@
 static void initclocks __P((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. */
-#if defined(SMP) && defined(BETTER_CLOCK)
-long cp_time[CPUSTATES];
-#else
-static long cp_time[CPUSTATES];
+/* System wide statistics */
+long           sys_time[NCPUSTATES];
+
+#ifndef SMP
+/* In the SMP case, this is in the per cpu private page */
+long           cpu_time[NCPUSTATES];
 #endif
 
 long tk_cancc;
@@ -343,10 +344,13 @@
 		 * Charge the time as appropriate.
 		 */
 		p->p_uticks++;
-		if (p->p_nice > NZERO)
-			cp_time[CP_NICE]++;
-		else
-			cp_time[CP_USER]++;
+		if (p->p_nice > NZERO) {
+			cpu_time[CPU_NICE]++;
+			sys_time[CPU_NICE]++;
+		} else {
+			cpu_time[CPU_USER]++;
+			sys_time[CPU_USER]++;
+		}
 	} else {
 #ifdef GPROF
 		/*
@@ -383,12 +387,16 @@
 		if (CLKF_INTR(frame)) {
 			if (p != NULL)
 				p->p_iticks++;
-			cp_time[CP_INTR]++;
+			cpu_time[CPU_INTR]++;
+			sys_time[CPU_INTR]++;
 		} else if (p != NULL) {
 			p->p_sticks++;
-			cp_time[CP_SYS]++;
-		} else
-			cp_time[CP_IDLE]++;
+			cpu_time[CPU_SYS]++;
+			sys_time[CPU_SYS]++;
+		} else {
+			cpu_time[CPU_IDLE]++;
+			sys_time[CPU_IDLE]++;
+		}
 	}
 	pscnt = psdiv;
 
--- sys/sys/dkstat.h	Tue Dec 28 20:24:40 1999
+++ sys.new/sys/dkstat.h	Fri May 12 22:04:50 2000
@@ -42,12 +42,12 @@
 #ifndef _SYS_DKSTAT_H_
 #define _SYS_DKSTAT_H_ 1
 
-#define	CP_USER		0
-#define	CP_NICE		1
-#define	CP_SYS		2
-#define	CP_INTR		3
-#define	CP_IDLE		4
-#define	CPUSTATES	5
+#define	CPU_USER		0
+#define	CPU_NICE		1
+#define	CPU_SYS			2
+#define	CPU_INTR		3
+#define	CPU_IDLE		4
+#define	NCPUSTATES		5
 
 #ifdef _KERNEL
 

>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200005130548.WAA00677>