2017-06-19 19:28:30 -04:00
# ifndef _MM_PERCPU_INTERNAL_H
# define _MM_PERCPU_INTERNAL_H
# include <linux/types.h>
# include <linux/percpu.h>
struct pcpu_chunk {
2017-06-19 19:28:31 -04:00
# ifdef CONFIG_PERCPU_STATS
int nr_alloc ; /* # of allocations */
size_t max_alloc_size ; /* largest allocation size */
# endif
2017-06-19 19:28:30 -04:00
struct list_head list ; /* linked to pcpu_slot lists */
int free_size ; /* free bytes in the chunk */
int contig_hint ; /* max contiguous size hint */
void * base_addr ; /* base address of this chunk */
int map_used ; /* # of map entries used before the sentry */
int map_alloc ; /* # of map entries allocated */
int * map ; /* allocation map */
struct list_head map_extend_list ; /* on pcpu_map_extend_chunks */
void * data ; /* chunk data */
int first_free ; /* no free below this */
bool immutable ; /* no [de]population allowed */
2017-06-19 19:28:31 -04:00
bool has_reserved ; /* Indicates if chunk has reserved space
at the beginning . Reserved chunk will
contain reservation for static chunk .
Dynamic chunk will contain reservation
for static and reserved chunks . */
2017-06-19 19:28:30 -04:00
int nr_populated ; /* # of populated pages */
unsigned long populated [ ] ; /* populated bitmap */
} ;
extern spinlock_t pcpu_lock ;
extern struct list_head * pcpu_slot ;
extern int pcpu_nr_slots ;
extern struct pcpu_chunk * pcpu_first_chunk ;
extern struct pcpu_chunk * pcpu_reserved_chunk ;
2017-06-19 19:28:31 -04:00
# ifdef CONFIG_PERCPU_STATS
# include <linux/spinlock.h>
struct percpu_stats {
u64 nr_alloc ; /* lifetime # of allocations */
u64 nr_dealloc ; /* lifetime # of deallocations */
u64 nr_cur_alloc ; /* current # of allocations */
u64 nr_max_alloc ; /* max # of live allocations */
u32 nr_chunks ; /* current # of live chunks */
u32 nr_max_chunks ; /* max # of live chunks */
size_t min_alloc_size ; /* min allocaiton size */
size_t max_alloc_size ; /* max allocation size */
} ;
extern struct percpu_stats pcpu_stats ;
extern struct pcpu_alloc_info pcpu_stats_ai ;
/*
* For debug purposes . We don ' t care about the flexible array .
*/
static inline void pcpu_stats_save_ai ( const struct pcpu_alloc_info * ai )
{
memcpy ( & pcpu_stats_ai , ai , sizeof ( struct pcpu_alloc_info ) ) ;
/* initialize min_alloc_size to unit_size */
pcpu_stats . min_alloc_size = pcpu_stats_ai . unit_size ;
}
/*
* pcpu_stats_area_alloc - increment area allocation stats
* @ chunk : the location of the area being allocated
* @ size : size of area to allocate in bytes
*
* CONTEXT :
* pcpu_lock .
*/
static inline void pcpu_stats_area_alloc ( struct pcpu_chunk * chunk , size_t size )
{
lockdep_assert_held ( & pcpu_lock ) ;
pcpu_stats . nr_alloc + + ;
pcpu_stats . nr_cur_alloc + + ;
pcpu_stats . nr_max_alloc =
max ( pcpu_stats . nr_max_alloc , pcpu_stats . nr_cur_alloc ) ;
pcpu_stats . min_alloc_size =
min ( pcpu_stats . min_alloc_size , size ) ;
pcpu_stats . max_alloc_size =
max ( pcpu_stats . max_alloc_size , size ) ;
chunk - > nr_alloc + + ;
chunk - > max_alloc_size = max ( chunk - > max_alloc_size , size ) ;
}
/*
* pcpu_stats_area_dealloc - decrement allocation stats
* @ chunk : the location of the area being deallocated
*
* CONTEXT :
* pcpu_lock .
*/
static inline void pcpu_stats_area_dealloc ( struct pcpu_chunk * chunk )
{
lockdep_assert_held ( & pcpu_lock ) ;
pcpu_stats . nr_dealloc + + ;
pcpu_stats . nr_cur_alloc - - ;
chunk - > nr_alloc - - ;
}
/*
* pcpu_stats_chunk_alloc - increment chunk stats
*/
static inline void pcpu_stats_chunk_alloc ( void )
{
2017-06-21 13:52:46 -04:00
unsigned long flags ;
spin_lock_irqsave ( & pcpu_lock , flags ) ;
2017-06-19 19:28:31 -04:00
pcpu_stats . nr_chunks + + ;
pcpu_stats . nr_max_chunks =
max ( pcpu_stats . nr_max_chunks , pcpu_stats . nr_chunks ) ;
2017-06-21 13:52:46 -04:00
spin_unlock_irqrestore ( & pcpu_lock , flags ) ;
2017-06-19 19:28:31 -04:00
}
/*
* pcpu_stats_chunk_dealloc - decrement chunk stats
*/
static inline void pcpu_stats_chunk_dealloc ( void )
{
2017-06-21 13:52:46 -04:00
unsigned long flags ;
spin_lock_irqsave ( & pcpu_lock , flags ) ;
2017-06-19 19:28:31 -04:00
pcpu_stats . nr_chunks - - ;
2017-06-21 13:52:46 -04:00
spin_unlock_irqrestore ( & pcpu_lock , flags ) ;
2017-06-19 19:28:31 -04:00
}
# else
static inline void pcpu_stats_save_ai ( const struct pcpu_alloc_info * ai )
{
}
static inline void pcpu_stats_area_alloc ( struct pcpu_chunk * chunk , size_t size )
{
}
static inline void pcpu_stats_area_dealloc ( struct pcpu_chunk * chunk )
{
}
static inline void pcpu_stats_chunk_alloc ( void )
{
}
static inline void pcpu_stats_chunk_dealloc ( void )
{
}
# endif /* !CONFIG_PERCPU_STATS */
2017-06-19 19:28:30 -04:00
# endif