diff options
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/x86/include/asm/current.h | 2 | ||||
| -rw-r--r-- | arch/x86/include/asm/percpu.h | 26 | ||||
| -rw-r--r-- | arch/x86/include/asm/thread_info.h | 2 |
3 files changed, 21 insertions, 9 deletions
diff --git a/arch/x86/include/asm/current.h b/arch/x86/include/asm/current.h index c68c361697e1..4d447b732d82 100644 --- a/arch/x86/include/asm/current.h +++ b/arch/x86/include/asm/current.h | |||
| @@ -11,7 +11,7 @@ DECLARE_PER_CPU(struct task_struct *, current_task); | |||
| 11 | 11 | ||
| 12 | static __always_inline struct task_struct *get_current(void) | 12 | static __always_inline struct task_struct *get_current(void) |
| 13 | { | 13 | { |
| 14 | return percpu_read(current_task); | 14 | return percpu_read_stable(current_task); |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | #define current get_current() | 17 | #define current get_current() |
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 103f1ddb0d85..04eacefcfd26 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h | |||
| @@ -49,7 +49,7 @@ | |||
| 49 | #define __percpu_arg(x) "%%"__stringify(__percpu_seg)":%P" #x | 49 | #define __percpu_arg(x) "%%"__stringify(__percpu_seg)":%P" #x |
| 50 | #define __my_cpu_offset percpu_read(this_cpu_off) | 50 | #define __my_cpu_offset percpu_read(this_cpu_off) |
| 51 | #else | 51 | #else |
| 52 | #define __percpu_arg(x) "%" #x | 52 | #define __percpu_arg(x) "%P" #x |
| 53 | #endif | 53 | #endif |
| 54 | 54 | ||
| 55 | /* | 55 | /* |
| @@ -104,36 +104,48 @@ do { \ | |||
| 104 | } \ | 104 | } \ |
| 105 | } while (0) | 105 | } while (0) |
| 106 | 106 | ||
| 107 | #define percpu_from_op(op, var) \ | 107 | #define percpu_from_op(op, var, constraint) \ |
| 108 | ({ \ | 108 | ({ \ |
| 109 | typeof(var) ret__; \ | 109 | typeof(var) ret__; \ |
| 110 | switch (sizeof(var)) { \ | 110 | switch (sizeof(var)) { \ |
| 111 | case 1: \ | 111 | case 1: \ |
| 112 | asm(op "b "__percpu_arg(1)",%0" \ | 112 | asm(op "b "__percpu_arg(1)",%0" \ |
| 113 | : "=q" (ret__) \ | 113 | : "=q" (ret__) \ |
| 114 | : "m" (var)); \ | 114 | : constraint); \ |
| 115 | break; \ | 115 | break; \ |
| 116 | case 2: \ | 116 | case 2: \ |
| 117 | asm(op "w "__percpu_arg(1)",%0" \ | 117 | asm(op "w "__percpu_arg(1)",%0" \ |
| 118 | : "=r" (ret__) \ | 118 | : "=r" (ret__) \ |
| 119 | : "m" (var)); \ | 119 | : constraint); \ |
| 120 | break; \ | 120 | break; \ |
| 121 | case 4: \ | 121 | case 4: \ |
| 122 | asm(op "l "__percpu_arg(1)",%0" \ | 122 | asm(op "l "__percpu_arg(1)",%0" \ |
| 123 | : "=r" (ret__) \ | 123 | : "=r" (ret__) \ |
| 124 | : "m" (var)); \ | 124 | : constraint); \ |
| 125 | break; \ | 125 | break; \ |
| 126 | case 8: \ | 126 | case 8: \ |
| 127 | asm(op "q "__percpu_arg(1)",%0" \ | 127 | asm(op "q "__percpu_arg(1)",%0" \ |
| 128 | : "=r" (ret__) \ | 128 | : "=r" (ret__) \ |
| 129 | : "m" (var)); \ | 129 | : constraint); \ |
| 130 | break; \ | 130 | break; \ |
| 131 | default: __bad_percpu_size(); \ | 131 | default: __bad_percpu_size(); \ |
| 132 | } \ | 132 | } \ |
| 133 | ret__; \ | 133 | ret__; \ |
| 134 | }) | 134 | }) |
| 135 | 135 | ||
| 136 | #define percpu_read(var) percpu_from_op("mov", per_cpu__##var) | 136 | /* |
| 137 | * percpu_read() makes gcc load the percpu variable every time it is | ||
| 138 | * accessed while percpu_read_stable() allows the value to be cached. | ||
| 139 | * percpu_read_stable() is more efficient and can be used if its value | ||
| 140 | * is guaranteed to be valid across cpus. The current users include | ||
| 141 | * get_current() and get_thread_info() both of which are actually | ||
| 142 | * per-thread variables implemented as per-cpu variables and thus | ||
| 143 | * stable for the duration of the respective task. | ||
| 144 | */ | ||
| 145 | #define percpu_read(var) percpu_from_op("mov", per_cpu__##var, \ | ||
| 146 | "m" (per_cpu__##var)) | ||
| 147 | #define percpu_read_stable(var) percpu_from_op("mov", per_cpu__##var, \ | ||
| 148 | "p" (&per_cpu__##var)) | ||
| 137 | #define percpu_write(var, val) percpu_to_op("mov", per_cpu__##var, val) | 149 | #define percpu_write(var, val) percpu_to_op("mov", per_cpu__##var, val) |
| 138 | #define percpu_add(var, val) percpu_to_op("add", per_cpu__##var, val) | 150 | #define percpu_add(var, val) percpu_to_op("add", per_cpu__##var, val) |
| 139 | #define percpu_sub(var, val) percpu_to_op("sub", per_cpu__##var, val) | 151 | #define percpu_sub(var, val) percpu_to_op("sub", per_cpu__##var, val) |
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index fad7d40b75f8..a1bb5a114bf2 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h | |||
| @@ -213,7 +213,7 @@ DECLARE_PER_CPU(unsigned long, kernel_stack); | |||
| 213 | static inline struct thread_info *current_thread_info(void) | 213 | static inline struct thread_info *current_thread_info(void) |
| 214 | { | 214 | { |
| 215 | struct thread_info *ti; | 215 | struct thread_info *ti; |
| 216 | ti = (void *)(percpu_read(kernel_stack) + | 216 | ti = (void *)(percpu_read_stable(kernel_stack) + |
| 217 | KERNEL_STACK_OFFSET - THREAD_SIZE); | 217 | KERNEL_STACK_OFFSET - THREAD_SIZE); |
| 218 | return ti; | 218 | return ti; |
| 219 | } | 219 | } |
