2006-03-25 14:08:08 +03:00
# include <linux/kernel.h>
# include <linux/bitops.h>
# include <linux/cpumask.h>
# include <linux/module.h>
2008-11-05 05:39:10 +03:00
# include <linux/bootmem.h>
2006-03-25 14:08:08 +03:00
int __first_cpu ( const cpumask_t * srcp )
{
return min_t ( int , NR_CPUS , find_first_bit ( srcp - > bits , NR_CPUS ) ) ;
}
EXPORT_SYMBOL ( __first_cpu ) ;
2006-03-25 14:08:09 +03:00
int __next_cpu ( int n , const cpumask_t * srcp )
{
return min_t ( int , NR_CPUS , find_next_bit ( srcp - > bits , NR_CPUS , n + 1 ) ) ;
}
EXPORT_SYMBOL ( __next_cpu ) ;
2006-03-25 14:08:09 +03:00
2008-05-12 23:21:13 +04:00
# if NR_CPUS > 64
int __next_cpu_nr ( int n , const cpumask_t * srcp )
{
return min_t ( int , nr_cpu_ids ,
find_next_bit ( srcp - > bits , nr_cpu_ids , n + 1 ) ) ;
}
EXPORT_SYMBOL ( __next_cpu_nr ) ;
# endif
2006-03-25 14:08:10 +03:00
int __any_online_cpu ( const cpumask_t * mask )
{
int cpu ;
for_each_cpu_mask ( cpu , * mask ) {
if ( cpu_online ( cpu ) )
break ;
}
return cpu ;
}
EXPORT_SYMBOL ( __any_online_cpu ) ;
2008-11-05 05:39:10 +03:00
/**
* cpumask_next_and - get the next cpu in * src1p & * src2p
* @ n : the cpu prior to the place to search ( ie . return will be > @ n )
* @ src1p : the first cpumask pointer
* @ src2p : the second cpumask pointer
*
* Returns > = nr_cpu_ids if no further cpus set in both .
*/
int cpumask_next_and ( int n , const struct cpumask * src1p ,
const struct cpumask * src2p )
{
while ( ( n = cpumask_next ( n , src1p ) ) < nr_cpu_ids )
if ( cpumask_test_cpu ( n , src2p ) )
break ;
return n ;
}
EXPORT_SYMBOL ( cpumask_next_and ) ;
/**
* cpumask_any_but - return a " random " in a cpumask , but not this one .
* @ mask : the cpumask to search
* @ cpu : the cpu to ignore .
*
* Often used to find any cpu but smp_processor_id ( ) in a mask .
* Returns > = nr_cpu_ids if no cpus set .
*/
int cpumask_any_but ( const struct cpumask * mask , unsigned int cpu )
{
unsigned int i ;
2008-11-08 12:24:19 +03:00
cpumask_check ( cpu ) ;
2008-11-05 05:39:10 +03:00
for_each_cpu ( i , mask )
if ( i ! = cpu )
break ;
return i ;
}
/* These are not inline because of header tangles. */
# ifdef CONFIG_CPUMASK_OFFSTACK
2008-12-19 09:26:52 +03:00
/**
* alloc_cpumask_var_node - allocate a struct cpumask on a given node
* @ mask : pointer to cpumask_var_t where the cpumask is returned
* @ flags : GFP_ flags
*
* Only defined when CONFIG_CPUMASK_OFFSTACK = y , otherwise is
* a nop returning a constant 1 ( in < linux / cpumask . h > )
* Returns TRUE if memory allocation succeeded , FALSE otherwise .
*
* In addition , mask will be NULL if this fails . Note that gcc is
* usually smart enough to know that mask can never be NULL if
* CONFIG_CPUMASK_OFFSTACK = n , so does code elimination in that case
* too .
*/
2008-12-19 09:26:37 +03:00
bool alloc_cpumask_var_node ( cpumask_var_t * mask , gfp_t flags , int node )
2008-11-05 05:39:10 +03:00
{
2009-05-25 16:10:58 +04:00
* mask = kmalloc_node ( cpumask_size ( ) , flags , node ) ;
2008-11-05 05:39:10 +03:00
# ifdef CONFIG_DEBUG_PER_CPU_MAPS
if ( ! * mask ) {
printk ( KERN_ERR " => alloc_cpumask_var: failed! \n " ) ;
dump_stack ( ) ;
}
# endif
2009-01-01 02:42:30 +03:00
/* FIXME: Bandaid to save us from old primitives which go to NR_CPUS. */
if ( * mask ) {
2009-04-03 03:59:48 +04:00
unsigned char * ptr = ( unsigned char * ) cpumask_bits ( * mask ) ;
2009-01-01 02:42:30 +03:00
unsigned int tail ;
tail = BITS_TO_LONGS ( NR_CPUS - nr_cpumask_bits ) * sizeof ( long ) ;
2009-04-03 03:59:48 +04:00
memset ( ptr + cpumask_size ( ) - tail , 0 , tail ) ;
2009-01-01 02:42:30 +03:00
}
2008-11-05 05:39:10 +03:00
return * mask ! = NULL ;
}
2008-12-19 09:26:37 +03:00
EXPORT_SYMBOL ( alloc_cpumask_var_node ) ;
2009-06-07 01:50:36 +04:00
bool zalloc_cpumask_var_node ( cpumask_var_t * mask , gfp_t flags , int node )
{
return alloc_cpumask_var_node ( mask , flags | __GFP_ZERO , node ) ;
}
EXPORT_SYMBOL ( zalloc_cpumask_var_node ) ;
2008-12-19 09:26:52 +03:00
/**
* alloc_cpumask_var - allocate a struct cpumask
* @ mask : pointer to cpumask_var_t where the cpumask is returned
* @ flags : GFP_ flags
*
* Only defined when CONFIG_CPUMASK_OFFSTACK = y , otherwise is
* a nop returning a constant 1 ( in < linux / cpumask . h > ) .
*
* See alloc_cpumask_var_node .
*/
2008-12-19 09:26:37 +03:00
bool alloc_cpumask_var ( cpumask_var_t * mask , gfp_t flags )
{
return alloc_cpumask_var_node ( mask , flags , numa_node_id ( ) ) ;
}
2008-11-05 05:39:10 +03:00
EXPORT_SYMBOL ( alloc_cpumask_var ) ;
2009-06-07 01:50:36 +04:00
bool zalloc_cpumask_var ( cpumask_var_t * mask , gfp_t flags )
{
return alloc_cpumask_var ( mask , flags | __GFP_ZERO ) ;
}
EXPORT_SYMBOL ( zalloc_cpumask_var ) ;
2008-12-19 09:26:52 +03:00
/**
* alloc_bootmem_cpumask_var - allocate a struct cpumask from the bootmem arena .
* @ mask : pointer to cpumask_var_t where the cpumask is returned
*
* Only defined when CONFIG_CPUMASK_OFFSTACK = y , otherwise is
2008-12-31 11:45:50 +03:00
* a nop ( in < linux / cpumask . h > ) .
2008-12-19 09:26:52 +03:00
* Either returns an allocated ( zero - filled ) cpumask , or causes the
* system to panic .
*/
2008-11-05 05:39:10 +03:00
void __init alloc_bootmem_cpumask_var ( cpumask_var_t * mask )
{
* mask = alloc_bootmem ( cpumask_size ( ) ) ;
}
2008-12-19 09:26:52 +03:00
/**
* free_cpumask_var - frees memory allocated for a struct cpumask .
* @ mask : cpumask to free
*
* This is safe on a NULL mask .
*/
2008-11-05 05:39:10 +03:00
void free_cpumask_var ( cpumask_var_t mask )
{
kfree ( mask ) ;
}
EXPORT_SYMBOL ( free_cpumask_var ) ;
2008-11-07 03:12:29 +03:00
2008-12-19 09:26:52 +03:00
/**
* free_bootmem_cpumask_var - frees result of alloc_bootmem_cpumask_var
* @ mask : cpumask to free
*/
2008-11-08 12:24:19 +03:00
void __init free_bootmem_cpumask_var ( cpumask_var_t mask )
2008-11-07 03:12:29 +03:00
{
free_bootmem ( ( unsigned long ) mask , cpumask_size ( ) ) ;
}
2008-11-05 05:39:10 +03:00
# endif