diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-05-10 12:04:11 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-05-10 12:13:49 -0400 |
commit | 1c02c4d2e92f2097f1bba63ec71560b0e05a7f36 (patch) | |
tree | ad2a722931398ce3cd3ae850c4cfa148558a52ea /tools/perf/util | |
parent | d118f8ba6ac2af2bf11d40cba657c813f0f39ca2 (diff) |
perf hist: Introduce hists class and move lots of methods to it
In cbbc79a we introduced support for multiple events by introducing a
new "event_stat_id" struct and then made several perf_session methods
receive a point to it instead of a pointer to perf_session, and kept the
event_stats and hists rb_tree in perf_session.
While working on the new newt based browser, I realised that it would be
better to introduce a new class, "hists" (short for "histograms"),
renaming the "event_stat_id" struct and the perf_session methods that
were really "hists" methods, as they manipulate only struct hists
members, not touching anything in the other perf_session members.
Other optimizations, such as calculating the maximum lenght of a symbol
name present in an hists instance will be possible as we add them,
avoiding a re-traversal just for finding that information.
The rationale for the name "hists" to replace "event_stat_id" is that we
may have multiple sets of hists for the same event_stat id, as, for
instance, the 'perf diff' tool has, so event stat id is not what
characterizes what this struct and the functions that manipulate it do.
Cc: Eric B Munson <ebmunson@us.ibm.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/event.c | 2 | ||||
-rw-r--r-- | tools/perf/util/event.h | 14 | ||||
-rw-r--r-- | tools/perf/util/hist.c | 92 | ||||
-rw-r--r-- | tools/perf/util/hist.h | 48 | ||||
-rw-r--r-- | tools/perf/util/session.c | 2 | ||||
-rw-r--r-- | tools/perf/util/session.h | 12 |
6 files changed, 79 insertions, 91 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index d2ea9dd9fdf1..cce006ec8f05 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -368,7 +368,7 @@ int event__process_comm(event_t *self, struct perf_session *session) | |||
368 | int event__process_lost(event_t *self, struct perf_session *session) | 368 | int event__process_lost(event_t *self, struct perf_session *session) |
369 | { | 369 | { |
370 | dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost); | 370 | dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost); |
371 | session->events_stats.lost += self->lost.lost; | 371 | session->hists.stats.lost += self->lost.lost; |
372 | return 0; | 372 | return 0; |
373 | } | 373 | } |
374 | 374 | ||
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 6cc1b1dced55..48c2cc9dae4f 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -131,20 +131,6 @@ typedef union event_union { | |||
131 | struct build_id_event build_id; | 131 | struct build_id_event build_id; |
132 | } event_t; | 132 | } event_t; |
133 | 133 | ||
134 | struct events_stats { | ||
135 | u64 total; | ||
136 | u64 lost; | ||
137 | }; | ||
138 | |||
139 | struct event_stat_id { | ||
140 | struct rb_node rb_node; | ||
141 | struct rb_root hists; | ||
142 | struct events_stats stats; | ||
143 | u64 config; | ||
144 | u64 event_stream; | ||
145 | u32 type; | ||
146 | }; | ||
147 | |||
148 | void event__print_totals(void); | 134 | void event__print_totals(void); |
149 | 135 | ||
150 | struct perf_session; | 136 | struct perf_session; |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 0f154a530dfd..410cf56c9662 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -8,21 +8,21 @@ struct callchain_param callchain_param = { | |||
8 | .min_percent = 0.5 | 8 | .min_percent = 0.5 |
9 | }; | 9 | }; |
10 | 10 | ||
11 | static void perf_session__add_cpumode_count(struct hist_entry *he, | 11 | static void hist_entry__add_cpumode_count(struct hist_entry *self, |
12 | unsigned int cpumode, u64 count) | 12 | unsigned int cpumode, u64 count) |
13 | { | 13 | { |
14 | switch (cpumode) { | 14 | switch (cpumode) { |
15 | case PERF_RECORD_MISC_KERNEL: | 15 | case PERF_RECORD_MISC_KERNEL: |
16 | he->count_sys += count; | 16 | self->count_sys += count; |
17 | break; | 17 | break; |
18 | case PERF_RECORD_MISC_USER: | 18 | case PERF_RECORD_MISC_USER: |
19 | he->count_us += count; | 19 | self->count_us += count; |
20 | break; | 20 | break; |
21 | case PERF_RECORD_MISC_GUEST_KERNEL: | 21 | case PERF_RECORD_MISC_GUEST_KERNEL: |
22 | he->count_guest_sys += count; | 22 | self->count_guest_sys += count; |
23 | break; | 23 | break; |
24 | case PERF_RECORD_MISC_GUEST_USER: | 24 | case PERF_RECORD_MISC_GUEST_USER: |
25 | he->count_guest_us += count; | 25 | self->count_guest_us += count; |
26 | break; | 26 | break; |
27 | default: | 27 | default: |
28 | break; | 28 | break; |
@@ -47,12 +47,11 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template) | |||
47 | return self; | 47 | return self; |
48 | } | 48 | } |
49 | 49 | ||
50 | struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, | 50 | struct hist_entry *__hists__add_entry(struct hists *self, |
51 | struct addr_location *al, | 51 | struct addr_location *al, |
52 | struct symbol *sym_parent, | 52 | struct symbol *sym_parent, u64 count) |
53 | u64 count) | ||
54 | { | 53 | { |
55 | struct rb_node **p = &hists->rb_node; | 54 | struct rb_node **p = &self->entries.rb_node; |
56 | struct rb_node *parent = NULL; | 55 | struct rb_node *parent = NULL; |
57 | struct hist_entry *he; | 56 | struct hist_entry *he; |
58 | struct hist_entry entry = { | 57 | struct hist_entry entry = { |
@@ -89,9 +88,9 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, | |||
89 | if (!he) | 88 | if (!he) |
90 | return NULL; | 89 | return NULL; |
91 | rb_link_node(&he->rb_node, parent, p); | 90 | rb_link_node(&he->rb_node, parent, p); |
92 | rb_insert_color(&he->rb_node, hists); | 91 | rb_insert_color(&he->rb_node, &self->entries); |
93 | out: | 92 | out: |
94 | perf_session__add_cpumode_count(he, al->cpumode, count); | 93 | hist_entry__add_cpumode_count(he, al->cpumode, count); |
95 | return he; | 94 | return he; |
96 | } | 95 | } |
97 | 96 | ||
@@ -167,7 +166,7 @@ static void collapse__insert_entry(struct rb_root *root, struct hist_entry *he) | |||
167 | rb_insert_color(&he->rb_node, root); | 166 | rb_insert_color(&he->rb_node, root); |
168 | } | 167 | } |
169 | 168 | ||
170 | void perf_session__collapse_resort(struct rb_root *hists) | 169 | void hists__collapse_resort(struct hists *self) |
171 | { | 170 | { |
172 | struct rb_root tmp; | 171 | struct rb_root tmp; |
173 | struct rb_node *next; | 172 | struct rb_node *next; |
@@ -177,28 +176,28 @@ void perf_session__collapse_resort(struct rb_root *hists) | |||
177 | return; | 176 | return; |
178 | 177 | ||
179 | tmp = RB_ROOT; | 178 | tmp = RB_ROOT; |
180 | next = rb_first(hists); | 179 | next = rb_first(&self->entries); |
181 | 180 | ||
182 | while (next) { | 181 | while (next) { |
183 | n = rb_entry(next, struct hist_entry, rb_node); | 182 | n = rb_entry(next, struct hist_entry, rb_node); |
184 | next = rb_next(&n->rb_node); | 183 | next = rb_next(&n->rb_node); |
185 | 184 | ||
186 | rb_erase(&n->rb_node, hists); | 185 | rb_erase(&n->rb_node, &self->entries); |
187 | collapse__insert_entry(&tmp, n); | 186 | collapse__insert_entry(&tmp, n); |
188 | } | 187 | } |
189 | 188 | ||
190 | *hists = tmp; | 189 | self->entries = tmp; |
191 | } | 190 | } |
192 | 191 | ||
193 | /* | 192 | /* |
194 | * reverse the map, sort on count. | 193 | * reverse the map, sort on count. |
195 | */ | 194 | */ |
196 | 195 | ||
197 | static void perf_session__insert_output_hist_entry(struct rb_root *root, | 196 | static void __hists__insert_output_entry(struct rb_root *entries, |
198 | struct hist_entry *he, | 197 | struct hist_entry *he, |
199 | u64 min_callchain_hits) | 198 | u64 min_callchain_hits) |
200 | { | 199 | { |
201 | struct rb_node **p = &root->rb_node; | 200 | struct rb_node **p = &entries->rb_node; |
202 | struct rb_node *parent = NULL; | 201 | struct rb_node *parent = NULL; |
203 | struct hist_entry *iter; | 202 | struct hist_entry *iter; |
204 | 203 | ||
@@ -217,10 +216,10 @@ static void perf_session__insert_output_hist_entry(struct rb_root *root, | |||
217 | } | 216 | } |
218 | 217 | ||
219 | rb_link_node(&he->rb_node, parent, p); | 218 | rb_link_node(&he->rb_node, parent, p); |
220 | rb_insert_color(&he->rb_node, root); | 219 | rb_insert_color(&he->rb_node, entries); |
221 | } | 220 | } |
222 | 221 | ||
223 | u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples) | 222 | u64 hists__output_resort(struct hists *self) |
224 | { | 223 | { |
225 | struct rb_root tmp; | 224 | struct rb_root tmp; |
226 | struct rb_node *next; | 225 | struct rb_node *next; |
@@ -228,23 +227,21 @@ u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples) | |||
228 | u64 min_callchain_hits; | 227 | u64 min_callchain_hits; |
229 | u64 nr_hists = 0; | 228 | u64 nr_hists = 0; |
230 | 229 | ||
231 | min_callchain_hits = | 230 | min_callchain_hits = self->stats.total * (callchain_param.min_percent / 100); |
232 | total_samples * (callchain_param.min_percent / 100); | ||
233 | 231 | ||
234 | tmp = RB_ROOT; | 232 | tmp = RB_ROOT; |
235 | next = rb_first(hists); | 233 | next = rb_first(&self->entries); |
236 | 234 | ||
237 | while (next) { | 235 | while (next) { |
238 | n = rb_entry(next, struct hist_entry, rb_node); | 236 | n = rb_entry(next, struct hist_entry, rb_node); |
239 | next = rb_next(&n->rb_node); | 237 | next = rb_next(&n->rb_node); |
240 | 238 | ||
241 | rb_erase(&n->rb_node, hists); | 239 | rb_erase(&n->rb_node, &self->entries); |
242 | perf_session__insert_output_hist_entry(&tmp, n, | 240 | __hists__insert_output_entry(&tmp, n, min_callchain_hits); |
243 | min_callchain_hits); | ||
244 | ++nr_hists; | 241 | ++nr_hists; |
245 | } | 242 | } |
246 | 243 | ||
247 | *hists = tmp; | 244 | self->entries = tmp; |
248 | return nr_hists; | 245 | return nr_hists; |
249 | } | 246 | } |
250 | 247 | ||
@@ -500,12 +497,9 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, | |||
500 | return ret; | 497 | return ret; |
501 | } | 498 | } |
502 | 499 | ||
503 | int hist_entry__snprintf(struct hist_entry *self, | 500 | int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size, |
504 | char *s, size_t size, | 501 | struct hists *pair_hists, bool show_displacement, |
505 | struct perf_session *pair_session, | 502 | long displacement, bool color, u64 session_total) |
506 | bool show_displacement, | ||
507 | long displacement, bool color, | ||
508 | u64 session_total) | ||
509 | { | 503 | { |
510 | struct sort_entry *se; | 504 | struct sort_entry *se; |
511 | u64 count, total, count_sys, count_us, count_guest_sys, count_guest_us; | 505 | u64 count, total, count_sys, count_us, count_guest_sys, count_guest_us; |
@@ -515,9 +509,9 @@ int hist_entry__snprintf(struct hist_entry *self, | |||
515 | if (symbol_conf.exclude_other && !self->parent) | 509 | if (symbol_conf.exclude_other && !self->parent) |
516 | return 0; | 510 | return 0; |
517 | 511 | ||
518 | if (pair_session) { | 512 | if (pair_hists) { |
519 | count = self->pair ? self->pair->count : 0; | 513 | count = self->pair ? self->pair->count : 0; |
520 | total = pair_session->events_stats.total; | 514 | total = pair_hists->stats.total; |
521 | count_sys = self->pair ? self->pair->count_sys : 0; | 515 | count_sys = self->pair ? self->pair->count_sys : 0; |
522 | count_us = self->pair ? self->pair->count_us : 0; | 516 | count_us = self->pair ? self->pair->count_us : 0; |
523 | count_guest_sys = self->pair ? self->pair->count_guest_sys : 0; | 517 | count_guest_sys = self->pair ? self->pair->count_guest_sys : 0; |
@@ -569,7 +563,7 @@ int hist_entry__snprintf(struct hist_entry *self, | |||
569 | ret += snprintf(s + ret, size - ret, "%11lld", count); | 563 | ret += snprintf(s + ret, size - ret, "%11lld", count); |
570 | } | 564 | } |
571 | 565 | ||
572 | if (pair_session) { | 566 | if (pair_hists) { |
573 | char bf[32]; | 567 | char bf[32]; |
574 | double old_percent = 0, new_percent = 0, diff; | 568 | double old_percent = 0, new_percent = 0, diff; |
575 | 569 | ||
@@ -615,14 +609,12 @@ int hist_entry__snprintf(struct hist_entry *self, | |||
615 | return ret; | 609 | return ret; |
616 | } | 610 | } |
617 | 611 | ||
618 | int hist_entry__fprintf(struct hist_entry *self, | 612 | int hist_entry__fprintf(struct hist_entry *self, struct hists *pair_hists, |
619 | struct perf_session *pair_session, | 613 | bool show_displacement, long displacement, FILE *fp, |
620 | bool show_displacement, | ||
621 | long displacement, FILE *fp, | ||
622 | u64 session_total) | 614 | u64 session_total) |
623 | { | 615 | { |
624 | char bf[512]; | 616 | char bf[512]; |
625 | hist_entry__snprintf(self, bf, sizeof(bf), pair_session, | 617 | hist_entry__snprintf(self, bf, sizeof(bf), pair_hists, |
626 | show_displacement, displacement, | 618 | show_displacement, displacement, |
627 | true, session_total); | 619 | true, session_total); |
628 | return fprintf(fp, "%s\n", bf); | 620 | return fprintf(fp, "%s\n", bf); |
@@ -644,10 +636,8 @@ static size_t hist_entry__fprintf_callchain(struct hist_entry *self, FILE *fp, | |||
644 | left_margin); | 636 | left_margin); |
645 | } | 637 | } |
646 | 638 | ||
647 | size_t perf_session__fprintf_hists(struct rb_root *hists, | 639 | size_t hists__fprintf(struct hists *self, struct hists *pair, |
648 | struct perf_session *pair, | 640 | bool show_displacement, FILE *fp) |
649 | bool show_displacement, FILE *fp, | ||
650 | u64 session_total) | ||
651 | { | 641 | { |
652 | struct sort_entry *se; | 642 | struct sort_entry *se; |
653 | struct rb_node *nd; | 643 | struct rb_node *nd; |
@@ -753,7 +743,7 @@ size_t perf_session__fprintf_hists(struct rb_root *hists, | |||
753 | fprintf(fp, "\n#\n"); | 743 | fprintf(fp, "\n#\n"); |
754 | 744 | ||
755 | print_entries: | 745 | print_entries: |
756 | for (nd = rb_first(hists); nd; nd = rb_next(nd)) { | 746 | for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { |
757 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); | 747 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); |
758 | 748 | ||
759 | if (show_displacement) { | 749 | if (show_displacement) { |
@@ -765,10 +755,10 @@ print_entries: | |||
765 | ++position; | 755 | ++position; |
766 | } | 756 | } |
767 | ret += hist_entry__fprintf(h, pair, show_displacement, | 757 | ret += hist_entry__fprintf(h, pair, show_displacement, |
768 | displacement, fp, session_total); | 758 | displacement, fp, self->stats.total); |
769 | 759 | ||
770 | if (symbol_conf.use_callchain) | 760 | if (symbol_conf.use_callchain) |
771 | ret += hist_entry__fprintf_callchain(h, fp, session_total); | 761 | ret += hist_entry__fprintf_callchain(h, fp, self->stats.total); |
772 | 762 | ||
773 | if (h->ms.map == NULL && verbose > 1) { | 763 | if (h->ms.map == NULL && verbose > 1) { |
774 | __map_groups__fprintf_maps(&h->thread->mg, | 764 | __map_groups__fprintf_maps(&h->thread->mg, |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index b49013adb34b..bdde81eca69f 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -6,34 +6,40 @@ | |||
6 | 6 | ||
7 | extern struct callchain_param callchain_param; | 7 | extern struct callchain_param callchain_param; |
8 | 8 | ||
9 | struct perf_session; | ||
10 | struct hist_entry; | 9 | struct hist_entry; |
11 | struct addr_location; | 10 | struct addr_location; |
12 | struct symbol; | 11 | struct symbol; |
13 | struct rb_root; | 12 | struct rb_root; |
14 | 13 | ||
15 | struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, | 14 | struct events_stats { |
16 | struct addr_location *al, | 15 | u64 total; |
17 | struct symbol *parent, | 16 | u64 lost; |
18 | u64 count); | 17 | }; |
18 | |||
19 | struct hists { | ||
20 | struct rb_node rb_node; | ||
21 | struct rb_root entries; | ||
22 | struct events_stats stats; | ||
23 | u64 config; | ||
24 | u64 event_stream; | ||
25 | u32 type; | ||
26 | }; | ||
27 | |||
28 | struct hist_entry *__hists__add_entry(struct hists *self, | ||
29 | struct addr_location *al, | ||
30 | struct symbol *parent, u64 count); | ||
19 | extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); | 31 | extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); |
20 | extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); | 32 | extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); |
21 | int hist_entry__fprintf(struct hist_entry *self, | 33 | int hist_entry__fprintf(struct hist_entry *self, struct hists *pair_hists, |
22 | struct perf_session *pair_session, | 34 | bool show_displacement, long displacement, FILE *fp, |
23 | bool show_displacement, | 35 | u64 total); |
24 | long displacement, FILE *fp, | 36 | int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size, |
25 | u64 session_total); | 37 | struct hists *pair_hists, bool show_displacement, |
26 | int hist_entry__snprintf(struct hist_entry *self, | 38 | long displacement, bool color, u64 total); |
27 | char *bf, size_t size, | ||
28 | struct perf_session *pair_session, | ||
29 | bool show_displacement, long displacement, | ||
30 | bool color, u64 session_total); | ||
31 | void hist_entry__free(struct hist_entry *); | 39 | void hist_entry__free(struct hist_entry *); |
32 | 40 | ||
33 | u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples); | 41 | u64 hists__output_resort(struct hists *self); |
34 | void perf_session__collapse_resort(struct rb_root *hists); | 42 | void hists__collapse_resort(struct hists *self); |
35 | size_t perf_session__fprintf_hists(struct rb_root *hists, | 43 | size_t hists__fprintf(struct hists *self, struct hists *pair, |
36 | struct perf_session *pair, | 44 | bool show_displacement, FILE *fp); |
37 | bool show_displacement, FILE *fp, | ||
38 | u64 session_total); | ||
39 | #endif /* __PERF_HIST_H */ | 45 | #endif /* __PERF_HIST_H */ |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 4130036a0109..72a7f6ae0293 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -89,7 +89,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc | |||
89 | 89 | ||
90 | memcpy(self->filename, filename, len); | 90 | memcpy(self->filename, filename, len); |
91 | self->threads = RB_ROOT; | 91 | self->threads = RB_ROOT; |
92 | self->stats_by_id = RB_ROOT; | 92 | self->hists_tree = RB_ROOT; |
93 | self->last_match = NULL; | 93 | self->last_match = NULL; |
94 | self->mmap_window = 32; | 94 | self->mmap_window = 32; |
95 | self->cwd = NULL; | 95 | self->cwd = NULL; |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 242d528bfae2..46190f94b547 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #ifndef __PERF_SESSION_H | 1 | #ifndef __PERF_SESSION_H |
2 | #define __PERF_SESSION_H | 2 | #define __PERF_SESSION_H |
3 | 3 | ||
4 | #include "hist.h" | ||
4 | #include "event.h" | 5 | #include "event.h" |
5 | #include "header.h" | 6 | #include "header.h" |
6 | #include "symbol.h" | 7 | #include "symbol.h" |
@@ -28,11 +29,16 @@ struct perf_session { | |||
28 | struct thread *last_match; | 29 | struct thread *last_match; |
29 | struct machine host_machine; | 30 | struct machine host_machine; |
30 | struct rb_root machines; | 31 | struct rb_root machines; |
31 | struct events_stats events_stats; | 32 | struct rb_root hists_tree; |
32 | struct rb_root stats_by_id; | ||
33 | unsigned long event_total[PERF_RECORD_MAX]; | 33 | unsigned long event_total[PERF_RECORD_MAX]; |
34 | unsigned long unknown_events; | 34 | unsigned long unknown_events; |
35 | struct rb_root hists; | 35 | /* |
36 | * FIXME: should point to the first entry in hists_tree and | ||
37 | * be a hists instance. Right now its only 'report' | ||
38 | * that is using ->hists_tree while all the rest use | ||
39 | * ->hists. | ||
40 | */ | ||
41 | struct hists hists; | ||
36 | u64 sample_type; | 42 | u64 sample_type; |
37 | int fd; | 43 | int fd; |
38 | bool fd_pipe; | 44 | bool fd_pipe; |