Diff below, gypped from jmatthew@, allows us to see how much time CPUs
spend spinning on a mutex or on the KERNEL_LOCK().
On my sparc64 with 16 CPUs, top(1) now reports:
16 CPUs: 16.8% user, 0.0% nice, 9.2% sys, 49.4% spin, 0.1% intr, 24.5% idle
And systat(1) CPU view:
CPU User Nice System Spin Interrupt Idle
0 3.9% 0.0% 3.9% 74.5% 2.0% 15.7%
1 5.9% 0.0% 21.6% 72.5% 0.0% 0.0%
2 9.8% 0.0% 5.9% 84.3% 0.0% 0.0%
3 5.9% 0.0% 9.8% 82.4% 0.0% 2.0%
...
15 2.0% 0.0% 13.7% 56.9% 0.0% 27.5%
To keep it simple, systat(1) vmstat view now shows the spinning time instead
of the nice time.
I'd like to put something like that in, to be able to better understand
profiling and performance analysis.
Comments? Oks?
Index: usr.bin/top/machine.c
===================================================================
RCS file: /cvs/src/usr.bin/top/machine.c,v
retrieving revision 1.89
diff -u -p -r1.89 machine.c
--- usr.bin/top/machine.c 30 May 2017 06:01:30 -0000 1.89
+++ usr.bin/top/machine.c 8 May 2018 14:51:28 -0000
@@ -108,7 +108,7 @@ char *procstatenames[] = {
/* these are for detailing the cpu states */
int64_t *cpu_states;
char *cpustatenames[] = {
- "user", "nice", "system", "interrupt", "idle", NULL
+ "user", "nice", "sys", "spin", "intr", "idle", NULL
};
/* these are for detailing the memory statistics */
Index: usr.bin/systat/vmstat.c
===================================================================
RCS file: /cvs/src/usr.bin/systat/vmstat.c,v
retrieving revision 1.83
diff -u -p -r1.83 vmstat.c
--- usr.bin/systat/vmstat.c 3 May 2018 07:49:18 -0000 1.83
+++ usr.bin/systat/vmstat.c 8 May 2018 15:53:18 -0000
@@ -268,7 +268,7 @@ labelkre(void)
mvprintw(GENSTATROW, GENSTATCOL, " Csw Trp Sys Int Sof Flt");
mvprintw(GRAPHROW, GRAPHCOL,
- " . %%Int . %%Sys . %%Usr . %%Nic . %%Idle");
+ " . %%Int . %%Sys . %%Usr . %%Spn . %%Idle");
mvprintw(PROCSROW, PROCSCOL, "Proc:r d s w");
mvprintw(GRAPHROW + 1, GRAPHCOL,
"| | | | | | | | | | |");
@@ -306,8 +306,8 @@ labelkre(void)
} while (0)
#define MAXFAIL 5
-static char cpuchar[CPUSTATES] = { '|', '=', '>', '-', ' ' };
-static char cpuorder[CPUSTATES] = { CP_INTR, CP_SYS, CP_USER, CP_NICE, CP_IDLE
};
+static char cpuchar[] = { '|', '=', '>', '-', ' ' };
+static char cpuorder[] = { CP_INTR, CP_SYS, CP_USER, CP_SPIN, CP_IDLE };
void
showkre(void)
@@ -367,7 +367,7 @@ showkre(void)
psiz = 0;
f2 = 0.0;
- for (c = 0; c < CPUSTATES; c++) {
+ for (c = 0; c < nitems(cpuorder); c++) {
i = cpuorder[c];
f1 = cputime(i);
f2 += f1;
Index: usr.bin/systat/cpu.c
===================================================================
RCS file: /cvs/src/usr.bin/systat/cpu.c,v
retrieving revision 1.5
diff -u -p -r1.5 cpu.c
--- usr.bin/systat/cpu.c 2 Jan 2016 20:02:40 -0000 1.5
+++ usr.bin/systat/cpu.c 8 May 2018 15:43:23 -0000
@@ -68,21 +68,23 @@ field_def fields_cpu[] = {
{ "User", 10, 20, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0 },
{ "Nice", 10, 20, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0 },
{ "System", 10, 20, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0 },
+ { "Spin", 10, 20, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0 },
{ "Interrupt", 10, 20, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0 },
{ "Idle", 10, 20, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0 },
};
#define FLD_CPU_CPU FIELD_ADDR(fields_cpu, 0)
-#define FLD_CPU_INT FIELD_ADDR(fields_cpu, 1)
-#define FLD_CPU_SYS FIELD_ADDR(fields_cpu, 2)
-#define FLD_CPU_USR FIELD_ADDR(fields_cpu, 3)
-#define FLD_CPU_NIC FIELD_ADDR(fields_cpu, 4)
-#define FLD_CPU_IDLE FIELD_ADDR(fields_cpu, 5)
+#define FLD_CPU_USR FIELD_ADDR(fields_cpu, 1)
+#define FLD_CPU_NIC FIELD_ADDR(fields_cpu, 2)
+#define FLD_CPU_SYS FIELD_ADDR(fields_cpu, 3)
+#define FLD_CPU_SPIN FIELD_ADDR(fields_cpu, 4)
+#define FLD_CPU_INT FIELD_ADDR(fields_cpu, 5)
+#define FLD_CPU_IDLE FIELD_ADDR(fields_cpu, 6)
/* Define views */
field_def *view_cpu_0[] = {
- FLD_CPU_CPU,
- FLD_CPU_INT, FLD_CPU_SYS, FLD_CPU_USR, FLD_CPU_NIC, FLD_CPU_IDLE, NULL
+ FLD_CPU_CPU, FLD_CPU_USR, FLD_CPU_NIC, FLD_CPU_SYS, FLD_CPU_SPIN,
+ FLD_CPU_INT, FLD_CPU_IDLE, NULL
};
/* Define view managers */
@@ -232,11 +234,12 @@ initcpu(void)
do { \
if (cur >= dispstart && cur < end) { \
print_fld_size(FLD_CPU_CPU, (v)); \
- print_fld_percentage(FLD_CPU_INT, (cs[0])); \
- print_fld_percentage(FLD_CPU_SYS, (cs[1])); \
- print_fld_percentage(FLD_CPU_USR, (cs[2])); \
- print_fld_percentage(FLD_CPU_NIC, (cs[3])); \
- print_fld_percentage(FLD_CPU_IDLE, (cs[4])); \
+ print_fld_percentage(FLD_CPU_USR, (cs[CP_USER]));\
+ print_fld_percentage(FLD_CPU_NIC, (cs[CP_NICE]));\
+ print_fld_percentage(FLD_CPU_SYS, (cs[CP_SYS]));\
+ print_fld_percentage(FLD_CPU_SPIN, (cs[CP_SPIN]));\
+ print_fld_percentage(FLD_CPU_INT, (cs[CP_INTR]));\
+ print_fld_percentage(FLD_CPU_IDLE, (cs[CP_IDLE]));
\
end_line(); \
} \
if (++cur >= end) \
Index: sys/sys/sched.h
===================================================================
RCS file: /cvs/src/sys/sys/sched.h,v
retrieving revision 1.44
diff -u -p -r1.44 sched.h
--- sys/sys/sched.h 14 Dec 2017 23:21:04 -0000 1.44
+++ sys/sys/sched.h 8 May 2018 14:51:50 -0000
@@ -83,9 +83,10 @@
#define CP_USER 0
#define CP_NICE 1
#define CP_SYS 2
-#define CP_INTR 3
-#define CP_IDLE 4
-#define CPUSTATES 5
+#define CP_SPIN 3
+#define CP_INTR 4
+#define CP_IDLE 5
+#define CPUSTATES 6
#define SCHED_NQS 32 /* 32 run queues. */
Index: sys/kern/kern_lock.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_lock.c,v
retrieving revision 1.63
diff -u -p -r1.63 kern_lock.c
--- sys/kern/kern_lock.c 26 Apr 2018 06:51:48 -0000 1.63
+++ sys/kern/kern_lock.c 8 May 2018 14:23:20 -0000
@@ -117,6 +117,7 @@ __mp_lock_spin(struct __mp_lock *mpl, u_
int nticks = __mp_lock_spinout;
#endif
+ curcpu()->ci_spinning = 1;
while (mpl->mpl_ticket != me) {
CPU_BUSY_CYCLE();
@@ -128,6 +129,7 @@ __mp_lock_spin(struct __mp_lock *mpl, u_
}
#endif
}
+ curcpu()->ci_spinning = 0;
}
void
@@ -261,6 +263,7 @@ __mtx_enter(struct mutex *mtx)
int nticks = __mp_lock_spinout;
#endif
+ curcpu()->ci_spinning = 1;
while (__mtx_enter_try(mtx) == 0) {
CPU_BUSY_CYCLE();
@@ -272,6 +275,7 @@ __mtx_enter(struct mutex *mtx)
}
#endif
}
+ curcpu()->ci_spinning = 0;
}
int
Index: sys/kern/kern_clock.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_clock.c,v
retrieving revision 1.93
diff -u -p -r1.93 kern_clock.c
--- sys/kern/kern_clock.c 22 Jul 2017 14:33:45 -0000 1.93
+++ sys/kern/kern_clock.c 8 May 2018 14:24:27 -0000
@@ -395,7 +395,9 @@ statclock(struct clockframe *frame)
if (p != NULL)
p->p_iticks++;
spc->spc_cp_time[CP_INTR]++;
- } else if (p != NULL && p != spc->spc_idleproc) {
+ } else if (ci->ci_spinning)
+ spc->spc_cp_time[CP_SPIN]++;
+ else if (p != NULL && p != spc->spc_idleproc) {
p->p_sticks++;
spc->spc_cp_time[CP_SYS]++;
} else
Index: sys/arch/sparc64/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/sparc64/include/cpu.h,v
retrieving revision 1.92
diff -u -p -r1.92 cpu.h
--- sys/arch/sparc64/include/cpu.h 3 Dec 2017 10:55:50 -0000 1.92
+++ sys/arch/sparc64/include/cpu.h 8 May 2018 14:27:51 -0000
@@ -163,6 +163,7 @@ struct cpu_info {
#ifdef GPROF
struct gmonparam *ci_gmon;
#endif
+ volatile int ci_spinning;
};
#define CPUF_RUNNING 0x0001 /* CPU is running */
Index: sys/arch/sh/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/sh/include/cpu.h,v
retrieving revision 1.27
diff -u -p -r1.27 cpu.h
--- sys/arch/sh/include/cpu.h 11 Jul 2014 10:53:07 -0000 1.27
+++ sys/arch/sh/include/cpu.h 8 May 2018 14:27:41 -0000
@@ -68,6 +68,7 @@ struct cpu_info {
#ifdef GPROF
struct gmonparam *ci_gmon;
#endif
+ volatile int ci_spinning;
};
extern struct cpu_info cpu_info_store;
Index: sys/arch/powerpc/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/powerpc/include/cpu.h,v
retrieving revision 1.63
diff -u -p -r1.63 cpu.h
--- sys/arch/powerpc/include/cpu.h 7 May 2016 22:46:54 -0000 1.63
+++ sys/arch/powerpc/include/cpu.h 8 May 2018 14:27:26 -0000
@@ -91,6 +91,7 @@ struct cpu_info {
#ifdef GPROF
struct gmonparam *ci_gmon;
#endif
+ volatile int ci_spinning;
};
static __inline struct cpu_info *
Index: sys/arch/mips64/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/mips64/include/cpu.h,v
retrieving revision 1.124
diff -u -p -r1.124 cpu.h
--- sys/arch/mips64/include/cpu.h 24 Feb 2018 11:42:31 -0000 1.124
+++ sys/arch/mips64/include/cpu.h 8 May 2018 14:27:22 -0000
@@ -219,6 +219,7 @@ struct cpu_info {
#ifdef GPROF
struct gmonparam *ci_gmon;
#endif
+ volatile int ci_spinning;
};
#define CPUF_PRIMARY 0x01 /* CPU is primary CPU */
Index: sys/arch/m88k/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/m88k/include/cpu.h,v
retrieving revision 1.65
diff -u -p -r1.65 cpu.h
--- sys/arch/m88k/include/cpu.h 19 Mar 2017 10:57:29 -0000 1.65
+++ sys/arch/m88k/include/cpu.h 8 May 2018 14:27:12 -0000
@@ -177,6 +177,7 @@ struct cpu_info {
#ifdef GPROF
struct gmonparam *ci_gmon;
#endif
+ volatile int ci_spinning;
};
extern cpuid_t master_cpu;
Index: sys/arch/i386/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/i386/include/cpu.h,v
retrieving revision 1.162
diff -u -p -r1.162 cpu.h
--- sys/arch/i386/include/cpu.h 11 Apr 2018 15:44:08 -0000 1.162
+++ sys/arch/i386/include/cpu.h 8 May 2018 14:27:03 -0000
@@ -206,6 +206,8 @@ struct cpu_info {
union vmm_cpu_cap ci_vmm_cap;
uint64_t ci_vmxon_region_pa; /* Must be 64 bit */
struct vmxon_region *ci_vmxon_region;
+
+ volatile int ci_spinning;
};
/*
Index: sys/arch/hppa/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/hppa/include/cpu.h,v
retrieving revision 1.90
diff -u -p -r1.90 cpu.h
--- sys/arch/hppa/include/cpu.h 18 May 2017 15:41:59 -0000 1.90
+++ sys/arch/hppa/include/cpu.h 8 May 2018 14:26:53 -0000
@@ -112,6 +112,7 @@ struct cpu_info {
#ifdef GPROF
struct gmonparam *ci_gmon;
#endif
+ volatile int ci_spinning;
} __attribute__((__aligned__(64)));
#define CPUF_RUNNING 0x0001 /* CPU is running. */
Index: sys/arch/arm64/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/arm64/include/cpu.h,v
retrieving revision 1.7
diff -u -p -r1.7 cpu.h
--- sys/arch/arm64/include/cpu.h 30 Jan 2018 15:46:12 -0000 1.7
+++ sys/arch/arm64/include/cpu.h 8 May 2018 14:26:46 -0000
@@ -124,6 +124,8 @@ struct cpu_info {
#ifdef GPROF
struct gmonparam *ci_gmon;
#endif
+
+ volatile int ci_spinning;
};
#define CPUF_PRIMARY (1<<0)
Index: sys/arch/arm/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/arm/include/cpu.h,v
retrieving revision 1.50
diff -u -p -r1.50 cpu.h
--- sys/arch/arm/include/cpu.h 26 Jan 2018 16:22:20 -0000 1.50
+++ sys/arch/arm/include/cpu.h 8 May 2018 14:26:38 -0000
@@ -209,6 +209,8 @@ struct cpu_info {
#endif
void (*ci_flush_bp)(void);
+
+ volatile int ci_spinning;
};
extern struct cpu_info cpu_info_primary;
Index: sys/arch/amd64/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/amd64/include/cpu.h,v
retrieving revision 1.120
diff -u -p -r1.120 cpu.h
--- sys/arch/amd64/include/cpu.h 29 Mar 2018 01:21:02 -0000 1.120
+++ sys/arch/amd64/include/cpu.h 8 May 2018 14:22:21 -0000
@@ -204,6 +204,8 @@ struct cpu_info {
union vmm_cpu_cap ci_vmm_cap;
paddr_t ci_vmxon_region_pa;
struct vmxon_region *ci_vmxon_region;
+
+ volatile int ci_spinning;
};
#define CPUF_BSP 0x0001 /* CPU is the original BSP */
Index: sys/arch/alpha/include/cpu.h
===================================================================
RCS file: /cvs/src/sys/arch/alpha/include/cpu.h,v
retrieving revision 1.59
diff -u -p -r1.59 cpu.h
--- sys/arch/alpha/include/cpu.h 9 Apr 2018 04:11:04 -0000 1.59
+++ sys/arch/alpha/include/cpu.h 8 May 2018 14:26:27 -0000
@@ -212,6 +212,7 @@ struct cpu_info {
#ifdef GPROF
struct gmonparam *ci_gmon;
#endif
+ volatile int ci_spinning;
};
#define CPUF_PRIMARY 0x01 /* CPU is primary CPU */