diff options
Diffstat (limited to 'kernel/cpuset.c')
-rw-r--r-- | kernel/cpuset.c | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 9fe58c46a426..0b1712dba587 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
@@ -123,6 +123,19 @@ static inline struct cpuset *task_cs(struct task_struct *task) | |||
123 | struct cpuset, css); | 123 | struct cpuset, css); |
124 | } | 124 | } |
125 | 125 | ||
126 | #ifdef CONFIG_NUMA | ||
127 | static inline bool task_has_mempolicy(struct task_struct *task) | ||
128 | { | ||
129 | return task->mempolicy; | ||
130 | } | ||
131 | #else | ||
132 | static inline bool task_has_mempolicy(struct task_struct *task) | ||
133 | { | ||
134 | return false; | ||
135 | } | ||
136 | #endif | ||
137 | |||
138 | |||
126 | /* bits in struct cpuset flags field */ | 139 | /* bits in struct cpuset flags field */ |
127 | typedef enum { | 140 | typedef enum { |
128 | CS_CPU_EXCLUSIVE, | 141 | CS_CPU_EXCLUSIVE, |
@@ -949,7 +962,7 @@ static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from, | |||
949 | static void cpuset_change_task_nodemask(struct task_struct *tsk, | 962 | static void cpuset_change_task_nodemask(struct task_struct *tsk, |
950 | nodemask_t *newmems) | 963 | nodemask_t *newmems) |
951 | { | 964 | { |
952 | bool masks_disjoint = !nodes_intersects(*newmems, tsk->mems_allowed); | 965 | bool need_loop; |
953 | 966 | ||
954 | repeat: | 967 | repeat: |
955 | /* | 968 | /* |
@@ -962,6 +975,14 @@ repeat: | |||
962 | return; | 975 | return; |
963 | 976 | ||
964 | task_lock(tsk); | 977 | task_lock(tsk); |
978 | /* | ||
979 | * Determine if a loop is necessary if another thread is doing | ||
980 | * get_mems_allowed(). If at least one node remains unchanged and | ||
981 | * tsk does not have a mempolicy, then an empty nodemask will not be | ||
982 | * possible when mems_allowed is larger than a word. | ||
983 | */ | ||
984 | need_loop = task_has_mempolicy(tsk) || | ||
985 | !nodes_intersects(*newmems, tsk->mems_allowed); | ||
965 | nodes_or(tsk->mems_allowed, tsk->mems_allowed, *newmems); | 986 | nodes_or(tsk->mems_allowed, tsk->mems_allowed, *newmems); |
966 | mpol_rebind_task(tsk, newmems, MPOL_REBIND_STEP1); | 987 | mpol_rebind_task(tsk, newmems, MPOL_REBIND_STEP1); |
967 | 988 | ||
@@ -981,11 +1002,9 @@ repeat: | |||
981 | 1002 | ||
982 | /* | 1003 | /* |
983 | * Allocation of memory is very fast, we needn't sleep when waiting | 1004 | * Allocation of memory is very fast, we needn't sleep when waiting |
984 | * for the read-side. No wait is necessary, however, if at least one | 1005 | * for the read-side. |
985 | * node remains unchanged. | ||
986 | */ | 1006 | */ |
987 | while (masks_disjoint && | 1007 | while (need_loop && ACCESS_ONCE(tsk->mems_allowed_change_disable)) { |
988 | ACCESS_ONCE(tsk->mems_allowed_change_disable)) { | ||
989 | task_unlock(tsk); | 1008 | task_unlock(tsk); |
990 | if (!task_curr(tsk)) | 1009 | if (!task_curr(tsk)) |
991 | yield(); | 1010 | yield(); |