2 #include "libbenchmark_topology_internal.h"
5 #define NUMBER_KEY_LINES 8
13 enum libbenchmark_topology_node_type
16 struct lfds710_list_asu_element
19 union libbenchmark_topology_node_extended_info
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 );
31 /****************************************************************************/
32 char *libbenchmark_topology_generate_string( struct libbenchmark_topology_state *ts, struct libshared_memory_state *ms, enum libbenchmark_topology_string_format format )
35 cache_type_enum_to_string_lookup[LIBBENCHMARK_TOPOLOGY_NODE_CACHE_TYPE_COUNT] =
39 *const key_strings[NUMBER_KEY_LINES] =
41 "R = Notional system root ",
43 "S = Socket (physical package)",
44 "LnU = Level n unified cache ",
45 "LnD = Level n data cache ",
46 "LnI = Level n instruction cache",
48 "nnn = Logical core ",
50 *const empty_key_string = " ";
64 number_topology_lines,
65 number_key_and_topology_lines;
67 struct lfds710_btree_au_element
73 struct lfds710_list_asu_element
76 struct lfds710_list_asu_state
79 struct libbenchmark_topology_node_state
82 LFDS710_PAL_ASSERT( ts != NULL );
83 LFDS710_PAL_ASSERT( ms != NULL );
84 // TRD : format can be any value in its range
86 lfds710_list_asu_init_valid_on_current_logical_core( &lines, NULL );
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) )
92 tns = LFDS710_BTREE_AU_GET_KEY_FROM_ELEMENT( *baue );
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
99 if( 0 == lfds710_list_asu_get_by_key(&lines, key_compare_function, tns, &lasue) )
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 );
112 line = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
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 );
121 case LIBBENCHMARK_TOPOLOGY_NODE_TYPE_CACHE:
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;
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 );
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 );
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 );
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 );
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
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 );
177 libshared_ansi_strcat( line->string, " " );
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
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
190 lfds710_list_asu_query( &lines, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void *) &number_topology_lines );
192 if( number_topology_lines < NUMBER_KEY_LINES )
193 number_key_and_topology_lines = NUMBER_KEY_LINES;
195 number_key_and_topology_lines = number_topology_lines;
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 );
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';
204 // TRD : now all the fun of the faire - time to compose the string
208 lasue = LFDS710_LIST_ASU_GET_START( lines );
210 while( lasue != NULL or key_line < NUMBER_KEY_LINES )
212 // TRD : copy in a blank topology line
214 for( loop = 0 ; loop < ts->line_width+1 ; loop++ )
215 libshared_ansi_strcat( topology_string, " " );
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 );
224 // TRD : copy in a blank key line
225 if( key_line == NUMBER_KEY_LINES )
226 libshared_ansi_strcat( topology_string, empty_key_string );
228 if( key_line < NUMBER_KEY_LINES )
229 libshared_ansi_strcat( topology_string, key_strings[key_line++] );
233 case LIBBENCHMARK_TOPOLOGY_STRING_FORMAT_STDOUT:
234 libshared_ansi_strcat( topology_string, "\n" );
237 case LIBBENCHMARK_TOPOLOGY_STRING_FORMAT_GNUPLOT:
238 libshared_ansi_strcat( topology_string, "\\n\\\n" );
243 return topology_string;
250 /****************************************************************************/
251 char *libbenchmark_topology_generate_lpset_string( struct libbenchmark_topology_state *ts, struct libshared_memory_state *ms, struct lfds710_list_aso_state *lpset )
254 *lpset_string = NULL;
259 struct libbenchmark_topology_lp_printing_offset
262 struct libbenchmark_topology_node_state
265 struct lfds710_btree_au_element
268 struct lfds710_list_aso_element
271 LFDS710_PAL_ASSERT( ts != NULL );
272 LFDS710_PAL_ASSERT( ms != NULL );
273 LFDS710_PAL_ASSERT( lpset != NULL );
275 lpset_string = libshared_memory_alloc_from_most_free_space_node( ms, sizeof(char) * (ts->line_width+1), sizeof(char) );
277 for( loop = 0 ; loop < ts->line_width ; loop++ )
278 lpset_string[loop] = ' ';
279 lpset_string[loop] = '\0';
281 while( LFDS710_LIST_ASO_GET_START_AND_THEN_NEXT(*lpset,lasoe) )
283 tns = LFDS710_LIST_ASO_GET_VALUE_FROM_ELEMENT( *lasoe );
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 );
288 lpset_string[tlpo->offset+1] = '1';
298 /****************************************************************************/
299 lfds710_pal_uint_t count_of_logical_processors_below_node( struct lfds710_btree_au_element *baue )
304 struct libbenchmark_topology_node_state
308 LFDS710_PAL_ASSERT( baue != NULL );
310 tns = LFDS710_BTREE_AU_GET_KEY_FROM_ELEMENT( *baue );
313 while( lfds710_btree_au_get_by_relative_position(&baue, LFDS710_BTREE_AU_RELATIVE_POSITION_NEXT_SMALLER_ELEMENT_IN_ENTIRE_TREE) )
315 tns = LFDS710_BTREE_AU_GET_KEY_FROM_ELEMENT( *baue );
317 if( tns->type == root_node->type and tns->type != LIBBENCHMARK_TOPOLOGY_NODE_TYPE_CACHE )
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 )
323 if( tns->type == LIBBENCHMARK_TOPOLOGY_NODE_TYPE_LOGICAL_PROCESSOR )
334 /****************************************************************************/
335 static int key_compare_function( void const *new_key, void const *existing_key )
337 struct libbenchmark_topology_node_state
343 LFDS710_PAL_ASSERT( new_key != NULL );
344 LFDS710_PAL_ASSERT( existing_key != NULL );
346 tns = (struct libbenchmark_topology_node_state *) new_key;
347 line = (struct line *) existing_key;
349 if( tns->type > line->type )
352 if( tns->type < line->type )
355 if( tns->type == line->type )
356 if( tns->type == LIBBENCHMARK_TOPOLOGY_NODE_TYPE_CACHE and line->type == LIBBENCHMARK_TOPOLOGY_NODE_TYPE_CACHE )
358 if( tns->extended_node_info.cache.level > line->extended_node_info.cache.level )
361 if( tns->extended_node_info.cache.level < line->extended_node_info.cache.level )
364 if( tns->extended_node_info.cache.level == line->extended_node_info.cache.level )
366 if( tns->extended_node_info.cache.type > line->extended_node_info.cache.type )
369 if( tns->extended_node_info.cache.type < line->extended_node_info.cache.type )
372 if( tns->extended_node_info.cache.type == line->extended_node_info.cache.type )
384 /****************************************************************************/
385 static void strcat_spaces( char *string, lfds710_pal_uint_t number_width )
390 LFDS710_PAL_ASSERT( string != NULL );
391 // TRD : number_width can be any value in its range
393 for( loop = 0 ; loop < number_width ; loop++ )
394 libshared_ansi_strcat( string, " " );