2007-11-21 17:02:58 +03:00
/*
* Define default pcounter functions
* Note that often used pcounters use dedicated functions to get a speed increase .
* ( see DEFINE_PCOUNTER / REF_PCOUNTER_MEMBER )
*/
# include <linux/module.h>
# include <linux/pcounter.h>
# include <linux/smp.h>
2008-01-04 07:41:28 +03:00
# include <linux/cpumask.h>
2007-11-21 17:02:58 +03:00
2008-01-04 07:41:28 +03:00
static void pcounter_dyn_add ( struct pcounter * self , int inc )
2007-11-21 17:02:58 +03:00
{
per_cpu_ptr ( self - > per_cpu_values , smp_processor_id ( ) ) [ 0 ] + = inc ;
}
2008-01-04 07:41:28 +03:00
static int pcounter_dyn_getval ( const struct pcounter * self , int cpu )
{
return per_cpu_ptr ( self - > per_cpu_values , cpu ) [ 0 ] ;
}
2007-11-21 17:02:58 +03:00
2008-01-04 07:41:28 +03:00
int pcounter_getval ( const struct pcounter * self )
2007-11-21 17:02:58 +03:00
{
int res = 0 , cpu ;
2008-01-04 07:41:28 +03:00
2007-11-21 17:02:58 +03:00
for_each_possible_cpu ( cpu )
2008-01-04 07:41:28 +03:00
res + = self - > getval ( self , cpu ) ;
2007-11-21 17:02:58 +03:00
return res ;
}
2008-01-04 07:41:28 +03:00
EXPORT_SYMBOL_GPL ( pcounter_getval ) ;
int pcounter_alloc ( struct pcounter * self )
{
int rc = 0 ;
if ( self - > add = = NULL ) {
self - > per_cpu_values = alloc_percpu ( int ) ;
if ( self - > per_cpu_values ! = NULL ) {
self - > add = pcounter_dyn_add ;
self - > getval = pcounter_dyn_getval ;
} else
rc = 1 ;
}
return rc ;
}
EXPORT_SYMBOL_GPL ( pcounter_alloc ) ;
void pcounter_free ( struct pcounter * self )
{
if ( self - > per_cpu_values ! = NULL ) {
free_percpu ( self - > per_cpu_values ) ;
self - > per_cpu_values = NULL ;
self - > getval = NULL ;
self - > add = NULL ;
}
}
EXPORT_SYMBOL_GPL ( pcounter_free ) ;
2007-11-21 17:02:58 +03:00