diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/cpuset.h | 47 | ||||
-rw-r--r-- | include/linux/init_task.h | 8 | ||||
-rw-r--r-- | include/linux/sched.h | 2 |
3 files changed, 29 insertions, 28 deletions
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h index e9eaec522655..7a7e5fd2a277 100644 --- a/include/linux/cpuset.h +++ b/include/linux/cpuset.h | |||
@@ -89,42 +89,33 @@ extern void rebuild_sched_domains(void); | |||
89 | extern void cpuset_print_task_mems_allowed(struct task_struct *p); | 89 | extern void cpuset_print_task_mems_allowed(struct task_struct *p); |
90 | 90 | ||
91 | /* | 91 | /* |
92 | * reading current mems_allowed and mempolicy in the fastpath must protected | 92 | * get_mems_allowed is required when making decisions involving mems_allowed |
93 | * by get_mems_allowed() | 93 | * such as during page allocation. mems_allowed can be updated in parallel |
94 | * and depending on the new value an operation can fail potentially causing | ||
95 | * process failure. A retry loop with get_mems_allowed and put_mems_allowed | ||
96 | * prevents these artificial failures. | ||
94 | */ | 97 | */ |
95 | static inline void get_mems_allowed(void) | 98 | static inline unsigned int get_mems_allowed(void) |
96 | { | 99 | { |
97 | current->mems_allowed_change_disable++; | 100 | return read_seqcount_begin(¤t->mems_allowed_seq); |
98 | |||
99 | /* | ||
100 | * ensure that reading mems_allowed and mempolicy happens after the | ||
101 | * update of ->mems_allowed_change_disable. | ||
102 | * | ||
103 | * the write-side task finds ->mems_allowed_change_disable is not 0, | ||
104 | * and knows the read-side task is reading mems_allowed or mempolicy, | ||
105 | * so it will clear old bits lazily. | ||
106 | */ | ||
107 | smp_mb(); | ||
108 | } | 101 | } |
109 | 102 | ||
110 | static inline void put_mems_allowed(void) | 103 | /* |
104 | * If this returns false, the operation that took place after get_mems_allowed | ||
105 | * may have failed. It is up to the caller to retry the operation if | ||
106 | * appropriate. | ||
107 | */ | ||
108 | static inline bool put_mems_allowed(unsigned int seq) | ||
111 | { | 109 | { |
112 | /* | 110 | return !read_seqcount_retry(¤t->mems_allowed_seq, seq); |
113 | * ensure that reading mems_allowed and mempolicy before reducing | ||
114 | * mems_allowed_change_disable. | ||
115 | * | ||
116 | * the write-side task will know that the read-side task is still | ||
117 | * reading mems_allowed or mempolicy, don't clears old bits in the | ||
118 | * nodemask. | ||
119 | */ | ||
120 | smp_mb(); | ||
121 | --ACCESS_ONCE(current->mems_allowed_change_disable); | ||
122 | } | 111 | } |
123 | 112 | ||
124 | static inline void set_mems_allowed(nodemask_t nodemask) | 113 | static inline void set_mems_allowed(nodemask_t nodemask) |
125 | { | 114 | { |
126 | task_lock(current); | 115 | task_lock(current); |
116 | write_seqcount_begin(¤t->mems_allowed_seq); | ||
127 | current->mems_allowed = nodemask; | 117 | current->mems_allowed = nodemask; |
118 | write_seqcount_end(¤t->mems_allowed_seq); | ||
128 | task_unlock(current); | 119 | task_unlock(current); |
129 | } | 120 | } |
130 | 121 | ||
@@ -234,12 +225,14 @@ static inline void set_mems_allowed(nodemask_t nodemask) | |||
234 | { | 225 | { |
235 | } | 226 | } |
236 | 227 | ||
237 | static inline void get_mems_allowed(void) | 228 | static inline unsigned int get_mems_allowed(void) |
238 | { | 229 | { |
230 | return 0; | ||
239 | } | 231 | } |
240 | 232 | ||
241 | static inline void put_mems_allowed(void) | 233 | static inline bool put_mems_allowed(unsigned int seq) |
242 | { | 234 | { |
235 | return true; | ||
243 | } | 236 | } |
244 | 237 | ||
245 | #endif /* !CONFIG_CPUSETS */ | 238 | #endif /* !CONFIG_CPUSETS */ |
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index f994d51f70f2..e4baff5f7ff4 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
@@ -29,6 +29,13 @@ extern struct fs_struct init_fs; | |||
29 | #define INIT_GROUP_RWSEM(sig) | 29 | #define INIT_GROUP_RWSEM(sig) |
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | #ifdef CONFIG_CPUSETS | ||
33 | #define INIT_CPUSET_SEQ \ | ||
34 | .mems_allowed_seq = SEQCNT_ZERO, | ||
35 | #else | ||
36 | #define INIT_CPUSET_SEQ | ||
37 | #endif | ||
38 | |||
32 | #define INIT_SIGNALS(sig) { \ | 39 | #define INIT_SIGNALS(sig) { \ |
33 | .nr_threads = 1, \ | 40 | .nr_threads = 1, \ |
34 | .wait_chldexit = __WAIT_QUEUE_HEAD_INITIALIZER(sig.wait_chldexit),\ | 41 | .wait_chldexit = __WAIT_QUEUE_HEAD_INITIALIZER(sig.wait_chldexit),\ |
@@ -192,6 +199,7 @@ extern struct cred init_cred; | |||
192 | INIT_FTRACE_GRAPH \ | 199 | INIT_FTRACE_GRAPH \ |
193 | INIT_TRACE_RECURSION \ | 200 | INIT_TRACE_RECURSION \ |
194 | INIT_TASK_RCU_PREEMPT(tsk) \ | 201 | INIT_TASK_RCU_PREEMPT(tsk) \ |
202 | INIT_CPUSET_SEQ \ | ||
195 | } | 203 | } |
196 | 204 | ||
197 | 205 | ||
diff --git a/include/linux/sched.h b/include/linux/sched.h index e074e1e54f85..0c147a4260a5 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1514,7 +1514,7 @@ struct task_struct { | |||
1514 | #endif | 1514 | #endif |
1515 | #ifdef CONFIG_CPUSETS | 1515 | #ifdef CONFIG_CPUSETS |
1516 | nodemask_t mems_allowed; /* Protected by alloc_lock */ | 1516 | nodemask_t mems_allowed; /* Protected by alloc_lock */ |
1517 | int mems_allowed_change_disable; | 1517 | seqcount_t mems_allowed_seq; /* Seqence no to catch updates */ |
1518 | int cpuset_mem_spread_rotor; | 1518 | int cpuset_mem_spread_rotor; |
1519 | int cpuset_slab_spread_rotor; | 1519 | int cpuset_slab_spread_rotor; |
1520 | #endif | 1520 | #endif |