Skip to content

Commit 2f96cb5

Browse files
committed
Merge branch 'sched-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'sched-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: sched: release buddies on yield fix for account_group_exec_runtime(), make sure ->signal can't be freed under rq->lock sched: clean up debug info
2 parents 09eb3b5 + 2002c69 commit 2f96cb5

File tree

5 files changed

+48
-26
lines changed

5 files changed

+48
-26
lines changed

include/linux/sched.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ extern void init_idle(struct task_struct *idle, int cpu);
247247
extern void init_idle_bootup_task(struct task_struct *idle);
248248

249249
extern int runqueue_is_locked(void);
250+
extern void task_rq_unlock_wait(struct task_struct *p);
250251

251252
extern cpumask_t nohz_cpu_mask;
252253
#if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ)

kernel/exit.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ static void __exit_signal(struct task_struct *tsk)
141141
if (sig) {
142142
flush_sigqueue(&sig->shared_pending);
143143
taskstats_tgid_free(sig);
144+
/*
145+
* Make sure ->signal can't go away under rq->lock,
146+
* see account_group_exec_runtime().
147+
*/
148+
task_rq_unlock_wait(tsk);
144149
__cleanup_signal(sig);
145150
}
146151
}

kernel/sched.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ struct cfs_rq {
399399
*/
400400
struct sched_entity *curr, *next, *last;
401401

402-
unsigned long nr_spread_over;
402+
unsigned int nr_spread_over;
403403

404404
#ifdef CONFIG_FAIR_GROUP_SCHED
405405
struct rq *rq; /* cpu runqueue to which this cfs_rq is attached */
@@ -969,6 +969,14 @@ static struct rq *task_rq_lock(struct task_struct *p, unsigned long *flags)
969969
}
970970
}
971971

972+
void task_rq_unlock_wait(struct task_struct *p)
973+
{
974+
struct rq *rq = task_rq(p);
975+
976+
smp_mb(); /* spin-unlock-wait is not a full memory barrier */
977+
spin_unlock_wait(&rq->lock);
978+
}
979+
972980
static void __task_rq_unlock(struct rq *rq)
973981
__releases(rq->lock)
974982
{

kernel/sched_debug.c

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
144144
last = __pick_last_entity(cfs_rq);
145145
if (last)
146146
max_vruntime = last->vruntime;
147-
min_vruntime = rq->cfs.min_vruntime;
147+
min_vruntime = cfs_rq->min_vruntime;
148148
rq0_min_vruntime = per_cpu(runqueues, 0).cfs.min_vruntime;
149149
spin_unlock_irqrestore(&rq->lock, flags);
150150
SEQ_printf(m, " .%-30s: %Ld.%06ld\n", "MIN_vruntime",
@@ -161,26 +161,8 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
161161
SPLIT_NS(spread0));
162162
SEQ_printf(m, " .%-30s: %ld\n", "nr_running", cfs_rq->nr_running);
163163
SEQ_printf(m, " .%-30s: %ld\n", "load", cfs_rq->load.weight);
164-
#ifdef CONFIG_SCHEDSTATS
165-
#define P(n) SEQ_printf(m, " .%-30s: %d\n", #n, rq->n);
166-
167-
P(yld_exp_empty);
168-
P(yld_act_empty);
169-
P(yld_both_empty);
170-
P(yld_count);
171164

172-
P(sched_switch);
173-
P(sched_count);
174-
P(sched_goidle);
175-
176-
P(ttwu_count);
177-
P(ttwu_local);
178-
179-
P(bkl_count);
180-
181-
#undef P
182-
#endif
183-
SEQ_printf(m, " .%-30s: %ld\n", "nr_spread_over",
165+
SEQ_printf(m, " .%-30s: %d\n", "nr_spread_over",
184166
cfs_rq->nr_spread_over);
185167
#ifdef CONFIG_FAIR_GROUP_SCHED
186168
#ifdef CONFIG_SMP
@@ -260,6 +242,25 @@ static void print_cpu(struct seq_file *m, int cpu)
260242
#undef P
261243
#undef PN
262244

245+
#ifdef CONFIG_SCHEDSTATS
246+
#define P(n) SEQ_printf(m, " .%-30s: %d\n", #n, rq->n);
247+
248+
P(yld_exp_empty);
249+
P(yld_act_empty);
250+
P(yld_both_empty);
251+
P(yld_count);
252+
253+
P(sched_switch);
254+
P(sched_count);
255+
P(sched_goidle);
256+
257+
P(ttwu_count);
258+
P(ttwu_local);
259+
260+
P(bkl_count);
261+
262+
#undef P
263+
#endif
263264
print_cfs_stats(m, cpu);
264265
print_rt_stats(m, cpu);
265266

kernel/sched_fair.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,15 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup)
716716
__enqueue_entity(cfs_rq, se);
717717
}
718718

719+
static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se)
720+
{
721+
if (cfs_rq->last == se)
722+
cfs_rq->last = NULL;
723+
724+
if (cfs_rq->next == se)
725+
cfs_rq->next = NULL;
726+
}
727+
719728
static void
720729
dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep)
721730
{
@@ -738,11 +747,7 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep)
738747
#endif
739748
}
740749

741-
if (cfs_rq->last == se)
742-
cfs_rq->last = NULL;
743-
744-
if (cfs_rq->next == se)
745-
cfs_rq->next = NULL;
750+
clear_buddies(cfs_rq, se);
746751

747752
if (se != cfs_rq->curr)
748753
__dequeue_entity(cfs_rq, se);
@@ -977,6 +982,8 @@ static void yield_task_fair(struct rq *rq)
977982
if (unlikely(cfs_rq->nr_running == 1))
978983
return;
979984

985+
clear_buddies(cfs_rq, se);
986+
980987
if (likely(!sysctl_sched_compat_yield) && curr->policy != SCHED_BATCH) {
981988
update_rq_clock(rq);
982989
/*

0 commit comments

Comments
 (0)