Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F133316867
D12019.id32223.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D12019.id32223.diff
View Options
Index: sys/kern/subr_smp.c
===================================================================
--- sys/kern/subr_smp.c
+++ sys/kern/subr_smp.c
@@ -64,6 +64,14 @@
#endif
static int sysctl_kern_smp_active(SYSCTL_HANDLER_ARGS);
+static bool topo_analyze_pkg(struct topo_node *pkg_node, int all,
+ struct topo_analysis *results);
+static bool topo_analyze_group(struct topo_node *group_node, int all,
+ struct topo_analysis *results);
+static bool topo_analyze_cachegroup(struct topo_node *cg_node, int all,
+ struct topo_analysis *results);
+static bool topo_analyze_core(struct topo_node *cg_node, int all,
+ struct topo_analysis *results);
/* This is used in modules that need to work in both SMP and UP. */
cpuset_t all_cpus;
@@ -993,7 +1001,7 @@
if ((next = TAILQ_NEXT(node, siblings)) != NULL)
return (next);
- while ((node = node->parent) != top)
+ while (node != top && (node = node->parent) != top)
if ((next = TAILQ_NEXT(node, siblings)) != NULL)
return (next);
@@ -1012,7 +1020,7 @@
if ((next = TAILQ_NEXT(node, siblings)) != NULL)
return (next);
- while ((node = node->parent) != top)
+ while (node != top && (node = node->parent) != top)
if ((next = TAILQ_NEXT(node, siblings)) != NULL)
return (next);
@@ -1047,27 +1055,23 @@
/*
* Check if the topology is uniform, that is, each package has the same number
* of cores in it and each core has the same number of threads (logical
- * processors) in it. If so, calculate the number of package, the number of
- * cores per package and the number of logical processors per core.
- * 'all' parameter tells whether to include administratively disabled logical
- * processors into the analysis.
+ * processors) in it. If so, calculate the number of packages, the number of
+ * groups per package, the number of cachegroups per group, and the number of
+ * logical processors per cachegroup. 'all' parameter tells whether to include
+ * administratively disabled logical processors into the analysis.
*/
int
topo_analyze(struct topo_node *topo_root, int all,
- int *pkg_count, int *cores_per_pkg, int *thrs_per_core)
+ struct topo_analysis *results)
{
struct topo_node *pkg_node;
- struct topo_node *core_node;
- struct topo_node *pu_node;
- int thrs_per_pkg;
- int cpp_counter;
- int tpc_counter;
- int tpp_counter;
-
- *pkg_count = 0;
- *cores_per_pkg = -1;
- *thrs_per_core = -1;
- thrs_per_pkg = -1;
+
+ results->pkg_count = 0;
+ results->cores_per_cachegroup = -1;
+ results->threads_per_core = -1;
+ results->groups_per_pkg = -1;
+ results->cachegroups_per_group = -1;
+
pkg_node = topo_root;
while (pkg_node != NULL) {
if (pkg_node->type != TOPO_TYPE_PKG) {
@@ -1079,70 +1083,81 @@
continue;
}
- (*pkg_count)++;
-
- cpp_counter = 0;
- tpp_counter = 0;
- core_node = pkg_node;
- while (core_node != NULL) {
- if (core_node->type == TOPO_TYPE_CORE) {
- if (!all && CPU_EMPTY(&core_node->cpuset)) {
- core_node =
- topo_next_nonchild_node(pkg_node,
- core_node);
- continue;
- }
-
- cpp_counter++;
-
- tpc_counter = 0;
- pu_node = core_node;
- while (pu_node != NULL) {
- if (pu_node->type == TOPO_TYPE_PU &&
- (all || !CPU_EMPTY(&pu_node->cpuset)))
- tpc_counter++;
- pu_node = topo_next_node(core_node,
- pu_node);
- }
-
- if (*thrs_per_core == -1)
- *thrs_per_core = tpc_counter;
- else if (*thrs_per_core != tpc_counter)
- return (0);
-
- core_node = topo_next_nonchild_node(pkg_node,
- core_node);
- } else {
- /* PU node directly under PKG. */
- if (core_node->type == TOPO_TYPE_PU &&
- (all || !CPU_EMPTY(&core_node->cpuset)))
- tpp_counter++;
- core_node = topo_next_node(pkg_node,
- core_node);
- }
- }
+ results->pkg_count++;
- if (*cores_per_pkg == -1)
- *cores_per_pkg = cpp_counter;
- else if (*cores_per_pkg != cpp_counter)
- return (0);
- if (thrs_per_pkg == -1)
- thrs_per_pkg = tpp_counter;
- else if (thrs_per_pkg != tpp_counter)
+ if (!topo_analyze_pkg(pkg_node, all, results))
return (0);
pkg_node = topo_next_nonchild_node(topo_root, pkg_node);
}
- KASSERT(*pkg_count > 0,
+ KASSERT(results->pkg_count > 0,
("bug in topology or analysis"));
- if (*cores_per_pkg == 0) {
- KASSERT(*thrs_per_core == -1 && thrs_per_pkg > 0,
- ("bug in topology or analysis"));
- *thrs_per_core = thrs_per_pkg;
- }
return (1);
}
+
+#define TOPO_ANALYZE(lvl, subgrpcond, nextlevel, rfield) \
+static bool \
+topo_analyze_ ## lvl(struct topo_node *root, int all, \
+ struct topo_analysis *results) \
+{ \
+ struct topo_node *node; \
+ int counter; \
+ \
+ counter = 0; \
+ node = topo_next_node(root, root); \
+ \
+ while (node != NULL) { \
+ if (!(subgrpcond)) { \
+ node = topo_next_node(root, node); \
+ continue; \
+ } \
+ if (!all && CPU_EMPTY(&node->cpuset)) { \
+ node = topo_next_nonchild_node(root, node); \
+ continue; \
+ } \
+ \
+ counter++; \
+ \
+ if (!nextlevel(node, all, results)) \
+ return (false); \
+ \
+ node = topo_next_nonchild_node(root, node); \
+ } \
+ \
+ /* No explicit subgroups is essentially one subgroup. */ \
+ if (counter == 0) { \
+ counter = 1; \
+ \
+ if (!nextlevel(root, all, results)) \
+ return (false); \
+ } \
+ \
+ if (results->rfield == -1) \
+ results->rfield = counter; \
+ else if (results->rfield != counter) \
+ return (false); \
+ \
+ return (true); \
+}
+
+static bool
+topo_bottom(struct topo_node *root __unused, int all __unused,
+ struct topo_analysis *results __unused)
+{
+ return (true);
+}
+
+TOPO_ANALYZE(pkg, node->type == TOPO_TYPE_GROUP, topo_analyze_group,
+ groups_per_pkg)
+TOPO_ANALYZE(group,
+ node->type == TOPO_TYPE_CACHE && node->subtype == CG_SHARE_L3,
+ topo_analyze_cachegroup, cachegroups_per_group)
+TOPO_ANALYZE(cachegroup, node->type == TOPO_TYPE_CORE, topo_analyze_core,
+ cores_per_cachegroup)
+TOPO_ANALYZE(core, node->type == TOPO_TYPE_PU, topo_bottom, threads_per_core)
+#undef TOPO_ANALYZE
+
#endif /* SMP */
Index: sys/sys/smp.h
===================================================================
--- sys/sys/smp.h
+++ sys/sys/smp.h
@@ -120,8 +120,22 @@
struct topo_node * topo_next_nonchild_node(struct topo_node *top,
struct topo_node *node);
void topo_set_pu_id(struct topo_node *node, cpuid_t id);
-int topo_analyze(struct topo_node *topo_root, int all, int *pkg_count,
- int *cores_per_pkg, int *thrs_per_core);
+struct topo_analysis {
+ int pkg_count;
+
+ /*
+ * Some systems have useful sub-package core organizations. On these,
+ * a package has one or more subgroups. Each subgroup contains one or
+ * more cache groups (cores that share a last level cache).
+ */
+ int groups_per_pkg;
+ int cachegroups_per_group;
+
+ int cores_per_cachegroup;
+ int threads_per_core;
+};
+int topo_analyze(struct topo_node *topo_root, int all,
+ struct topo_analysis *results);
#define TOPO_FOREACH(i, root) \
for (i = root; i != NULL; i = topo_next_node(root, i))
Index: sys/x86/x86/mp_x86.c
===================================================================
--- sys/x86/x86/mp_x86.c
+++ sys/x86/x86/mp_x86.c
@@ -656,18 +656,19 @@
{
struct topo_node *node;
const char *hyperthread;
- int pkg_count;
- int cores_per_pkg;
- int thrs_per_core;
+ struct topo_analysis topology;
printf("FreeBSD/SMP: ");
- if (topo_analyze(&topo_root, 1, &pkg_count,
- &cores_per_pkg, &thrs_per_core)) {
- printf("%d package(s)", pkg_count);
- if (cores_per_pkg > 0)
- printf(" x %d core(s)", cores_per_pkg);
- if (thrs_per_core > 1)
- printf(" x %d hardware threads", thrs_per_core);
+ if (topo_analyze(&topo_root, 1, &topology)) {
+ printf("%d package(s)", topology.pkg_count);
+ if (topology.groups_per_pkg > 1)
+ printf(" x %d groups", topology.groups_per_pkg);
+ if (topology.cachegroups_per_group > 1)
+ printf(" x %d cache groups", topology.cachegroups_per_group);
+ if (topology.cores_per_cachegroup > 0)
+ printf(" x %d core(s)", topology.cores_per_cachegroup);
+ if (topology.threads_per_core > 1)
+ printf(" x %d hardware threads", topology.threads_per_core);
} else {
printf("Non-uniform topology");
}
@@ -675,13 +676,19 @@
if (disabled_cpus) {
printf("FreeBSD/SMP Online: ");
- if (topo_analyze(&topo_root, 0, &pkg_count,
- &cores_per_pkg, &thrs_per_core)) {
- printf("%d package(s)", pkg_count);
- if (cores_per_pkg > 0)
- printf(" x %d core(s)", cores_per_pkg);
- if (thrs_per_core > 1)
- printf(" x %d hardware threads", thrs_per_core);
+ if (topo_analyze(&topo_root, 0, &topology)) {
+ printf("%d package(s)", topology.pkg_count);
+ if (topology.groups_per_pkg > 1)
+ printf(" x %d groups", topology.groups_per_pkg);
+ if (topology.cachegroups_per_group > 1)
+ printf(" x %d cache groups",
+ topology.cachegroups_per_group);
+ if (topology.cores_per_cachegroup > 0)
+ printf(" x %d core(s)",
+ topology.cores_per_cachegroup);
+ if (topology.threads_per_core > 1)
+ printf(" x %d hardware threads",
+ topology.threads_per_core);
} else {
printf("Non-uniform topology");
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Oct 25, 9:34 PM (11 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24191708
Default Alt Text
D12019.id32223.diff (9 KB)
Attached To
Mode
D12019: subr_smp: Clean up topology analysis, add additional layers
Attached
Detach File
Event Timeline
Log In to Comment