percpu.h 4.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2
#ifndef __LINUX_PERCPU_H
#define __LINUX_PERCPU_H
3

4
#include <linux/preempt.h>
L
Linus Torvalds 已提交
5 6
#include <linux/slab.h> /* For kmalloc() */
#include <linux/smp.h>
7
#include <linux/cpumask.h>
T
Tejun Heo 已提交
8
#include <linux/pfn.h>
9

L
Linus Torvalds 已提交
10 11
#include <asm/percpu.h>

T
Tejun Heo 已提交
12
/* enough to cover all DEFINE_PER_CPUs in modules */
13
#ifdef CONFIG_MODULES
T
Tejun Heo 已提交
14
#define PERCPU_MODULE_RESERVE		(8 << 10)
15
#else
T
Tejun Heo 已提交
16
#define PERCPU_MODULE_RESERVE		0
L
Linus Torvalds 已提交
17 18
#endif

T
Tejun Heo 已提交
19
#ifndef PERCPU_ENOUGH_ROOM
20
#define PERCPU_ENOUGH_ROOM						\
T
Tejun Heo 已提交
21 22 23
	(ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES) +	\
	 PERCPU_MODULE_RESERVE)
#endif
24

25 26 27 28 29
/*
 * Must be an lvalue. Since @var must be a simple identifier,
 * we force a syntax error here if it isn't.
 */
#define get_cpu_var(var) (*({				\
30
	extern int simple_identifier_##var(void);	\
31 32
	preempt_disable();				\
	&__get_cpu_var(var); }))
L
Linus Torvalds 已提交
33 34 35 36
#define put_cpu_var(var) preempt_enable()

#ifdef CONFIG_SMP

37
#ifdef CONFIG_HAVE_DYNAMIC_PER_CPU_AREA
L
Linus Torvalds 已提交
38

39
/* minimum unit size, also is the maximum supported allocation size */
T
Tejun Heo 已提交
40
#define PCPU_MIN_UNIT_SIZE		PFN_ALIGN(64 << 10)
41 42 43

/*
 * PERCPU_DYNAMIC_RESERVE indicates the amount of free area to piggy
44 45 46
 * back on the first chunk for dynamic percpu allocation if arch is
 * manually allocating and mapping it for faster access (as a part of
 * large page mapping for example).
47
 *
48 49 50 51
 * The following values give between one and two pages of free space
 * after typical minimal boot (2-way SMP, single disk and NIC) with
 * both defconfig and a distro config on x86_64 and 32.  More
 * intelligent way to determine this would be nice.
52
 */
53 54 55 56 57
#if BITS_PER_LONG > 32
#define PERCPU_DYNAMIC_RESERVE		(20 << 10)
#else
#define PERCPU_DYNAMIC_RESERVE		(12 << 10)
#endif
58

59
extern void *pcpu_base_addr;
L
Linus Torvalds 已提交
60

61
typedef struct page * (*pcpu_get_page_fn_t)(unsigned int cpu, int pageno);
62 63
typedef void (*pcpu_populate_pte_fn_t)(unsigned long addr);

64
extern size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn,
65
				size_t static_size, size_t reserved_size,
66
				ssize_t dyn_size, ssize_t unit_size,
67 68
				void *base_addr,
				pcpu_populate_pte_fn_t populate_pte_fn);
69

70 71 72 73
extern ssize_t __init pcpu_embed_first_chunk(
				size_t static_size, size_t reserved_size,
				ssize_t dyn_size, ssize_t unit_size);

74 75 76 77 78
/*
 * Use this to get to a cpu's version of the per-cpu object
 * dynamically allocated. Non-atomic access to the current CPU's
 * version should probably be combined with get_cpu()/put_cpu().
 */
79 80
#define per_cpu_ptr(ptr, cpu)	SHIFT_PERCPU_PTR((ptr), per_cpu_offset((cpu)))

81 82
extern void *__alloc_reserved_percpu(size_t size, size_t align);

83 84 85 86 87 88 89 90
#else /* CONFIG_HAVE_DYNAMIC_PER_CPU_AREA */

struct percpu_data {
	void *ptrs[1];
};

#define __percpu_disguise(pdata) (struct percpu_data *)~(unsigned long)(pdata)

91 92 93 94 95 96
#define per_cpu_ptr(ptr, cpu)						\
({									\
        struct percpu_data *__p = __percpu_disguise(ptr);		\
        (__typeof__(ptr))__p->ptrs[(cpu)];				\
})

97 98
#endif /* CONFIG_HAVE_DYNAMIC_PER_CPU_AREA */

99 100
extern void *__alloc_percpu(size_t size, size_t align);
extern void free_percpu(void *__pdata);
L
Linus Torvalds 已提交
101 102 103

#else /* CONFIG_SMP */

104
#define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); })
105

106
static inline void *__alloc_percpu(size_t size, size_t align)
107
{
108 109 110 111 112
	/*
	 * Can't easily make larger alignment work with kmalloc.  WARN
	 * on it.  Larger alignment should only be used for module
	 * percpu sections on SMP for which this path isn't used.
	 */
113
	WARN_ON_ONCE(align > SMP_CACHE_BYTES);
I
Ingo Molnar 已提交
114
	return kzalloc(size, GFP_KERNEL);
115 116
}

117
static inline void free_percpu(void *p)
118
{
119
	kfree(p);
L
Linus Torvalds 已提交
120 121 122 123
}

#endif /* CONFIG_SMP */

124 125
#define alloc_percpu(type)	(type *)__alloc_percpu(sizeof(type), \
						       __alignof__(type))
L
Linus Torvalds 已提交
126

T
Tejun Heo 已提交
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
/*
 * Optional methods for optimized non-lvalue per-cpu variable access.
 *
 * @var can be a percpu variable or a field of it and its size should
 * equal char, int or long.  percpu_read() evaluates to a lvalue and
 * all others to void.
 *
 * These operations are guaranteed to be atomic w.r.t. preemption.
 * The generic versions use plain get/put_cpu_var().  Archs are
 * encouraged to implement single-instruction alternatives which don't
 * require preemption protection.
 */
#ifndef percpu_read
# define percpu_read(var)						\
  ({									\
	typeof(per_cpu_var(var)) __tmp_var__;				\
	__tmp_var__ = get_cpu_var(var);					\
	put_cpu_var(var);						\
	__tmp_var__;							\
  })
#endif

#define __percpu_generic_to_op(var, val, op)				\
do {									\
	get_cpu_var(var) op val;					\
	put_cpu_var(var);						\
} while (0)

#ifndef percpu_write
# define percpu_write(var, val)		__percpu_generic_to_op(var, (val), =)
#endif

#ifndef percpu_add
# define percpu_add(var, val)		__percpu_generic_to_op(var, (val), +=)
#endif

#ifndef percpu_sub
# define percpu_sub(var, val)		__percpu_generic_to_op(var, (val), -=)
#endif

#ifndef percpu_and
# define percpu_and(var, val)		__percpu_generic_to_op(var, (val), &=)
#endif

#ifndef percpu_or
# define percpu_or(var, val)		__percpu_generic_to_op(var, (val), |=)
#endif

#ifndef percpu_xor
# define percpu_xor(var, val)		__percpu_generic_to_op(var, (val), ^=)
#endif

L
Linus Torvalds 已提交
179
#endif /* __LINUX_PERCPU_H */