lockde,sched: Better pinning
Subsystems (2)
Peter Zijlstra
maintainercover lockde,sched: Better pinning
I've been sitting on these patches for a long while and finally got around to finishing them.
They implement a better pinning, as requested by Ingo. I'm not entirely sure I like what 2/3 does, but it does avoid extra code bloat, where all other attempts resulted in changed code for !lockdep.
Peter Zijlstra
maintainerPATCH 1/3 sched: Out-of-line task_rq_lock()
Its a rather large function, inline doesn't seems to make much sense.
$ size defconfig-build/kernel/sched/core.o{.orig,}
text data bss dec hex filename
56533 21037 2320 79890 13812 defconfig-build/kernel/sched/core.o.orig
55733 21037 2320 79090 134f2 defconfig-build/kernel/sched/core.o$ for i in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor ; do echo performance > $i ; done $ perf stat --null --repeat 25 -- perf bench sched messaging -g 40 -l 5000
pre:
4.582798193 seconds time elapsed ( +- 1.41% )
4.733374877 seconds time elapsed ( +- 2.10% )
4.560955136 seconds time elapsed ( +- 1.43% )
4.631062303 seconds time elapsed ( +- 1.40% )post:
4.364765213 seconds time elapsed ( +- 0.91% )
4.454442734 seconds time elapsed ( +- 1.18% )
4.448893817 seconds time elapsed ( +- 1.41% )
4.424346872 seconds time elapsed ( +- 0.97% )---
kernel/sched/core.c +65 -0
@@ -170,6 +170,71 @@ static struct rq *this_rq_lock(void)return rq; } +/* +* __task_rq_lock - lock the rq @p resides on. +*/ +struct rq *__task_rq_lock (struct task_struct *p) + __acquires(rq->lock) +{ +struct rq *rq; + +lockdep_assert_held (&p->pi_lock); + +for (;;) { + rq =task_rq (p); +raw_spin_lock (&rq->lock); +if (likely (rq ==task_rq (p) && !task_on_rq_migrating (p))) { +lockdep_pin_lock (&rq->lock); +return rq; + } +raw_spin_unlock (&rq->lock); + +while (unlikely (task_on_rq_migrating (p))) +cpu_relax (); + } +} + +/* +* task_rq_lock - lock p->pi_lock and lock the rq @p resides on. +*/ +struct rq *task_rq_lock (struct task_struct *p,unsigned long *flags) + __acquires(p->pi_lock) + __acquires(rq->lock) +{ +struct rq *rq; + +for (;;) { +raw_spin_lock_irqsave (&p->pi_lock, *flags); + rq =task_rq (p); +raw_spin_lock (&rq->lock); +/* +* move_queued_task() task_rq_lock() +* +* ACQUIRE (rq->lock) +* [S] ->on_rq = MIGRATING [L] rq = task_rq() +* WMB (__set_task_cpu()) ACQUIRE (rq->lock); +* [S] ->cpu = new_cpu [L] task_rq() +* [L] ->on_rq +* RELEASE (rq->lock) +* +* If we observe the old cpu in task_rq_lock, the acquire of +* the old rq->lock will fully serialize against the stores. +* +* If we observe the new cpu in task_rq_lock, the acquire will +* pair with the WMB to ensure we must then also see migrating. +*/ +if (likely (rq ==task_rq (p) && !task_on_rq_migrating (p))) { +lockdep_pin_lock (&rq->lock); +return rq; + } +raw_spin_unlock (&rq->lock); +raw_spin_unlock_irqrestore (&p->pi_lock, *flags); + +while (unlikely (task_on_rq_migrating (p))) +cpu_relax (); + } +} +#ifdef CONFIG_SCHED_HRTICK /* * Use HR-timers to deliver accurate preemption points.
kernel/sched/sched.h +4 -63
74 lines not on this page · raw message
Peter Zijlstra
maintainerPATCH 2/3 sched: Introduce struct rq_flags
In reply to Peter ZijlstraIn order to pass around more than just the IRQ flags, add a rq_flags structure.
No difference in code generation for the x86_64-defconfig build I tested.
--- kernel/sched/core.c | 98 ++++++++++++++++++++++++------------------------ kernel/sched/deadline.c | 6 +- kernel/sched/sched.h | 14 ++++-- 3 files changed, 62 insertions(+), 56 deletions(-)
kernel/sched/core.c +50 -48
@@ -173,7 +173,7 @@ static struct rq *this_rq_lock(void)/* * __task_rq_lock - lock the rq @p resides on. */ -struct rq *__task_rq_lock (struct task_struct *p) +struct rq *__task_rq_lock (struct task_struct *p,struct rq_flags *rf) __acquires(rq->lock) {struct rq *rq;
@@ -197,14 +197,14 @@ struct rq *__task_rq_lock(struct task_st/* * task_rq_lock - lock p->pi_lock and lock the rq @p resides on. */ -struct rq *task_rq_lock (struct task_struct *p,unsigned long *flags) +struct rq *task_rq_lock (struct task_struct *p,struct rq_flags *rf) __acquires(p->pi_lock) __acquires(rq->lock) {struct rq *rq;for (;;) { -raw_spin_lock_irqsave (&p->pi_lock, *flags); +raw_spin_lock_irqsave (&p->pi_lock, rf->flags); rq =task_rq (p);raw_spin_lock (&rq->lock);/*
@@ -228,7 +228,7 @@ struct rq *task_rq_lock(struct task_strureturn rq; }raw_spin_unlock (&rq->lock); -raw_spin_unlock_irqrestore (&p->pi_lock, *flags); +raw_spin_unlock_irqrestore (&p->pi_lock, rf->flags);while (unlikely (task_on_rq_migrating (p)))cpu_relax ();
@@ -1147,12 +1147,12 @@ void do_set_cpus_allowed(struct task_strstatic int __set_cpus_allowed_ptr (struct task_struct *p,const struct cpumask *new_mask,bool check) { -unsigned long flags; -struct rq *rq;unsigned int dest_cpu; +struct rq_flags rf; +struct rq *rq;int ret =0 ; - rq =task_rq_lock (p, &flags); + rq =task_rq_lock (p, &rf);/* * Must re-check here, to close a race against __kthread_bind(),
@@ -1181,7 +1181,7 @@ static int __set_cpus_allowed_ptr(structif (task_running (rq, p) || p->state ==TASK_WAKING ) {struct migration_arg arg = { p, dest_cpu };/* Need help from migration thread: drop lock and wait. */ -task_rq_unlock (rq, p, &flags); +task_rq_unlock (rq, p, &rf);stop_one_cpu (cpu_of (rq), migration_cpu_stop, &arg);tlb_migrate_finish (p->mm);return 0 ;
@@ -1195,7 +1195,7 @@ static int __set_cpus_allowed_ptr(structlockdep_pin_lock (&rq->lock); } out: -task_rq_unlock (rq, p, &flags); +task_rq_unlock (rq, p, &rf);return ret; }
@@ -1379,8 +1379,8 @@ int migrate_swap(struct task_struct *cur*/ unsigned long wait_task_inactive (struct task_struct *p,long match_state) { -unsigned long flags;int running, queued; +struct rq_flags rf;unsigned long ncsw;struct rq *rq;
@@ -1415,14 +1415,14 @@ unsigned long wait_task_inactive(struct* lock now, to be *sure*. If we're wrong, we'll * just go back and repeat. */ - rq =task_rq_lock (p, &flags); + rq =task_rq_lock (p, &rf);trace_sched_wait_task (p); running =task_running (rq, p); queued =task_on_rq_queued (p); ncsw =0 ;if (!match_state || p->state == match_state) ncsw = p->nvcsw |LONG_MIN ;/* sets MSB */ -task_rq_unlock (rq, p, &flags); +task_rq_unlock (rq, p, &rf);/* * If it changed from the expected state, bail out now.
@@ -1720,17 +1720,18 @@ ttwu_do_activate(struct rq *rq, struct t*/ static int ttwu_remote (struct task_struct *p,int wake_flags) { +struct rq_flags rf;struct rq *rq;int ret =0 ; - rq =__task_rq_lock (p); + rq =__task_rq_lock (p, &rf);if (task_on_rq_queued (p)) {/* check_preempt_curr() may use rq clock */ update_rq_clock (rq);ttwu_do_wakeup (rq, p, wake_flags); ret =1 ; } -__task_rq_unlock (rq); +__task_rq_unlock (rq, &rf);return ret; }
@@ -2483,12 +2484,12 @@ extern void init_dl_bw(struct dl_bw *dl_*/ void wake_up_new_task (struct task_struct *p) { -unsigned long flags; +struct rq_flags rf;struct rq *rq; -raw_spin_lock_irqsave (&p->pi_lock, flags);/* Initialize new task's runnable average */ init_entity_runnable_average (&p->se); +raw_spin_lock_irqsave (&p->pi_lock, rf.flags);#ifdef CONFIG_SMP /* * Fork balancing, do it here and not earlier because:
@@ -2500,7 +2501,7 @@ void wake_up_new_task(struct task_struct/* Post initialize new task's util average when its cfs_rq is set */ post_init_entity_util_avg (&p->se); - rq =__task_rq_lock (p); + rq =__task_rq_lock (p, &rf);activate_task (rq, p,0 ); p->on_rq =TASK_ON_RQ_QUEUED ;trace_sched_wakeup_new (p);
@@ -2516,7 +2517,7 @@ void wake_up_new_task(struct task_struct lockdep_pin_lock(&rq->lock); }#endif -task_rq_unlock (rq, p, &flags); +task_rq_unlock (rq, p, &rf); }#ifdef CONFIG_PREEMPT_NOTIFIERS
@@ -2932,7 +2933,7 @@ EXPORT_PER_CPU_SYMBOL(kernel_cpustat);*/ unsigned long long task_sched_runtime (struct task_struct *p) { -unsigned long flags; +struct rq_flags rf;struct rq *rq;u64 ns;
@@ -2952,7 +2953,7 @@ unsigned long long task_sched_runtime(streturn p->se.sum_exec_runtime;#endif - rq =task_rq_lock (p, &flags); + rq =task_rq_lock (p, &rf);/* * Must be ->curr _and_ ->on_rq. If dequeued, we would * project cycles that may never be accounted to this
@@ -2963,7 +2964,7 @@ unsigned long long task_sched_runtime(st p->sched_class->update_curr (rq); } ns = p->se.sum_exec_runtime; -task_rq_unlock (rq, p, &flags); +task_rq_unlock (rq, p, &rf);return ns; }
@@ -3521,12 +3522,13 @@ EXPORT_SYMBOL(default_wake_function);void rt_mutex_setprio (struct task_struct *p,int prio) {int oldprio, queued, running, queue_flag =DEQUEUE_SAVE |DEQUEUE_MOVE ; -struct rq *rq;const struct sched_class *prev_class; +struct rq_flags rf; +struct rq *rq;BUG_ON (prio >MAX_PRIO ); - rq =__task_rq_lock (p); + rq =__task_rq_lock (p, &rf);/* * Idle task boosting is a nono in general. There is one
@@ -3602,7 +3604,7 @@ void rt_mutex_setprio(struct task_structcheck_class_changed (rq, p, prev_class, oldprio); out_unlock:preempt_disable ();/* avoid rq from going away on us */ -__task_rq_unlock (rq); +__task_rq_unlock (rq, &rf);balance_callback (rq);preempt_enable ();
@@ -3612,7 +3614,7 @@ void rt_mutex_setprio(struct task_structvoid set_user_nice (struct task_struct *p,long nice) {int old_prio, delta, queued; -unsigned long flags; +struct rq_flags rf;struct rq *rq;if (task_nice (p) == nice || nice <MIN_NICE || nice >MAX_NICE )
@@ -3621,7 +3623,7 @@ void set_user_nice(struct task_struct *p* We have to be careful, if called from sys_setpriority(), * the task might be in the middle of scheduling on another CPU. */ - rq =task_rq_lock (p, &flags); + rq =task_rq_lock (p, &rf);/* * The RT priorities are set via sched_setscheduler(), but we still * allow the 'normal' nice value to be set - but as expected
@@ -3652,7 +3654,7 @@ void set_user_nice(struct task_struct *presched_curr (rq); } out_unlock: -task_rq_unlock (rq, p, &flags); +task_rq_unlock (rq, p, &rf); }EXPORT_SYMBOL (set_user_nice);
@@ -3949,11 +3951,11 @@ static int __sched_setscheduler(struct tMAX_RT_PRIO -1 - attr->sched_priority;int retval, oldprio, oldpolicy =-1 , queued, running;int new_effective_prio, policy = attr->sched_policy; -unsigned long flags;const struct sched_class *prev_class; -struct rq *rq; +struct rq_flags rf;int reset_on_fork;int queue_flags =DEQUEUE_SAVE |DEQUEUE_MOVE ; +struct rq *rq;/* may grab non-irq protected spin_locks */ BUG_ON (in_interrupt ());
@@ -4048,13 +4050,13 @@ static int __sched_setscheduler(struct t* To be able to change p->policy safely, the appropriate * runqueue lock must be held. */ - rq =task_rq_lock (p, &flags); + rq =task_rq_lock (p, &rf);/* * Changing the policy of the stop threads its a very bad idea */ if (p == rq->stop) { -task_rq_unlock (rq, p, &flags); +task_rq_unlock (rq, p, &rf);return -EINVAL ; }
@@ -4071,7 +4073,7 @@ static int __sched_setscheduler(struct t goto change; p->sched_reset_on_fork = reset_on_fork; -task_rq_unlock (rq, p, &flags); +task_rq_unlock (rq, p, &rf);return 0 ; } change:
@@ -4085,7 +4087,7 @@ static int __sched_setscheduler(struct tif (rt_bandwidth_enabled () &&rt_policy (policy) &&task_group (p)->rt_bandwidth.rt_runtime ==0 && !task_group_is_autogroup (task_group (p))) { -task_rq_unlock (rq, p, &flags); +task_rq_unlock (rq, p, &rf);return -EPERM ; }#endif
@@ -4100,7 +4102,7 @@ static int __sched_setscheduler(struct t*/ if (!cpumask_subset (span, &p->cpus_allowed) || rq->rd->dl_bw.bw ==0 ) { -task_rq_unlock (rq, p, &flags); +task_rq_unlock (rq, p, &rf);return -EPERM ; } }
@@ -4110,7 +4112,7 @@ static int __sched_setscheduler(struct t/* recheck policy now with rq lock held */ if (unlikely (oldpolicy !=-1 && oldpolicy != p->policy)) { policy = oldpolicy =-1 ; -task_rq_unlock (rq, p, &flags); +task_rq_unlock (rq, p, &rf); goto recheck; }
@@ -4120,7 +4122,7 @@ static int __sched_setscheduler(struct t* is available. */ if ((dl_policy (policy) ||dl_task (p)) &&dl_overflow (p, policy, attr)) { -task_rq_unlock (rq, p, &flags); +task_rq_unlock (rq, p, &rf);return -EBUSY ; }
@@ -4165,7 +4167,7 @@ static int __sched_setscheduler(struct tcheck_class_changed (rq, p, prev_class, oldprio);preempt_disable ();/* avoid rq from going away on us */ -task_rq_unlock (rq, p, &flags); +task_rq_unlock (rq, p, &rf);if (pi)rt_mutex_adjust_pi (p);
@@ -5018,10 +5020,10 @@ SYSCALL_DEFINE2(sched_rr_get_interval, p {struct task_struct *p;unsigned int time_slice; -unsigned long flags; +struct rq_flags rf; +struct timespec t;struct rq *rq;int retval; -struct timespec t;if (pid <0 )return -EINVAL ;
@@ -5036,11 +5038,11 @@ SYSCALL_DEFINE2(sched_rr_get_interval, pif (retval) goto out_unlock; - rq =task_rq_lock (p, &flags); + rq =task_rq_lock (p, &rf); time_slice =0 ;if (p->sched_class->get_rr_interval) time_slice = p->sched_class->get_rr_interval (rq, p); -task_rq_unlock (rq, p, &flags); +task_rq_unlock (rq, p, &rf);rcu_read_unlock ();jiffies_to_timespec (time_slice, &t);
@@ -5304,11 +5306,11 @@ int migrate_task_to(struct task_struct **/ void sched_setnuma (struct task_struct *p,int nid) { -struct rq *rq; -unsigned long flags;bool queued, running; +struct rq_flags rf; +struct rq *rq; - rq =task_rq_lock (p, &flags); + rq =task_rq_lock (p, &rf); queued =task_on_rq_queued (p); running =task_current (rq, p);
@@ -5323,7 +5325,7 @@ void sched_setnuma(struct task_struct *p p->sched_class->set_curr_task (rq);if (queued)enqueue_task (rq, p,ENQUEUE_RESTORE ); - task_rq_unlock(rq, p, &flags); + task_rq_unlock(rq, p, &rf); }#endif /* CONFIG_NUMA_BALANCING */
@@ -7754,10 +7756,10 @@ void sched_move_task(struct task_struct {struct task_group *tg;int queued, running; -unsigned long flags; +struct rq_flags rf;struct rq *rq; - rq =task_rq_lock (tsk, &flags); + rq =task_rq_lock (tsk, &rf); running =task_current (rq, tsk); queued =task_on_rq_queued (tsk);
@@ -7789,7 +7791,7 @@ void sched_move_task(struct task_structif (queued)enqueue_task (rq, tsk,ENQUEUE_RESTORE |ENQUEUE_MOVE ); - task_rq_unlock(rq, tsk, &flags); + task_rq_unlock(rq, tsk, &rf); }#endif /* CONFIG_CGROUP_SCHED */
kernel/sched/deadline.c +3 -3
@@ -591,10 +591,10 @@ static enum hrtimer_restart dl_task_time struct sched_dl_entity, dl_timer);struct task_struct *p =dl_task_of (dl_se); -unsigned long flags; +struct rq_flags rf;struct rq *rq; - rq =task_rq_lock (p, &flags); + rq =task_rq_lock (p, &rf);/* * The task might have changed its scheduling policy to something
@@ -677,7 +677,7 @@ static enum hrtimer_restart dl_task_time#endif unlock: -task_rq_unlock (rq, p, &flags); +task_rq_unlock (rq, p, &rf);/* * This can free the task_struct, including this hrtimer, do not touch
kernel/sched/sched.h +9 -5
@@ -1451,13 +1451,17 @@ static inline void sched_rt_avg_update(sstatic inline void sched_avg_update (struct rq *rq) { }#endif -struct rq *__task_rq_lock (struct task_struct *p) +struct rq_flags { +unsigned long flags; +}; + +struct rq *__task_rq_lock (struct task_struct *p,struct rq_flags *rf) __acquires(rq->lock); -struct rq *task_rq_lock (struct task_struct *p,unsigned long *flags) +struct rq *task_rq_lock (struct task_struct *p,struct rq_flags *rf) __acquires(p->pi_lock) __acquires(rq->lock); -static inline void __task_rq_unlock (struct rq *rq) +static inline void __task_rq_unlock (struct rq *rq,struct rq_flags *rf) __releases(rq->lock) {lockdep_unpin_lock (&rq->lock);
@@ -1465,13 +1469,13 @@ static inline void __task_rq_unlock(stru }static inline void -task_rq_unlock (struct rq *rq,struct task_struct *p,unsigned long *flags) +task_rq_unlock (struct rq *rq,struct task_struct *p,struct rq_flags *rf) __releases(rq->lock) __releases(p->pi_lock) {lockdep_unpin_lock (&rq->lock);raw_spin_unlock (&rq->lock); -raw_spin_unlock_irqrestore (&p->pi_lock, *flags); +raw_spin_unlock_irqrestore (&p->pi_lock, rf->flags); }#ifdef CONFIG_SMP
Peter Zijlstra
maintainerPATCH 3/3 lockdep,sched: Implement a better lock pinning scheme
In reply to Peter ZijlstraThe problem with the existing lock pinning is that each pin is of value 1; this mean you can simply unpin if you know its pinned, without having any extra information.
This scheme generates a random (16 bit) cookie for each pin and requires this same cookie to unpin. This means you have to keep the cookie in context.
No objsize difference for !LOCKDEP kernels.
--- include/linux/lockdep.h | 23 ++++++++++--- kernel/locking/lockdep.c | 71 ++++++++++++++++++++++++++++++++++++------ kernel/sched/core.c | 79 ++++++++++++++++++++++++----------------------- kernel/sched/deadline.c | 11 +++--- kernel/sched/fair.c | 6 +-- kernel/sched/idle_task.c | 2 - kernel/sched/rt.c | 6 +-- kernel/sched/sched.h | 8 ++-- kernel/sched/stop_task.c | 2 - 9 files changed, 140 insertions(+), 68 deletions(-)
include/linux/lockdep.h +17 -6
@@ -356,8 +356,13 @@ extern void lockdep_set_current_reclaim_extern void lockdep_clear_current_reclaim_state (void );extern void lockdep_trace_alloc (gfp_t mask); -extern void lock_pin_lock (struct lockdep_map *lock); -extern void lock_unpin_lock (struct lockdep_map *lock); +struct pin_cookie {unsigned int val; }; + +#define NIL_COOKIE (struct pin_cookie){ .val = 0U, } + +extern struct pin_cookie lock_pin_lock (struct lockdep_map *lock); +extern void lock_repin_lock (struct lockdep_map *lock,struct pin_cookie ); +extern void lock_unpin_lock (struct lockdep_map *lock,struct pin_cookie );# define INIT_LOCKDEP .lockdep_recursion = 0, .lockdep_reclaim_gfp = 0,
@@ -373,8 +378,9 @@ extern void lock_unpin_lock(struct lockd#define lockdep_recursing (tsk) ((tsk)->lockdep_recursion) -#define lockdep_pin_lock (l) lock_pin_lock(&(l)->dep_map) -#define lockdep_unpin_lock (l) lock_unpin_lock(&(l)->dep_map) +#define lockdep_pin_lock (l) lock_pin_lock(&(l)->dep_map) +#define lockdep_repin_lock (l,c) lock_repin_lock(&(l)->dep_map, (c)) +#define lockdep_unpin_lock (l,c) lock_unpin_lock(&(l)->dep_map, (c))#else /* !CONFIG_LOCKDEP */
@@ -427,8 +433,13 @@ struct lock_class_key { };#define lockdep_recursing (tsk) (0) -#define lockdep_pin_lock (l) do { (void)(l); } while (0) -#define lockdep_unpin_lock (l) do { (void)(l); } while (0) +struct pin_cookie { }; + +#define NIL_COOKIE (struct pin_cookie){ } + +#define lockdep_pin_lock (l) ({ struct pin_cookie cookie; cookie; }) +#define lockdep_repin_lock (l, c) do { (void)(l); (void)(c); } while (0) +#define lockdep_unpin_lock (l, c) do { (void)(l); (void)(c); } while (0)#endif /* !LOCKDEP */
kernel/locking/lockdep.c +62 -9
127 lines not on this page · raw message
kernel/sched/core.c +42 -37
271 lines not on this page · raw message
kernel/sched/deadline.c +6 -5
@@ -670,9 +670,9 @@ static enum hrtimer_restart dl_task_time* Nothing relies on rq->lock after this, so its safe to drop * rq->lock. */ -lockdep_unpin_lock (&rq->lock); +lockdep_unpin_lock (&rq->lock, rf.cookie);push_dl_task (rq); - lockdep_pin_lock(&rq->lock); + lockdep_repin_lock(&rq->lock, rf.cookie); }#endif
@@ -1125,7 +1125,8 @@ static struct sched_dl_entity *pick_next return rb_entry(left, struct sched_dl_entity, rb_node); } -struct task_struct *pick_next_task_dl (struct rq *rq,struct task_struct *prev) +struct task_struct * +pick_next_task_dl (struct rq *rq,struct task_struct *prev,struct pin_cookie cookie) {struct sched_dl_entity *dl_se;struct task_struct *p;
@@ -1140,9 +1141,9 @@ struct task_struct *pick_next_task_dl(st* disabled avoiding further scheduler activity on it and we're * being very careful to re-start the picking loop. */ -lockdep_unpin_lock (&rq->lock); +lockdep_unpin_lock (&rq->lock, cookie);pull_dl_task (rq); -lockdep_pin_lock (&rq->lock); +lockdep_repin_lock (&rq->lock, cookie);/* * pull_rt_task() can drop (and re-acquire) rq->lock; this * means a stop task can slip in, in which case we need to
kernel/sched/fair.c +3 -3
@@ -5542,7 +5542,7 @@ static void check_preempt_wakeup(struct }static struct task_struct * -pick_next_task_fair (struct rq *rq,struct task_struct *prev) +pick_next_task_fair (struct rq *rq,struct task_struct *prev,struct pin_cookie cookie) {struct cfs_rq *cfs_rq = &rq->cfs;struct sched_entity *se;
@@ -5655,9 +5655,9 @@ pick_next_task_fair(struct rq *rq, struc* further scheduler activity on it and we're being very careful to * re-start the picking loop. */ -lockdep_unpin_lock (&rq->lock); +lockdep_unpin_lock (&rq->lock, cookie); new_tasks =idle_balance (rq); -lockdep_pin_lock (&rq->lock); +lockdep_repin_lock (&rq->lock, cookie);/* * Because idle_balance() releases (and re-acquires) rq->lock, it is * possible for any higher priority task to appear. In that case we
kernel/sched/idle_task.c +1 -1
@@ -24,7 +24,7 @@ static void check_preempt_curr_idle(stru }static struct task_struct * -pick_next_task_idle (struct rq *rq,struct task_struct *prev) +pick_next_task_idle (struct rq *rq,struct task_struct *prev,struct pin_cookie cookie) {put_prev_task (rq, prev);
kernel/sched/rt.c +3 -3
@@ -1524,7 +1524,7 @@ static struct task_struct *_pick_next_ta }static struct task_struct * -pick_next_task_rt (struct rq *rq,struct task_struct *prev) +pick_next_task_rt (struct rq *rq,struct task_struct *prev,struct pin_cookie cookie) {struct task_struct *p;struct rt_rq *rt_rq = &rq->rt;
@@ -1536,9 +1536,9 @@ pick_next_task_rt(struct rq *rq, struct* disabled avoiding further scheduler activity on it and we're * being very careful to re-start the picking loop. */ -lockdep_unpin_lock (&rq->lock); +lockdep_unpin_lock (&rq->lock, cookie);pull_rt_task (rq); -lockdep_pin_lock (&rq->lock); +lockdep_repin_lock (&rq->lock, cookie);/* * pull_rt_task() can drop (and re-acquire) rq->lock; this * means a dl or stop task can slip in, in which case we need
kernel/sched/sched.h +5 -3
@@ -1202,7 +1202,8 @@ struct sched_class {* tasks. */ struct task_struct * (*pick_next_task) (struct rq *rq, -struct task_struct *prev); +struct task_struct *prev, +struct pin_cookie cookie);void (*put_prev_task) (struct rq *rq,struct task_struct *p);#ifdef CONFIG_SMP
@@ -1453,6 +1454,7 @@ static inline void sched_avg_update(strustruct rq_flags {unsigned long flags; +struct pin_cookie cookie; };struct rq *__task_rq_lock (struct task_struct *p,struct rq_flags *rf)
@@ -1464,7 +1466,7 @@ struct rq *task_rq_lock(struct task_strustatic inline void __task_rq_unlock (struct rq *rq,struct rq_flags *rf) __releases(rq->lock) { -lockdep_unpin_lock (&rq->lock); +lockdep_unpin_lock (&rq->lock, rf->cookie);raw_spin_unlock (&rq->lock); }
@@ -1473,7 +1475,7 @@ task_rq_unlock(struct rq *rq, struct tas __releases(rq->lock) __releases(p->pi_lock) { -lockdep_unpin_lock (&rq->lock); +lockdep_unpin_lock (&rq->lock, rf->cookie);raw_spin_unlock (&rq->lock);raw_spin_unlock_irqrestore (&p->pi_lock, rf->flags); }
kernel/sched/stop_task.c +1 -1
@@ -24,7 +24,7 @@ check_preempt_curr_stop(struct rq *rq, s }static struct task_struct * -pick_next_task_stop (struct rq *rq,struct task_struct *prev) +pick_next_task_stop (struct rq *rq,struct task_struct *prev,struct pin_cookie cookie) {struct task_struct *stop = rq->stop;