Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 27 Nov 2007 00:50:22 GMT
From:      Peter Wemm <peter@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 129605 for review
Message-ID:  <200711270050.lAR0oMYU069098@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=129605

Change 129605 by peter@peter_melody on 2007/11/27 00:50:01

	Checkpoint kernel side of cp_times diff.  Parts unashamedly stolen
	from jhb or merged with his diffs - linprocfs, some layout and strategies.
	Unlike his, I'm keeping cp_time in pcpu rather than a tightly packed array
	for better cache behavior.

Affected files ...

.. //depot/projects/hammer/sys/compat/linprocfs/linprocfs.c#38 edit
.. //depot/projects/hammer/sys/kern/kern_clock.c#42 edit
.. //depot/projects/hammer/sys/sys/pcpu.h#14 edit
.. //depot/projects/hammer/sys/sys/resource.h#13 edit

Differences ...

==== //depot/projects/hammer/sys/compat/linprocfs/linprocfs.c#38 (text+ko) ====

@@ -374,19 +374,28 @@
 static int
 linprocfs_dostat(PFS_FILL_ARGS)
 {
+	struct pcpu *pcpu;
+	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;
+		pcpu = pcpu_find(i);
+		cp = pcpu->pc_cp_time;
 		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 +419,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/hammer/sys/kern/kern_clock.c#42 (text+ko) ====

@@ -81,9 +81,6 @@
 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];
-
 /* Spin-lock protecting profiling statistics. */
 static struct mtx time_lock;
 
@@ -91,10 +88,14 @@
 sysctl_kern_cp_time(SYSCTL_HANDLER_ARGS)
 {
 	int error;
+	long cp_time[CPUSTATES];
 #ifdef SCTL_MASK32
 	int i;
 	unsigned int cp_time32[CPUSTATES];
+#endif
 
+	read_cpu_time(cp_time);
+#ifdef SCTL_MASK32
 	if (req->flags & SCTL_MASK32) {
 		if (!req->oldptr)
 			return SYSCTL_OUT(req, 0, sizeof(cp_time32));
@@ -114,6 +115,67 @@
 SYSCTL_PROC(_kern, OID_AUTO, cp_time, CTLTYPE_LONG|CTLFLAG_RD,
     0,0, sysctl_kern_cp_time, "LU", "CPU time statistics");
 
+
+static long empty[CPUSTATES];
+
+static int
+sysctl_kern_cp_times(SYSCTL_HANDLER_ARGS)
+{
+	struct pcpu *pcpu;
+	int error;
+	int i, c;
+	long *times;
+#ifdef SCTL_MASK32
+	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) * (mp_maxid + 1));
+		else
+#endif
+			return SYSCTL_OUT(req, 0, sizeof(long) * CPUSTATES * (mp_maxid + 1));
+	}
+	for (error = 0, c = 0; error == 0 && c <= mp_maxid; c++) {
+		if (!CPU_ABSENT(c)) {
+			pcpu = pcpu_find(c);
+			times = pcpu->pc_cp_time;
+		} else {
+			times = empty;
+		}
+#ifdef SCTL_MASK32
+		if (req->flags & SCTL_MASK32) {
+			for (i = 0; i < CPUSTATES; i++)
+				cp_time32[i] = (unsigned int)times[i];
+			error = SYSCTL_OUT(req, cp_time32, sizeof(cp_time32));
+		} else
+#endif
+			error = SYSCTL_OUT(req, times, sizeof(long) * CPUSTATES);
+	}
+	return error;
+}
+
+SYSCTL_PROC(_kern, OID_AUTO, cp_times, CTLTYPE_LONG|CTLFLAG_RD,
+    0,0, sysctl_kern_cp_times, "LU", "per-CPU time statistics");
+
+void
+read_cpu_time(long *cp_time)
+{
+	struct pcpu *pc;
+	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;
+		pc = pcpu_find(i);
+		for (j = 0; j < CPUSTATES; j++)
+			cp_time[j] += pc->pc_cp_time[j];
+	}
+}
+
 #ifdef SW_WATCHDOG
 #include <sys/watchdog.h>
 
@@ -405,11 +467,12 @@
 	struct thread *td;
 	struct proc *p;
 	long rss;
+	long *times;
 
 	td = curthread;
 	p = td->td_proc;
 
-	thread_lock_flags(td, MTX_QUIET);
+	times = (long *)PCPU_PTR(cp_time);
 	if (usermode) {
 		/*
 		 * Charge the time as appropriate.
@@ -420,9 +483,9 @@
 #endif
 		td->td_uticks++;
 		if (p->p_nice > NZERO)
-			atomic_add_long(&cp_time[CP_NICE], 1);
+			times[CP_NICE]++;
 		else
-			atomic_add_long(&cp_time[CP_USER], 1);
+			times[CP_USER]++;
 	} else {
 		/*
 		 * Came from kernel mode, so we were:
@@ -439,7 +502,7 @@
 		if ((td->td_pflags & TDP_ITHREAD) ||
 		    td->td_intr_nesting_level >= 2) {
 			td->td_iticks++;
-			atomic_add_long(&cp_time[CP_INTR], 1);
+			times[CP_INTR]++;
 		} else {
 #ifdef KSE
 			if (p->p_flag & P_SA)
@@ -448,9 +511,9 @@
 			td->td_pticks++;
 			td->td_sticks++;
 			if (!TD_IS_IDLETHREAD(td))
-				atomic_add_long(&cp_time[CP_SYS], 1);
+				times[CP_SYS]++;
 			else
-				atomic_add_long(&cp_time[CP_IDLE], 1);
+				times[CP_IDLE]++;
 		}
 	}
 
@@ -466,6 +529,7 @@
 		ru->ru_maxrss = rss;
 	CTR4(KTR_SCHED, "statclock: %p(%s) prio %d stathz %d",
 	    td, td->td_name, td->td_priority, (stathz)?stathz:hz);
+	thread_lock_flags(td, MTX_QUIET);
 	sched_clock(td);
 	thread_unlock(td);
 }

==== //depot/projects/hammer/sys/sys/pcpu.h#14 (text+ko) ====

@@ -43,6 +43,7 @@
 
 #include <sys/queue.h>
 #include <sys/vmmeter.h>
+#include <sys/resource.h>
 #include <machine/pcpu.h>
 
 struct pcb;
@@ -82,6 +83,7 @@
 #endif
 	PCPU_MD_FIELDS;
 	struct vmmeter	pc_cnt;			/* VM stats counters */
+	long		pc_cp_time[CPUSTATES];
 	struct device	*pc_device;
 
 	/* 

==== //depot/projects/hammer/sys/sys/resource.h#13 (text+ko) ====

@@ -154,7 +154,7 @@
 #ifdef _KERNEL
 
 extern struct loadavg averunnable;
-extern long cp_time[CPUSTATES];
+void	read_cpu_time(long *cp_time);	/* Writes array of CPUSTATES */
 
 #else
 



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