aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-04-18 11:37:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-18 11:37:41 -0400
commit73e3e6481f56b3b5b618671a8d32b19a35f84316 (patch)
tree44addba339ca1279a82d6d702e92e6cc2c183810 /kernel
parent4adeaaf51ebcc3f629f5512b96aebb5089388bca (diff)
parent6993fc5bbc5d63ccd55985b39c34417e430e75e9 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-hrt
* git://git.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-hrt: clocksource: make clocksource watchdog cycle through online CPUs Documentation: move timer related documentation to a single place clockevents: optimise tick_nohz_stop_sched_tick() a bit locking: remove unused double_spin_lock() hrtimers: simplify lockdep handling timers: simplify lockdep handling posix-timers: fix shadowed variables timer_list: add annotations to workqueue.c hrtimer: use nanosleep specific restart_block fields hrtimer: add nanosleep specific restart_block member
Diffstat (limited to 'kernel')
-rw-r--r--kernel/compat.c15
-rw-r--r--kernel/hrtimer.c22
-rw-r--r--kernel/posix-cpu-timers.c30
-rw-r--r--kernel/time/clocksource.c18
-rw-r--r--kernel/time/tick-sched.c6
-rw-r--r--kernel/timer.c16
-rw-r--r--kernel/workqueue.c2
7 files changed, 54 insertions, 55 deletions
diff --git a/kernel/compat.c b/kernel/compat.c
index 5f0e201bcfd3..9c48abfcd4a5 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -47,15 +47,14 @@ static long compat_nanosleep_restart(struct restart_block *restart)
47 mm_segment_t oldfs; 47 mm_segment_t oldfs;
48 long ret; 48 long ret;
49 49
50 rmtp = (struct compat_timespec __user *)(restart->arg1); 50 restart->nanosleep.rmtp = (struct timespec __user *) &rmt;
51 restart->arg1 = (unsigned long)&rmt;
52 oldfs = get_fs(); 51 oldfs = get_fs();
53 set_fs(KERNEL_DS); 52 set_fs(KERNEL_DS);
54 ret = hrtimer_nanosleep_restart(restart); 53 ret = hrtimer_nanosleep_restart(restart);
55 set_fs(oldfs); 54 set_fs(oldfs);
56 55
57 if (ret) { 56 if (ret) {
58 restart->arg1 = (unsigned long)rmtp; 57 rmtp = restart->nanosleep.compat_rmtp;
59 58
60 if (rmtp && put_compat_timespec(&rmt, rmtp)) 59 if (rmtp && put_compat_timespec(&rmt, rmtp))
61 return -EFAULT; 60 return -EFAULT;
@@ -89,7 +88,7 @@ asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
89 = &current_thread_info()->restart_block; 88 = &current_thread_info()->restart_block;
90 89
91 restart->fn = compat_nanosleep_restart; 90 restart->fn = compat_nanosleep_restart;
92 restart->arg1 = (unsigned long)rmtp; 91 restart->nanosleep.compat_rmtp = rmtp;
93 92
94 if (rmtp && put_compat_timespec(&rmt, rmtp)) 93 if (rmtp && put_compat_timespec(&rmt, rmtp))
95 return -EFAULT; 94 return -EFAULT;
@@ -607,9 +606,9 @@ static long compat_clock_nanosleep_restart(struct restart_block *restart)
607 long err; 606 long err;
608 mm_segment_t oldfs; 607 mm_segment_t oldfs;
609 struct timespec tu; 608 struct timespec tu;
610 struct compat_timespec *rmtp = (struct compat_timespec *)(restart->arg1); 609 struct compat_timespec *rmtp = restart->nanosleep.compat_rmtp;
611 610
612 restart->arg1 = (unsigned long) &tu; 611 restart->nanosleep.rmtp = (struct timespec __user *) &tu;
613 oldfs = get_fs(); 612 oldfs = get_fs();
614 set_fs(KERNEL_DS); 613 set_fs(KERNEL_DS);
615 err = clock_nanosleep_restart(restart); 614 err = clock_nanosleep_restart(restart);
@@ -621,7 +620,7 @@ static long compat_clock_nanosleep_restart(struct restart_block *restart)
621 620
622 if (err == -ERESTART_RESTARTBLOCK) { 621 if (err == -ERESTART_RESTARTBLOCK) {
623 restart->fn = compat_clock_nanosleep_restart; 622 restart->fn = compat_clock_nanosleep_restart;
624 restart->arg1 = (unsigned long) rmtp; 623 restart->nanosleep.compat_rmtp = rmtp;
625 } 624 }
626 return err; 625 return err;
627} 626}
@@ -652,7 +651,7 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
652 if (err == -ERESTART_RESTARTBLOCK) { 651 if (err == -ERESTART_RESTARTBLOCK) {
653 restart = &current_thread_info()->restart_block; 652 restart = &current_thread_info()->restart_block;
654 restart->fn = compat_clock_nanosleep_restart; 653 restart->fn = compat_clock_nanosleep_restart;
655 restart->arg1 = (unsigned long) rmtp; 654 restart->nanosleep.compat_rmtp = rmtp;
656 } 655 }
657 return err; 656 return err;
658} 657}
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 98bee013f71f..c642ef75069f 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -1354,13 +1354,13 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
1354 struct hrtimer_sleeper t; 1354 struct hrtimer_sleeper t;
1355 struct timespec __user *rmtp; 1355 struct timespec __user *rmtp;
1356 1356
1357 hrtimer_init(&t.timer, restart->arg0, HRTIMER_MODE_ABS); 1357 hrtimer_init(&t.timer, restart->nanosleep.index, HRTIMER_MODE_ABS);
1358 t.timer.expires.tv64 = ((u64)restart->arg3 << 32) | (u64) restart->arg2; 1358 t.timer.expires.tv64 = restart->nanosleep.expires;
1359 1359
1360 if (do_nanosleep(&t, HRTIMER_MODE_ABS)) 1360 if (do_nanosleep(&t, HRTIMER_MODE_ABS))
1361 return 0; 1361 return 0;
1362 1362
1363 rmtp = (struct timespec __user *)restart->arg1; 1363 rmtp = restart->nanosleep.rmtp;
1364 if (rmtp) { 1364 if (rmtp) {
1365 int ret = update_rmtp(&t.timer, rmtp); 1365 int ret = update_rmtp(&t.timer, rmtp);
1366 if (ret <= 0) 1366 if (ret <= 0)
@@ -1394,10 +1394,9 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
1394 1394
1395 restart = &current_thread_info()->restart_block; 1395 restart = &current_thread_info()->restart_block;
1396 restart->fn = hrtimer_nanosleep_restart; 1396 restart->fn = hrtimer_nanosleep_restart;
1397 restart->arg0 = (unsigned long) t.timer.base->index; 1397 restart->nanosleep.index = t.timer.base->index;
1398 restart->arg1 = (unsigned long) rmtp; 1398 restart->nanosleep.rmtp = rmtp;
1399 restart->arg2 = t.timer.expires.tv64 & 0xFFFFFFFF; 1399 restart->nanosleep.expires = t.timer.expires.tv64;
1400 restart->arg3 = t.timer.expires.tv64 >> 32;
1401 1400
1402 return -ERESTART_RESTARTBLOCK; 1401 return -ERESTART_RESTARTBLOCK;
1403} 1402}
@@ -1425,7 +1424,6 @@ static void __cpuinit init_hrtimers_cpu(int cpu)
1425 int i; 1424 int i;
1426 1425
1427 spin_lock_init(&cpu_base->lock); 1426 spin_lock_init(&cpu_base->lock);
1428 lockdep_set_class(&cpu_base->lock, &cpu_base->lock_key);
1429 1427
1430 for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) 1428 for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++)
1431 cpu_base->clock_base[i].cpu_base = cpu_base; 1429 cpu_base->clock_base[i].cpu_base = cpu_base;
@@ -1466,16 +1464,16 @@ static void migrate_hrtimers(int cpu)
1466 tick_cancel_sched_timer(cpu); 1464 tick_cancel_sched_timer(cpu);
1467 1465
1468 local_irq_disable(); 1466 local_irq_disable();
1469 double_spin_lock(&new_base->lock, &old_base->lock, 1467 spin_lock(&new_base->lock);
1470 smp_processor_id() < cpu); 1468 spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
1471 1469
1472 for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) { 1470 for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
1473 migrate_hrtimer_list(&old_base->clock_base[i], 1471 migrate_hrtimer_list(&old_base->clock_base[i],
1474 &new_base->clock_base[i]); 1472 &new_base->clock_base[i]);
1475 } 1473 }
1476 1474
1477 double_spin_unlock(&new_base->lock, &old_base->lock, 1475 spin_unlock(&old_base->lock);
1478 smp_processor_id() < cpu); 1476 spin_unlock(&new_base->lock);
1479 local_irq_enable(); 1477 local_irq_enable();
1480 put_cpu_var(hrtimer_bases); 1478 put_cpu_var(hrtimer_bases);
1481} 1479}
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 2eae91f954ca..ae5c6c147c4b 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -1087,45 +1087,45 @@ static void check_process_timers(struct task_struct *tsk,
1087 maxfire = 20; 1087 maxfire = 20;
1088 prof_expires = cputime_zero; 1088 prof_expires = cputime_zero;
1089 while (!list_empty(timers)) { 1089 while (!list_empty(timers)) {
1090 struct cpu_timer_list *t = list_first_entry(timers, 1090 struct cpu_timer_list *tl = list_first_entry(timers,
1091 struct cpu_timer_list, 1091 struct cpu_timer_list,
1092 entry); 1092 entry);
1093 if (!--maxfire || cputime_lt(ptime, t->expires.cpu)) { 1093 if (!--maxfire || cputime_lt(ptime, tl->expires.cpu)) {
1094 prof_expires = t->expires.cpu; 1094 prof_expires = tl->expires.cpu;
1095 break; 1095 break;
1096 } 1096 }
1097 t->firing = 1; 1097 tl->firing = 1;
1098 list_move_tail(&t->entry, firing); 1098 list_move_tail(&tl->entry, firing);
1099 } 1099 }
1100 1100
1101 ++timers; 1101 ++timers;
1102 maxfire = 20; 1102 maxfire = 20;
1103 virt_expires = cputime_zero; 1103 virt_expires = cputime_zero;
1104 while (!list_empty(timers)) { 1104 while (!list_empty(timers)) {
1105 struct cpu_timer_list *t = list_first_entry(timers, 1105 struct cpu_timer_list *tl = list_first_entry(timers,
1106 struct cpu_timer_list, 1106 struct cpu_timer_list,
1107 entry); 1107 entry);
1108 if (!--maxfire || cputime_lt(utime, t->expires.cpu)) { 1108 if (!--maxfire || cputime_lt(utime, tl->expires.cpu)) {
1109 virt_expires = t->expires.cpu; 1109 virt_expires = tl->expires.cpu;
1110 break; 1110 break;
1111 } 1111 }
1112 t->firing = 1; 1112 tl->firing = 1;
1113 list_move_tail(&t->entry, firing); 1113 list_move_tail(&tl->entry, firing);
1114 } 1114 }
1115 1115
1116 ++timers; 1116 ++timers;
1117 maxfire = 20; 1117 maxfire = 20;
1118 sched_expires = 0; 1118 sched_expires = 0;
1119 while (!list_empty(timers)) { 1119 while (!list_empty(timers)) {
1120 struct cpu_timer_list *t = list_first_entry(timers, 1120 struct cpu_timer_list *tl = list_first_entry(timers,
1121 struct cpu_timer_list, 1121 struct cpu_timer_list,
1122 entry); 1122 entry);
1123 if (!--maxfire || sum_sched_runtime < t->expires.sched) { 1123 if (!--maxfire || sum_sched_runtime < tl->expires.sched) {
1124 sched_expires = t->expires.sched; 1124 sched_expires = tl->expires.sched;
1125 break; 1125 break;
1126 } 1126 }
1127 t->firing = 1; 1127 tl->firing = 1;
1128 list_move_tail(&t->entry, firing); 1128 list_move_tail(&tl->entry, firing);
1129 } 1129 }
1130 1130
1131 /* 1131 /*
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index f61402b1f2d0..73961f35fdc8 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -141,8 +141,16 @@ static void clocksource_watchdog(unsigned long data)
141 } 141 }
142 142
143 if (!list_empty(&watchdog_list)) { 143 if (!list_empty(&watchdog_list)) {
144 __mod_timer(&watchdog_timer, 144 /*
145 watchdog_timer.expires + WATCHDOG_INTERVAL); 145 * Cycle through CPUs to check if the CPUs stay
146 * synchronized to each other.
147 */
148 int next_cpu = next_cpu(raw_smp_processor_id(), cpu_online_map);
149
150 if (next_cpu >= NR_CPUS)
151 next_cpu = first_cpu(cpu_online_map);
152 watchdog_timer.expires += WATCHDOG_INTERVAL;
153 add_timer_on(&watchdog_timer, next_cpu);
146 } 154 }
147 spin_unlock(&watchdog_lock); 155 spin_unlock(&watchdog_lock);
148} 156}
@@ -164,7 +172,8 @@ static void clocksource_check_watchdog(struct clocksource *cs)
164 if (!started && watchdog) { 172 if (!started && watchdog) {
165 watchdog_last = watchdog->read(); 173 watchdog_last = watchdog->read();
166 watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL; 174 watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL;
167 add_timer(&watchdog_timer); 175 add_timer_on(&watchdog_timer,
176 first_cpu(cpu_online_map));
168 } 177 }
169 } else { 178 } else {
170 if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) 179 if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS)
@@ -185,7 +194,8 @@ static void clocksource_check_watchdog(struct clocksource *cs)
185 watchdog_last = watchdog->read(); 194 watchdog_last = watchdog->read();
186 watchdog_timer.expires = 195 watchdog_timer.expires =
187 jiffies + WATCHDOG_INTERVAL; 196 jiffies + WATCHDOG_INTERVAL;
188 add_timer(&watchdog_timer); 197 add_timer_on(&watchdog_timer,
198 first_cpu(cpu_online_map));
189 } 199 }
190 } 200 }
191 } 201 }
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 686da821d376..69dba0c71727 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -158,9 +158,8 @@ void tick_nohz_stop_idle(int cpu)
158 } 158 }
159} 159}
160 160
161static ktime_t tick_nohz_start_idle(int cpu) 161static ktime_t tick_nohz_start_idle(struct tick_sched *ts)
162{ 162{
163 struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
164 ktime_t now, delta; 163 ktime_t now, delta;
165 164
166 now = ktime_get(); 165 now = ktime_get();
@@ -201,8 +200,8 @@ void tick_nohz_stop_sched_tick(void)
201 local_irq_save(flags); 200 local_irq_save(flags);
202 201
203 cpu = smp_processor_id(); 202 cpu = smp_processor_id();
204 now = tick_nohz_start_idle(cpu);
205 ts = &per_cpu(tick_cpu_sched, cpu); 203 ts = &per_cpu(tick_cpu_sched, cpu);
204 now = tick_nohz_start_idle(ts);
206 205
207 /* 206 /*
208 * If this cpu is offline and it is the one which updates 207 * If this cpu is offline and it is the one which updates
@@ -222,7 +221,6 @@ void tick_nohz_stop_sched_tick(void)
222 if (need_resched()) 221 if (need_resched())
223 goto end; 222 goto end;
224 223
225 cpu = smp_processor_id();
226 if (unlikely(local_softirq_pending())) { 224 if (unlikely(local_softirq_pending())) {
227 static int ratelimit; 225 static int ratelimit;
228 226
diff --git a/kernel/timer.c b/kernel/timer.c
index b024106daa70..f3d35d4ea42e 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1228,13 +1228,6 @@ asmlinkage long sys_sysinfo(struct sysinfo __user *info)
1228 return 0; 1228 return 0;
1229} 1229}
1230 1230
1231/*
1232 * lockdep: we want to track each per-CPU base as a separate lock-class,
1233 * but timer-bases are kmalloc()-ed, so we need to attach separate
1234 * keys to them:
1235 */
1236static struct lock_class_key base_lock_keys[NR_CPUS];
1237
1238static int __cpuinit init_timers_cpu(int cpu) 1231static int __cpuinit init_timers_cpu(int cpu)
1239{ 1232{
1240 int j; 1233 int j;
@@ -1277,7 +1270,6 @@ static int __cpuinit init_timers_cpu(int cpu)
1277 } 1270 }
1278 1271
1279 spin_lock_init(&base->lock); 1272 spin_lock_init(&base->lock);
1280 lockdep_set_class(&base->lock, base_lock_keys + cpu);
1281 1273
1282 for (j = 0; j < TVN_SIZE; j++) { 1274 for (j = 0; j < TVN_SIZE; j++) {
1283 INIT_LIST_HEAD(base->tv5.vec + j); 1275 INIT_LIST_HEAD(base->tv5.vec + j);
@@ -1316,8 +1308,8 @@ static void __cpuinit migrate_timers(int cpu)
1316 new_base = get_cpu_var(tvec_bases); 1308 new_base = get_cpu_var(tvec_bases);
1317 1309
1318 local_irq_disable(); 1310 local_irq_disable();
1319 double_spin_lock(&new_base->lock, &old_base->lock, 1311 spin_lock(&new_base->lock);
1320 smp_processor_id() < cpu); 1312 spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
1321 1313
1322 BUG_ON(old_base->running_timer); 1314 BUG_ON(old_base->running_timer);
1323 1315
@@ -1330,8 +1322,8 @@ static void __cpuinit migrate_timers(int cpu)
1330 migrate_timer_list(new_base, old_base->tv5.vec + i); 1322 migrate_timer_list(new_base, old_base->tv5.vec + i);
1331 } 1323 }
1332 1324
1333 double_spin_unlock(&new_base->lock, &old_base->lock, 1325 spin_unlock(&old_base->lock);
1334 smp_processor_id() < cpu); 1326 spin_unlock(&new_base->lock);
1335 local_irq_enable(); 1327 local_irq_enable();
1336 put_cpu_var(tvec_bases); 1328 put_cpu_var(tvec_bases);
1337} 1329}
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index ff06611655af..00ff4d08e370 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -219,6 +219,7 @@ int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
219 struct timer_list *timer = &dwork->timer; 219 struct timer_list *timer = &dwork->timer;
220 struct work_struct *work = &dwork->work; 220 struct work_struct *work = &dwork->work;
221 221
222 timer_stats_timer_set_start_info(&dwork->timer);
222 if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) { 223 if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) {
223 BUG_ON(timer_pending(timer)); 224 BUG_ON(timer_pending(timer));
224 BUG_ON(!list_empty(&work->entry)); 225 BUG_ON(!list_empty(&work->entry));
@@ -580,6 +581,7 @@ EXPORT_SYMBOL(schedule_delayed_work);
580int schedule_delayed_work_on(int cpu, 581int schedule_delayed_work_on(int cpu,
581 struct delayed_work *dwork, unsigned long delay) 582 struct delayed_work *dwork, unsigned long delay)
582{ 583{
584 timer_stats_timer_set_start_info(&dwork->timer);
583 return queue_delayed_work_on(cpu, keventd_wq, dwork, delay); 585 return queue_delayed_work_on(cpu, keventd_wq, dwork, delay);
584} 586}
585EXPORT_SYMBOL(schedule_delayed_work_on); 587EXPORT_SYMBOL(schedule_delayed_work_on);