Date: Wed, 29 Oct 2008 13:36:23 +0000 (UTC) From: Ivan Voras <ivoras@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r184439 - head/sys/kern Message-ID: <200810291336.m9TDaNCn023910@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ivoras Date: Wed Oct 29 13:36:23 2008 New Revision: 184439 URL: http://svn.freebsd.org/changeset/base/184439 Log: Introduce a new sysctl, kern.sched.topology_spec, that returns an XML dump of detected ULE CPU topology. This dump can be used to check the topology detection and for general system information. An example of CPU topology dump is: kern.sched.topology_spec: <groups> <group level="1" cache-level="0"> <cpu count="8" mask="0xff">0, 1, 2, 3, 4, 5, 6, 7</cpu> <flags></flags> <children> <group level="2" cache-level="0"> <cpu count="4" mask="0xf">0, 1, 2, 3</cpu> <flags></flags> </group> <group level="2" cache-level="0"> <cpu count="4" mask="0xf0">4, 5, 6, 7</cpu> <flags></flags> </group> </children> </group> </groups> Reviewed by: jeff Approved by: gnn (mentor) Modified: head/sys/kern/sched_ule.c Modified: head/sys/kern/sched_ule.c ============================================================================== --- head/sys/kern/sched_ule.c Wed Oct 29 12:11:48 2008 (r184438) +++ head/sys/kern/sched_ule.c Wed Oct 29 13:36:23 2008 (r184439) @@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$"); #include <sys/umtx.h> #include <sys/vmmeter.h> #include <sys/cpuset.h> +#include <sys/sbuf.h> #ifdef KTRACE #include <sys/uio.h> #include <sys/ktrace.h> @@ -223,7 +224,7 @@ struct tdq { #define TDQ_IDLE 2 #ifdef SMP -struct cpu_group *cpu_top; +struct cpu_group *cpu_top; /* CPU topology */ #define SCHED_AFFINITY_DEFAULT (max(1, hz / 1000)) #define SCHED_AFFINITY(ts, t) ((ts)->ts_rltick > ticks - ((t) * affinity)) @@ -293,6 +294,9 @@ static inline struct tdq *sched_setcpu(s static inline struct mtx *thread_block_switch(struct thread *); static inline void thread_unblock_switch(struct thread *, struct mtx *); static struct mtx *sched_switch_migrate(struct tdq *, struct thread *, int); +static int sysctl_kern_sched_topology_spec(SYSCTL_HANDLER_ARGS); +static int sysctl_kern_sched_topology_spec_internal(struct sbuf *sb, + struct cpu_group *cg, int indent); #endif static void sched_setup(void *dummy); @@ -2601,6 +2605,83 @@ sched_fork_exit(struct thread *td) &TDQ_LOCKPTR(tdq)->lock_object, 0, 0, __FILE__, __LINE__); } +#ifdef SMP + +/* + * Build the CPU topology dump string. Is recursively called to collect + * the topology tree. + */ +static int +sysctl_kern_sched_topology_spec_internal(struct sbuf *sb, struct cpu_group *cg, + int indent) +{ + int i, first; + + sbuf_printf(sb, "%*s<group level=\"%d\" cache-level=\"%d\">\n", indent, + "", indent, cg->cg_level); + sbuf_printf(sb, "%*s <cpu count=\"%d\" mask=\"0x%x\">", indent, "", + cg->cg_count, cg->cg_mask); + first = TRUE; + for (i = 0; i < MAXCPU; i++) { + if ((cg->cg_mask & (1 << i)) != 0) { + if (!first) + sbuf_printf(sb, ", "); + else + first = FALSE; + sbuf_printf(sb, "%d", i); + } + } + sbuf_printf(sb, "</cpu>\n"); + + sbuf_printf(sb, "%*s <flags>", indent, ""); + if (cg->cg_flags != 0) { + if ((cg->cg_flags & CG_FLAG_HTT) != 0) + sbuf_printf(sb, "<flag name=\"HTT\">HTT group</flag>"); + if ((cg->cg_flags & CG_FLAG_THREAD) != 0) + sbuf_printf(sb, "<flag name=\"THREAD\">SMT group</flag>"); + } + sbuf_printf(sb, "</flags>\n"); + + if (cg->cg_children > 0) { + sbuf_printf(sb, "%*s <children>\n", indent, ""); + for (i = 0; i < cg->cg_children; i++) + sysctl_kern_sched_topology_spec_internal(sb, + &cg->cg_child[i], indent+2); + sbuf_printf(sb, "%*s </children>\n", indent, ""); + } + sbuf_printf(sb, "%*s</group>\n", indent, ""); + return (0); +} + +/* + * Sysctl handler for retrieving topology dump. It's a wrapper for + * the recursive sysctl_kern_smp_topology_spec_internal(). + */ +static int +sysctl_kern_sched_topology_spec(SYSCTL_HANDLER_ARGS) +{ + struct sbuf *topo; + int err; + + KASSERT(cpu_top != NULL, ("cpu_top isn't initialized")); + + topo = sbuf_new(NULL, NULL, 100, SBUF_AUTOEXTEND); + if (topo == NULL) + return (ENOMEM); + + sbuf_printf(topo, "<groups>\n"); + err = sysctl_kern_sched_topology_spec_internal(topo, cpu_top, 1); + sbuf_printf(topo, "</groups>\n"); + + if (err == 0) { + sbuf_finish(topo); + err = SYSCTL_OUT(req, sbuf_data(topo), sbuf_len(topo)); + } + sbuf_delete(topo); + return (err); +} +#endif + SYSCTL_NODE(_kern, OID_AUTO, sched, CTLFLAG_RW, 0, "Scheduler"); SYSCTL_STRING(_kern_sched, OID_AUTO, name, CTLFLAG_RD, "ULE", 0, "Scheduler name"); @@ -2630,6 +2711,11 @@ SYSCTL_INT(_kern_sched, OID_AUTO, steal_ "Attempts to steal work from other cores before idling"); SYSCTL_INT(_kern_sched, OID_AUTO, steal_thresh, CTLFLAG_RW, &steal_thresh, 0, "Minimum load on remote cpu before we'll steal"); + +/* Retrieve SMP topology */ +SYSCTL_PROC(_kern_sched, OID_AUTO, topology_spec, CTLTYPE_STRING | + CTLFLAG_RD, NULL, 0, sysctl_kern_sched_topology_spec, "A", + "XML dump of detected CPU topology"); #endif /* ps compat. All cpu percentages from ULE are weighted. */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200810291336.m9TDaNCn023910>