2013-09-11 16:56:44 +02:00
# include "comm.h"
# include "util.h"
# include <stdlib.h>
# include <stdio.h>
2015-05-19 19:07:42 -03:00
# include <linux/atomic.h>
2013-09-11 16:56:44 +02:00
struct comm_str {
char * str ;
struct rb_node rb_node ;
2015-05-19 19:07:42 -03:00
atomic_t refcnt ;
2013-09-11 16:56:44 +02:00
} ;
/* Should perhaps be moved to struct machine */
static struct rb_root comm_str_root ;
2015-05-19 19:07:42 -03:00
static struct comm_str * comm_str__get ( struct comm_str * cs )
2013-09-11 16:56:44 +02:00
{
2015-05-19 19:07:42 -03:00
if ( cs )
atomic_inc ( & cs - > refcnt ) ;
return cs ;
2013-09-11 16:56:44 +02:00
}
static void comm_str__put ( struct comm_str * cs )
{
2015-05-19 19:07:42 -03:00
if ( cs & & atomic_dec_and_test ( & cs - > refcnt ) ) {
2013-09-11 16:56:44 +02:00
rb_erase ( & cs - > rb_node , & comm_str_root ) ;
2013-12-27 16:55:14 -03:00
zfree ( & cs - > str ) ;
2013-09-11 16:56:44 +02:00
free ( cs ) ;
}
}
static struct comm_str * comm_str__alloc ( const char * str )
{
struct comm_str * cs ;
cs = zalloc ( sizeof ( * cs ) ) ;
if ( ! cs )
return NULL ;
cs - > str = strdup ( str ) ;
if ( ! cs - > str ) {
free ( cs ) ;
return NULL ;
}
2015-05-19 19:07:42 -03:00
atomic_set ( & cs - > refcnt , 0 ) ;
2013-09-11 16:56:44 +02:00
return cs ;
}
static struct comm_str * comm_str__findnew ( const char * str , struct rb_root * root )
{
struct rb_node * * p = & root - > rb_node ;
struct rb_node * parent = NULL ;
struct comm_str * iter , * new ;
int cmp ;
while ( * p ! = NULL ) {
parent = * p ;
iter = rb_entry ( parent , struct comm_str , rb_node ) ;
cmp = strcmp ( str , iter - > str ) ;
if ( ! cmp )
return iter ;
if ( cmp < 0 )
p = & ( * p ) - > rb_left ;
else
p = & ( * p ) - > rb_right ;
}
new = comm_str__alloc ( str ) ;
if ( ! new )
return NULL ;
rb_link_node ( & new - > rb_node , parent , p ) ;
rb_insert_color ( & new - > rb_node , root ) ;
return new ;
}
2014-07-31 09:00:44 +03:00
struct comm * comm__new ( const char * str , u64 timestamp , bool exec )
2013-09-11 16:56:44 +02:00
{
struct comm * comm = zalloc ( sizeof ( * comm ) ) ;
if ( ! comm )
return NULL ;
comm - > start = timestamp ;
2014-07-31 09:00:44 +03:00
comm - > exec = exec ;
2013-09-11 16:56:44 +02:00
comm - > comm_str = comm_str__findnew ( str , & comm_str_root ) ;
if ( ! comm - > comm_str ) {
free ( comm ) ;
return NULL ;
}
comm_str__get ( comm - > comm_str ) ;
return comm ;
}
2014-07-31 09:00:44 +03:00
int comm__override ( struct comm * comm , const char * str , u64 timestamp , bool exec )
2013-09-13 16:28:57 +09:00
{
2014-01-14 16:37:14 +01:00
struct comm_str * new , * old = comm - > comm_str ;
2013-09-13 16:28:57 +09:00
2014-01-14 16:37:14 +01:00
new = comm_str__findnew ( str , & comm_str_root ) ;
if ( ! new )
return - ENOMEM ;
2013-09-13 16:28:57 +09:00
2014-01-14 16:37:14 +01:00
comm_str__get ( new ) ;
2013-09-13 16:28:57 +09:00
comm_str__put ( old ) ;
2014-01-14 16:37:14 +01:00
comm - > comm_str = new ;
comm - > start = timestamp ;
2014-07-31 09:00:44 +03:00
if ( exec )
comm - > exec = true ;
2014-01-14 16:37:14 +01:00
return 0 ;
2013-09-13 16:28:57 +09:00
}
2013-09-11 16:56:44 +02:00
void comm__free ( struct comm * comm )
{
comm_str__put ( comm - > comm_str ) ;
free ( comm ) ;
}
const char * comm__str ( const struct comm * comm )
{
return comm - > comm_str - > str ;
}