aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2010-05-08 12:11:19 -0400
committerIngo Molnar <mingo@elte.hu>2010-05-08 12:11:19 -0400
commite7858f52a5cb868289a72264534a1f05f3340c6c (patch)
treeaa7308603cf30d8aec6e45ecaddc6c8ed29d2edb /kernel/sched.c
parent27a9da6538ee18046d7bff8e36a9f783542c54c3 (diff)
parentbbf1bb3eee86f2eef2baa14e600be454d09109ee (diff)
Merge branch 'cpu_stop' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc into sched/core
Diffstat (limited to 'kernel/sched.c')
-rw-r--r--kernel/sched.c285
1 files changed, 60 insertions, 225 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index 11ac0eb0bce7..39aa9c7e22c0 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -55,9 +55,9 @@
55#include <linux/cpu.h> 55#include <linux/cpu.h>
56#include <linux/cpuset.h> 56#include <linux/cpuset.h>
57#include <linux/percpu.h> 57#include <linux/percpu.h>
58#include <linux/kthread.h>
59#include <linux/proc_fs.h> 58#include <linux/proc_fs.h>
60#include <linux/seq_file.h> 59#include <linux/seq_file.h>
60#include <linux/stop_machine.h>
61#include <linux/sysctl.h> 61#include <linux/sysctl.h>
62#include <linux/syscalls.h> 62#include <linux/syscalls.h>
63#include <linux/times.h> 63#include <linux/times.h>
@@ -539,15 +539,13 @@ struct rq {
539 int post_schedule; 539 int post_schedule;
540 int active_balance; 540 int active_balance;
541 int push_cpu; 541 int push_cpu;
542 struct cpu_stop_work active_balance_work;
542 /* cpu of this runqueue: */ 543 /* cpu of this runqueue: */
543 int cpu; 544 int cpu;
544 int online; 545 int online;
545 546
546 unsigned long avg_load_per_task; 547 unsigned long avg_load_per_task;
547 548
548 struct task_struct *migration_thread;
549 struct list_head migration_queue;
550
551 u64 rt_avg; 549 u64 rt_avg;
552 u64 age_stamp; 550 u64 age_stamp;
553 u64 idle_stamp; 551 u64 idle_stamp;
@@ -2037,21 +2035,18 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
2037 __set_task_cpu(p, new_cpu); 2035 __set_task_cpu(p, new_cpu);
2038} 2036}
2039 2037
2040struct migration_req { 2038struct migration_arg {
2041 struct list_head list;
2042
2043 struct task_struct *task; 2039 struct task_struct *task;
2044 int dest_cpu; 2040 int dest_cpu;
2045
2046 struct completion done;
2047}; 2041};
2048 2042
2043static int migration_cpu_stop(void *data);
2044
2049/* 2045/*
2050 * The task's runqueue lock must be held. 2046 * The task's runqueue lock must be held.
2051 * Returns true if you have to wait for migration thread. 2047 * Returns true if you have to wait for migration thread.
2052 */ 2048 */
2053static int 2049static bool migrate_task(struct task_struct *p, int dest_cpu)
2054migrate_task(struct task_struct *p, int dest_cpu, struct migration_req *req)
2055{ 2050{
2056 struct rq *rq = task_rq(p); 2051 struct rq *rq = task_rq(p);
2057 2052
@@ -2059,15 +2054,7 @@ migrate_task(struct task_struct *p, int dest_cpu, struct migration_req *req)
2059 * If the task is not on a runqueue (and not running), then 2054 * If the task is not on a runqueue (and not running), then
2060 * the next wake-up will properly place the task. 2055 * the next wake-up will properly place the task.
2061 */ 2056 */
2062 if (!p->se.on_rq && !task_running(rq, p)) 2057 return p->se.on_rq || task_running(rq, p);
2063 return 0;
2064
2065 init_completion(&req->done);
2066 req->task = p;
2067 req->dest_cpu = dest_cpu;
2068 list_add(&req->list, &rq->migration_queue);
2069
2070 return 1;
2071} 2058}
2072 2059
2073/* 2060/*
@@ -3110,7 +3097,6 @@ static void update_cpu_load(struct rq *this_rq)
3110void sched_exec(void) 3097void sched_exec(void)
3111{ 3098{
3112 struct task_struct *p = current; 3099 struct task_struct *p = current;
3113 struct migration_req req;
3114 unsigned long flags; 3100 unsigned long flags;
3115 struct rq *rq; 3101 struct rq *rq;
3116 int dest_cpu; 3102 int dest_cpu;
@@ -3124,17 +3110,11 @@ void sched_exec(void)
3124 * select_task_rq() can race against ->cpus_allowed 3110 * select_task_rq() can race against ->cpus_allowed
3125 */ 3111 */
3126 if (cpumask_test_cpu(dest_cpu, &p->cpus_allowed) && 3112 if (cpumask_test_cpu(dest_cpu, &p->cpus_allowed) &&
3127 likely(cpu_active(dest_cpu)) && 3113 likely(cpu_active(dest_cpu)) && migrate_task(p, dest_cpu)) {
3128 migrate_task(p, dest_cpu, &req)) { 3114 struct migration_arg arg = { p, dest_cpu };
3129 /* Need to wait for migration thread (might exit: take ref). */
3130 struct task_struct *mt = rq->migration_thread;
3131 3115
3132 get_task_struct(mt);
3133 task_rq_unlock(rq, &flags); 3116 task_rq_unlock(rq, &flags);
3134 wake_up_process(mt); 3117 stop_one_cpu(cpu_of(rq), migration_cpu_stop, &arg);
3135 put_task_struct(mt);
3136 wait_for_completion(&req.done);
3137
3138 return; 3118 return;
3139 } 3119 }
3140unlock: 3120unlock:
@@ -5290,17 +5270,15 @@ static inline void sched_init_granularity(void)
5290/* 5270/*
5291 * This is how migration works: 5271 * This is how migration works:
5292 * 5272 *
5293 * 1) we queue a struct migration_req structure in the source CPU's 5273 * 1) we invoke migration_cpu_stop() on the target CPU using
5294 * runqueue and wake up that CPU's migration thread. 5274 * stop_one_cpu().
5295 * 2) we down() the locked semaphore => thread blocks. 5275 * 2) stopper starts to run (implicitly forcing the migrated thread
5296 * 3) migration thread wakes up (implicitly it forces the migrated 5276 * off the CPU)
5297 * thread off the CPU) 5277 * 3) it checks whether the migrated task is still in the wrong runqueue.
5298 * 4) it gets the migration request and checks whether the migrated 5278 * 4) if it's in the wrong runqueue then the migration thread removes
5299 * task is still in the wrong runqueue.
5300 * 5) if it's in the wrong runqueue then the migration thread removes
5301 * it and puts it into the right queue. 5279 * it and puts it into the right queue.
5302 * 6) migration thread up()s the semaphore. 5280 * 5) stopper completes and stop_one_cpu() returns and the migration
5303 * 7) we wake up and the migration is done. 5281 * is done.
5304 */ 5282 */
5305 5283
5306/* 5284/*
@@ -5314,9 +5292,9 @@ static inline void sched_init_granularity(void)
5314 */ 5292 */
5315int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask) 5293int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask)
5316{ 5294{
5317 struct migration_req req;
5318 unsigned long flags; 5295 unsigned long flags;
5319 struct rq *rq; 5296 struct rq *rq;
5297 unsigned int dest_cpu;
5320 int ret = 0; 5298 int ret = 0;
5321 5299
5322 /* 5300 /*
@@ -5354,15 +5332,12 @@ again:
5354 if (cpumask_test_cpu(task_cpu(p), new_mask)) 5332 if (cpumask_test_cpu(task_cpu(p), new_mask))
5355 goto out; 5333 goto out;
5356 5334
5357 if (migrate_task(p, cpumask_any_and(cpu_active_mask, new_mask), &req)) { 5335 dest_cpu = cpumask_any_and(cpu_active_mask, new_mask);
5336 if (migrate_task(p, dest_cpu)) {
5337 struct migration_arg arg = { p, dest_cpu };
5358 /* Need help from migration thread: drop lock and wait. */ 5338 /* Need help from migration thread: drop lock and wait. */
5359 struct task_struct *mt = rq->migration_thread;
5360
5361 get_task_struct(mt);
5362 task_rq_unlock(rq, &flags); 5339 task_rq_unlock(rq, &flags);
5363 wake_up_process(mt); 5340 stop_one_cpu(cpu_of(rq), migration_cpu_stop, &arg);
5364 put_task_struct(mt);
5365 wait_for_completion(&req.done);
5366 tlb_migrate_finish(p->mm); 5341 tlb_migrate_finish(p->mm);
5367 return 0; 5342 return 0;
5368 } 5343 }
@@ -5420,70 +5395,22 @@ fail:
5420 return ret; 5395 return ret;
5421} 5396}
5422 5397
5423#define RCU_MIGRATION_IDLE 0
5424#define RCU_MIGRATION_NEED_QS 1
5425#define RCU_MIGRATION_GOT_QS 2
5426#define RCU_MIGRATION_MUST_SYNC 3
5427
5428/* 5398/*
5429 * migration_thread - this is a highprio system thread that performs 5399 * migration_cpu_stop - this will be executed by a highprio stopper thread
5430 * thread migration by bumping thread off CPU then 'pushing' onto 5400 * and performs thread migration by bumping thread off CPU then
5431 * another runqueue. 5401 * 'pushing' onto another runqueue.
5432 */ 5402 */
5433static int migration_thread(void *data) 5403static int migration_cpu_stop(void *data)
5434{ 5404{
5435 int badcpu; 5405 struct migration_arg *arg = data;
5436 int cpu = (long)data;
5437 struct rq *rq;
5438
5439 rq = cpu_rq(cpu);
5440 BUG_ON(rq->migration_thread != current);
5441
5442 set_current_state(TASK_INTERRUPTIBLE);
5443 while (!kthread_should_stop()) {
5444 struct migration_req *req;
5445 struct list_head *head;
5446
5447 raw_spin_lock_irq(&rq->lock);
5448
5449 if (cpu_is_offline(cpu)) {
5450 raw_spin_unlock_irq(&rq->lock);
5451 break;
5452 }
5453
5454 if (rq->active_balance) {
5455 active_load_balance(rq, cpu);
5456 rq->active_balance = 0;
5457 }
5458
5459 head = &rq->migration_queue;
5460
5461 if (list_empty(head)) {
5462 raw_spin_unlock_irq(&rq->lock);
5463 schedule();
5464 set_current_state(TASK_INTERRUPTIBLE);
5465 continue;
5466 }
5467 req = list_entry(head->next, struct migration_req, list);
5468 list_del_init(head->next);
5469
5470 if (req->task != NULL) {
5471 raw_spin_unlock(&rq->lock);
5472 __migrate_task(req->task, cpu, req->dest_cpu);
5473 } else if (likely(cpu == (badcpu = smp_processor_id()))) {
5474 req->dest_cpu = RCU_MIGRATION_GOT_QS;
5475 raw_spin_unlock(&rq->lock);
5476 } else {
5477 req->dest_cpu = RCU_MIGRATION_MUST_SYNC;
5478 raw_spin_unlock(&rq->lock);
5479 WARN_ONCE(1, "migration_thread() on CPU %d, expected %d\n", badcpu, cpu);
5480 }
5481 local_irq_enable();
5482
5483 complete(&req->done);
5484 }
5485 __set_current_state(TASK_RUNNING);
5486 5406
5407 /*
5408 * The original target cpu might have gone down and we might
5409 * be on another cpu but it doesn't matter.
5410 */
5411 local_irq_disable();
5412 __migrate_task(arg->task, raw_smp_processor_id(), arg->dest_cpu);
5413 local_irq_enable();
5487 return 0; 5414 return 0;
5488} 5415}
5489 5416
@@ -5850,35 +5777,20 @@ static void set_rq_offline(struct rq *rq)
5850static int __cpuinit 5777static int __cpuinit
5851migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) 5778migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
5852{ 5779{
5853 struct task_struct *p;
5854 int cpu = (long)hcpu; 5780 int cpu = (long)hcpu;
5855 unsigned long flags; 5781 unsigned long flags;
5856 struct rq *rq; 5782 struct rq *rq = cpu_rq(cpu);
5857 5783
5858 switch (action) { 5784 switch (action) {
5859 5785
5860 case CPU_UP_PREPARE: 5786 case CPU_UP_PREPARE:
5861 case CPU_UP_PREPARE_FROZEN: 5787 case CPU_UP_PREPARE_FROZEN:
5862 p = kthread_create(migration_thread, hcpu, "migration/%d", cpu);
5863 if (IS_ERR(p))
5864 return NOTIFY_BAD;
5865 kthread_bind(p, cpu);
5866 /* Must be high prio: stop_machine expects to yield to it. */
5867 rq = task_rq_lock(p, &flags);
5868 __setscheduler(rq, p, SCHED_FIFO, MAX_RT_PRIO-1);
5869 task_rq_unlock(rq, &flags);
5870 get_task_struct(p);
5871 cpu_rq(cpu)->migration_thread = p;
5872 rq->calc_load_update = calc_load_update; 5788 rq->calc_load_update = calc_load_update;
5873 break; 5789 break;
5874 5790
5875 case CPU_ONLINE: 5791 case CPU_ONLINE:
5876 case CPU_ONLINE_FROZEN: 5792 case CPU_ONLINE_FROZEN:
5877 /* Strictly unnecessary, as first user will wake it. */
5878 wake_up_process(cpu_rq(cpu)->migration_thread);
5879
5880 /* Update our root-domain */ 5793 /* Update our root-domain */
5881 rq = cpu_rq(cpu);
5882 raw_spin_lock_irqsave(&rq->lock, flags); 5794 raw_spin_lock_irqsave(&rq->lock, flags);
5883 if (rq->rd) { 5795 if (rq->rd) {
5884 BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); 5796 BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span));
@@ -5889,25 +5801,9 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
5889 break; 5801 break;
5890 5802
5891#ifdef CONFIG_HOTPLUG_CPU 5803#ifdef CONFIG_HOTPLUG_CPU
5892 case CPU_UP_CANCELED:
5893 case CPU_UP_CANCELED_FROZEN:
5894 if (!cpu_rq(cpu)->migration_thread)
5895 break;
5896 /* Unbind it from offline cpu so it can run. Fall thru. */
5897 kthread_bind(cpu_rq(cpu)->migration_thread,
5898 cpumask_any(cpu_online_mask));
5899 kthread_stop(cpu_rq(cpu)->migration_thread);
5900 put_task_struct(cpu_rq(cpu)->migration_thread);
5901 cpu_rq(cpu)->migration_thread = NULL;
5902 break;
5903
5904 case CPU_DEAD: 5804 case CPU_DEAD:
5905 case CPU_DEAD_FROZEN: 5805 case CPU_DEAD_FROZEN:
5906 migrate_live_tasks(cpu); 5806 migrate_live_tasks(cpu);
5907 rq = cpu_rq(cpu);
5908 kthread_stop(rq->migration_thread);
5909 put_task_struct(rq->migration_thread);
5910 rq->migration_thread = NULL;
5911 /* Idle task back to normal (off runqueue, low prio) */ 5807 /* Idle task back to normal (off runqueue, low prio) */
5912 raw_spin_lock_irq(&rq->lock); 5808 raw_spin_lock_irq(&rq->lock);
5913 deactivate_task(rq, rq->idle, 0); 5809 deactivate_task(rq, rq->idle, 0);
@@ -5918,29 +5814,11 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
5918 migrate_nr_uninterruptible(rq); 5814 migrate_nr_uninterruptible(rq);
5919 BUG_ON(rq->nr_running != 0); 5815 BUG_ON(rq->nr_running != 0);
5920 calc_global_load_remove(rq); 5816 calc_global_load_remove(rq);
5921 /*
5922 * No need to migrate the tasks: it was best-effort if
5923 * they didn't take sched_hotcpu_mutex. Just wake up
5924 * the requestors.
5925 */
5926 raw_spin_lock_irq(&rq->lock);
5927 while (!list_empty(&rq->migration_queue)) {
5928 struct migration_req *req;
5929
5930 req = list_entry(rq->migration_queue.next,
5931 struct migration_req, list);
5932 list_del_init(&req->list);
5933 raw_spin_unlock_irq(&rq->lock);
5934 complete(&req->done);
5935 raw_spin_lock_irq(&rq->lock);
5936 }
5937 raw_spin_unlock_irq(&rq->lock);
5938 break; 5817 break;
5939 5818
5940 case CPU_DYING: 5819 case CPU_DYING:
5941 case CPU_DYING_FROZEN: 5820 case CPU_DYING_FROZEN:
5942 /* Update our root-domain */ 5821 /* Update our root-domain */
5943 rq = cpu_rq(cpu);
5944 raw_spin_lock_irqsave(&rq->lock, flags); 5822 raw_spin_lock_irqsave(&rq->lock, flags);
5945 if (rq->rd) { 5823 if (rq->rd) {
5946 BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); 5824 BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span));
@@ -7757,10 +7635,8 @@ void __init sched_init(void)
7757 rq->push_cpu = 0; 7635 rq->push_cpu = 0;
7758 rq->cpu = i; 7636 rq->cpu = i;
7759 rq->online = 0; 7637 rq->online = 0;
7760 rq->migration_thread = NULL;
7761 rq->idle_stamp = 0; 7638 rq->idle_stamp = 0;
7762 rq->avg_idle = 2*sysctl_sched_migration_cost; 7639 rq->avg_idle = 2*sysctl_sched_migration_cost;
7763 INIT_LIST_HEAD(&rq->migration_queue);
7764 rq_attach_root(rq, &def_root_domain); 7640 rq_attach_root(rq, &def_root_domain);
7765#endif 7641#endif
7766 init_rq_hrtick(rq); 7642 init_rq_hrtick(rq);
@@ -9054,43 +8930,32 @@ struct cgroup_subsys cpuacct_subsys = {
9054 8930
9055#ifndef CONFIG_SMP 8931#ifndef CONFIG_SMP
9056 8932
9057int rcu_expedited_torture_stats(char *page)
9058{
9059 return 0;
9060}
9061EXPORT_SYMBOL_GPL(rcu_expedited_torture_stats);
9062
9063void synchronize_sched_expedited(void) 8933void synchronize_sched_expedited(void)
9064{ 8934{
8935 barrier();
9065} 8936}
9066EXPORT_SYMBOL_GPL(synchronize_sched_expedited); 8937EXPORT_SYMBOL_GPL(synchronize_sched_expedited);
9067 8938
9068#else /* #ifndef CONFIG_SMP */ 8939#else /* #ifndef CONFIG_SMP */
9069 8940
9070static DEFINE_PER_CPU(struct migration_req, rcu_migration_req); 8941static atomic_t synchronize_sched_expedited_count = ATOMIC_INIT(0);
9071static DEFINE_MUTEX(rcu_sched_expedited_mutex);
9072
9073#define RCU_EXPEDITED_STATE_POST -2
9074#define RCU_EXPEDITED_STATE_IDLE -1
9075
9076static int rcu_expedited_state = RCU_EXPEDITED_STATE_IDLE;
9077 8942
9078int rcu_expedited_torture_stats(char *page) 8943static int synchronize_sched_expedited_cpu_stop(void *data)
9079{ 8944{
9080 int cnt = 0; 8945 /*
9081 int cpu; 8946 * There must be a full memory barrier on each affected CPU
9082 8947 * between the time that try_stop_cpus() is called and the
9083 cnt += sprintf(&page[cnt], "state: %d /", rcu_expedited_state); 8948 * time that it returns.
9084 for_each_online_cpu(cpu) { 8949 *
9085 cnt += sprintf(&page[cnt], " %d:%d", 8950 * In the current initial implementation of cpu_stop, the
9086 cpu, per_cpu(rcu_migration_req, cpu).dest_cpu); 8951 * above condition is already met when the control reaches
9087 } 8952 * this point and the following smp_mb() is not strictly
9088 cnt += sprintf(&page[cnt], "\n"); 8953 * necessary. Do smp_mb() anyway for documentation and
9089 return cnt; 8954 * robustness against future implementation changes.
8955 */
8956 smp_mb(); /* See above comment block. */
8957 return 0;
9090} 8958}
9091EXPORT_SYMBOL_GPL(rcu_expedited_torture_stats);
9092
9093static long synchronize_sched_expedited_count;
9094 8959
9095/* 8960/*
9096 * Wait for an rcu-sched grace period to elapse, but use "big hammer" 8961 * Wait for an rcu-sched grace period to elapse, but use "big hammer"
@@ -9104,18 +8969,14 @@ static long synchronize_sched_expedited_count;
9104 */ 8969 */
9105void synchronize_sched_expedited(void) 8970void synchronize_sched_expedited(void)
9106{ 8971{
9107 int cpu; 8972 int snap, trycount = 0;
9108 unsigned long flags;
9109 bool need_full_sync = 0;
9110 struct rq *rq;
9111 struct migration_req *req;
9112 long snap;
9113 int trycount = 0;
9114 8973
9115 smp_mb(); /* ensure prior mod happens before capturing snap. */ 8974 smp_mb(); /* ensure prior mod happens before capturing snap. */
9116 snap = ACCESS_ONCE(synchronize_sched_expedited_count) + 1; 8975 snap = atomic_read(&synchronize_sched_expedited_count) + 1;
9117 get_online_cpus(); 8976 get_online_cpus();
9118 while (!mutex_trylock(&rcu_sched_expedited_mutex)) { 8977 while (try_stop_cpus(cpu_online_mask,
8978 synchronize_sched_expedited_cpu_stop,
8979 NULL) == -EAGAIN) {
9119 put_online_cpus(); 8980 put_online_cpus();
9120 if (trycount++ < 10) 8981 if (trycount++ < 10)
9121 udelay(trycount * num_online_cpus()); 8982 udelay(trycount * num_online_cpus());
@@ -9123,41 +8984,15 @@ void synchronize_sched_expedited(void)
9123 synchronize_sched(); 8984 synchronize_sched();
9124 return; 8985 return;
9125 } 8986 }
9126 if (ACCESS_ONCE(synchronize_sched_expedited_count) - snap > 0) { 8987 if (atomic_read(&synchronize_sched_expedited_count) - snap > 0) {
9127 smp_mb(); /* ensure test happens before caller kfree */ 8988 smp_mb(); /* ensure test happens before caller kfree */
9128 return; 8989 return;
9129 } 8990 }
9130 get_online_cpus(); 8991 get_online_cpus();
9131 } 8992 }
9132 rcu_expedited_state = RCU_EXPEDITED_STATE_POST; 8993 atomic_inc(&synchronize_sched_expedited_count);
9133 for_each_online_cpu(cpu) { 8994 smp_mb__after_atomic_inc(); /* ensure post-GP actions seen after GP. */
9134 rq = cpu_rq(cpu);
9135 req = &per_cpu(rcu_migration_req, cpu);
9136 init_completion(&req->done);
9137 req->task = NULL;
9138 req->dest_cpu = RCU_MIGRATION_NEED_QS;
9139 raw_spin_lock_irqsave(&rq->lock, flags);
9140 list_add(&req->list, &rq->migration_queue);
9141 raw_spin_unlock_irqrestore(&rq->lock, flags);
9142 wake_up_process(rq->migration_thread);
9143 }
9144 for_each_online_cpu(cpu) {
9145 rcu_expedited_state = cpu;
9146 req = &per_cpu(rcu_migration_req, cpu);
9147 rq = cpu_rq(cpu);
9148 wait_for_completion(&req->done);
9149 raw_spin_lock_irqsave(&rq->lock, flags);
9150 if (unlikely(req->dest_cpu == RCU_MIGRATION_MUST_SYNC))
9151 need_full_sync = 1;
9152 req->dest_cpu = RCU_MIGRATION_IDLE;
9153 raw_spin_unlock_irqrestore(&rq->lock, flags);
9154 }
9155 rcu_expedited_state = RCU_EXPEDITED_STATE_IDLE;
9156 synchronize_sched_expedited_count++;
9157 mutex_unlock(&rcu_sched_expedited_mutex);
9158 put_online_cpus(); 8995 put_online_cpus();
9159 if (need_full_sync)
9160 synchronize_sched();
9161} 8996}
9162EXPORT_SYMBOL_GPL(synchronize_sched_expedited); 8997EXPORT_SYMBOL_GPL(synchronize_sched_expedited);
9163 8998