f1e0215f99bd6baaa0efbc786ee37bbb63a85e1f
[linux-2.6.git] / linux-2.6-591-chopstix-intern.patch
1 diff -Nurb linux-2.6.27-590/arch/Kconfig linux-2.6.27-591/arch/Kconfig
2 --- linux-2.6.27-590/arch/Kconfig       2010-01-29 16:29:46.000000000 -0500
3 +++ linux-2.6.27-591/arch/Kconfig       2010-01-29 16:30:22.000000000 -0500
4 @@ -13,9 +13,18 @@
5  
6           If unsure, say N.
7  
8 +config CHOPSTIX
9 +       bool "Chopstix (PlanetLab)"
10 +       depends on MODULES && OPROFILE
11 +       help
12 +         Chopstix allows you to monitor various events by summarizing them
13 +         in lossy data structures and transferring these data structures
14 +         into user space. If in doubt, say "N".
15 +
16  config HAVE_OPROFILE
17         def_bool n
18  
19 +
20  config KPROBES
21         bool "Kprobes"
22         depends on KALLSYMS && MODULES
23 diff -Nurb linux-2.6.27-590/arch/x86/kernel/asm-offsets_32.c linux-2.6.27-591/arch/x86/kernel/asm-offsets_32.c
24 --- linux-2.6.27-590/arch/x86/kernel/asm-offsets_32.c   2008-10-09 18:13:53.000000000 -0400
25 +++ linux-2.6.27-591/arch/x86/kernel/asm-offsets_32.c   2010-01-29 16:45:48.000000000 -0500
26 @@ -9,6 +9,7 @@
27  #include <linux/signal.h>
28  #include <linux/personality.h>
29  #include <linux/suspend.h>
30 +#include <linux/arrays.h>
31  #include <linux/kbuild.h>
32  #include <asm/ucontext.h>
33  #include "sigframe.h"
34 @@ -24,9 +25,20 @@
35  #include <linux/lguest.h>
36  #include "../../../drivers/lguest/lg.h"
37  
38 +
39 +#define STACKOFFSET(sym, str, mem) \
40 +       DEFINE(sym, offsetof(struct str, mem)-sizeof(struct str));
41 +
42  /* workaround for a warning with -Wmissing-prototypes */
43  void foo(void);
44  
45 +struct event_spec {
46 +       unsigned long pc;
47 +       unsigned long dcookie;
48 +       unsigned count;
49 +       unsigned int number;
50 +};
51 +
52  void foo(void)
53  {
54         OFFSET(IA32_SIGCONTEXT_ax, sigcontext, ax);
55 @@ -50,6 +62,16 @@
56         OFFSET(CPUINFO_x86_vendor_id, cpuinfo_x86, x86_vendor_id);
57         BLANK();
58  
59 +    STACKOFFSET(TASK_thread, task_struct, thread);
60 +    STACKOFFSET(THREAD_esp, thread_struct, sp);
61 +    STACKOFFSET(EVENT_event_data, event, event_data);
62 +    STACKOFFSET(EVENT_task, event, task);
63 +    STACKOFFSET(EVENT_event_type, event, event_type);
64 +    STACKOFFSET(SPEC_number, event_spec, number);
65 +    DEFINE(EVENT_SIZE, sizeof(struct event));
66 +    DEFINE(SPEC_SIZE, sizeof(struct event_spec));
67 +    DEFINE(SPEC_EVENT_SIZE, sizeof(struct event_spec)+sizeof(struct event));
68 +
69         OFFSET(TI_task, thread_info, task);
70         OFFSET(TI_exec_domain, thread_info, exec_domain);
71         OFFSET(TI_flags, thread_info, flags);
72 diff -Nurb linux-2.6.27-590/arch/x86/kernel/asm-offsets_32.c.rej linux-2.6.27-591/arch/x86/kernel/asm-offsets_32.c.rej
73 --- linux-2.6.27-590/arch/x86/kernel/asm-offsets_32.c.rej       1969-12-31 19:00:00.000000000 -0500
74 +++ linux-2.6.27-591/arch/x86/kernel/asm-offsets_32.c.rej       2010-01-31 22:21:08.000000000 -0500
75 @@ -0,0 +1,17 @@
76 +***************
77 +*** 63,69 ****
78 +       BLANK();
79 +  
80 +      STACKOFFSET(TASK_thread, task_struct, thread);
81 +-     STACKOFFSET(THREAD_esp, thread_struct, esp);
82 +      STACKOFFSET(EVENT_event_data, event, event_data);
83 +      STACKOFFSET(EVENT_task, event, task);
84 +      STACKOFFSET(EVENT_event_type, event, event_type);
85 +--- 63,69 ----
86 +       BLANK();
87 +  
88 +      STACKOFFSET(TASK_thread, task_struct, thread);
89 ++     STACKOFFSET(THREAD_esp, thread_struct, sp);
90 +      STACKOFFSET(EVENT_event_data, event, event_data);
91 +      STACKOFFSET(EVENT_task, event, task);
92 +      STACKOFFSET(EVENT_event_type, event, event_type);
93 diff -Nurb linux-2.6.27-590/arch/x86/kernel/entry_32.S linux-2.6.27-591/arch/x86/kernel/entry_32.S
94 --- linux-2.6.27-590/arch/x86/kernel/entry_32.S 2008-10-09 18:13:53.000000000 -0400
95 +++ linux-2.6.27-591/arch/x86/kernel/entry_32.S 2010-01-29 16:30:22.000000000 -0500
96 @@ -426,6 +426,33 @@
97         cmpl $(nr_syscalls), %eax
98         jae syscall_badsys
99  syscall_call:
100 +    /* Move Chopstix syscall probe here */
101 +    /* Save and clobber: eax, ecx, ebp  */
102 +    pushl   %eax
103 +    pushl   %ecx
104 +    pushl   %ebp
105 +    movl    %esp, %ebp
106 +    subl    $SPEC_EVENT_SIZE, %esp 
107 +    movl    rec_event, %ecx
108 +    testl   %ecx, %ecx
109 +    jz  carry_on
110 +    # struct event is first, just below %ebp
111 +    movl    %eax, (SPEC_number-EVENT_SIZE)(%ebp)
112 +    leal    -SPEC_EVENT_SIZE(%ebp), %eax
113 +    movl    %eax, EVENT_event_data(%ebp)
114 +    movl    $6, EVENT_event_type(%ebp)
115 +    movl    rec_event, %edx
116 +    movl    $1, 4(%esp)
117 +    leal    -EVENT_SIZE(%ebp), %eax
118 +    movl    %eax, (%esp)
119 +    call    rec_event_asm 
120 +carry_on: 
121 +    addl $SPEC_EVENT_SIZE, %esp
122 +    popl %ebp
123 +    popl %ecx
124 +    popl %eax
125 +     /* End chopstix */
126 +
127         call *sys_call_table(,%eax,4)
128         movl %eax,PT_EAX(%esp)          # store the return value
129  syscall_exit:
130 diff -Nurb linux-2.6.27-590/arch/x86/mm/fault.c linux-2.6.27-591/arch/x86/mm/fault.c
131 --- linux-2.6.27-590/arch/x86/mm/fault.c        2010-01-29 16:29:46.000000000 -0500
132 +++ linux-2.6.27-591/arch/x86/mm/fault.c        2010-01-29 16:30:22.000000000 -0500
133 @@ -79,6 +79,15 @@
134  #endif
135  }
136  
137 +
138 +extern void (*rec_event)(void *,unsigned int);
139 +struct event_spec {
140 +       unsigned long pc;
141 +       unsigned long dcookie; 
142 +       unsigned count;
143 +       unsigned char reason;
144 +};
145 +
146  /*
147   * X86_32
148   * Sometimes AMD Athlon/Opteron CPUs report invalid exceptions on prefetch.
149 diff -Nurb linux-2.6.27-590/drivers/oprofile/cpu_buffer.c linux-2.6.27-591/drivers/oprofile/cpu_buffer.c
150 --- linux-2.6.27-590/drivers/oprofile/cpu_buffer.c      2008-10-09 18:13:53.000000000 -0400
151 +++ linux-2.6.27-591/drivers/oprofile/cpu_buffer.c      2010-01-29 16:30:22.000000000 -0500
152 @@ -21,6 +21,7 @@
153  #include <linux/oprofile.h>
154  #include <linux/vmalloc.h>
155  #include <linux/errno.h>
156 +#include <linux/arrays.h>
157   
158  #include "event_buffer.h"
159  #include "cpu_buffer.h"
160 @@ -147,6 +148,17 @@
161                 b->head_pos = 0;
162  }
163  
164 +#ifdef CONFIG_CHOPSTIX
165 +
166 +struct event_spec {
167 +       unsigned int pc;
168 +       unsigned long dcookie;
169 +       unsigned count;
170 +};
171 +
172 +extern void (*rec_event)(void *,unsigned int);
173 +#endif
174 +
175  static inline void
176  add_sample(struct oprofile_cpu_buffer * cpu_buf,
177             unsigned long pc, unsigned long event)
178 @@ -155,6 +167,7 @@
179         entry->eip = pc;
180         entry->event = event;
181         increment_head(cpu_buf);
182 +
183  }
184  
185  static inline void
186 @@ -250,8 +263,28 @@
187  {
188         int is_kernel = !user_mode(regs);
189         unsigned long pc = profile_pc(regs);
190 +       int res=0;
191  
192 +#ifdef CONFIG_CHOPSTIX
193 +       if (rec_event) {
194 +               struct event esig;
195 +               struct event_spec espec;
196 +               esig.task = current;
197 +               espec.pc=pc;
198 +               espec.count=1;
199 +               esig.event_data=&espec;
200 +               esig.event_type=event; /* index in the event array currently set up */
201 +                                       /* make sure the counters are loaded in the order we want them to show up*/ 
202 +               (*rec_event)(&esig, 1);
203 +       }
204 +       else {
205         oprofile_add_ext_sample(pc, regs, event, is_kernel);
206 +       }
207 +#else
208 +       oprofile_add_ext_sample(pc, regs, event, is_kernel);
209 +#endif
210 +
211 +
212  }
213  
214  void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event)
215 diff -Nurb linux-2.6.27-590/fs/bio.c linux-2.6.27-591/fs/bio.c
216 --- linux-2.6.27-590/fs/bio.c   2008-10-09 18:13:53.000000000 -0400
217 +++ linux-2.6.27-591/fs/bio.c   2010-01-31 22:21:09.000000000 -0500
218 @@ -27,6 +27,7 @@
219  #include <linux/workqueue.h>
220  #include <linux/blktrace_api.h>
221  #include <scsi/sg.h>           /* for struct sg_iovec */
222 +#include <linux/arrays.h>
223  
224  static struct kmem_cache *bio_slab __read_mostly;
225  
226 @@ -44,6 +45,7 @@
227  };
228  #undef BV
229  
230 +
231  /*
232   * fs_bio_set is the bio_set containing bio and iovec memory pools used by
233   * IO code that does not need private memory pools.
234 @@ -1171,6 +1173,14 @@
235         }
236  }
237  
238 +struct event_spec {
239 +       unsigned long pc;
240 +       unsigned long dcookie;
241 +       unsigned count;
242 +       unsigned char reason;
243 +};
244 +
245 +extern void (*rec_event)(void *,unsigned int);
246  /**
247   * bio_endio - end I/O on a bio
248   * @bio:       bio
249 @@ -1192,6 +1202,24 @@
250         else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
251                 error = -EIO;
252  
253 +#if 0
254 +               if (rec_event) {
255 +                       struct event event;
256 +                       struct event_spec espec;
257 +                       unsigned long eip;
258 +                       
259 +                       espec.reason = 1;/*response */
260 +
261 +                       eip = bio->bi_end_io;
262 +                       event.event_data=&espec;
263 +                       espec.pc=eip;
264 +                       event.event_type=3; 
265 +                       /* index in the event array currently set up */
266 +                       /* make sure the counters are loaded in the order we want them to show up*/ 
267 +                       (*rec_event)(&event, bytes_done);
268 +               }
269 +#endif
270 +
271         if (bio->bi_end_io)
272                 bio->bi_end_io(bio, error);
273  }
274 diff -Nurb linux-2.6.27-590/fs/exec.c linux-2.6.27-591/fs/exec.c
275 --- linux-2.6.27-590/fs/exec.c  2010-01-29 16:29:48.000000000 -0500
276 +++ linux-2.6.27-591/fs/exec.c  2010-01-29 16:45:48.000000000 -0500
277 @@ -27,6 +27,7 @@
278  #include <linux/fdtable.h>
279  #include <linux/mm.h>
280  #include <linux/stat.h>
281 +#include <linux/dcookies.h>
282  #include <linux/fcntl.h>
283  #include <linux/smp_lock.h>
284  #include <linux/swap.h>
285 @@ -698,6 +699,13 @@
286                 goto out;
287         }
288  
289 + #ifdef CONFIG_CHOPSTIX
290 +    unsigned long cookie;
291 +    extern void (*rec_event)(void *, unsigned int);
292 +    if (rec_event && !nd.dentry->d_cookie)
293 +        get_dcookie(nd.dentry, nd.mnt, &cookie);
294 + #endif
295 +
296         return file;
297  
298   out_path_put:
299 diff -Nurb linux-2.6.27-590/fs/exec.c.rej linux-2.6.27-591/fs/exec.c.rej
300 --- linux-2.6.27-590/fs/exec.c.rej      1969-12-31 19:00:00.000000000 -0500
301 +++ linux-2.6.27-591/fs/exec.c.rej      2010-01-31 22:21:18.000000000 -0500
302 @@ -0,0 +1,36 @@
303 +***************
304 +*** 40,46 ****
305 +  #include <linux/personality.h>
306 +  #include <linux/binfmts.h>
307 +  #include <linux/utsname.h>
308 +- /*#include <linux/pid_namespace.h>*/
309 +  #include <linux/module.h>
310 +  #include <linux/namei.h>
311 +  #include <linux/proc_fs.h>
312 +--- 40,46 ----
313 +  #include <linux/personality.h>
314 +  #include <linux/binfmts.h>
315 +  #include <linux/utsname.h>
316 ++ #include <linux/pid_namespace.h>
317 +  #include <linux/module.h>
318 +  #include <linux/namei.h>
319 +  #include <linux/proc_fs.h>
320 +***************
321 +*** 702,709 ****
322 +   #ifdef CONFIG_CHOPSTIX
323 +      unsigned long cookie;
324 +      extern void (*rec_event)(void *, unsigned int);
325 +-     if (rec_event && !nd.dentry->d_cookie)
326 +-         get_dcookie(nd.dentry, nd.mnt, &cookie);
327 +   #endif
328 +  
329 +       return file;
330 +--- 702,709 ----
331 +   #ifdef CONFIG_CHOPSTIX
332 +      unsigned long cookie;
333 +      extern void (*rec_event)(void *, unsigned int);
334 ++     if (rec_event && !nd.path.dentry->d_cookie)
335 ++         get_dcookie(&nd.path, &cookie);
336 +   #endif
337 +  
338 +       return file;
339 diff -Nurb linux-2.6.27-590/include/linux/arrays.h linux-2.6.27-591/include/linux/arrays.h
340 --- linux-2.6.27-590/include/linux/arrays.h     1969-12-31 19:00:00.000000000 -0500
341 +++ linux-2.6.27-591/include/linux/arrays.h     2010-01-29 16:30:22.000000000 -0500
342 @@ -0,0 +1,36 @@
343 +#ifndef __ARRAYS_H__
344 +#define __ARRAYS_H__
345 +#include <linux/list.h>
346 +
347 +#define SAMPLING_METHOD_DEFAULT 0
348 +#define SAMPLING_METHOD_LOG 1
349 +
350 +/* Every probe has an array handler */
351 +
352 +/* XXX - Optimize this structure */
353 +
354 +extern void (*rec_event)(void *,unsigned int);
355 +struct array_handler {
356 +       struct list_head link;
357 +       unsigned int (*hash_func)(void *);
358 +       unsigned int (*sampling_func)(void *,int,void *);
359 +       unsigned short size;
360 +       unsigned int threshold;
361 +       unsigned char **expcount;
362 +       unsigned int sampling_method;
363 +       unsigned int **arrays;
364 +       unsigned int arraysize;
365 +       unsigned int num_samples[2];
366 +       void **epoch_samples; /* size-sized lists of samples */
367 +       unsigned int (*serialize)(void *, void *);
368 +       unsigned char code[5];
369 +};
370 +
371 +struct event {
372 +       struct list_head link;
373 +       void *event_data;
374 +       unsigned int count;
375 +       unsigned int event_type;
376 +       struct task_struct *task;
377 +};
378 +#endif
379 diff -Nurb linux-2.6.27-590/include/linux/sched.h.rej linux-2.6.27-591/include/linux/sched.h.rej
380 --- linux-2.6.27-590/include/linux/sched.h.rej  1969-12-31 19:00:00.000000000 -0500
381 +++ linux-2.6.27-591/include/linux/sched.h.rej  2010-01-29 16:30:22.000000000 -0500
382 @@ -0,0 +1,19 @@
383 +***************
384 +*** 850,855 ****
385 +  #endif
386 +       unsigned long sleep_avg;
387 +       unsigned long long timestamp, last_ran;
388 +       unsigned long long sched_time; /* sched_clock time spent running */
389 +       enum sleep_type sleep_type;
390 +  
391 +--- 850,859 ----
392 +  #endif
393 +       unsigned long sleep_avg;
394 +       unsigned long long timestamp, last_ran;
395 ++ #ifdef CONFIG_CHOPSTIX
396 ++      unsigned long last_interrupted, last_ran_j;
397 ++ #endif
398 ++ 
399 +       unsigned long long sched_time; /* sched_clock time spent running */
400 +       enum sleep_type sleep_type;
401 +  
402 diff -Nurb linux-2.6.27-590/kernel/sched.c linux-2.6.27-591/kernel/sched.c
403 --- linux-2.6.27-590/kernel/sched.c     2010-01-29 16:29:48.000000000 -0500
404 +++ linux-2.6.27-591/kernel/sched.c     2010-01-31 22:21:08.000000000 -0500
405 @@ -10,7 +10,7 @@
406   *  1998-11-19 Implemented schedule_timeout() and related stuff
407   *             by Andrea Arcangeli
408   *  2002-01-04 New ultra-scalable O(1) scheduler by Ingo Molnar:
409 - *             hybrid priority-list and round-robin design with
410 + *             hybrid priority-list and round-robin deventn with
411   *             an array-switch method of distributing timeslices
412   *             and per-CPU runqueues.  Cleanups and useful suggestions
413   *             by Davide Libenzi, preemptible kernel bits by Robert Love.
414 @@ -73,12 +73,16 @@
415  #include <linux/ftrace.h>
416  #include <linux/vs_sched.h>
417  #include <linux/vs_cvirt.h>
418 +#include <linux/arrays.h>
419  
420  #include <asm/tlb.h>
421  #include <asm/irq_regs.h>
422  
423  #include "sched_cpupri.h"
424  
425 +#define INTERRUPTIBLE   -1
426 +#define RUNNING         0
427 +
428  /*
429   * Convert user-nice values [ -20 ... 0 ... 19 ]
430   * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
431 @@ -4428,6 +4432,29 @@
432         }
433  }
434  
435 +void (*rec_event)(void *,unsigned int) = NULL;
436 +EXPORT_SYMBOL(rec_event);
437 +#ifdef CONFIG_CHOPSTIX
438 +
439 +struct event_spec {
440 +    unsigned long pc;
441 +    unsigned long dcookie;
442 +    unsigned int count;
443 +    unsigned int reason;
444 +};
445 +
446 +/* To support safe calling from asm */
447 +asmlinkage void rec_event_asm (struct event *event_signature_in, unsigned int count) {
448 +    struct pt_regs *regs;
449 +    struct event_spec *es = event_signature_in->event_data;
450 +    regs = task_pt_regs(current);
451 +    event_signature_in->task=current;
452 +    es->pc=regs->ip;
453 +    event_signature_in->count=1;
454 +    (*rec_event)(event_signature_in, count);
455 +}
456 +#endif
457 +
458  /*
459   * schedule() is the main scheduler function.
460   */
461 @@ -5369,6 +5396,7 @@
462         get_task_struct(p);
463         read_unlock(&tasklist_lock);
464  
465 +
466         retval = -EPERM;
467         if ((current->euid != p->euid) && (current->euid != p->uid) &&
468                         !capable(CAP_SYS_NICE))
469 @@ -9296,3 +9324,26 @@
470         .subsys_id = cpuacct_subsys_id,
471  };
472  #endif /* CONFIG_CGROUP_CPUACCT */
473 +
474 +#ifdef CONFIG_CHOPSTIX
475 +void (*rec_event)();
476 +EXPORT_SYMBOL(rec_event);
477 +
478 +struct event_spec {
479 +    unsigned long pc;
480 +    unsigned long dcookie;
481 +    unsigned int count;
482 +    unsigned int reason;
483 +};
484 +
485 +/* To support safe calling from asm */
486 +asmlinkage void rec_event_asm (struct event *event_signature_in, unsigned int count) {
487 +    struct pt_regs *regs;
488 +    struct event_spec *es = event_signature_in->event_data;
489 +    regs = task_pt_regs(current);
490 +    event_signature_in->task=current;
491 +    es->pc=regs->ip;
492 +    event_signature_in->count=1;
493 +    (*rec_event)(event_signature_in, count);
494 +}
495 +#endif
496 diff -Nurb linux-2.6.27-590/kernel/sched.c.rej linux-2.6.27-591/kernel/sched.c.rej
497 --- linux-2.6.27-590/kernel/sched.c.rej 1969-12-31 19:00:00.000000000 -0500
498 +++ linux-2.6.27-591/kernel/sched.c.rej 2010-01-29 16:30:22.000000000 -0500
499 @@ -0,0 +1,258 @@
500 +***************
501 +*** 23,28 ****
502 +  #include <linux/nmi.h>
503 +  #include <linux/init.h>
504 +  #include <asm/uaccess.h>
505 +  #include <linux/highmem.h>
506 +  #include <linux/smp_lock.h>
507 +  #include <asm/mmu_context.h>
508 +--- 23,29 ----
509 +  #include <linux/nmi.h>
510 +  #include <linux/init.h>
511 +  #include <asm/uaccess.h>
512 ++ #include <linux/arrays.h>
513 +  #include <linux/highmem.h>
514 +  #include <linux/smp_lock.h>
515 +  #include <asm/mmu_context.h>
516 +***************
517 +*** 451,456 ****
518 +  
519 +  repeat_lock_task:
520 +       rq = task_rq(p);
521 +       spin_lock(&rq->lock);
522 +       if (unlikely(rq != task_rq(p))) {
523 +               spin_unlock(&rq->lock);
524 +--- 455,461 ----
525 +  
526 +  repeat_lock_task:
527 +       rq = task_rq(p);
528 ++ 
529 +       spin_lock(&rq->lock);
530 +       if (unlikely(rq != task_rq(p))) {
531 +               spin_unlock(&rq->lock);
532 +***************
533 +*** 1761,1766 ****
534 +        * event cannot wake it up and insert it on the runqueue either.
535 +        */
536 +       p->state = TASK_RUNNING;
537 +  
538 +       /*
539 +        * Make sure we do not leak PI boosting priority to the child:
540 +--- 1766,1786 ----
541 +        * event cannot wake it up and insert it on the runqueue either.
542 +        */
543 +       p->state = TASK_RUNNING;
544 ++ #ifdef CONFIG_CHOPSTIX
545 ++     /* The jiffy of last interruption */
546 ++     if (p->state & TASK_UNINTERRUPTIBLE) {
547 ++                              p->last_interrupted=jiffies;
548 ++      }
549 ++     else
550 ++     if (p->state & TASK_INTERRUPTIBLE) {
551 ++                              p->last_interrupted=INTERRUPTIBLE;
552 ++      }
553 ++     else
554 ++          p->last_interrupted=RUNNING;
555 ++ 
556 ++     /* The jiffy of last execution */ 
557 ++      p->last_ran_j=jiffies;
558 ++ #endif
559 +  
560 +       /*
561 +        * Make sure we do not leak PI boosting priority to the child:
562 +***************
563 +*** 3628,3633 ****
564 +  
565 +  #endif
566 +  
567 +  static inline int interactive_sleep(enum sleep_type sleep_type)
568 +  {
569 +       return (sleep_type == SLEEP_INTERACTIVE ||
570 +--- 3648,3654 ----
571 +  
572 +  #endif
573 +  
574 ++ 
575 +  static inline int interactive_sleep(enum sleep_type sleep_type)
576 +  {
577 +       return (sleep_type == SLEEP_INTERACTIVE ||
578 +***************
579 +*** 3637,3652 ****
580 +  /*
581 +   * schedule() is the main scheduler function.
582 +   */
583 +  asmlinkage void __sched schedule(void)
584 +  {
585 +       struct task_struct *prev, *next;
586 +       struct prio_array *array;
587 +       struct list_head *queue;
588 +       unsigned long long now;
589 +-      unsigned long run_time;
590 +       int cpu, idx, new_prio;
591 +       long *switch_count;
592 +       struct rq *rq;
593 +  
594 +       /*
595 +        * Test if we are atomic.  Since do_exit() needs to call into
596 +--- 3658,3685 ----
597 +  /*
598 +   * schedule() is the main scheduler function.
599 +   */
600 ++ 
601 ++ #ifdef CONFIG_CHOPSTIX
602 ++ extern void (*rec_event)(void *,unsigned int);
603 ++ struct event_spec {
604 ++      unsigned long pc;
605 ++      unsigned long dcookie;
606 ++      unsigned int count;
607 ++      unsigned int reason;
608 ++ };
609 ++ #endif
610 ++ 
611 +  asmlinkage void __sched schedule(void)
612 +  {
613 +       struct task_struct *prev, *next;
614 +       struct prio_array *array;
615 +       struct list_head *queue;
616 +       unsigned long long now;
617 ++      unsigned long run_time, diff;
618 +       int cpu, idx, new_prio;
619 +       long *switch_count;
620 +       struct rq *rq;
621 ++      int sampling_reason;
622 +  
623 +       /*
624 +        * Test if we are atomic.  Since do_exit() needs to call into
625 +***************
626 +*** 3700,3705 ****
627 +       switch_count = &prev->nivcsw;
628 +       if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
629 +               switch_count = &prev->nvcsw;
630 +               if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
631 +                               unlikely(signal_pending(prev))))
632 +                       prev->state = TASK_RUNNING;
633 +--- 3733,3739 ----
634 +       switch_count = &prev->nivcsw;
635 +       if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
636 +               switch_count = &prev->nvcsw;
637 ++ 
638 +               if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
639 +                               unlikely(signal_pending(prev))))
640 +                       prev->state = TASK_RUNNING;
641 +***************
642 +*** 3709,3714 ****
643 +                               vx_uninterruptible_inc(prev);
644 +                       }
645 +                       deactivate_task(prev, rq);
646 +               }
647 +       }
648 +  
649 +--- 3743,3759 ----
650 +                               vx_uninterruptible_inc(prev);
651 +                       }
652 +                       deactivate_task(prev, rq);
653 ++ #ifdef CONFIG_CHOPSTIX
654 ++             /* An uninterruptible process just yielded. Record the current jiffie */
655 ++                      if (prev->state & TASK_UNINTERRUPTIBLE) {
656 ++                              prev->last_interrupted=jiffies;
657 ++                      }
658 ++             /* An interruptible process just yielded, or it got preempted. 
659 ++              * Mark it as interruptible */
660 ++                      else if (prev->state & TASK_INTERRUPTIBLE) {
661 ++                              prev->last_interrupted=INTERRUPTIBLE;
662 ++                      }
663 ++ #endif
664 +               }
665 +       }
666 +  
667 +***************
668 +*** 3785,3790 ****
669 +               prev->sleep_avg = 0;
670 +       prev->timestamp = prev->last_ran = now;
671 +  
672 +       sched_info_switch(prev, next);
673 +       if (likely(prev != next)) {
674 +               next->timestamp = next->last_ran = now;
675 +--- 3830,3869 ----
676 +               prev->sleep_avg = 0;
677 +       prev->timestamp = prev->last_ran = now;
678 +  
679 ++ #ifdef CONFIG_CHOPSTIX
680 ++      /* Run only if the Chopstix module so decrees it */
681 ++      if (rec_event) {
682 ++              prev->last_ran_j = jiffies;
683 ++              if (next->last_interrupted!=INTERRUPTIBLE) {
684 ++                      if (next->last_interrupted!=RUNNING) {
685 ++                              diff = (jiffies-next->last_interrupted);
686 ++                              sampling_reason = 0;/* BLOCKING */
687 ++                      }
688 ++                      else {
689 ++                              diff = jiffies-next->last_ran_j; 
690 ++                              sampling_reason = 1;/* PREEMPTION */
691 ++                      }
692 ++ 
693 ++                      if (diff >= HZ/10) {
694 ++                              struct event event;
695 ++                              struct event_spec espec;
696 ++                 struct pt_regs *regs;
697 ++                 regs = task_pt_regs(current);
698 ++ 
699 ++                              espec.reason = sampling_reason;
700 ++                              event.event_data=&espec;
701 ++                              event.task=next;
702 ++                              espec.pc=regs->eip;
703 ++                              event.event_type=2; 
704 ++                              /* index in the event array currently set up */
705 ++                              /* make sure the counters are loaded in the order we want them to show up*/ 
706 ++                              (*rec_event)(&event, diff);
707 ++                      }
708 ++              }
709 ++         /* next has been elected to run */
710 ++              next->last_interrupted=0;
711 ++      }
712 ++ #endif
713 +       sched_info_switch(prev, next);
714 +       if (likely(prev != next)) {
715 +               next->timestamp = next->last_ran = now;
716 +***************
717 +*** 5737,5742 ****
718 +       jiffies_to_timespec(p->policy == SCHED_FIFO ?
719 +                               0 : task_timeslice(p), &t);
720 +       read_unlock(&tasklist_lock);
721 +       retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
722 +  out_nounlock:
723 +       return retval;
724 +--- 5817,5823 ----
725 +       jiffies_to_timespec(p->policy == SCHED_FIFO ?
726 +                               0 : task_timeslice(p), &t);
727 +       read_unlock(&tasklist_lock);
728 ++ 
729 +       retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
730 +  out_nounlock:
731 +       return retval;
732 +***************
733 +*** 7980,7982 ****
734 +  }
735 +  
736 +  #endif
737 +--- 8061,8080 ----
738 +  }
739 +  
740 +  #endif
741 ++ 
742 ++ #ifdef CONFIG_CHOPSTIX
743 ++ void (*rec_event)(void *,unsigned int) = NULL;
744 ++ 
745 ++ /* To support safe calling from asm */
746 ++ asmlinkage void rec_event_asm (struct event *event_signature_in, unsigned int count) {
747 ++     struct pt_regs *regs;
748 ++     struct event_spec *es = event_signature_in->event_data;
749 ++     regs = task_pt_regs(current);
750 ++      event_signature_in->task=current;
751 ++      es->pc=regs->eip;
752 ++     event_signature_in->count=1;
753 ++     (*rec_event)(event_signature_in, count);
754 ++ }
755 ++ EXPORT_SYMBOL(rec_event);
756 ++ EXPORT_SYMBOL(in_sched_functions);
757 ++ #endif
758 diff -Nurb linux-2.6.27-590/mm/memory.c linux-2.6.27-591/mm/memory.c
759 --- linux-2.6.27-590/mm/memory.c        2010-01-29 16:29:48.000000000 -0500
760 +++ linux-2.6.27-591/mm/memory.c        2010-01-31 22:21:18.000000000 -0500
761 @@ -61,6 +61,7 @@
762  
763  #include <linux/swapops.h>
764  #include <linux/elf.h>
765 +#include <linux/arrays.h>
766  
767  #include "internal.h"
768  
769 @@ -2690,6 +2691,15 @@
770         return ret;
771  }
772  
773 +extern void (*rec_event)(void *,unsigned int);
774 +struct event_spec {
775 +       unsigned long pc;
776 +       unsigned long dcookie; 
777 +       unsigned count;
778 +       unsigned char reason;
779 +};
780 +
781 +
782  /*
783   * By the time we get here, we already hold the mm semaphore
784   */
785 @@ -2719,6 +2729,24 @@
786         if (!pte)
787                 return VM_FAULT_OOM;
788  
789 +#ifdef CONFIG_CHOPSTIX
790 +       if (rec_event) {
791 +               struct event event;
792 +               struct event_spec espec;
793 +        struct pt_regs *regs;
794 +        unsigned int pc;
795 +        regs = task_pt_regs(current);
796 +        pc = regs->ip & (unsigned int) ~4095;
797 +
798 +               espec.reason = 0; /* alloc */
799 +               event.event_data=&espec;
800 +               event.task = current;
801 +               espec.pc=pc;
802 +               event.event_type=5; 
803 +               (*rec_event)(&event, 1);
804 +       }
805 +#endif
806 +
807         return handle_pte_fault(mm, vma, address, pte, pmd, write_access);
808  }
809  
810 diff -Nurb linux-2.6.27-590/mm/slab.c linux-2.6.27-591/mm/slab.c
811 --- linux-2.6.27-590/mm/slab.c  2010-01-29 16:29:48.000000000 -0500
812 +++ linux-2.6.27-591/mm/slab.c  2010-01-29 16:30:22.000000000 -0500
813 @@ -110,6 +110,7 @@
814  #include       <linux/fault-inject.h>
815  #include       <linux/rtmutex.h>
816  #include       <linux/reciprocal_div.h>
817 +#include <linux/arrays.h>
818  #include       <linux/debugobjects.h>
819  
820  #include       <asm/cacheflush.h>
821 @@ -248,6 +249,14 @@
822         void *addr;
823  };
824  
825 +extern void (*rec_event)(void *,unsigned int);
826 +struct event_spec {
827 +       unsigned long pc;
828 +       unsigned long dcookie; 
829 +       unsigned count;
830 +       unsigned char reason;
831 +};
832 +
833  /*
834   * struct array_cache
835   *
836 @@ -3469,6 +3478,19 @@
837         local_irq_restore(save_flags);
838         objp = cache_alloc_debugcheck_after(cachep, flags, objp, caller);
839         prefetchw(objp);
840 +#ifdef CONFIG_CHOPSTIX
841 +       if (rec_event && objp) {
842 +               struct event event;
843 +               struct event_spec espec;
844 +
845 +               espec.reason = 0; /* alloc */
846 +               event.event_data=&espec;
847 +               event.task = current;
848 +               espec.pc=caller;
849 +               event.event_type=5; 
850 +               (*rec_event)(&event, cachep->buffer_size);
851 +       }
852 +#endif
853  
854         if (unlikely((flags & __GFP_ZERO) && objp))
855                 memset(objp, 0, obj_size(cachep));
856 @@ -3578,12 +3600,26 @@
857   * Release an obj back to its cache. If the obj has a constructed state, it must
858   * be in this state _before_ it is released.  Called with disabled ints.
859   */
860 -static inline void __cache_free(struct kmem_cache *cachep, void *objp)
861 +static inline void __cache_free(struct kmem_cache *cachep, void *objp, void *caller)
862  {
863         struct array_cache *ac = cpu_cache_get(cachep);
864  
865         check_irq_off();
866 -       objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
867 +       objp = cache_free_debugcheck(cachep, objp, caller);
868 + #ifdef CONFIG_CHOPSTIX
869 +       if (rec_event && objp) {
870 +               struct event event;
871 +               struct event_spec espec;
872 +  
873 +               espec.reason = 1; /* free */
874 +               event.event_data=&espec;
875 +               event.task = current;
876 +               espec.pc=caller;
877 +               event.event_type=4; 
878 +               (*rec_event)(&event, cachep->buffer_size);
879 +       }
880 + #endif
881 +
882         vx_slab_free(cachep);
883  
884         /*
885 @@ -3714,6 +3750,7 @@
886                                           void *caller)
887  {
888         struct kmem_cache *cachep;
889 +       void *ret;
890  
891         /* If you want to save a few bytes .text space: replace
892          * __ with kmem_.
893 @@ -3741,10 +3778,17 @@
894  EXPORT_SYMBOL(__kmalloc_track_caller);
895  
896  #else
897 +#ifdef CONFIG_CHOPSTIX
898 +void *__kmalloc(size_t size, gfp_t flags)
899 +{
900 +       return __do_kmalloc(size, flags, __builtin_return_address(0));
901 +}
902 +#else
903  void *__kmalloc(size_t size, gfp_t flags)
904  {
905         return __do_kmalloc(size, flags, NULL);
906  }
907 +#endif
908  EXPORT_SYMBOL(__kmalloc);
909  #endif
910  
911 @@ -3764,7 +3808,7 @@
912         debug_check_no_locks_freed(objp, obj_size(cachep));
913         if (!(cachep->flags & SLAB_DEBUG_OBJECTS))
914                 debug_check_no_obj_freed(objp, obj_size(cachep));
915 -       __cache_free(cachep, objp);
916 +       __cache_free(cachep, objp,__builtin_return_address(0));
917         local_irq_restore(flags);
918  }
919  EXPORT_SYMBOL(kmem_cache_free);
920 @@ -3790,7 +3834,7 @@
921         c = virt_to_cache(objp);
922         debug_check_no_locks_freed(objp, obj_size(c));
923         debug_check_no_obj_freed(objp, obj_size(c));
924 -       __cache_free(c, (void *)objp);
925 +       __cache_free(c, (void *)objp,__builtin_return_address(0));
926         local_irq_restore(flags);
927  }
928  EXPORT_SYMBOL(kfree);