aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/timer.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-06-11 17:31:52 -0400
committerIngo Molnar <mingo@elte.hu>2009-06-11 17:31:52 -0400
commit0d5959723e1db3fd7323c198a50c16cecf96c7a9 (patch)
tree802b623fff261ebcbbddadf84af5524398364a18 /kernel/timer.c
parent62fdac5913f71f8f200bd2c9bd59a02e9a1498e9 (diff)
parent512626a04e72aca60effe111fa0333ed0b195d21 (diff)
Merge branch 'linus' into x86/mce3
Conflicts: arch/x86/kernel/cpu/mcheck/mce_64.c arch/x86/kernel/irq.c Merge reason: Resolve the conflicts above. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/timer.c')
-rw-r--r--kernel/timer.c89
1 files changed, 11 insertions, 78 deletions
diff --git a/kernel/timer.c b/kernel/timer.c
index e2c47b82ac36..faf2db897de4 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -37,6 +37,7 @@
37#include <linux/delay.h> 37#include <linux/delay.h>
38#include <linux/tick.h> 38#include <linux/tick.h>
39#include <linux/kallsyms.h> 39#include <linux/kallsyms.h>
40#include <linux/perf_counter.h>
40 41
41#include <asm/uaccess.h> 42#include <asm/uaccess.h>
42#include <asm/unistd.h> 43#include <asm/unistd.h>
@@ -1124,53 +1125,14 @@ void update_process_times(int user_tick)
1124} 1125}
1125 1126
1126/* 1127/*
1127 * Nr of active tasks - counted in fixed-point numbers
1128 */
1129static unsigned long count_active_tasks(void)
1130{
1131 return nr_active() * FIXED_1;
1132}
1133
1134/*
1135 * Hmm.. Changed this, as the GNU make sources (load.c) seems to
1136 * imply that avenrun[] is the standard name for this kind of thing.
1137 * Nothing else seems to be standardized: the fractional size etc
1138 * all seem to differ on different machines.
1139 *
1140 * Requires xtime_lock to access.
1141 */
1142unsigned long avenrun[3];
1143
1144EXPORT_SYMBOL(avenrun);
1145
1146/*
1147 * calc_load - given tick count, update the avenrun load estimates.
1148 * This is called while holding a write_lock on xtime_lock.
1149 */
1150static inline void calc_load(unsigned long ticks)
1151{
1152 unsigned long active_tasks; /* fixed-point */
1153 static int count = LOAD_FREQ;
1154
1155 count -= ticks;
1156 if (unlikely(count < 0)) {
1157 active_tasks = count_active_tasks();
1158 do {
1159 CALC_LOAD(avenrun[0], EXP_1, active_tasks);
1160 CALC_LOAD(avenrun[1], EXP_5, active_tasks);
1161 CALC_LOAD(avenrun[2], EXP_15, active_tasks);
1162 count += LOAD_FREQ;
1163 } while (count < 0);
1164 }
1165}
1166
1167/*
1168 * This function runs timers and the timer-tq in bottom half context. 1128 * This function runs timers and the timer-tq in bottom half context.
1169 */ 1129 */
1170static void run_timer_softirq(struct softirq_action *h) 1130static void run_timer_softirq(struct softirq_action *h)
1171{ 1131{
1172 struct tvec_base *base = __get_cpu_var(tvec_bases); 1132 struct tvec_base *base = __get_cpu_var(tvec_bases);
1173 1133
1134 perf_counter_do_pending();
1135
1174 hrtimer_run_pending(); 1136 hrtimer_run_pending();
1175 1137
1176 if (time_after_eq(jiffies, base->timer_jiffies)) 1138 if (time_after_eq(jiffies, base->timer_jiffies))
@@ -1188,16 +1150,6 @@ void run_local_timers(void)
1188} 1150}
1189 1151
1190/* 1152/*
1191 * Called by the timer interrupt. xtime_lock must already be taken
1192 * by the timer IRQ!
1193 */
1194static inline void update_times(unsigned long ticks)
1195{
1196 update_wall_time();
1197 calc_load(ticks);
1198}
1199
1200/*
1201 * The 64-bit jiffies value is not atomic - you MUST NOT read it 1153 * The 64-bit jiffies value is not atomic - you MUST NOT read it
1202 * without sampling the sequence number in xtime_lock. 1154 * without sampling the sequence number in xtime_lock.
1203 * jiffies is defined in the linker script... 1155 * jiffies is defined in the linker script...
@@ -1206,7 +1158,8 @@ static inline void update_times(unsigned long ticks)
1206void do_timer(unsigned long ticks) 1158void do_timer(unsigned long ticks)
1207{ 1159{
1208 jiffies_64 += ticks; 1160 jiffies_64 += ticks;
1209 update_times(ticks); 1161 update_wall_time();
1162 calc_global_load();
1210} 1163}
1211 1164
1212#ifdef __ARCH_WANT_SYS_ALARM 1165#ifdef __ARCH_WANT_SYS_ALARM
@@ -1407,37 +1360,17 @@ int do_sysinfo(struct sysinfo *info)
1407{ 1360{
1408 unsigned long mem_total, sav_total; 1361 unsigned long mem_total, sav_total;
1409 unsigned int mem_unit, bitcount; 1362 unsigned int mem_unit, bitcount;
1410 unsigned long seq; 1363 struct timespec tp;
1411 1364
1412 memset(info, 0, sizeof(struct sysinfo)); 1365 memset(info, 0, sizeof(struct sysinfo));
1413 1366
1414 do { 1367 ktime_get_ts(&tp);
1415 struct timespec tp; 1368 monotonic_to_bootbased(&tp);
1416 seq = read_seqbegin(&xtime_lock); 1369 info->uptime = tp.tv_sec + (tp.tv_nsec ? 1 : 0);
1417
1418 /*
1419 * This is annoying. The below is the same thing
1420 * posix_get_clock_monotonic() does, but it wants to
1421 * take the lock which we want to cover the loads stuff
1422 * too.
1423 */
1424
1425 getnstimeofday(&tp);
1426 tp.tv_sec += wall_to_monotonic.tv_sec;
1427 tp.tv_nsec += wall_to_monotonic.tv_nsec;
1428 monotonic_to_bootbased(&tp);
1429 if (tp.tv_nsec - NSEC_PER_SEC >= 0) {
1430 tp.tv_nsec = tp.tv_nsec - NSEC_PER_SEC;
1431 tp.tv_sec++;
1432 }
1433 info->uptime = tp.tv_sec + (tp.tv_nsec ? 1 : 0);
1434 1370
1435 info->loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT); 1371 get_avenrun(info->loads, 0, SI_LOAD_SHIFT - FSHIFT);
1436 info->loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
1437 info->loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);
1438 1372
1439 info->procs = nr_threads; 1373 info->procs = nr_threads;
1440 } while (read_seqretry(&xtime_lock, seq));
1441 1374
1442 si_meminfo(info); 1375 si_meminfo(info);
1443 si_swapinfo(info); 1376 si_swapinfo(info);