aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2024-02-09 16:13:27 -0300
committerArnaldo Carvalho de Melo <acme@redhat.com>2024-02-09 17:46:15 -0300
commit4fa81a30b9ca3b78212fb93443f5508a0af29043 (patch)
treeffaf0a298f4242e3a7e1d3cbb83335f98883128a
parent85bdd96404efca198ff441ab73513a6b3bb3a4e0 (diff)
downloadpahole-4fa81a30b9ca3b78212fb93443f5508a0af29043.tar.gz
fprintf: Print number of bit holes in class member types
In addition to paddings (holes at the end of a struct) and byte holes, inform about bit holes in bitfields in the middle of the structs of non-pointer members. For instance, for 'struct task_struct' in the Linux kernel we get this extra info: --- task_struct.before.c 2024-02-09 16:19:34.221134835 -0300 +++ task_struct.after.c 2024-02-09 17:45:41.137097839 -0300 @@ -35,6 +35,9 @@ /* --- cacheline 6 boundary (384 bytes) --- */ struct sched_rt_entity rt; /* 384 48 */ struct sched_dl_entity dl; /* 432 224 */ + + /* XXX last struct has 1 bit hole */ + /* --- cacheline 10 boundary (640 bytes) was 16 bytes ago --- */ const struct sched_class * sched_class; /* 656 8 */ struct rb_node core_node; /* 664 24 */ @@ -405,12 +408,12 @@ /* --- cacheline 145 boundary (9280 bytes) --- */ struct thread_struct thread __attribute__((__aligned__(64))); /* 9280 4416 */ - /* XXX last struct has 1 hole */ + /* XXX last struct has 1 hole, 1 bit hole */ /* size: 13696, cachelines: 214, members: 262 */ /* sum members: 13518, holes: 21, sum holes: 162 */ /* sum bitfield members: 82 bits, bit holes: 2, sum bit holes: 46 bits */ - /* member types with holes: 4, total of those holes: 6 */ + /* member types with holes: 4, total: 6, bit holes: 2, total: 2 */ /* paddings: 6, sum paddings: 49 */ /* forced alignments: 2, forced holes: 2, sum forced holes: 88 */ }; Out of curiosity, lets try one taking advantage that most if not all distros these days comes with /sys/kernel/btf/vmlinux so that we can ask just for the type, without specifying where to find it: $ pahole sched_dl_entity struct sched_dl_entity { struct rb_node rb_node; /* 0 24 */ u64 dl_runtime; /* 24 8 */ u64 dl_deadline; /* 32 8 */ u64 dl_period; /* 40 8 */ u64 dl_bw; /* 48 8 */ u64 dl_density; /* 56 8 */ /* --- cacheline 1 boundary (64 bytes) --- */ s64 runtime; /* 64 8 */ u64 deadline; /* 72 8 */ unsigned int flags; /* 80 4 */ unsigned int dl_throttled:1; /* 84: 0 4 */ unsigned int dl_yielded:1; /* 84: 1 4 */ unsigned int dl_non_contending:1; /* 84: 2 4 */ unsigned int dl_overrun:1; /* 84: 3 4 */ /* XXX 28 bits hole, try to pack */ struct hrtimer dl_timer; /* 88 64 */ /* XXX last struct has 4 bytes of padding */ /* --- cacheline 2 boundary (128 bytes) was 24 bytes ago --- */ struct hrtimer inactive_timer; /* 152 64 */ /* XXX last struct has 4 bytes of padding */ /* --- cacheline 3 boundary (192 bytes) was 24 bytes ago --- */ struct sched_dl_entity * pi_se; /* 216 8 */ /* size: 224, cachelines: 4, members: 16 */ /* sum members: 220 */ /* sum bitfield members: 4 bits, bit holes: 1, sum bit holes: 28 bits */ /* paddings: 2, sum paddings: 8 */ /* last cacheline: 32 bytes */ }; Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--dwarves_fprintf.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/dwarves_fprintf.c b/dwarves_fprintf.c
index 1169d359..2fa489a4 100644
--- a/dwarves_fprintf.c
+++ b/dwarves_fprintf.c
@@ -1465,7 +1465,9 @@ out:
struct member_types_holes {
uint16_t nr_paddings;
uint16_t nr_with_holes;
+ uint16_t nr_with_bit_holes;
uint16_t total_nr_holes;
+ uint16_t total_nr_bit_holes;
uint32_t sum_paddings;
};
@@ -1475,7 +1477,7 @@ static size_t class__fprintf_member_type_holes(struct class *class, const struct
{
size_t printed = 0;
uint16_t padding;
- uint8_t nr_holes;
+ uint8_t nr_holes, nr_bit_holes;
bool first = true;
/*
* We may not yet have looked for holes and paddings in this member's
@@ -1486,8 +1488,9 @@ static size_t class__fprintf_member_type_holes(struct class *class, const struct
padding = class->padding;
nr_holes = class->nr_holes;
+ nr_bit_holes = class->nr_bit_holes;
- if (!padding && !nr_holes)
+ if (!padding && !nr_holes && !nr_bit_holes)
return 0;
if (!(*newline)++) {
@@ -1510,6 +1513,14 @@ static size_t class__fprintf_member_type_holes(struct class *class, const struct
holes->total_nr_holes += nr_holes;
printed += fprintf(fp, "%s %d hole%s", first ? "" : ",", nr_holes, nr_holes != 1 ? "s" : "");
+ first = false;
+ }
+
+ if (nr_bit_holes) {
+ ++holes->nr_with_bit_holes;
+ holes->total_nr_bit_holes += nr_bit_holes;
+
+ printed += fprintf(fp, "%s %d bit hole%s", first ? "" : ",", nr_bit_holes, nr_bit_holes != 1 ? "s" : "");
}
return printed + fprintf(fp, " */");
@@ -1873,10 +1884,21 @@ static size_t __class__fprintf(struct class *class, const struct cu *cu,
printed += fprintf(fp, "%.*s/* padding: %u */\n",
cconf.indent,
tabs, class->padding);
- if (member_types_holes.nr_with_holes > 0) {
- printed += fprintf(fp, "%.*s/* member types with holes: %u, total of those holes: %u */\n",
- cconf.indent, tabs,
- member_types_holes.nr_with_holes, member_types_holes.total_nr_holes);
+
+ if (member_types_holes.nr_with_holes > 0 || member_types_holes.nr_with_bit_holes > 0) {
+ bool first = true;
+
+ printed += fprintf(fp, "%.*s/* member types with ", cconf.indent, tabs);
+ if (member_types_holes.nr_with_holes > 0) {
+ printed += fprintf(fp, "holes: %u, total: %u",
+ member_types_holes.nr_with_holes, member_types_holes.total_nr_holes);
+ first = false;
+ }
+ if (member_types_holes.nr_with_bit_holes > 0) {
+ printed += fprintf(fp, "%sbit holes: %u, total: %u", first ? "" : ", ",
+ member_types_holes.nr_with_bit_holes, member_types_holes.total_nr_bit_holes);
+ }
+ printed += fprintf(fp, " */\n");
}
if (member_types_holes.nr_paddings > 0)
printed += fprintf(fp, "%.*s/* paddings: %u, sum paddings: "