2016-05-05 17:44:28 +03:00
# ifndef _PERF_RESORT_RB_H_
# define _PERF_RESORT_RB_H_
/*
* Template for creating a class to resort an existing rb_tree according to
* a new sort criteria , that must be present in the entries of the source
* rb_tree .
*
* ( c ) 2016 Arnaldo Carvalho de Melo < acme @ redhat . com >
*
* Quick example , resorting threads by its shortname :
*
* First define the prefix ( threads ) to be used for the functions and data
* structures created , and provide an expression for the sorting , then the
* fields to be present in each of the entries in the new , sorted , rb_tree .
*
* The body of the init function should collect the fields , maybe
* pre - calculating them from multiple entries in the original ' entry ' from
* the rb_tree used as a source for the entries to be sorted :
DEFINE_RB_RESORT_RB ( threads , strcmp ( a - > thread - > shortname ,
b - > thread - > shortname ) < 0 ,
struct thread * thread ;
)
{
entry - > thread = rb_entry ( nd , struct thread , rb_node ) ;
}
* After this it is just a matter of instantiating it and iterating it ,
* for a few data structures with existing rb_trees , such as ' struct machine ' ,
* helpers are available to get the rb_root and the nr_entries :
DECLARE_RESORT_RB_MACHINE_THREADS ( threads , machine_ptr ) ;
* This will instantiate the new rb_tree and a cursor for it , that can be used as :
struct rb_node * nd ;
2016-06-23 17:34:10 +03:00
resort_rb__for_each_entry ( nd , threads ) {
2016-05-05 17:44:28 +03:00
struct thread * t = threads_entry ;
printf ( " %s: %d \n " , t - > shortname , t - > tid ) ;
}
* Then delete it :
resort_rb__delete ( threads ) ;
* The name of the data structures and functions will have a _sorted suffix
* right before the method names , i . e . will look like :
*
* struct threads_sorted_entry { }
* threads_sorted__insert ( )
*/
# define DEFINE_RESORT_RB(__name, __comp, ...) \
struct __name # # _sorted_entry { \
struct rb_node rb_node ; \
__VA_ARGS__ \
} ; \
static void __name # # _sorted__init_entry ( struct rb_node * nd , \
struct __name # # _sorted_entry * entry ) ; \
\
static int __name # # _sorted__cmp ( struct rb_node * nda , struct rb_node * ndb ) \
{ \
struct __name # # _sorted_entry * a , * b ; \
a = rb_entry ( nda , struct __name # # _sorted_entry , rb_node ) ; \
b = rb_entry ( ndb , struct __name # # _sorted_entry , rb_node ) ; \
return __comp ; \
} \
\
struct __name # # _sorted { \
struct rb_root entries ; \
struct __name # # _sorted_entry nd [ 0 ] ; \
} ; \
\
static void __name # # _sorted__insert ( struct __name # # _sorted * sorted , \
struct rb_node * sorted_nd ) \
{ \
struct rb_node * * p = & sorted - > entries . rb_node , * parent = NULL ; \
while ( * p ! = NULL ) { \
parent = * p ; \
if ( __name # # _sorted__cmp ( sorted_nd , parent ) ) \
p = & ( * p ) - > rb_left ; \
else \
p = & ( * p ) - > rb_right ; \
} \
rb_link_node ( sorted_nd , parent , p ) ; \
rb_insert_color ( sorted_nd , & sorted - > entries ) ; \
} \
\
static void __name # # _sorted__sort ( struct __name # # _sorted * sorted , \
struct rb_root * entries ) \
{ \
struct rb_node * nd ; \
unsigned int i = 0 ; \
for ( nd = rb_first ( entries ) ; nd ; nd = rb_next ( nd ) ) { \
struct __name # # _sorted_entry * snd = & sorted - > nd [ i + + ] ; \
__name # # _sorted__init_entry ( nd , snd ) ; \
__name # # _sorted__insert ( sorted , & snd - > rb_node ) ; \
} \
} \
\
static struct __name # # _sorted * __name # # _sorted__new ( struct rb_root * entries , \
int nr_entries ) \
{ \
struct __name # # _sorted * sorted ; \
sorted = malloc ( sizeof ( * sorted ) + sizeof ( sorted - > nd [ 0 ] ) * nr_entries ) ; \
if ( sorted ) { \
sorted - > entries = RB_ROOT ; \
__name # # _sorted__sort ( sorted , entries ) ; \
} \
return sorted ; \
} \
\
static void __name # # _sorted__delete ( struct __name # # _sorted * sorted ) \
{ \
free ( sorted ) ; \
} \
\
static void __name # # _sorted__init_entry ( struct rb_node * nd , \
struct __name # # _sorted_entry * entry )
# define DECLARE_RESORT_RB(__name) \
struct __name # # _sorted_entry * __name # # _entry ; \
struct __name # # _sorted * __name = __name # # _sorted__new
2016-06-23 17:34:10 +03:00
# define resort_rb__for_each_entry(__nd, __name) \
2016-05-05 17:44:28 +03:00
for ( __nd = rb_first ( & __name - > entries ) ; \
__name # # _entry = rb_entry ( __nd , struct __name # # _sorted_entry , \
rb_node ) , __nd ; \
__nd = rb_next ( __nd ) )
# define resort_rb__delete(__name) \
__name # # _sorted__delete ( __name ) , __name = NULL
/*
* Helpers for other classes that contains both an rbtree and the
* number of entries in it :
*/
/* For 'struct intlist' */
# define DECLARE_RESORT_RB_INTLIST(__name, __ilist) \
DECLARE_RESORT_RB ( __name ) ( & __ilist - > rblist . entries , \
__ilist - > rblist . nr_entries )
/* For 'struct machine->threads' */
# define DECLARE_RESORT_RB_MACHINE_THREADS(__name, __machine) \
DECLARE_RESORT_RB ( __name ) ( & __machine - > threads , __machine - > nr_threads )
# endif /* _PERF_RESORT_RB_H_ */