]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.1.0/test_and_benchmark/libbenchmark/src/libbenchmark_topology/libbenchmark_topology_string.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.1.0 / test_and_benchmark / libbenchmark / src / libbenchmark_topology / libbenchmark_topology_string.c
1 /***** includes *****/
2 #include "libbenchmark_topology_internal.h"
3
4 /***** defines *****/
5 #define NUMBER_KEY_LINES 8
6
7 /***** structs *****/
8 struct line
9 {
10   char
11     *string;
12
13   enum libbenchmark_topology_node_type
14     type;
15
16   struct lfds710_list_asu_element
17     lasue;
18
19   union libbenchmark_topology_node_extended_info
20     extended_node_info;
21 };
22
23 /***** private prototypes *****/
24 static int key_compare_function( void const *new_key, void const *existing_key );
25 static void strcat_spaces( char *string, lfds710_pal_uint_t number_width );
26
27
28
29
30
31 /****************************************************************************/
32 char *libbenchmark_topology_generate_string( struct libbenchmark_topology_state *ts, struct libshared_memory_state *ms, enum libbenchmark_topology_string_format format )
33 {
34   char const
35     cache_type_enum_to_string_lookup[LIBBENCHMARK_TOPOLOGY_NODE_CACHE_TYPE_COUNT] = 
36     {
37       'D', 'I', 'U'
38     },
39     *const key_strings[NUMBER_KEY_LINES] = 
40     {
41       "R   = Notional system root     ",
42       "N   = NUMA node                ",
43       "S   = Socket (physical package)",
44       "LnU = Level n unified cache    ",
45       "LnD = Level n data cache       ",
46       "LnI = Level n instruction cache",
47       "P   = Physical core            ",
48       "nnn = Logical core             ",
49     },
50     *const empty_key_string = "                               ";
51
52   char
53     *topology_string;
54
55   int
56     final_length = 0,
57     half_space_width,
58     loop,
59     space_width;
60
61   lfds710_pal_uint_t
62     key_line,
63     lp_count,
64     number_topology_lines,
65     number_key_and_topology_lines;
66
67   struct lfds710_btree_au_element
68     *baue;
69
70   struct line
71     *line;
72
73   struct lfds710_list_asu_element
74     *lasue = NULL;
75
76   struct lfds710_list_asu_state
77     lines;
78
79   struct libbenchmark_topology_node_state
80     *tns;
81
82   LFDS710_PAL_ASSERT( ts != NULL );
83   LFDS710_PAL_ASSERT( ms != NULL );
84   // TRD : format can be any value in its range
85
86   lfds710_list_asu_init_valid_on_current_logical_core( &lines, NULL );
87
88   baue = NULL;
89
90   while( lfds710_btree_au_get_by_absolute_position_and_then_by_relative_position(&ts->topology_tree, &baue, LFDS710_BTREE_AU_ABSOLUTE_POSITION_LARGEST_IN_TREE, LFDS710_BTREE_AU_RELATIVE_POSITION_NEXT_SMALLER_ELEMENT_IN_ENTIRE_TREE) )
91   {
92     tns = LFDS710_BTREE_AU_GET_KEY_FROM_ELEMENT( *baue );
93
94     /* TRD : look for this node type in the list of lines
95              if it's not there, add it to the end
96              if it is there, use it
97     */
98
99     if( 0 == lfds710_list_asu_get_by_key(&lines, key_compare_function, tns, &lasue) )
100     {
101       line = libshared_memory_alloc_from_most_free_space_node( ms, sizeof(struct line), LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
102       line->type = tns->type;
103       line->extended_node_info = tns->extended_node_info;
104       // TRD : +2 for trailing space and for trailing NULL
105       line->string = libshared_memory_alloc_from_most_free_space_node( ms, ts->line_width+2, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
106       *line->string = '\0';
107       LFDS710_LIST_ASU_SET_KEY_IN_ELEMENT( line->lasue, line );
108       LFDS710_LIST_ASU_SET_VALUE_IN_ELEMENT( line->lasue, line );
109       lfds710_list_asu_insert_at_end( &lines, &line->lasue );
110     }
111     else
112       line = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
113
114     switch( tns->type )
115     {
116       case LIBBENCHMARK_TOPOLOGY_NODE_TYPE_LOGICAL_PROCESSOR:
117         // libshared_ansi_strcat( line->string, " L " );
118         libshared_ansi_strcat_number_with_leading_zeros( line->string, LIBBENCHMARK_TOPOLOGY_NODE_GET_LOGICAL_PROCESSOR_NUMBER(*tns), 3 );
119       break;
120
121       case LIBBENCHMARK_TOPOLOGY_NODE_TYPE_CACHE:
122       {
123         lp_count = count_of_logical_processors_below_node( baue );
124         space_width = (int) ( lp_count * 3 + lp_count - 3 );
125         half_space_width = space_width / 2;
126
127         strcat_spaces( line->string, half_space_width );
128         libshared_ansi_strcat( line->string, "L" );
129         libshared_ansi_strcat_number( line->string, tns->extended_node_info.cache.level );
130         libshared_ansi_strcat_char( line->string, cache_type_enum_to_string_lookup[tns->extended_node_info.cache.type] );
131         strcat_spaces( line->string, half_space_width );
132       }
133       break;
134
135       case LIBBENCHMARK_TOPOLOGY_NODE_TYPE_PHYSICAL_PROCESSOR:
136         lp_count = count_of_logical_processors_below_node( baue );
137         space_width = (int) ( lp_count * 3 + lp_count - 1 );
138         half_space_width = space_width / 2;
139         strcat_spaces( line->string, half_space_width );
140         libshared_ansi_strcat( line->string, "P" );
141         strcat_spaces( line->string, half_space_width );
142       break;
143
144       case LIBBENCHMARK_TOPOLOGY_NODE_TYPE_SOCKET:
145         lp_count = count_of_logical_processors_below_node( baue );
146         space_width = (int) ( lp_count * 3 + lp_count - 1 );
147         half_space_width = space_width / 2;
148         strcat_spaces( line->string, half_space_width );
149         libshared_ansi_strcat( line->string, "S" );
150         strcat_spaces( line->string, half_space_width );
151       break;
152
153       case LIBBENCHMARK_TOPOLOGY_NODE_TYPE_NUMA:
154         lp_count = count_of_logical_processors_below_node( baue );
155         space_width = (int) ( lp_count * 3 + lp_count - 1 );
156         half_space_width = space_width / 2;
157         strcat_spaces( line->string, half_space_width );
158         libshared_ansi_strcat( line->string, "N" );
159         strcat_spaces( line->string, half_space_width );
160       break;
161
162       case LIBBENCHMARK_TOPOLOGY_NODE_TYPE_SYSTEM:
163         /* TRD : count the number of LPs below this node
164                  assume for now each has caches so it three letters side
165                  compute the space_width and print R in the middle
166         */
167
168         lp_count = count_of_logical_processors_below_node( baue );
169         space_width = (int) ( lp_count * 3 + lp_count - 1 );
170         half_space_width = space_width / 2;
171         strcat_spaces( line->string, half_space_width );
172         libshared_ansi_strcat( line->string, "R" );
173         strcat_spaces( line->string, half_space_width );
174       break;
175     }
176
177     libshared_ansi_strcat( line->string, " " );
178   }
179
180   /* TRD : so, we have the topology
181            but we also want to print the key on the same lines
182            the topology may have more or less lines than the key
183            if we run out of topology lines, we need to print white spaces to keep the justification correct
184            same for running out of key lines
185
186            first we compute the length of the final string, so we can allocate the topology string
187            then we actually form up the string
188   */
189
190   lfds710_list_asu_query( &lines, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void *) &number_topology_lines );
191
192   if( number_topology_lines < NUMBER_KEY_LINES )
193     number_key_and_topology_lines = NUMBER_KEY_LINES;
194   else
195     number_key_and_topology_lines = number_topology_lines;
196
197   // TRD : +1 for one space, +31 for the text, +1 for final newline, +5 for gnuplot stuff ("\\n\\", which we won't need if stdout)
198   final_length = (int) ( (ts->line_width + 39) * number_key_and_topology_lines );
199
200   // TRD : and a trailing NULL
201   topology_string = libshared_memory_alloc_from_most_free_space_node( ms, final_length+1, 1 );
202   *topology_string = '\0';
203
204   // TRD : now all the fun of the faire - time to compose the string
205
206   key_line = 0;
207
208   lasue = LFDS710_LIST_ASU_GET_START( lines );
209
210   while( lasue != NULL or key_line < NUMBER_KEY_LINES )
211   {
212     // TRD : copy in a blank topology line
213     if( lasue == NULL )
214       for( loop = 0 ; loop < ts->line_width+1 ; loop++ )
215         libshared_ansi_strcat( topology_string, " " );
216
217     if( lasue != NULL )
218     {
219       line = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
220       libshared_ansi_strcat( topology_string, line->string );
221       lasue = LFDS710_LIST_ASU_GET_NEXT( *lasue );
222     }
223
224     // TRD : copy in a blank key line
225     if( key_line == NUMBER_KEY_LINES )
226       libshared_ansi_strcat( topology_string, empty_key_string );
227
228     if( key_line < NUMBER_KEY_LINES )
229       libshared_ansi_strcat( topology_string, key_strings[key_line++] );
230
231     switch( format )
232     {
233       case LIBBENCHMARK_TOPOLOGY_STRING_FORMAT_STDOUT:
234         libshared_ansi_strcat( topology_string, "\n" );
235       break;
236
237       case LIBBENCHMARK_TOPOLOGY_STRING_FORMAT_GNUPLOT:
238         libshared_ansi_strcat( topology_string, "\\n\\\n" );
239       break;
240     }
241   }
242
243   return topology_string;
244 }
245
246
247
248
249
250 /****************************************************************************/
251 char *libbenchmark_topology_generate_lpset_string( struct libbenchmark_topology_state *ts, struct libshared_memory_state *ms, struct lfds710_list_aso_state *lpset )
252 {
253   char
254     *lpset_string = NULL;
255
256   int
257     loop;
258
259   struct libbenchmark_topology_lp_printing_offset
260     *tlpo;
261
262   struct libbenchmark_topology_node_state
263     *tns;
264
265   struct lfds710_btree_au_element
266     *baue;
267
268   struct lfds710_list_aso_element
269     *lasoe = NULL;
270
271   LFDS710_PAL_ASSERT( ts != NULL );
272   LFDS710_PAL_ASSERT( ms != NULL );
273   LFDS710_PAL_ASSERT( lpset != NULL );
274
275   lpset_string = libshared_memory_alloc_from_most_free_space_node( ms, sizeof(char) * (ts->line_width+1), sizeof(char) );
276
277   for( loop = 0 ; loop < ts->line_width ; loop++ )
278     lpset_string[loop] = ' ';
279   lpset_string[loop] = '\0';
280
281   while( LFDS710_LIST_ASO_GET_START_AND_THEN_NEXT(*lpset,lasoe) )
282   {
283     tns = LFDS710_LIST_ASO_GET_VALUE_FROM_ELEMENT( *lasoe );
284
285     lfds710_btree_au_get_by_key( &ts->lp_printing_offset_lookup_tree, libbenchmark_topology_compare_node_against_lp_printing_offset_function, tns, &baue );
286     tlpo = LFDS710_BTREE_AU_GET_VALUE_FROM_ELEMENT( *baue );
287
288     lpset_string[tlpo->offset+1] = '1';
289   }
290
291   return lpset_string;
292 }
293
294
295
296
297
298 /****************************************************************************/
299 lfds710_pal_uint_t count_of_logical_processors_below_node( struct lfds710_btree_au_element *baue )
300 {
301   lfds710_pal_uint_t
302     lp_count = 0;
303
304   struct libbenchmark_topology_node_state
305     *root_node,
306     *tns;
307
308   LFDS710_PAL_ASSERT( baue != NULL );
309
310   tns = LFDS710_BTREE_AU_GET_KEY_FROM_ELEMENT( *baue );
311   root_node = tns;
312
313   while( lfds710_btree_au_get_by_relative_position(&baue, LFDS710_BTREE_AU_RELATIVE_POSITION_NEXT_SMALLER_ELEMENT_IN_ENTIRE_TREE) )
314   {
315     tns = LFDS710_BTREE_AU_GET_KEY_FROM_ELEMENT( *baue );
316
317     if( tns->type == root_node->type and tns->type != LIBBENCHMARK_TOPOLOGY_NODE_TYPE_CACHE )
318       break;
319
320     if( tns->type == root_node->type and tns->type == LIBBENCHMARK_TOPOLOGY_NODE_TYPE_CACHE and tns->extended_node_info.cache.type == root_node->extended_node_info.cache.type and tns->extended_node_info.cache.level == root_node->extended_node_info.cache.level )
321       break;
322
323     if( tns->type == LIBBENCHMARK_TOPOLOGY_NODE_TYPE_LOGICAL_PROCESSOR )
324       lp_count++;
325   }
326
327   return lp_count;
328 }
329
330
331
332
333
334 /****************************************************************************/
335 static int key_compare_function( void const *new_key, void const *existing_key )
336 {
337   struct libbenchmark_topology_node_state
338     *tns;
339
340   struct line
341     *line;
342
343   LFDS710_PAL_ASSERT( new_key != NULL );
344   LFDS710_PAL_ASSERT( existing_key != NULL );
345
346   tns = (struct libbenchmark_topology_node_state *) new_key;
347   line = (struct line *) existing_key;
348
349   if( tns->type > line->type )
350     return 1;
351
352   if( tns->type < line->type )
353     return -1;
354
355   if( tns->type == line->type )
356     if( tns->type == LIBBENCHMARK_TOPOLOGY_NODE_TYPE_CACHE and line->type == LIBBENCHMARK_TOPOLOGY_NODE_TYPE_CACHE )
357     {
358       if( tns->extended_node_info.cache.level > line->extended_node_info.cache.level )
359         return 1;
360
361       if( tns->extended_node_info.cache.level < line->extended_node_info.cache.level )
362         return -1;
363
364       if( tns->extended_node_info.cache.level == line->extended_node_info.cache.level )
365       {
366         if( tns->extended_node_info.cache.type > line->extended_node_info.cache.type )
367           return 1;
368
369         if( tns->extended_node_info.cache.type < line->extended_node_info.cache.type )
370           return -1;
371
372         if( tns->extended_node_info.cache.type == line->extended_node_info.cache.type )
373           return 0;
374       }
375     }
376
377   return 0;
378 }
379
380
381
382
383
384 /****************************************************************************/
385 static void strcat_spaces( char *string, lfds710_pal_uint_t number_width )
386 {
387   lfds710_pal_uint_t
388     loop;
389
390   LFDS710_PAL_ASSERT( string != NULL );
391   // TRD : number_width can be any value in its range
392
393   for( loop = 0 ; loop < number_width ; loop++ )
394     libshared_ansi_strcat( string, " " );
395
396   return;
397 }
398
399