From 7480e588de2048f0699c909b865c5a22a7992f4d Mon Sep 17 00:00:00 2001 From: Andy Bavier Date: Fri, 4 Apr 2008 18:03:29 +0000 Subject: [PATCH] Copy from trunk --- linux-2.6-590-chopstix-intern.patch | 383 ++++++++++++++++++++++++++++ 1 file changed, 383 insertions(+) create mode 100644 linux-2.6-590-chopstix-intern.patch diff --git a/linux-2.6-590-chopstix-intern.patch b/linux-2.6-590-chopstix-intern.patch new file mode 100644 index 000000000..dbc006de4 --- /dev/null +++ b/linux-2.6-590-chopstix-intern.patch @@ -0,0 +1,383 @@ +diff -Nurb linux-2.6.22-580/arch/i386/Kconfig linux-2.6.22-590/arch/i386/Kconfig +--- linux-2.6.22-580/arch/i386/Kconfig 2008-03-21 18:07:23.000000000 -0400 ++++ linux-2.6.22-590/arch/i386/Kconfig 2008-03-21 18:07:50.000000000 -0400 +@@ -1217,6 +1217,14 @@ + + source "arch/i386/oprofile/Kconfig" + ++config CHOPSTIX ++ bool "Chopstix (PlanetLab)" ++ depends on MODULES && OPROFILE ++ help ++ Chopstix allows you to monitor various events by summarizing them ++ in lossy data structures and transferring these data structures ++ into user space. If in doubt, say "N". ++ + config KPROBES + bool "Kprobes (EXPERIMENTAL)" + depends on KALLSYMS && EXPERIMENTAL && MODULES +diff -Nurb linux-2.6.22-580/drivers/oprofile/cpu_buffer.c linux-2.6.22-590/drivers/oprofile/cpu_buffer.c +--- linux-2.6.22-580/drivers/oprofile/cpu_buffer.c 2007-07-08 19:32:17.000000000 -0400 ++++ linux-2.6.22-590/drivers/oprofile/cpu_buffer.c 2008-03-21 18:07:50.000000000 -0400 +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #include "event_buffer.h" + #include "cpu_buffer.h" +@@ -143,6 +144,17 @@ + b->head_pos = 0; + } + ++#ifdef CONFIG_CHOPSTIX ++ ++struct event_spec { ++ unsigned int pc; ++ unsigned long dcookie; ++ unsigned count; ++}; ++ ++extern void (*rec_event)(void *,unsigned int); ++#endif ++ + static inline void + add_sample(struct oprofile_cpu_buffer * cpu_buf, + unsigned long pc, unsigned long event) +@@ -151,6 +163,7 @@ + entry->eip = pc; + entry->event = event; + increment_head(cpu_buf); ++ + } + + static inline void +@@ -237,12 +250,75 @@ + oprofile_end_trace(cpu_buf); + } + ++#ifdef CONFIG_CHOPSTIX ++ ++static int proc_pid_cmdline(struct task_struct *task, char * buffer) ++{ ++ int res = 0; ++ unsigned int len; ++ struct mm_struct *mm = get_task_mm(task); ++ if (!mm) ++ goto out; ++ if (!mm->arg_end) ++ goto out_mm; /* Shh! No looking before we're done */ ++ ++ len = mm->arg_end - mm->arg_start; ++ ++ if (len > PAGE_SIZE) ++ len = PAGE_SIZE; ++ ++ res = access_process_vm(task, mm->arg_start, buffer, len, 0); ++ ++ // If the nul at the end of args has been overwritten, then ++ // assume application is using setproctitle(3). ++ if (res > 0 && buffer[res-1] != '\0' && len < PAGE_SIZE) { ++ len = strnlen(buffer, res); ++ if (len < res) { ++ res = len; ++ } else { ++ len = mm->env_end - mm->env_start; ++ if (len > PAGE_SIZE - res) ++ len = PAGE_SIZE - res; ++ res += access_process_vm(task, mm->env_start, buffer+res, len, 0); ++ res = strnlen(buffer, res); ++ } ++ } ++out_mm: ++ mmput(mm); ++out: ++ return res; ++} ++#endif ++ ++ ++ + void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) + { + int is_kernel = !user_mode(regs); + unsigned long pc = profile_pc(regs); ++ int res=0; + ++#ifdef CONFIG_CHOPSTIX ++ if (rec_event) { ++ struct event esig; ++ struct event_spec espec; ++ /*res = proc_pid_cmdline(current, espec->appname);*/ ++ esig.task = current; ++ espec.pc=pc; ++ espec.count=1; ++ esig.event_data=&espec; ++ esig.event_type=event; /* index in the event array currently set up */ ++ /* make sure the counters are loaded in the order we want them to show up*/ ++ (*rec_event)(&esig, 1); ++ } ++ else { + oprofile_add_ext_sample(pc, regs, event, is_kernel); ++ } ++#else ++ oprofile_add_ext_sample(pc, regs, event, is_kernel); ++#endif ++ ++ + } + + void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event) +diff -Nurb linux-2.6.22-580/fs/exec.c linux-2.6.22-590/fs/exec.c +--- linux-2.6.22-580/fs/exec.c 2008-03-21 18:07:24.000000000 -0400 ++++ linux-2.6.22-590/fs/exec.c 2008-03-21 18:07:50.000000000 -0400 +@@ -52,6 +52,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -488,6 +489,12 @@ + + if (!err) { + struct inode *inode = nd.dentry->d_inode; ++#ifdef CONFIG_CHOPSTIX ++ unsigned long cookie; ++ if (!nd.dentry->d_cookie) ++ get_dcookie(nd.dentry, nd.mnt, &cookie); ++#endif ++ + file = ERR_PTR(-EACCES); + if (!(nd.mnt->mnt_flags & MNT_NOEXEC) && + S_ISREG(inode->i_mode)) { +diff -Nurb linux-2.6.22-580/include/linux/arrays.h linux-2.6.22-590/include/linux/arrays.h +--- linux-2.6.22-580/include/linux/arrays.h 1969-12-31 19:00:00.000000000 -0500 ++++ linux-2.6.22-590/include/linux/arrays.h 2008-03-21 18:07:50.000000000 -0400 +@@ -0,0 +1,35 @@ ++#ifndef __ARRAYS_H__ ++#define __ARRAYS_H__ ++#include ++ ++#define SAMPLING_METHOD_DEFAULT 0 ++#define SAMPLING_METHOD_LOG 1 ++ ++/* Every probe has an array handler */ ++ ++/* XXX - Optimize this structure */ ++ ++struct array_handler { ++ struct list_head link; ++ unsigned int (*hash_func)(void *); ++ unsigned int (*sampling_func)(void *,int,void *); ++ unsigned short size; ++ unsigned int threshold; ++ unsigned char **expcount; ++ unsigned int sampling_method; ++ unsigned int **arrays; ++ unsigned int arraysize; ++ unsigned int num_samples[2]; ++ void **epoch_samples; /* size-sized lists of samples */ ++ unsigned int (*serialize)(void *, void *); ++ unsigned char code[5]; ++}; ++ ++struct event { ++ struct list_head link; ++ void *event_data; ++ unsigned int count; ++ unsigned int event_type; ++ struct task_struct *task; ++}; ++#endif +diff -Nurb linux-2.6.22-580/include/linux/sched.h linux-2.6.22-590/include/linux/sched.h +--- linux-2.6.22-580/include/linux/sched.h 2008-03-21 18:07:27.000000000 -0400 ++++ linux-2.6.22-590/include/linux/sched.h 2008-03-24 15:32:53.000000000 -0400 +@@ -850,6 +850,10 @@ + #endif + unsigned long sleep_avg; + unsigned long long timestamp, last_ran; ++#ifdef CONFIG_CHOPSTIX ++ unsigned long last_interrupted, last_ran_j; ++#endif ++ + unsigned long long sched_time; /* sched_clock time spent running */ + enum sleep_type sleep_type; + +diff -Nurb linux-2.6.22-580/kernel/fork.c linux-2.6.22-590/kernel/fork.c +--- linux-2.6.22-580/kernel/fork.c 2008-03-21 18:07:28.000000000 -0400 ++++ linux-2.6.22-590/kernel/fork.c 2008-03-21 18:07:50.000000000 -0400 +@@ -197,6 +197,11 @@ + tsk->btrace_seq = 0; + #endif + tsk->splice_pipe = NULL; ++ //tsk->cmdline[0]='\0'; ++#ifdef CONFIG_CHOPSTIX ++ tsk->last_interrupted = 0; ++ tsk->last_ran_j = 0; ++#endif + return tsk; + } + +diff -Nurb linux-2.6.22-580/kernel/sched.c linux-2.6.22-590/kernel/sched.c +--- linux-2.6.22-580/kernel/sched.c 2008-03-21 18:07:28.000000000 -0400 ++++ linux-2.6.22-590/kernel/sched.c 2008-03-21 18:07:50.000000000 -0400 +@@ -10,7 +10,7 @@ + * 1998-11-19 Implemented schedule_timeout() and related stuff + * by Andrea Arcangeli + * 2002-01-04 New ultra-scalable O(1) scheduler by Ingo Molnar: +- * hybrid priority-list and round-robin design with ++ * hybrid priority-list and round-robin deventn with + * an array-switch method of distributing timeslices + * and per-CPU runqueues. Cleanups and useful suggestions + * by Davide Libenzi, preemptible kernel bits by Robert Love. +@@ -56,6 +56,7 @@ + + #include + #include ++#include + #include + #include + +@@ -3608,6 +3609,7 @@ + + #endif + ++ + static inline int interactive_sleep(enum sleep_type sleep_type) + { + return (sleep_type == SLEEP_INTERACTIVE || +@@ -3617,16 +3619,54 @@ + /* + * schedule() is the main scheduler function. + */ ++ ++#ifdef CONFIG_CHOPSTIX ++extern void (*rec_event)(void *,unsigned int); ++struct event_spec { ++ unsigned long pc; ++ unsigned long dcookie; ++ unsigned count; ++ unsigned char reason; ++}; ++ ++#define top_esp (THREAD_SIZE - sizeof(unsigned long)) ++#define top_ebp (THREAD_SIZE - 2*sizeof(unsigned long)) ++ ++static inline unsigned long my_get_wchan(struct task_struct *p) ++{ ++ unsigned long ebp, esp, eip; ++ unsigned long stack_page; ++ int count = 0; ++ stack_page = (unsigned long)task_stack_page(p); ++ esp = p->thread.esp; ++ if (!stack_page || esp < stack_page || esp > top_esp+stack_page) ++ return 0; ++ /* include/asm-i386/system.h:switch_to() pushes ebp last. */ ++ ebp = *(unsigned long *) esp; ++ do { ++ if (ebp < stack_page || ebp > top_ebp+stack_page) ++ return 0; ++ eip = *(unsigned long *) (ebp+4); ++ if (!in_sched_functions(eip)) ++ return eip; ++ ebp = *(unsigned long *) ebp; ++ } while (count++ < 16); ++ return 0; ++} ++/* CHOPSTIX */ ++#endif ++ + asmlinkage void __sched schedule(void) + { + struct task_struct *prev, *next; + struct prio_array *array; + struct list_head *queue; + unsigned long long now; +- unsigned long run_time; ++ unsigned long run_time, diff; + int cpu, idx, new_prio; + long *switch_count; + struct rq *rq; ++ int sampling_reason; + + /* + * Test if we are atomic. Since do_exit() needs to call into +@@ -3680,6 +3720,7 @@ + switch_count = &prev->nivcsw; + if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { + switch_count = &prev->nvcsw; ++ + if (unlikely((prev->state & TASK_INTERRUPTIBLE) && + unlikely(signal_pending(prev)))) + prev->state = TASK_RUNNING; +@@ -3689,6 +3730,11 @@ + vx_uninterruptible_inc(prev); + } + deactivate_task(prev, rq); ++#ifdef CONFIG_CHOPSTIX ++ if (prev->state & TASK_INTERRUPTIBLE) { ++ prev->last_interrupted=jiffies; ++ } ++#endif + } + } + +@@ -3763,8 +3809,45 @@ + prev->sleep_avg -= run_time; + if ((long)prev->sleep_avg <= 0) + prev->sleep_avg = 0; ++ + prev->timestamp = prev->last_ran = now; ++#ifdef CONFIG_CHOPSTIX + ++ /* CHOPSTIX */ ++ ++ prev->last_ran_j = jiffies; ++ if (next->last_interrupted) { ++ diff = (jiffies-next->last_interrupted); ++ next->last_interrupted = 0; ++ sampling_reason = 0; ++ } ++ else { ++ diff = jiffies-next->last_ran_j; ++ sampling_reason = 1; ++ } ++ ++ if (rec_event && (diff>HZ/5)) { ++ struct event event; ++ struct event_spec espec; ++ unsigned long eip; ++ unsigned int state = next->state; ++ ++ espec.reason = sampling_reason; ++ ++ next->state = 0; ++ eip = next->thread.esp; ++ next->state = state; ++ ++ next->last_interrupted = 0; ++ event.event_data=&espec; ++ event.task=next; ++ espec.pc=eip; ++ event.event_type=2; ++ /* index in the event array currently set up */ ++ /* make sure the counters are loaded in the order we want them to show up*/ ++ (*rec_event)(&event, diff); ++ } ++#endif + sched_info_switch(prev, next); + if (likely(prev != next)) { + next->timestamp = next->last_ran = now; +@@ -7275,3 +7358,9 @@ + } + + #endif ++ ++#ifdef CONFIG_CHOPSTIX ++void (*rec_event)(void *,unsigned int); ++EXPORT_SYMBOL(rec_event); ++EXPORT_SYMBOL(in_sched_functions); ++#endif -- 2.43.0