Dropping Block I/O probe. Needs work.
[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/entry_32.S linux-2.6.27-591/arch/x86/kernel/entry_32.S
73 --- linux-2.6.27-590/arch/x86/kernel/entry_32.S 2008-10-09 18:13:53.000000000 -0400
74 +++ linux-2.6.27-591/arch/x86/kernel/entry_32.S 2010-01-29 16:30:22.000000000 -0500
75 @@ -426,6 +426,33 @@
76         cmpl $(nr_syscalls), %eax
77         jae syscall_badsys
78  syscall_call:
79 +    /* Move Chopstix syscall probe here */
80 +    /* Save and clobber: eax, ecx, ebp  */
81 +    pushl   %eax
82 +    pushl   %ecx
83 +    pushl   %ebp
84 +    movl    %esp, %ebp
85 +    subl    $SPEC_EVENT_SIZE, %esp 
86 +    movl    rec_event, %ecx
87 +    testl   %ecx, %ecx
88 +    jz  carry_on
89 +    # struct event is first, just below %ebp
90 +    movl    %eax, (SPEC_number-EVENT_SIZE)(%ebp)
91 +    leal    -SPEC_EVENT_SIZE(%ebp), %eax
92 +    movl    %eax, EVENT_event_data(%ebp)
93 +    movl    $6, EVENT_event_type(%ebp)
94 +    movl    rec_event, %edx
95 +    movl    $1, 4(%esp)
96 +    leal    -EVENT_SIZE(%ebp), %eax
97 +    movl    %eax, (%esp)
98 +    call    rec_event_asm 
99 +carry_on: 
100 +    addl $SPEC_EVENT_SIZE, %esp
101 +    popl %ebp
102 +    popl %ecx
103 +    popl %eax
104 +     /* End chopstix */
105 +
106         call *sys_call_table(,%eax,4)
107         movl %eax,PT_EAX(%esp)          # store the return value
108  syscall_exit:
109 diff -Nurb linux-2.6.27-590/arch/x86/mm/fault.c linux-2.6.27-591/arch/x86/mm/fault.c
110 --- linux-2.6.27-590/arch/x86/mm/fault.c        2010-01-29 16:29:46.000000000 -0500
111 +++ linux-2.6.27-591/arch/x86/mm/fault.c        2010-01-29 16:30:22.000000000 -0500
112 @@ -79,6 +79,15 @@
113  #endif
114  }
115  
116 +
117 +extern void (*rec_event)(void *,unsigned int);
118 +struct event_spec {
119 +       unsigned long pc;
120 +       unsigned long dcookie; 
121 +       unsigned count;
122 +       unsigned char reason;
123 +};
124 +
125  /*
126   * X86_32
127   * Sometimes AMD Athlon/Opteron CPUs report invalid exceptions on prefetch.
128 diff -Nurb linux-2.6.27-590/drivers/oprofile/cpu_buffer.c linux-2.6.27-591/drivers/oprofile/cpu_buffer.c
129 --- linux-2.6.27-590/drivers/oprofile/cpu_buffer.c      2008-10-09 18:13:53.000000000 -0400
130 +++ linux-2.6.27-591/drivers/oprofile/cpu_buffer.c      2010-01-29 16:30:22.000000000 -0500
131 @@ -21,6 +21,7 @@
132  #include <linux/oprofile.h>
133  #include <linux/vmalloc.h>
134  #include <linux/errno.h>
135 +#include <linux/arrays.h>
136   
137  #include "event_buffer.h"
138  #include "cpu_buffer.h"
139 @@ -147,6 +148,17 @@
140                 b->head_pos = 0;
141  }
142  
143 +#ifdef CONFIG_CHOPSTIX
144 +
145 +struct event_spec {
146 +       unsigned int pc;
147 +       unsigned long dcookie;
148 +       unsigned count;
149 +};
150 +
151 +extern void (*rec_event)(void *,unsigned int);
152 +#endif
153 +
154  static inline void
155  add_sample(struct oprofile_cpu_buffer * cpu_buf,
156             unsigned long pc, unsigned long event)
157 @@ -155,6 +167,7 @@
158         entry->eip = pc;
159         entry->event = event;
160         increment_head(cpu_buf);
161 +
162  }
163  
164  static inline void
165 @@ -250,8 +263,28 @@
166  {
167         int is_kernel = !user_mode(regs);
168         unsigned long pc = profile_pc(regs);
169 +       int res=0;
170  
171 +#ifdef CONFIG_CHOPSTIX
172 +       if (rec_event) {
173 +               struct event esig;
174 +               struct event_spec espec;
175 +               esig.task = current;
176 +               espec.pc=pc;
177 +               espec.count=1;
178 +               esig.event_data=&espec;
179 +               esig.event_type=event; /* index in the event array currently set up */
180 +                                       /* make sure the counters are loaded in the order we want them to show up*/ 
181 +               (*rec_event)(&esig, 1);
182 +       }
183 +       else {
184         oprofile_add_ext_sample(pc, regs, event, is_kernel);
185 +       }
186 +#else
187 +       oprofile_add_ext_sample(pc, regs, event, is_kernel);
188 +#endif
189 +
190 +
191  }
192  
193  void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event)
194 diff -Nurb linux-2.6.27-590/fs/exec.c linux-2.6.27-591/fs/exec.c
195 --- linux-2.6.27-590/fs/exec.c  2010-01-29 16:29:48.000000000 -0500
196 +++ linux-2.6.27-591/fs/exec.c  2010-01-29 16:45:48.000000000 -0500
197 @@ -27,6 +27,7 @@
198  #include <linux/fdtable.h>
199  #include <linux/mm.h>
200  #include <linux/stat.h>
201 +#include <linux/dcookies.h>
202  #include <linux/fcntl.h>
203  #include <linux/smp_lock.h>
204  #include <linux/swap.h>
205 @@ -698,6 +699,13 @@
206                 goto out;
207         }
208  
209 + #ifdef CONFIG_CHOPSTIX
210 +    unsigned long cookie;
211 +    extern void (*rec_event)(void *, unsigned int);
212 +    if (rec_event && !nd.path.dentry->d_cookie)
213 +        get_dcookie(&nd.path, &cookie);
214 + #endif
215 +
216         return file;
217  
218   out_path_put:
219 diff -Nurb linux-2.6.27-590/include/linux/arrays.h linux-2.6.27-591/include/linux/arrays.h
220 --- linux-2.6.27-590/include/linux/arrays.h     1969-12-31 19:00:00.000000000 -0500
221 +++ linux-2.6.27-591/include/linux/arrays.h     2010-01-29 16:30:22.000000000 -0500
222 @@ -0,0 +1,36 @@
223 +#ifndef __ARRAYS_H__
224 +#define __ARRAYS_H__
225 +#include <linux/list.h>
226 +
227 +#define SAMPLING_METHOD_DEFAULT 0
228 +#define SAMPLING_METHOD_LOG 1
229 +
230 +/* Every probe has an array handler */
231 +
232 +/* XXX - Optimize this structure */
233 +
234 +extern void (*rec_event)(void *,unsigned int);
235 +struct array_handler {
236 +       struct list_head link;
237 +       unsigned int (*hash_func)(void *);
238 +       unsigned int (*sampling_func)(void *,int,void *);
239 +       unsigned short size;
240 +       unsigned int threshold;
241 +       unsigned char **expcount;
242 +       unsigned int sampling_method;
243 +       unsigned int **arrays;
244 +       unsigned int arraysize;
245 +       unsigned int num_samples[2];
246 +       void **epoch_samples; /* size-sized lists of samples */
247 +       unsigned int (*serialize)(void *, void *);
248 +       unsigned char code[5];
249 +};
250 +
251 +struct event {
252 +       struct list_head link;
253 +       void *event_data;
254 +       unsigned int count;
255 +       unsigned int event_type;
256 +       struct task_struct *task;
257 +};
258 +#endif
259 diff -Nurb linux-2.6.27-590/include/linux/sched.h.rej linux-2.6.27-591/include/linux/sched.h.rej
260 --- linux-2.6.27-590/include/linux/sched.h.rej  1969-12-31 19:00:00.000000000 -0500
261 +++ linux-2.6.27-591/include/linux/sched.h.rej  2010-01-29 16:30:22.000000000 -0500
262 @@ -0,0 +1,19 @@
263 +***************
264 +*** 850,855 ****
265 +  #endif
266 +       unsigned long sleep_avg;
267 +       unsigned long long timestamp, last_ran;
268 +       unsigned long long sched_time; /* sched_clock time spent running */
269 +       enum sleep_type sleep_type;
270 +  
271 +--- 850,859 ----
272 +  #endif
273 +       unsigned long sleep_avg;
274 +       unsigned long long timestamp, last_ran;
275 ++ #ifdef CONFIG_CHOPSTIX
276 ++      unsigned long last_interrupted, last_ran_j;
277 ++ #endif
278 ++ 
279 +       unsigned long long sched_time; /* sched_clock time spent running */
280 +       enum sleep_type sleep_type;
281 +  
282 diff -Nurb linux-2.6.27-590/kernel/sched.c linux-2.6.27-591/kernel/sched.c
283 --- linux-2.6.27-590/kernel/sched.c     2010-01-29 16:29:48.000000000 -0500
284 +++ linux-2.6.27-591/kernel/sched.c     2010-01-29 16:30:22.000000000 -0500
285 @@ -10,7 +10,7 @@
286   *  1998-11-19 Implemented schedule_timeout() and related stuff
287   *             by Andrea Arcangeli
288   *  2002-01-04 New ultra-scalable O(1) scheduler by Ingo Molnar:
289 - *             hybrid priority-list and round-robin design with
290 + *             hybrid priority-list and round-robin deventn with
291   *             an array-switch method of distributing timeslices
292   *             and per-CPU runqueues.  Cleanups and useful suggestions
293   *             by Davide Libenzi, preemptible kernel bits by Robert Love.
294 @@ -79,6 +79,9 @@
295  
296  #include "sched_cpupri.h"
297  
298 +#define INTERRUPTIBLE   -1
299 +#define RUNNING         0
300 +
301  /*
302   * Convert user-nice values [ -20 ... 0 ... 19 ]
303   * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
304 @@ -5369,6 +5372,7 @@
305         get_task_struct(p);
306         read_unlock(&tasklist_lock);
307  
308 +
309         retval = -EPERM;
310         if ((current->euid != p->euid) && (current->euid != p->uid) &&
311                         !capable(CAP_SYS_NICE))
312 diff -Nurb linux-2.6.27-590/kernel/sched.c.rej linux-2.6.27-591/kernel/sched.c.rej
313 --- linux-2.6.27-590/kernel/sched.c.rej 1969-12-31 19:00:00.000000000 -0500
314 +++ linux-2.6.27-591/kernel/sched.c.rej 2010-01-29 16:30:22.000000000 -0500
315 @@ -0,0 +1,258 @@
316 +***************
317 +*** 23,28 ****
318 +  #include <linux/nmi.h>
319 +  #include <linux/init.h>
320 +  #include <asm/uaccess.h>
321 +  #include <linux/highmem.h>
322 +  #include <linux/smp_lock.h>
323 +  #include <asm/mmu_context.h>
324 +--- 23,29 ----
325 +  #include <linux/nmi.h>
326 +  #include <linux/init.h>
327 +  #include <asm/uaccess.h>
328 ++ #include <linux/arrays.h>
329 +  #include <linux/highmem.h>
330 +  #include <linux/smp_lock.h>
331 +  #include <asm/mmu_context.h>
332 +***************
333 +*** 451,456 ****
334 +  
335 +  repeat_lock_task:
336 +       rq = task_rq(p);
337 +       spin_lock(&rq->lock);
338 +       if (unlikely(rq != task_rq(p))) {
339 +               spin_unlock(&rq->lock);
340 +--- 455,461 ----
341 +  
342 +  repeat_lock_task:
343 +       rq = task_rq(p);
344 ++ 
345 +       spin_lock(&rq->lock);
346 +       if (unlikely(rq != task_rq(p))) {
347 +               spin_unlock(&rq->lock);
348 +***************
349 +*** 1761,1766 ****
350 +        * event cannot wake it up and insert it on the runqueue either.
351 +        */
352 +       p->state = TASK_RUNNING;
353 +  
354 +       /*
355 +        * Make sure we do not leak PI boosting priority to the child:
356 +--- 1766,1786 ----
357 +        * event cannot wake it up and insert it on the runqueue either.
358 +        */
359 +       p->state = TASK_RUNNING;
360 ++ #ifdef CONFIG_CHOPSTIX
361 ++     /* The jiffy of last interruption */
362 ++     if (p->state & TASK_UNINTERRUPTIBLE) {
363 ++                              p->last_interrupted=jiffies;
364 ++      }
365 ++     else
366 ++     if (p->state & TASK_INTERRUPTIBLE) {
367 ++                              p->last_interrupted=INTERRUPTIBLE;
368 ++      }
369 ++     else
370 ++          p->last_interrupted=RUNNING;
371 ++ 
372 ++     /* The jiffy of last execution */ 
373 ++      p->last_ran_j=jiffies;
374 ++ #endif
375 +  
376 +       /*
377 +        * Make sure we do not leak PI boosting priority to the child:
378 +***************
379 +*** 3628,3633 ****
380 +  
381 +  #endif
382 +  
383 +  static inline int interactive_sleep(enum sleep_type sleep_type)
384 +  {
385 +       return (sleep_type == SLEEP_INTERACTIVE ||
386 +--- 3648,3654 ----
387 +  
388 +  #endif
389 +  
390 ++ 
391 +  static inline int interactive_sleep(enum sleep_type sleep_type)
392 +  {
393 +       return (sleep_type == SLEEP_INTERACTIVE ||
394 +***************
395 +*** 3637,3652 ****
396 +  /*
397 +   * schedule() is the main scheduler function.
398 +   */
399 +  asmlinkage void __sched schedule(void)
400 +  {
401 +       struct task_struct *prev, *next;
402 +       struct prio_array *array;
403 +       struct list_head *queue;
404 +       unsigned long long now;
405 +-      unsigned long run_time;
406 +       int cpu, idx, new_prio;
407 +       long *switch_count;
408 +       struct rq *rq;
409 +  
410 +       /*
411 +        * Test if we are atomic.  Since do_exit() needs to call into
412 +--- 3658,3685 ----
413 +  /*
414 +   * schedule() is the main scheduler function.
415 +   */
416 ++ 
417 ++ #ifdef CONFIG_CHOPSTIX
418 ++ extern void (*rec_event)(void *,unsigned int);
419 ++ struct event_spec {
420 ++      unsigned long pc;
421 ++      unsigned long dcookie;
422 ++      unsigned int count;
423 ++      unsigned int reason;
424 ++ };
425 ++ #endif
426 ++ 
427 +  asmlinkage void __sched schedule(void)
428 +  {
429 +       struct task_struct *prev, *next;
430 +       struct prio_array *array;
431 +       struct list_head *queue;
432 +       unsigned long long now;
433 ++      unsigned long run_time, diff;
434 +       int cpu, idx, new_prio;
435 +       long *switch_count;
436 +       struct rq *rq;
437 ++      int sampling_reason;
438 +  
439 +       /*
440 +        * Test if we are atomic.  Since do_exit() needs to call into
441 +***************
442 +*** 3700,3705 ****
443 +       switch_count = &prev->nivcsw;
444 +       if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
445 +               switch_count = &prev->nvcsw;
446 +               if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
447 +                               unlikely(signal_pending(prev))))
448 +                       prev->state = TASK_RUNNING;
449 +--- 3733,3739 ----
450 +       switch_count = &prev->nivcsw;
451 +       if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
452 +               switch_count = &prev->nvcsw;
453 ++ 
454 +               if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
455 +                               unlikely(signal_pending(prev))))
456 +                       prev->state = TASK_RUNNING;
457 +***************
458 +*** 3709,3714 ****
459 +                               vx_uninterruptible_inc(prev);
460 +                       }
461 +                       deactivate_task(prev, rq);
462 +               }
463 +       }
464 +  
465 +--- 3743,3759 ----
466 +                               vx_uninterruptible_inc(prev);
467 +                       }
468 +                       deactivate_task(prev, rq);
469 ++ #ifdef CONFIG_CHOPSTIX
470 ++             /* An uninterruptible process just yielded. Record the current jiffie */
471 ++                      if (prev->state & TASK_UNINTERRUPTIBLE) {
472 ++                              prev->last_interrupted=jiffies;
473 ++                      }
474 ++             /* An interruptible process just yielded, or it got preempted. 
475 ++              * Mark it as interruptible */
476 ++                      else if (prev->state & TASK_INTERRUPTIBLE) {
477 ++                              prev->last_interrupted=INTERRUPTIBLE;
478 ++                      }
479 ++ #endif
480 +               }
481 +       }
482 +  
483 +***************
484 +*** 3785,3790 ****
485 +               prev->sleep_avg = 0;
486 +       prev->timestamp = prev->last_ran = now;
487 +  
488 +       sched_info_switch(prev, next);
489 +       if (likely(prev != next)) {
490 +               next->timestamp = next->last_ran = now;
491 +--- 3830,3869 ----
492 +               prev->sleep_avg = 0;
493 +       prev->timestamp = prev->last_ran = now;
494 +  
495 ++ #ifdef CONFIG_CHOPSTIX
496 ++      /* Run only if the Chopstix module so decrees it */
497 ++      if (rec_event) {
498 ++              prev->last_ran_j = jiffies;
499 ++              if (next->last_interrupted!=INTERRUPTIBLE) {
500 ++                      if (next->last_interrupted!=RUNNING) {
501 ++                              diff = (jiffies-next->last_interrupted);
502 ++                              sampling_reason = 0;/* BLOCKING */
503 ++                      }
504 ++                      else {
505 ++                              diff = jiffies-next->last_ran_j; 
506 ++                              sampling_reason = 1;/* PREEMPTION */
507 ++                      }
508 ++ 
509 ++                      if (diff >= HZ/10) {
510 ++                              struct event event;
511 ++                              struct event_spec espec;
512 ++                 struct pt_regs *regs;
513 ++                 regs = task_pt_regs(current);
514 ++ 
515 ++                              espec.reason = sampling_reason;
516 ++                              event.event_data=&espec;
517 ++                              event.task=next;
518 ++                              espec.pc=regs->ip;
519 ++                              event.event_type=2; 
520 ++                              /* index in the event array currently set up */
521 ++                              /* make sure the counters are loaded in the order we want them to show up*/ 
522 ++                              (*rec_event)(&event, diff);
523 ++                      }
524 ++              }
525 ++         /* next has been elected to run */
526 ++              next->last_interrupted=0;
527 ++      }
528 ++ #endif
529 +       sched_info_switch(prev, next);
530 +       if (likely(prev != next)) {
531 +               next->timestamp = next->last_ran = now;
532 +***************
533 +*** 5737,5742 ****
534 +       jiffies_to_timespec(p->policy == SCHED_FIFO ?
535 +                               0 : task_timeslice(p), &t);
536 +       read_unlock(&tasklist_lock);
537 +       retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
538 +  out_nounlock:
539 +       return retval;
540 +--- 5817,5823 ----
541 +       jiffies_to_timespec(p->policy == SCHED_FIFO ?
542 +                               0 : task_timeslice(p), &t);
543 +       read_unlock(&tasklist_lock);
544 ++ 
545 +       retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
546 +  out_nounlock:
547 +       return retval;
548 +***************
549 +*** 7980,7982 ****
550 +  }
551 +  
552 +  #endif
553 +--- 8061,8080 ----
554 +  }
555 +  
556 +  #endif
557 ++ 
558 ++ #ifdef CONFIG_CHOPSTIX
559 ++ void (*rec_event)(void *,unsigned int) = NULL;
560 ++ 
561 ++ /* To support safe calling from asm */
562 ++ asmlinkage void rec_event_asm (struct event *event_signature_in, unsigned int count) {
563 ++     struct pt_regs *regs;
564 ++     struct event_spec *es = event_signature_in->event_data;
565 ++     regs = task_pt_regs(current);
566 ++      event_signature_in->task=current;
567 ++      es->pc=regs->ip;
568 ++     event_signature_in->count=1;
569 ++     (*rec_event)(event_signature_in, count);
570 ++ }
571 ++ EXPORT_SYMBOL(rec_event);
572 ++ EXPORT_SYMBOL(in_sched_functions);
573 ++ #endif
574 diff -Nurb linux-2.6.27-590/mm/memory.c linux-2.6.27-591/mm/memory.c
575 --- linux-2.6.27-590/mm/memory.c        2010-01-29 16:29:48.000000000 -0500
576 +++ linux-2.6.27-591/mm/memory.c        2010-01-29 16:30:22.000000000 -0500
577 @@ -61,6 +61,7 @@
578  
579  #include <linux/swapops.h>
580  #include <linux/elf.h>
581 +#include <linux/arrays.h>
582  
583  #include "internal.h"
584  
585 @@ -2690,6 +2691,15 @@
586         return ret;
587  }
588  
589 +extern void (*rec_event)(void *,unsigned int);
590 +struct event_spec {
591 +       unsigned long pc;
592 +       unsigned long dcookie; 
593 +       unsigned count;
594 +       unsigned char reason;
595 +};
596 +
597 +
598  /*
599   * By the time we get here, we already hold the mm semaphore
600   */
601 @@ -2719,6 +2729,24 @@
602         if (!pte)
603                 return VM_FAULT_OOM;
604  
605 +#ifdef CONFIG_CHOPSTIX
606 +       if (rec_event) {
607 +               struct event event;
608 +               struct event_spec espec;
609 +        struct pt_regs *regs;
610 +        unsigned int pc;
611 +        regs = task_pt_regs(current);
612 +        pc = regs->ip & (unsigned int) ~4095;
613 +
614 +               espec.reason = 0; /* alloc */
615 +               event.event_data=&espec;
616 +               event.task = current;
617 +               espec.pc=pc;
618 +               event.event_type=5; 
619 +               (*rec_event)(&event, 1);
620 +       }
621 +#endif
622 +
623         return handle_pte_fault(mm, vma, address, pte, pmd, write_access);
624  }
625  
626 diff -Nurb linux-2.6.27-590/mm/slab.c linux-2.6.27-591/mm/slab.c
627 --- linux-2.6.27-590/mm/slab.c  2010-01-29 16:29:48.000000000 -0500
628 +++ linux-2.6.27-591/mm/slab.c  2010-01-29 16:30:22.000000000 -0500
629 @@ -110,6 +110,7 @@
630  #include       <linux/fault-inject.h>
631  #include       <linux/rtmutex.h>
632  #include       <linux/reciprocal_div.h>
633 +#include <linux/arrays.h>
634  #include       <linux/debugobjects.h>
635  
636  #include       <asm/cacheflush.h>
637 @@ -248,6 +249,14 @@
638         void *addr;
639  };
640  
641 +extern void (*rec_event)(void *,unsigned int);
642 +struct event_spec {
643 +       unsigned long pc;
644 +       unsigned long dcookie; 
645 +       unsigned count;
646 +       unsigned char reason;
647 +};
648 +
649  /*
650   * struct array_cache
651   *
652 @@ -3469,6 +3478,19 @@
653         local_irq_restore(save_flags);
654         objp = cache_alloc_debugcheck_after(cachep, flags, objp, caller);
655         prefetchw(objp);
656 +#ifdef CONFIG_CHOPSTIX
657 +       if (rec_event && objp) {
658 +               struct event event;
659 +               struct event_spec espec;
660 +
661 +               espec.reason = 0; /* alloc */
662 +               event.event_data=&espec;
663 +               event.task = current;
664 +               espec.pc=caller;
665 +               event.event_type=5; 
666 +               (*rec_event)(&event, cachep->buffer_size);
667 +       }
668 +#endif
669  
670         if (unlikely((flags & __GFP_ZERO) && objp))
671                 memset(objp, 0, obj_size(cachep));
672 @@ -3578,12 +3600,26 @@
673   * Release an obj back to its cache. If the obj has a constructed state, it must
674   * be in this state _before_ it is released.  Called with disabled ints.
675   */
676 -static inline void __cache_free(struct kmem_cache *cachep, void *objp)
677 +static inline void __cache_free(struct kmem_cache *cachep, void *objp, void *caller)
678  {
679         struct array_cache *ac = cpu_cache_get(cachep);
680  
681         check_irq_off();
682 -       objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
683 +       objp = cache_free_debugcheck(cachep, objp, caller);
684 + #ifdef CONFIG_CHOPSTIX
685 +       if (rec_event && objp) {
686 +               struct event event;
687 +               struct event_spec espec;
688 +  
689 +               espec.reason = 1; /* free */
690 +               event.event_data=&espec;
691 +               event.task = current;
692 +               espec.pc=caller;
693 +               event.event_type=4; 
694 +               (*rec_event)(&event, cachep->buffer_size);
695 +       }
696 + #endif
697 +
698         vx_slab_free(cachep);
699  
700         /*
701 @@ -3714,6 +3750,7 @@
702                                           void *caller)
703  {
704         struct kmem_cache *cachep;
705 +       void *ret;
706  
707         /* If you want to save a few bytes .text space: replace
708          * __ with kmem_.
709 @@ -3741,10 +3778,17 @@
710  EXPORT_SYMBOL(__kmalloc_track_caller);
711  
712  #else
713 +#ifdef CONFIG_CHOPSTIX
714 +void *__kmalloc(size_t size, gfp_t flags)
715 +{
716 +       return __do_kmalloc(size, flags, __builtin_return_address(0));
717 +}
718 +#else
719  void *__kmalloc(size_t size, gfp_t flags)
720  {
721         return __do_kmalloc(size, flags, NULL);
722  }
723 +#endif
724  EXPORT_SYMBOL(__kmalloc);
725  #endif
726  
727 @@ -3764,7 +3808,7 @@
728         debug_check_no_locks_freed(objp, obj_size(cachep));
729         if (!(cachep->flags & SLAB_DEBUG_OBJECTS))
730                 debug_check_no_obj_freed(objp, obj_size(cachep));
731 -       __cache_free(cachep, objp);
732 +       __cache_free(cachep, objp,__builtin_return_address(0));
733         local_irq_restore(flags);
734  }
735  EXPORT_SYMBOL(kmem_cache_free);
736 @@ -3790,7 +3834,7 @@
737         c = virt_to_cache(objp);
738         debug_check_no_locks_freed(objp, obj_size(c));
739         debug_check_no_obj_freed(objp, obj_size(c));
740 -       __cache_free(c, (void *)objp);
741 +       __cache_free(c, (void *)objp,__builtin_return_address(0));
742         local_irq_restore(flags);
743  }
744  EXPORT_SYMBOL(kfree);