1 /*
2  * Copyright © 2009 CNRS
3  * Copyright © 2009-2021 Inria.  All rights reserved.
4  * Copyright © 2009-2010, 2012, 2015 Université Bordeaux
5  * Copyright © 2011 Cisco Systems, Inc.  All rights reserved.
6  * Copyright © 2020 Hewlett Packard Enterprise.  All rights reserved.
7  * See COPYING in top-level directory.
8  */
9 
10 #ifndef UTILS_LSTOPO_H
11 #define UTILS_LSTOPO_H
12 
13 #include "private/autogen/config.h"
14 #include "hwloc.h"
15 #include "misc.h"
16 
17 enum lstopo_drawing_e {
18   LSTOPO_DRAWING_PREPARE,
19   LSTOPO_DRAWING_DRAW
20 };
21 
22 enum lstopo_orient_e {
23   LSTOPO_ORIENT_NONE = 0,
24   LSTOPO_ORIENT_HORIZ,
25   LSTOPO_ORIENT_VERT,
26   LSTOPO_ORIENT_RECT
27 };
28 
29 enum lstopo_index_type_e {
30   LSTOPO_INDEX_TYPE_DEFAULT,
31   LSTOPO_INDEX_TYPE_PHYSICAL,
32   LSTOPO_INDEX_TYPE_LOGICAL,
33   LSTOPO_INDEX_TYPE_NONE /* only used during the interactive display */
34 };
35 
36 enum lstopo_show_legend_e {
37   LSTOPO_SHOW_LEGEND_ALL,
38   LSTOPO_SHOW_LEGEND_NONE,
39   LSTOPO_SHOW_LEGEND_NO_DEFAULT
40 };
41 
42 FILE *open_output(const char *filename, int overwrite) __hwloc_attribute_malloc;
43 
44 struct draw_methods;
45 
46 /* if embedded in backend-specific output structure, must be at the beginning */
47 struct lstopo_output {
48   hwloc_topology_t topology;
49   unsigned depth;
50 
51   /* when an interactive backends want a refresh of the topology */
52   int needs_topology_refresh;
53   /* when actually doing a refresh */
54   int refreshing;
55 
56   /* file config */
57   FILE *file;
58   int overwrite;
59 
60   /* misc config */
61   enum lstopo_index_type_e index_type;
62   int verbose_mode;
63   int ignore_pus;
64   int ignore_numanodes;
65   int pci_collapse_enabled; /* global toggle for PCI collapsing */
66   int pid_number;
67   hwloc_pid_t pid;
68   hwloc_bitmap_t cpubind_set, membind_set;
69 
70   /* misc cached data */
71   int need_pci_domain;
72   unsigned nr_cpukind_styles;
73 
74   /* export config */
75   unsigned long export_synthetic_flags;
76   unsigned long export_xml_flags;
77   uint64_t shmem_output_addr;
78 
79   /* legend */
80   enum lstopo_show_legend_e show_legend;
81 #define LSTOPO_LEGEND_DEFAULT_LINES 3 /* hostname + index + date */
82   char legend_default_lines[LSTOPO_LEGEND_DEFAULT_LINES][128];
83   unsigned legend_default_lines_nr;
84   unsigned legend_info_lines_nr;
85   char ** legend_append;
86   unsigned legend_append_nr;
87   unsigned legend_maxtextwidth;
88 
89   /* text config */
90   int show_distances_only;
91   int show_memattrs_only;
92   int show_cpukinds_only;
93   int show_windows_processor_groups_only;
94   hwloc_obj_type_t show_only;
95   int show_cpuset;
96   int show_taskset;
97   int transform_distances;
98 
99   /* draw config */
100   char title[256];
101   unsigned plain_children_order;
102   unsigned int gridsize, fontsize, linespacing, thickness;
103   float text_xscale;
104   enum lstopo_orient_e force_orient[HWLOC_OBJ_TYPE_MAX]; /* orientation of children within an object of the given type */
105   unsigned no_half_lines; /* set by ASCII backend because it cannot write between lines of the terminal */
106   int show_indexes[HWLOC_OBJ_TYPE_MAX]; /* enabled by global toggle index_type */
107   int show_text_enabled; /* global toggle for interactive keyboard shortcuts */
108   int show_text[HWLOC_OBJ_TYPE_MAX];
109   int show_attrs_enabled; /* global toggle for interactive keyboard shortcuts */
110   int show_attrs[HWLOC_OBJ_TYPE_MAX];
111   int show_binding;
112   int show_disallowed;
113   int show_cpukinds;
114   int factorize_enabled; /* global toggle for interactive keyboard shortcuts */
115   unsigned factorize_min[HWLOC_OBJ_TYPE_MAX]; /* minimum number of object before factorizing (parent->arity must be strictly higher) */
116 #define FACTORIZE_MIN_DEFAULT 4
117 #define FACTORIZE_MIN_DISABLED UINT_MAX
118   unsigned factorize_first[HWLOC_OBJ_TYPE_MAX]; /* number of first children to keep before factorizing */
119   unsigned factorize_last[HWLOC_OBJ_TYPE_MAX]; /* number of last children to keep after factorizing */
120 
121   /* draw internal data */
122   void *backend_data;
123   struct draw_methods *methods;
124   enum lstopo_drawing_e drawing;
125   unsigned width, height; /* total output size */
126 };
127 
128 struct lstopo_color {
129   /* these variables must be initialized before passing the structure to declare_color() */
130   int r, g, b;
131   int free; /* 1 if lstopo should free() this structure at exit */
132 
133   /* these variable are initialized by declare_color() */
134   /* backend specific private data */
135   union lstopo_color_private_u {
136     struct lstopo_color_private_ascii_s {
137       int color;
138     } ascii;
139     struct lstopo_color_private_fig_s {
140       int color;
141     } fig;
142 #ifdef HWLOC_WIN_SYS
143     struct lstopo_color_private_windows_s {
144       HGDIOBJ brush;
145       COLORREF color;
146     } windows;
147 #endif
148   } private;
149   /* list of colors */
150   struct lstopo_color *next;
151 };
152 
153 struct lstopo_style {
154   struct lstopo_color
155 	*bg,	/* main box background color */
156 	*t,	/* main text color */
157 	*t2;	/* other text color */
158 };
159 
160 #define LSTOPO_CHILD_KIND_NORMAL 0x1
161 #define LSTOPO_CHILD_KIND_MEMORY 0x2
162 #define LSTOPO_CHILD_KIND_IO     0x4
163 #define LSTOPO_CHILD_KIND_MISC   0x8
164 #define LSTOPO_CHILD_KIND_ALL    0xf
165 
166 struct lstopo_obj_userdata {
167   /* original common userdata (we replace the first one with this extended structure) */
168   struct hwloc_utils_userdata common;
169 
170   /* PCI collapsing */
171   int pci_collapsed; /* 0 if no collapsing, -1 if collapsed with a previous one, >1 if collapsed with several next */
172   int factorized; /* 0 if no factorizing, -1 if hidden, 1 if replaced with dots */
173 
174   /* custom style */
175   struct lstopo_style style;
176 #define LSTOPO_STYLE_BG  0x1
177 #define LSTOPO_STYLE_T   0x2
178 #define LSTOPO_STYLE_T2  0x4
179   unsigned style_set; /* OR'ed LSTOPO_STYLE_* */
180 
181   /* PU style for CPU kind */
182   unsigned cpukind_style;
183 
184   /* object size (including children if they are outside of it, not including borders) */
185   unsigned width;
186   unsigned height;
187 
188   /* a child position is: its parent position + parent->children_*rel + child->*rel */
189   /* relative position of first child with respect to top-left corner of this object */
190   struct lstopo_children_position {
191     unsigned kinds;
192     unsigned width;
193     unsigned height;
194     unsigned xrel;
195     unsigned yrel;
196     unsigned box;
197     struct lstopo_color *boxcolor;
198   } children;
199   /* relative position of first memory child */
200   struct lstopo_children_position above_children;
201 
202   /* relative position of this object within its parent children zone */
203   unsigned xrel;
204   unsigned yrel;
205 
206   /* children orientation */
207   enum lstopo_orient_e orient;
208 
209   /* text lines within object */
210 #define LSTOPO_OBJ_TEXT_MAX 4 /* current max number of lines is osdev name + 3 cuda attributes */
211   struct lstopo_text_line {
212     char text[128];
213     unsigned width;
214     unsigned xoffset;
215   } text[LSTOPO_OBJ_TEXT_MAX];
216   unsigned ntext;
217   unsigned textwidth; /* required width for all lines of text,
218 		       * max of above text[].width + optional padding
219 		       */
220 };
221 
222 typedef int output_method (struct lstopo_output *output, const char *filename);
223 extern output_method output_console, output_synthetic, output_ascii, output_tikz, output_fig, output_png, output_pdf, output_ps, output_nativesvg, output_cairosvg, output_x11, output_windows, output_xml, output_android, output_shmem;
224 
225 extern int lstopo_shmem_adopt(const char *input, hwloc_topology_t *topologyp);
226 
227 struct draw_methods {
228   int (*declare_color) (struct lstopo_output *loutput, struct lstopo_color *lcolor);
229   void (*destroy_color) (struct lstopo_output *loutput, struct lstopo_color *lcolor);
230   /* only called when loutput->draw_methods == LSTOPO_DRAWING_DRAW */
231   void (*box) (struct lstopo_output *loutput, const struct lstopo_color *lcolor, unsigned depth, unsigned x, unsigned width, unsigned y, unsigned height, hwloc_obj_t obj, unsigned box_id);
232   void (*line) (struct lstopo_output *loutput, const struct lstopo_color *lcolor, unsigned depth, unsigned x1, unsigned y1, unsigned x2, unsigned y2, hwloc_obj_t obj, unsigned line_id);
233   void (*text) (struct lstopo_output *loutput, const struct lstopo_color *lcolor, int size, unsigned depth, unsigned x, unsigned y, const char *text, hwloc_obj_t obj, unsigned text_id);
234   /* may be called when loutput->drawing == LSTOPO_DRAWING_PREPARE */
235   void (*textsize) (struct lstopo_output *loutput, const char *text, unsigned textlength, unsigned fontsize, unsigned *width);
236 };
237 
238 extern void output_draw(struct lstopo_output *output);
239 
240 extern void lstopo_prepare_custom_styles(struct lstopo_output *loutput);
241 extern void declare_colors(struct lstopo_output *output);
242 extern void destroy_colors(struct lstopo_output *output);
243 
lstopo_pu_disallowed(struct lstopo_output * loutput,hwloc_obj_t l)244 static __hwloc_inline int lstopo_pu_disallowed(struct lstopo_output *loutput, hwloc_obj_t l)
245 {
246   hwloc_topology_t topology = loutput->topology;
247   return !hwloc_bitmap_isset(hwloc_topology_get_allowed_cpuset(topology), l->os_index);
248 }
249 
lstopo_pu_binding(struct lstopo_output * loutput,hwloc_obj_t l)250 static __hwloc_inline int lstopo_pu_binding(struct lstopo_output *loutput, hwloc_obj_t l)
251 {
252   return loutput->pid_number != -1 && hwloc_bitmap_isset(loutput->cpubind_set, l->os_index);
253 }
254 
lstopo_numa_disallowed(struct lstopo_output * loutput,hwloc_obj_t l)255 static __hwloc_inline int lstopo_numa_disallowed(struct lstopo_output *loutput, hwloc_obj_t l)
256 {
257   hwloc_topology_t topology = loutput->topology;
258   return !hwloc_bitmap_isset(hwloc_topology_get_allowed_nodeset(topology), l->os_index);
259 }
260 
lstopo_numa_binding(struct lstopo_output * loutput,hwloc_obj_t l)261 static __hwloc_inline int lstopo_numa_binding(struct lstopo_output *loutput, hwloc_obj_t l)
262 {
263   return loutput->pid_number != -1 && hwloc_bitmap_isset(loutput->membind_set, l->os_index);
264 }
265 
lstopo_busid_snprintf(struct lstopo_output * loutput,char * text,size_t textlen,hwloc_obj_t firstobj,int collapse,unsigned needdomain)266 static __hwloc_inline int lstopo_busid_snprintf(struct lstopo_output *loutput, char *text, size_t textlen, hwloc_obj_t firstobj, int collapse, unsigned needdomain)
267 {
268   hwloc_obj_t lastobj;
269   char domain[10] = "";
270   unsigned i;
271 
272   if (needdomain)
273     snprintf(domain, sizeof(domain), "%04x:", firstobj->attr->pcidev.domain);
274 
275   /* single busid */
276   if (!loutput->pci_collapse_enabled || collapse <= 1) {
277       return snprintf(text, textlen, "%s%02x:%02x.%01x",
278 		      domain,
279 		      firstobj->attr->pcidev.bus,
280 		      firstobj->attr->pcidev.dev,
281 		      firstobj->attr->pcidev.func);
282   }
283 
284   assert(collapse >= 0); /* should be called on the first object of a collapsed range */
285 
286   for(lastobj=firstobj, i=1; i<(unsigned)collapse; i++)
287     lastobj = lastobj->next_cousin;
288 
289   /* multiple busid functions for same busid device */
290   if (firstobj->attr->pcidev.dev == lastobj->attr->pcidev.dev)
291     return snprintf(text, textlen, "%s%02x:%02x.%01x-%01x",
292 		    domain,
293 		    firstobj->attr->pcidev.bus,
294 		    firstobj->attr->pcidev.dev,
295 		    firstobj->attr->pcidev.func,
296 		    lastobj->attr->pcidev.func);
297 
298   /* multiple busid devices */
299   return snprintf(text, textlen, "%s%02x:%02x.%01x-%02x.%01x",
300 		  domain,
301 		  firstobj->attr->pcidev.bus,
302 		  firstobj->attr->pcidev.dev,
303 		  firstobj->attr->pcidev.func,
304 		  lastobj->attr->pcidev.dev,
305 		  lastobj->attr->pcidev.func);
306 }
307 
308 extern void lstopo_show_interactive_cli_options(const struct lstopo_output *loutput);
309 extern void lstopo_show_interactive_help(void);
310 
311 #endif /* UTILS_LSTOPO_H */
312