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