{
smp_intr_init();
- #ifdef CONFIG_X86_LOCAL_APIC
-#ifdef CONFIG_X86_64
++#ifdef CONFIG_X86_THERMAL_VECTOR
+ alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
++#endif
++#ifdef CONFIG_X86_THRESHOLD
+ alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
+ #endif
++#if defined(CONFIG_X86_NEW_MCE) && defined(CONFIG_X86_LOCAL_APIC)
++ alloc_intr_gate(MCE_SELF_VECTOR, mce_self_interrupt);
++#endif
+
+ #if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
/* self generated IPI for local APIC timer */
alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
/* IPI vectors for APIC spurious and error interrupts */
alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
+
+ /* Performance monitoring interrupts: */
# ifdef CONFIG_PERF_COUNTERS
- alloc_intr_gate(LOCAL_PERF_VECTOR, perf_counter_interrupt);
alloc_intr_gate(LOCAL_PENDING_VECTOR, perf_pending_interrupt);
# endif
- # ifdef CONFIG_X86_MCE_P4THERMAL
-#endif
-
-#ifdef CONFIG_X86_32
-#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_MCE_P4THERMAL)
-- /* thermal monitor LVT interrupt */
-- alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
- # endif
-#endif
#endif
}
* Copyright (C) 2001, 2002 Andi Kleen, SuSE Labs.
* Copyright (C) 2008-2009, Red Hat Inc., Ingo Molnar
*/
- #include <linux/interrupt.h>
- #include <linux/mmiotrace.h>
- #include <linux/bootmem.h>
- #include <linux/compiler.h>
- #include <linux/highmem.h>
- #include <linux/kprobes.h>
- #include <linux/uaccess.h>
- #include <linux/vmalloc.h>
- #include <linux/vt_kern.h>
- #include <linux/signal.h>
- #include <linux/kernel.h>
- #include <linux/ptrace.h>
- #include <linux/string.h>
- #include <linux/module.h>
- #include <linux/kdebug.h>
- #include <linux/errno.h>
- #include <linux/magic.h>
- #include <linux/sched.h>
- #include <linux/types.h>
- #include <linux/init.h>
- #include <linux/mman.h>
- #include <linux/tty.h>
- #include <linux/smp.h>
- #include <linux/mm.h>
- #include <linux/perf_counter.h>
-
- #include <asm-generic/sections.h>
-
- #include <asm/tlbflush.h>
- #include <asm/pgalloc.h>
- #include <asm/segment.h>
- #include <asm/system.h>
- #include <asm/proto.h>
- #include <asm/traps.h>
- #include <asm/desc.h>
+ #include <linux/magic.h> /* STACK_END_MAGIC */
+ #include <linux/sched.h> /* test_thread_flag(), ... */
+ #include <linux/kdebug.h> /* oops_begin/end, ... */
+ #include <linux/module.h> /* search_exception_table */
+ #include <linux/bootmem.h> /* max_low_pfn */
+ #include <linux/kprobes.h> /* __kprobes, ... */
+ #include <linux/mmiotrace.h> /* kmmio_handler, ... */
++#include <linux/perf_counter.h> /* perf_swcounter_event */
+
+ #include <asm/traps.h> /* dotraplinkage, ... */
+ #include <asm/pgalloc.h> /* pgd_*(), ... */
/*
* Page fault error code bits:
struct futex_pi_state;
struct robust_list_head;
struct bio;
- struct bts_tracer;
struct fs_struct;
+ struct bts_context;
+struct perf_counter_context;
/*
* List of flags we want to share for kernel threads,
extern int nr_processes(void);
extern unsigned long nr_running(void);
extern unsigned long nr_uninterruptible(void);
- extern unsigned long nr_active(void);
extern unsigned long nr_iowait(void);
+ extern void calc_global_load(void);
+extern u64 cpu_nr_migrations(int cpu);
extern unsigned long get_parent_ip(unsigned long addr);
obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
obj-$(CONFIG_FUNCTION_TRACER) += trace/
obj-$(CONFIG_TRACING) += trace/
+ obj-$(CONFIG_X86_DS) += trace/
obj-$(CONFIG_SMP) += sched_cpupri.o
obj-$(CONFIG_SLOW_WORK) += slow-work.o
+obj-$(CONFIG_PERF_COUNTERS) += perf_counter.o
ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y)
# According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
#include <linux/tracehook.h>
#include <linux/fs_struct.h>
#include <linux/init_task.h>
- #include <trace/sched.h>
+#include <linux/perf_counter.h>
+ #include <trace/events/sched.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <linux/proc_fs.h>
#include <linux/blkdev.h>
#include <linux/fs_struct.h>
- #include <trace/sched.h>
#include <linux/magic.h>
+#include <linux/perf_counter.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
return sum;
}
- unsigned long nr_active(void)
+ /* Variables and functions for calc_load */
+ static atomic_long_t calc_load_tasks;
+ static unsigned long calc_load_update;
+ unsigned long avenrun[3];
+ EXPORT_SYMBOL(avenrun);
+
+ /**
+ * get_avenrun - get the load average array
+ * @loads: pointer to dest load array
+ * @offset: offset to add
+ * @shift: shift count to shift the result left
+ *
+ * These values are estimates at best, so no need for locking.
+ */
+ void get_avenrun(unsigned long *loads, unsigned long offset, int shift)
+ {
+ loads[0] = (avenrun[0] + offset) << shift;
+ loads[1] = (avenrun[1] + offset) << shift;
+ loads[2] = (avenrun[2] + offset) << shift;
+ }
+
+ static unsigned long
+ calc_load(unsigned long load, unsigned long exp, unsigned long active)
{
- unsigned long i, running = 0, uninterruptible = 0;
+ load *= exp;
+ load += active * (FIXED_1 - exp);
+ return load >> FSHIFT;
+ }
- for_each_online_cpu(i) {
- running += cpu_rq(i)->nr_running;
- uninterruptible += cpu_rq(i)->nr_uninterruptible;
- }
+ /*
+ * calc_load - update the avenrun load estimates 10 ticks after the
+ * CPUs have updated calc_load_tasks.
+ */
+ void calc_global_load(void)
+ {
+ unsigned long upd = calc_load_update + 10;
+ long active;
- if (unlikely((long)uninterruptible < 0))
- uninterruptible = 0;
+ if (time_before(jiffies, upd))
+ return;
- return running + uninterruptible;
+ active = atomic_long_read(&calc_load_tasks);
+ active = active > 0 ? active * FIXED_1 : 0;
+
+ avenrun[0] = calc_load(avenrun[0], EXP_1, active);
+ avenrun[1] = calc_load(avenrun[1], EXP_5, active);
+ avenrun[2] = calc_load(avenrun[2], EXP_15, active);
+
+ calc_load_update += LOAD_FREQ;
+ }
+
+ /*
+ * Either called from update_cpu_load() or from a cpu going idle
+ */
+ static void calc_load_account_active(struct rq *this_rq)
+ {
+ long nr_active, delta;
+
+ nr_active = this_rq->nr_running;
+ nr_active += (long) this_rq->nr_uninterruptible;
+
+ if (nr_active != this_rq->calc_load_active) {
+ delta = nr_active - this_rq->calc_load_active;
+ this_rq->calc_load_active = nr_active;
+ atomic_long_add(delta, &calc_load_tasks);
+ }
}
+/*
+ * Externally visible per-cpu scheduler statistics:
+ * cpu_nr_migrations(cpu) - number of migrations into that cpu
+ */
+u64 cpu_nr_migrations(int cpu)
+{
+ return cpu_rq(cpu)->nr_migrations_in;
+}
+
/*
* Update rq->cpu_load[] statistics. This function is usually called every
* scheduler tick (TICK_NSEC).