diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/exit.c | 5 | ||||
-rw-r--r-- | kernel/sched.c | 10 | ||||
-rw-r--r-- | kernel/sched_debug.c | 41 | ||||
-rw-r--r-- | kernel/sched_fair.c | 17 | ||||
-rw-r--r-- | kernel/trace/ring_buffer.c | 2 | ||||
-rw-r--r-- | kernel/trace/trace.c | 19 |
6 files changed, 65 insertions, 29 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 80137a5d9467..ae2b92be5fae 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -141,6 +141,11 @@ static void __exit_signal(struct task_struct *tsk) | |||
141 | if (sig) { | 141 | if (sig) { |
142 | flush_sigqueue(&sig->shared_pending); | 142 | flush_sigqueue(&sig->shared_pending); |
143 | taskstats_tgid_free(sig); | 143 | 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); | ||
144 | __cleanup_signal(sig); | 149 | __cleanup_signal(sig); |
145 | } | 150 | } |
146 | } | 151 | } |
diff --git a/kernel/sched.c b/kernel/sched.c index 57c933ffbee1..50a21f964679 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -399,7 +399,7 @@ struct cfs_rq { | |||
399 | */ | 399 | */ |
400 | struct sched_entity *curr, *next, *last; | 400 | struct sched_entity *curr, *next, *last; |
401 | 401 | ||
402 | unsigned long nr_spread_over; | 402 | unsigned int nr_spread_over; |
403 | 403 | ||
404 | #ifdef CONFIG_FAIR_GROUP_SCHED | 404 | #ifdef CONFIG_FAIR_GROUP_SCHED |
405 | struct rq *rq; /* cpu runqueue to which this cfs_rq is attached */ | 405 | 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) | |||
969 | } | 969 | } |
970 | } | 970 | } |
971 | 971 | ||
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 | |||
972 | static void __task_rq_unlock(struct rq *rq) | 980 | static void __task_rq_unlock(struct rq *rq) |
973 | __releases(rq->lock) | 981 | __releases(rq->lock) |
974 | { | 982 | { |
diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c index 5ae17762ec32..48ecc51e7701 100644 --- a/kernel/sched_debug.c +++ b/kernel/sched_debug.c | |||
@@ -144,7 +144,7 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) | |||
144 | last = __pick_last_entity(cfs_rq); | 144 | last = __pick_last_entity(cfs_rq); |
145 | if (last) | 145 | if (last) |
146 | max_vruntime = last->vruntime; | 146 | max_vruntime = last->vruntime; |
147 | min_vruntime = rq->cfs.min_vruntime; | 147 | min_vruntime = cfs_rq->min_vruntime; |
148 | rq0_min_vruntime = per_cpu(runqueues, 0).cfs.min_vruntime; | 148 | rq0_min_vruntime = per_cpu(runqueues, 0).cfs.min_vruntime; |
149 | spin_unlock_irqrestore(&rq->lock, flags); | 149 | spin_unlock_irqrestore(&rq->lock, flags); |
150 | SEQ_printf(m, " .%-30s: %Ld.%06ld\n", "MIN_vruntime", | 150 | 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) | |||
161 | SPLIT_NS(spread0)); | 161 | SPLIT_NS(spread0)); |
162 | SEQ_printf(m, " .%-30s: %ld\n", "nr_running", cfs_rq->nr_running); | 162 | SEQ_printf(m, " .%-30s: %ld\n", "nr_running", cfs_rq->nr_running); |
163 | SEQ_printf(m, " .%-30s: %ld\n", "load", cfs_rq->load.weight); | 163 | 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); | ||
171 | 164 | ||
172 | P(sched_switch); | 165 | SEQ_printf(m, " .%-30s: %d\n", "nr_spread_over", |
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", | ||
184 | cfs_rq->nr_spread_over); | 166 | cfs_rq->nr_spread_over); |
185 | #ifdef CONFIG_FAIR_GROUP_SCHED | 167 | #ifdef CONFIG_FAIR_GROUP_SCHED |
186 | #ifdef CONFIG_SMP | 168 | #ifdef CONFIG_SMP |
@@ -260,6 +242,25 @@ static void print_cpu(struct seq_file *m, int cpu) | |||
260 | #undef P | 242 | #undef P |
261 | #undef PN | 243 | #undef PN |
262 | 244 | ||
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 | ||
263 | print_cfs_stats(m, cpu); | 264 | print_cfs_stats(m, cpu); |
264 | print_rt_stats(m, cpu); | 265 | print_rt_stats(m, cpu); |
265 | 266 | ||
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 51aa3e102acb..98345e45b059 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c | |||
@@ -716,6 +716,15 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup) | |||
716 | __enqueue_entity(cfs_rq, se); | 716 | __enqueue_entity(cfs_rq, se); |
717 | } | 717 | } |
718 | 718 | ||
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 | |||
719 | static void | 728 | static void |
720 | dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) | 729 | dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) |
721 | { | 730 | { |
@@ -738,11 +747,7 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) | |||
738 | #endif | 747 | #endif |
739 | } | 748 | } |
740 | 749 | ||
741 | if (cfs_rq->last == se) | 750 | clear_buddies(cfs_rq, se); |
742 | cfs_rq->last = NULL; | ||
743 | |||
744 | if (cfs_rq->next == se) | ||
745 | cfs_rq->next = NULL; | ||
746 | 751 | ||
747 | if (se != cfs_rq->curr) | 752 | if (se != cfs_rq->curr) |
748 | __dequeue_entity(cfs_rq, se); | 753 | __dequeue_entity(cfs_rq, se); |
@@ -977,6 +982,8 @@ static void yield_task_fair(struct rq *rq) | |||
977 | if (unlikely(cfs_rq->nr_running == 1)) | 982 | if (unlikely(cfs_rq->nr_running == 1)) |
978 | return; | 983 | return; |
979 | 984 | ||
985 | clear_buddies(cfs_rq, se); | ||
986 | |||
980 | if (likely(!sysctl_sched_compat_yield) && curr->policy != SCHED_BATCH) { | 987 | if (likely(!sysctl_sched_compat_yield) && curr->policy != SCHED_BATCH) { |
981 | update_rq_clock(rq); | 988 | update_rq_clock(rq); |
982 | /* | 989 | /* |
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 3f3380638646..2f76193c3489 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
@@ -1060,7 +1060,7 @@ rb_reserve_next_event(struct ring_buffer_per_cpu *cpu_buffer, | |||
1060 | 1060 | ||
1061 | /* Did the write stamp get updated already? */ | 1061 | /* Did the write stamp get updated already? */ |
1062 | if (unlikely(ts < cpu_buffer->write_stamp)) | 1062 | if (unlikely(ts < cpu_buffer->write_stamp)) |
1063 | goto again; | 1063 | delta = 0; |
1064 | 1064 | ||
1065 | if (test_time_stamp(delta)) { | 1065 | if (test_time_stamp(delta)) { |
1066 | 1066 | ||
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 9f3b478f9171..697eda36b86a 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -1755,7 +1755,7 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter) | |||
1755 | return TRACE_TYPE_HANDLED; | 1755 | return TRACE_TYPE_HANDLED; |
1756 | 1756 | ||
1757 | SEQ_PUT_FIELD_RET(s, entry->pid); | 1757 | SEQ_PUT_FIELD_RET(s, entry->pid); |
1758 | SEQ_PUT_FIELD_RET(s, iter->cpu); | 1758 | SEQ_PUT_FIELD_RET(s, entry->cpu); |
1759 | SEQ_PUT_FIELD_RET(s, iter->ts); | 1759 | SEQ_PUT_FIELD_RET(s, iter->ts); |
1760 | 1760 | ||
1761 | switch (entry->type) { | 1761 | switch (entry->type) { |
@@ -2676,7 +2676,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
2676 | { | 2676 | { |
2677 | unsigned long val; | 2677 | unsigned long val; |
2678 | char buf[64]; | 2678 | char buf[64]; |
2679 | int ret; | 2679 | int ret, cpu; |
2680 | struct trace_array *tr = filp->private_data; | 2680 | struct trace_array *tr = filp->private_data; |
2681 | 2681 | ||
2682 | if (cnt >= sizeof(buf)) | 2682 | if (cnt >= sizeof(buf)) |
@@ -2704,6 +2704,14 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
2704 | goto out; | 2704 | goto out; |
2705 | } | 2705 | } |
2706 | 2706 | ||
2707 | /* disable all cpu buffers */ | ||
2708 | for_each_tracing_cpu(cpu) { | ||
2709 | if (global_trace.data[cpu]) | ||
2710 | atomic_inc(&global_trace.data[cpu]->disabled); | ||
2711 | if (max_tr.data[cpu]) | ||
2712 | atomic_inc(&max_tr.data[cpu]->disabled); | ||
2713 | } | ||
2714 | |||
2707 | if (val != global_trace.entries) { | 2715 | if (val != global_trace.entries) { |
2708 | ret = ring_buffer_resize(global_trace.buffer, val); | 2716 | ret = ring_buffer_resize(global_trace.buffer, val); |
2709 | if (ret < 0) { | 2717 | if (ret < 0) { |
@@ -2735,6 +2743,13 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
2735 | if (tracing_disabled) | 2743 | if (tracing_disabled) |
2736 | cnt = -ENOMEM; | 2744 | cnt = -ENOMEM; |
2737 | out: | 2745 | out: |
2746 | for_each_tracing_cpu(cpu) { | ||
2747 | if (global_trace.data[cpu]) | ||
2748 | atomic_dec(&global_trace.data[cpu]->disabled); | ||
2749 | if (max_tr.data[cpu]) | ||
2750 | atomic_dec(&max_tr.data[cpu]->disabled); | ||
2751 | } | ||
2752 | |||
2738 | max_tr.entries = global_trace.entries; | 2753 | max_tr.entries = global_trace.entries; |
2739 | mutex_unlock(&trace_types_lock); | 2754 | mutex_unlock(&trace_types_lock); |
2740 | 2755 | ||