Chopstix base patch.
authorSapan Bhatia <sapanb@cs.princeton.edu>
Wed, 27 Feb 2008 19:25:04 +0000 (19:25 +0000)
committerSapan Bhatia <sapanb@cs.princeton.edu>
Wed, 27 Feb 2008 19:25:04 +0000 (19:25 +0000)
Awriiggggggggggggghht!!!

kernel-2.6.spec
linux-2.6-590-chopstix-intern.patch [new file with mode: 0644]

index 1db746e..133a97f 100644 (file)
@@ -163,6 +163,7 @@ Patch550: linux-2.6-550-raise-default-nfile-ulimit.patch
 Patch560: linux-2.6-560-mmconf.patch
 Patch570: linux-2.6-570-tagxid.patch
 Patch580: linux-2.6-580-show-proc-virt.patch
+Patch590: linux-2.6-590-chopstix-intern.patch
 
 # See also the file named 'sources' here for the related checksums
 # NOTE. iwlwifi should be in-kernel starting from 2.6.24
@@ -351,6 +352,7 @@ KERNEL_PREVIOUS=vanilla
 %ApplyPatch 560
 %ApplyPatch 570
 %ApplyPatch 580
+%ApplyPatch 590
 
 # NetNS conflict-resolving patch for VINI. Will work with patch vini_pl_patch-1 but may
 # break with later patches.
diff --git a/linux-2.6-590-chopstix-intern.patch b/linux-2.6-590-chopstix-intern.patch
new file mode 100644 (file)
index 0000000..5798a1b
--- /dev/null
@@ -0,0 +1,382 @@
+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-02-27 13:53:47.000000000 -0500
+@@ -21,6 +21,7 @@
+ #include <linux/oprofile.h>
+ #include <linux/vmalloc.h>
+ #include <linux/errno.h>
++#include <linux/arrays.h>
+  
+ #include "event_buffer.h"
+ #include "cpu_buffer.h"
+@@ -143,6 +144,14 @@
+               b->head_pos = 0;
+ }
++struct event_spec {
++      unsigned int pc;
++      unsigned long dcookie;
++      unsigned count;
++};
++
++extern void (*rec_event)(void *,unsigned int);
++
+ static inline void
+ add_sample(struct oprofile_cpu_buffer * cpu_buf,
+            unsigned long pc, unsigned long event)
+@@ -151,6 +160,7 @@
+       entry->eip = pc;
+       entry->event = event;
+       increment_head(cpu_buf);
++
+ }
+ static inline void
+@@ -237,12 +247,66 @@
+       oprofile_end_trace(cpu_buf);
+ }
++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;
++}
++
++
++
+ 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;
++      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);
++      }
+ }
+ void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event)
+diff -Nurb linux-2.6.22-580/drivers/oprofile/oprof.c linux-2.6.22-590/drivers/oprofile/oprof.c
+--- linux-2.6.22-580/drivers/oprofile/oprof.c  2007-07-08 19:32:17.000000000 -0400
++++ linux-2.6.22-590/drivers/oprofile/oprof.c  2008-02-27 13:48:29.000000000 -0500
+@@ -33,6 +33,8 @@
+  */
+ static int timer = 0;
++extern void *rec_event;
++
+ int oprofile_setup(void)
+ {
+       int err;
+@@ -53,7 +55,7 @@
+        * us missing task deaths and eventually oopsing
+        * when trying to process the event buffer.
+        */
+-      if ((err = sync_start()))
++      if (err = sync_start())
+               goto out3;
+       is_setup = 1;
+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-02-27 13:46:38.000000000 -0500
++++ linux-2.6.22-590/fs/exec.c 2008-02-27 13:49:58.000000000 -0500
+@@ -52,6 +52,7 @@
+ #include <linux/audit.h>
+ #include <linux/signalfd.h>
+ #include <linux/vs_memory.h>
++#include <linux/dcookies.h>
+ #include <asm/uaccess.h>
+ #include <asm/mmu_context.h>
+@@ -488,6 +489,10 @@
+       if (!err) {
+               struct inode *inode = nd.dentry->d_inode;
++              unsigned long cookie;
++              if (!nd.dentry->d_cookie)
++                      get_dcookie(nd.dentry, nd.mnt, &cookie);
++
+               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-02-27 13:48:29.000000000 -0500
+@@ -0,0 +1,35 @@
++#ifndef __ARRAYS_H__
++#define __ARRAYS_H__
++#include <linux/list.h>
++
++#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-02-27 13:46:40.000000000 -0500
++++ linux-2.6.22-590/include/linux/sched.h     2008-02-27 13:48:29.000000000 -0500
+@@ -849,7 +849,7 @@
+       unsigned int btrace_seq;
+ #endif
+       unsigned long sleep_avg;
+-      unsigned long long timestamp, last_ran;
++      unsigned long long timestamp, last_ran, last_interrupted, last_ran_j;
+       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-02-27 13:46:40.000000000 -0500
++++ linux-2.6.22-590/kernel/fork.c     2008-02-27 13:48:29.000000000 -0500
+@@ -197,6 +197,8 @@
+       tsk->btrace_seq = 0;
+ #endif
+       tsk->splice_pipe = NULL;
++      //tsk->cmdline[0]='\0';
++      tsk->last_interrupted = 0;
+       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-02-27 13:46:40.000000000 -0500
++++ linux-2.6.22-590/kernel/sched.c    2008-02-27 14:08:26.000000000 -0500
+@@ -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 <asm/tlb.h>
+ #include <asm/unistd.h>
++#include <linux/arrays.h>
+ #include <linux/vs_sched.h>
+ #include <linux/vs_cvirt.h>
+@@ -3608,6 +3609,8 @@
+ #endif
++extern void (*rec_event)(void *,unsigned int);
++
+ static inline int interactive_sleep(enum sleep_type sleep_type)
+ {
+       return (sleep_type == SLEEP_INTERACTIVE ||
+@@ -3617,16 +3620,51 @@
+ /*
+  * schedule() is the main scheduler function.
+  */
++
++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 */
++
+ 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 +3718,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 +3728,9 @@
+                               vx_uninterruptible_inc(prev);
+                       }
+                       deactivate_task(prev, rq);
++                      if (prev->state & TASK_INTERRUPTIBLE) {
++                              prev->last_interrupted=jiffies;
++                      }
+               }
+       }
+@@ -3763,8 +3805,44 @@
+       prev->sleep_avg -= run_time;
+       if ((long)prev->sleep_avg <= 0)
+               prev->sleep_avg = 0;
++      
+       prev->timestamp = prev->last_ran = now;
++      /* 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);
++      }
++
+       sched_info_switch(prev, next);
+       if (likely(prev != next)) {
+               next->timestamp = next->last_ran = now;
+@@ -7275,3 +7353,7 @@
+ }
+ #endif
++
++void (*rec_event)(void *,unsigned int);
++EXPORT_SYMBOL(rec_event);
++EXPORT_SYMBOL(in_sched_functions);
+diff -Nurb linux-2.6.22-580/kernel/sched.c.rej linux-2.6.22-590/kernel/sched.c.rej
+--- linux-2.6.22-580/kernel/sched.c.rej        1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.22-590/kernel/sched.c.rej        2008-02-27 13:48:29.000000000 -0500
+@@ -0,0 +1,18 @@
++***************
++*** 56,61 ****
++  
++  #include <asm/tlb.h>
++  #include <asm/unistd.h>
++  
++  /*
++   * Scheduler clock - returns current time in nanosec units.
++--- 56,64 ----
++  
++  #include <asm/tlb.h>
++  #include <asm/unistd.h>
+++ #include <linux/arrays.h>
+++ 
+++ 
++  
++  /*
++   * Scheduler clock - returns current time in nanosec units.