diff options
Diffstat (limited to 'kernel/sched_cpupri.c')
-rw-r--r-- | kernel/sched_cpupri.c | 45 |
1 files changed, 30 insertions, 15 deletions
diff --git a/kernel/sched_cpupri.c b/kernel/sched_cpupri.c index e6c251790dde..0f052fc674d5 100644 --- a/kernel/sched_cpupri.c +++ b/kernel/sched_cpupri.c | |||
@@ -81,8 +81,21 @@ int cpupri_find(struct cpupri *cp, struct task_struct *p, | |||
81 | if (cpumask_any_and(&p->cpus_allowed, vec->mask) >= nr_cpu_ids) | 81 | if (cpumask_any_and(&p->cpus_allowed, vec->mask) >= nr_cpu_ids) |
82 | continue; | 82 | continue; |
83 | 83 | ||
84 | if (lowest_mask) | 84 | if (lowest_mask) { |
85 | cpumask_and(lowest_mask, &p->cpus_allowed, vec->mask); | 85 | cpumask_and(lowest_mask, &p->cpus_allowed, vec->mask); |
86 | |||
87 | /* | ||
88 | * We have to ensure that we have at least one bit | ||
89 | * still set in the array, since the map could have | ||
90 | * been concurrently emptied between the first and | ||
91 | * second reads of vec->mask. If we hit this | ||
92 | * condition, simply act as though we never hit this | ||
93 | * priority level and continue on. | ||
94 | */ | ||
95 | if (cpumask_any(lowest_mask) >= nr_cpu_ids) | ||
96 | continue; | ||
97 | } | ||
98 | |||
86 | return 1; | 99 | return 1; |
87 | } | 100 | } |
88 | 101 | ||
@@ -114,21 +127,11 @@ void cpupri_set(struct cpupri *cp, int cpu, int newpri) | |||
114 | 127 | ||
115 | /* | 128 | /* |
116 | * If the cpu was currently mapped to a different value, we | 129 | * If the cpu was currently mapped to a different value, we |
117 | * first need to unmap the old value | 130 | * need to map it to the new value then remove the old value. |
131 | * Note, we must add the new value first, otherwise we risk the | ||
132 | * cpu being cleared from pri_active, and this cpu could be | ||
133 | * missed for a push or pull. | ||
118 | */ | 134 | */ |
119 | if (likely(oldpri != CPUPRI_INVALID)) { | ||
120 | struct cpupri_vec *vec = &cp->pri_to_cpu[oldpri]; | ||
121 | |||
122 | spin_lock_irqsave(&vec->lock, flags); | ||
123 | |||
124 | vec->count--; | ||
125 | if (!vec->count) | ||
126 | clear_bit(oldpri, cp->pri_active); | ||
127 | cpumask_clear_cpu(cpu, vec->mask); | ||
128 | |||
129 | spin_unlock_irqrestore(&vec->lock, flags); | ||
130 | } | ||
131 | |||
132 | if (likely(newpri != CPUPRI_INVALID)) { | 135 | if (likely(newpri != CPUPRI_INVALID)) { |
133 | struct cpupri_vec *vec = &cp->pri_to_cpu[newpri]; | 136 | struct cpupri_vec *vec = &cp->pri_to_cpu[newpri]; |
134 | 137 | ||
@@ -141,6 +144,18 @@ void cpupri_set(struct cpupri *cp, int cpu, int newpri) | |||
141 | 144 | ||
142 | spin_unlock_irqrestore(&vec->lock, flags); | 145 | spin_unlock_irqrestore(&vec->lock, flags); |
143 | } | 146 | } |
147 | if (likely(oldpri != CPUPRI_INVALID)) { | ||
148 | struct cpupri_vec *vec = &cp->pri_to_cpu[oldpri]; | ||
149 | |||
150 | spin_lock_irqsave(&vec->lock, flags); | ||
151 | |||
152 | vec->count--; | ||
153 | if (!vec->count) | ||
154 | clear_bit(oldpri, cp->pri_active); | ||
155 | cpumask_clear_cpu(cpu, vec->mask); | ||
156 | |||
157 | spin_unlock_irqrestore(&vec->lock, flags); | ||
158 | } | ||
144 | 159 | ||
145 | *currpri = newpri; | 160 | *currpri = newpri; |
146 | } | 161 | } |