diff options
Diffstat (limited to 'kernel/sched/membarrier.c')
-rw-r--r-- | kernel/sched/membarrier.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/kernel/sched/membarrier.c b/kernel/sched/membarrier.c index a92fddc22747..dd7908743dab 100644 --- a/kernel/sched/membarrier.c +++ b/kernel/sched/membarrier.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/membarrier.h> | 18 | #include <linux/membarrier.h> |
19 | #include <linux/tick.h> | 19 | #include <linux/tick.h> |
20 | #include <linux/cpumask.h> | 20 | #include <linux/cpumask.h> |
21 | #include <linux/atomic.h> | ||
21 | 22 | ||
22 | #include "sched.h" /* for cpu_rq(). */ | 23 | #include "sched.h" /* for cpu_rq(). */ |
23 | 24 | ||
@@ -26,21 +27,26 @@ | |||
26 | * except MEMBARRIER_CMD_QUERY. | 27 | * except MEMBARRIER_CMD_QUERY. |
27 | */ | 28 | */ |
28 | #define MEMBARRIER_CMD_BITMASK \ | 29 | #define MEMBARRIER_CMD_BITMASK \ |
29 | (MEMBARRIER_CMD_SHARED | MEMBARRIER_CMD_PRIVATE_EXPEDITED) | 30 | (MEMBARRIER_CMD_SHARED | MEMBARRIER_CMD_PRIVATE_EXPEDITED \ |
31 | | MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED) | ||
30 | 32 | ||
31 | static void ipi_mb(void *info) | 33 | static void ipi_mb(void *info) |
32 | { | 34 | { |
33 | smp_mb(); /* IPIs should be serializing but paranoid. */ | 35 | smp_mb(); /* IPIs should be serializing but paranoid. */ |
34 | } | 36 | } |
35 | 37 | ||
36 | static void membarrier_private_expedited(void) | 38 | static int membarrier_private_expedited(void) |
37 | { | 39 | { |
38 | int cpu; | 40 | int cpu; |
39 | bool fallback = false; | 41 | bool fallback = false; |
40 | cpumask_var_t tmpmask; | 42 | cpumask_var_t tmpmask; |
41 | 43 | ||
44 | if (!(atomic_read(¤t->mm->membarrier_state) | ||
45 | & MEMBARRIER_STATE_PRIVATE_EXPEDITED_READY)) | ||
46 | return -EPERM; | ||
47 | |||
42 | if (num_online_cpus() == 1) | 48 | if (num_online_cpus() == 1) |
43 | return; | 49 | return 0; |
44 | 50 | ||
45 | /* | 51 | /* |
46 | * Matches memory barriers around rq->curr modification in | 52 | * Matches memory barriers around rq->curr modification in |
@@ -94,6 +100,24 @@ static void membarrier_private_expedited(void) | |||
94 | * rq->curr modification in scheduler. | 100 | * rq->curr modification in scheduler. |
95 | */ | 101 | */ |
96 | smp_mb(); /* exit from system call is not a mb */ | 102 | smp_mb(); /* exit from system call is not a mb */ |
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static void membarrier_register_private_expedited(void) | ||
107 | { | ||
108 | struct task_struct *p = current; | ||
109 | struct mm_struct *mm = p->mm; | ||
110 | |||
111 | /* | ||
112 | * We need to consider threads belonging to different thread | ||
113 | * groups, which use the same mm. (CLONE_VM but not | ||
114 | * CLONE_THREAD). | ||
115 | */ | ||
116 | if (atomic_read(&mm->membarrier_state) | ||
117 | & MEMBARRIER_STATE_PRIVATE_EXPEDITED_READY) | ||
118 | return; | ||
119 | atomic_or(MEMBARRIER_STATE_PRIVATE_EXPEDITED_READY, | ||
120 | &mm->membarrier_state); | ||
97 | } | 121 | } |
98 | 122 | ||
99 | /** | 123 | /** |
@@ -144,7 +168,9 @@ SYSCALL_DEFINE2(membarrier, int, cmd, int, flags) | |||
144 | synchronize_sched(); | 168 | synchronize_sched(); |
145 | return 0; | 169 | return 0; |
146 | case MEMBARRIER_CMD_PRIVATE_EXPEDITED: | 170 | case MEMBARRIER_CMD_PRIVATE_EXPEDITED: |
147 | membarrier_private_expedited(); | 171 | return membarrier_private_expedited(); |
172 | case MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED: | ||
173 | membarrier_register_private_expedited(); | ||
148 | return 0; | 174 | return 0; |
149 | default: | 175 | default: |
150 | return -EINVAL; | 176 | return -EINVAL; |