daf166a63b440a4fa33ffa4ab1a5372e9002664c
[linux-2.6.git] / linux-2.6-590-chopstix-intern.patch
1 diff -Nurb --exclude='*.cmd' --exclude='*.orig' --exclude='*.swp' --exclude=tags --exclude='*.patch' --exclude='*.diff' --exclude='*.svn*' linux-2.6.22-590/arch/i386/Kconfig linux-2.6.22-591/arch/i386/Kconfig
2 --- linux-2.6.22-590/arch/i386/Kconfig  2009-03-16 20:49:42.000000000 -0400
3 +++ linux-2.6.22-591/arch/i386/Kconfig  2009-03-16 20:58:59.000000000 -0400
4 @@ -1217,6 +1217,14 @@
5  
6  source "arch/i386/oprofile/Kconfig"
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 KPROBES
17         bool "Kprobes (EXPERIMENTAL)"
18         depends on KALLSYMS && EXPERIMENTAL && MODULES
19 --- linux-2.6.22-590/arch/i386/kernel/asm-offsets.c     2007-07-08 19:32:17.000000000 -0400
20 +++ linux-2.6.22-591/arch/i386/kernel/asm-offsets.c     2009-03-16 20:58:59.000000000 -0400
21 @@ -9,6 +9,7 @@
22  #include <linux/signal.h>
23  #include <linux/personality.h>
24  #include <linux/suspend.h>
25 +#include <linux/arrays.h>
26  #include <asm/ucontext.h>
27  #include "sigframe.h"
28  #include <asm/pgtable.h>
29 @@ -25,9 +26,19 @@
30  #define OFFSET(sym, str, mem) \
31         DEFINE(sym, offsetof(struct str, mem));
32  
33 +#define STACKOFFSET(sym, str, mem) \
34 +       DEFINE(sym, offsetof(struct str, mem)-sizeof(struct str));
35 +
36  /* workaround for a warning with -Wmissing-prototypes */
37  void foo(void);
38  
39 +struct event_spec {
40 +       unsigned long pc;
41 +       unsigned long dcookie;
42 +       unsigned count;
43 +       unsigned int number;
44 +};
45 +
46  void foo(void)
47  {
48         OFFSET(SIGCONTEXT_eax, sigcontext, eax);
49 @@ -51,7 +62,16 @@
50         OFFSET(CPUINFO_x86_vendor_id, cpuinfo_x86, x86_vendor_id);
51         BLANK();
52  
53 -       OFFSET(TI_task, thread_info, task);
54 +    STACKOFFSET(TASK_thread, task_struct, thread);
55 +    STACKOFFSET(THREAD_esp, thread_struct, esp);
56 +    STACKOFFSET(EVENT_event_data, event, event_data);
57 +    STACKOFFSET(EVENT_task, event, task);
58 +    STACKOFFSET(EVENT_event_type, event, event_type);
59 +    STACKOFFSET(SPEC_number, event_spec, number);
60 +    DEFINE(EVENT_SIZE, sizeof(struct event));
61 +    DEFINE(SPEC_SIZE, sizeof(struct event_spec));
62 +    DEFINE(SPEC_EVENT_SIZE, sizeof(struct event_spec)+sizeof(struct event));
63 +
64         OFFSET(TI_exec_domain, thread_info, exec_domain);
65         OFFSET(TI_flags, thread_info, flags);
66         OFFSET(TI_status, thread_info, status);
67 --- linux-2.6.22-590/arch/i386/mm/fault.c       2009-03-16 20:49:42.000000000 -0400
68 +++ linux-2.6.22-591/arch/i386/mm/fault.c       2009-03-16 20:58:59.000000000 -0400
69 @@ -60,6 +60,15 @@
70                                           DIE_PAGE_FAULT, &args);
71  }
72  
73 +
74 +extern void (*rec_event)(void *,unsigned int);
75 +struct event_spec {
76 +       unsigned long pc;
77 +       unsigned long dcookie; 
78 +       unsigned count;
79 +       unsigned char reason;
80 +};
81 +
82  /*
83   * Return EIP plus the CS segment base.  The segment limit is also
84   * adjusted, clamped to the kernel/user address space (whichever is
85 @@ -296,6 +305,8 @@
86   *     bit 3 == 1 means use of reserved bit detected
87   *     bit 4 == 1 means fault was an instruction fetch
88   */
89 +
90 +
91  fastcall void __kprobes do_page_fault(struct pt_regs *regs,
92                                       unsigned long error_code)
93  {
94 --- linux-2.6.22-590/block/ll_rw_blk.c  2009-03-16 20:49:07.000000000 -0400
95 +++ linux-2.6.22-591/block/ll_rw_blk.c  2009-03-16 20:58:59.000000000 -0400
96 @@ -30,6 +30,7 @@
97  #include <linux/cpu.h>
98  #include <linux/blktrace_api.h>
99  #include <linux/fault-inject.h>
100 +#include <linux/arrays.h>
101  
102  /*
103   * for max sense size
104 @@ -3102,6 +3103,13 @@
105  
106  #endif /* CONFIG_FAIL_MAKE_REQUEST */
107  
108 +extern void (*rec_event)(void *,unsigned int);
109 +struct event_spec {
110 +       unsigned long pc;
111 +       unsigned long dcookie;
112 +       unsigned count;
113 +       unsigned char reason;
114 +};
115  /**
116   * generic_make_request: hand a buffer to its device driver for I/O
117   * @bio:  The bio describing the location in memory and on the device.
118 @@ -3220,7 +3228,23 @@
119                                 goto end_io;
120                         }
121                 }
122 -
123 +#ifdef CONFIG_CHOPSTIX
124 +               if (rec_event) {
125 +                       struct event event;
126 +                       struct event_spec espec;
127 +                       unsigned long eip;
128 +                       
129 +                       espec.reason = 0;/*request */
130 +
131 +                       eip = bio->bi_end_io;
132 +                       event.event_data=&espec;
133 +                       espec.pc=eip;
134 +                       event.event_type=3; 
135 +                       /* index in the event array currently set up */
136 +                       /* make sure the counters are loaded in the order we want them to show up*/ 
137 +                       (*rec_event)(&event, bio->bi_size);
138 +               }
139 +#endif
140                 ret = q->make_request_fn(q, bio);
141         } while (ret);
142  }
143 --- linux-2.6.22-590/drivers/oprofile/cpu_buffer.c      2007-07-08 19:32:17.000000000 -0400
144 +++ linux-2.6.22-591/drivers/oprofile/cpu_buffer.c      2009-03-16 20:58:59.000000000 -0400
145 @@ -21,6 +21,7 @@
146  #include <linux/oprofile.h>
147  #include <linux/vmalloc.h>
148  #include <linux/errno.h>
149 +#include <linux/arrays.h>
150   
151  #include "event_buffer.h"
152  #include "cpu_buffer.h"
153 @@ -143,6 +144,17 @@
154                 b->head_pos = 0;
155  }
156  
157 +#ifdef CONFIG_CHOPSTIX
158 +
159 +struct event_spec {
160 +       unsigned int pc;
161 +       unsigned long dcookie;
162 +       unsigned count;
163 +};
164 +
165 +extern void (*rec_event)(void *,unsigned int);
166 +#endif
167 +
168  static inline void
169  add_sample(struct oprofile_cpu_buffer * cpu_buf,
170             unsigned long pc, unsigned long event)
171 @@ -151,6 +163,7 @@
172         entry->eip = pc;
173         entry->event = event;
174         increment_head(cpu_buf);
175 +
176  }
177  
178  static inline void
179 @@ -241,8 +254,28 @@
180  {
181         int is_kernel = !user_mode(regs);
182         unsigned long pc = profile_pc(regs);
183 +       int res=0;
184  
185 +#ifdef CONFIG_CHOPSTIX
186 +       if (rec_event) {
187 +               struct event esig;
188 +               struct event_spec espec;
189 +               esig.task = current;
190 +               espec.pc=pc;
191 +               espec.count=1;
192 +               esig.event_data=&espec;
193 +               esig.event_type=event; /* index in the event array currently set up */
194 +                                       /* make sure the counters are loaded in the order we want them to show up*/ 
195 +               (*rec_event)(&esig, 1);
196 +       }
197 +       else {
198         oprofile_add_ext_sample(pc, regs, event, is_kernel);
199 +       }
200 +#else
201 +       oprofile_add_ext_sample(pc, regs, event, is_kernel);
202 +#endif
203 +
204 +
205  }
206  
207  void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event)
208 --- linux-2.6.22-590/fs/bio.c   2007-07-08 19:32:17.000000000 -0400
209 +++ linux-2.6.22-591/fs/bio.c   2009-03-16 20:58:59.000000000 -0400
210 @@ -27,6 +27,7 @@
211  #include <linux/workqueue.h>
212  #include <linux/blktrace_api.h>
213  #include <scsi/sg.h>           /* for struct sg_iovec */
214 +#include <linux/arrays.h>
215  
216  #define BIO_POOL_SIZE 2
217  
218 @@ -47,6 +48,7 @@
219         struct kmem_cache *slab;
220  };
221  
222 +
223  /*
224   * if you change this list, also change bvec_alloc or things will
225   * break badly! cannot be bigger than what you can fit into an
226 @@ -999,6 +1001,14 @@
227         }
228  }
229  
230 +struct event_spec {
231 +       unsigned long pc;
232 +       unsigned long dcookie;
233 +       unsigned count;
234 +       unsigned char reason;
235 +};
236 +
237 +extern void (*rec_event)(void *,unsigned int);
238  /**
239   * bio_endio - end I/O on a bio
240   * @bio:       bio
241 @@ -1028,6 +1038,24 @@
242         bio->bi_size -= bytes_done;
243         bio->bi_sector += (bytes_done >> 9);
244  
245 +#ifdef CONFIG_CHOPSTIX
246 +               if (rec_event) {
247 +                       struct event event;
248 +                       struct event_spec espec;
249 +                       unsigned long eip;
250 +                       
251 +                       espec.reason = 1;/*response */
252 +
253 +                       eip = bio->bi_end_io;
254 +                       event.event_data=&espec;
255 +                       espec.pc=eip;
256 +                       event.event_type=3; 
257 +                       /* index in the event array currently set up */
258 +                       /* make sure the counters are loaded in the order we want them to show up*/ 
259 +                       (*rec_event)(&event, bytes_done);
260 +               }
261 +#endif
262 +
263         if (bio->bi_end_io)
264                 bio->bi_end_io(bio, bytes_done, error);
265  }
266 --- linux-2.6.22-590/fs/exec.c  2009-03-16 20:49:42.000000000 -0400
267 +++ linux-2.6.22-591/fs/exec.c  2009-03-16 20:58:59.000000000 -0400
268 @@ -27,6 +27,7 @@
269  #include <linux/mman.h>
270  #include <linux/a.out.h>
271  #include <linux/stat.h>
272 +#include <linux/dcookies.h>
273  #include <linux/fcntl.h>
274  #include <linux/smp_lock.h>
275  #include <linux/init.h>
276 @@ -38,7 +39,7 @@
277  #include <linux/binfmts.h>
278  #include <linux/swap.h>
279  #include <linux/utsname.h>
280 -#include <linux/pid_namespace.h>
281 +/*#include <linux/pid_namespace.h>*/
282  #include <linux/module.h>
283  #include <linux/namei.h>
284  #include <linux/proc_fs.h>
285 @@ -488,6 +489,12 @@
286  
287         if (!err) {
288                 struct inode *inode = nd.dentry->d_inode;
289 +#ifdef CONFIG_CHOPSTIX
290 +               unsigned long cookie;
291 +               if (!nd.dentry->d_cookie)
292 +                       get_dcookie(nd.dentry, nd.mnt, &cookie);
293 +#endif
294 +
295                 file = ERR_PTR(-EACCES);
296                 if (!(nd.mnt->mnt_flags & MNT_NOEXEC) &&
297                     S_ISREG(inode->i_mode)) {
298 @@ -627,8 +634,10 @@
299          * Reparenting needs write_lock on tasklist_lock,
300          * so it is safe to do it under read_lock.
301          */
302 +       /*
303         if (unlikely(tsk->group_leader == child_reaper(tsk)))
304                 tsk->nsproxy->pid_ns->child_reaper = tsk;
305 +               */
306  
307         zap_other_threads(tsk);
308         read_unlock(&tasklist_lock);
309 --- linux-2.6.22-590/include/linux/arrays.h     1969-12-31 19:00:00.000000000 -0500
310 +++ linux-2.6.22-591/include/linux/arrays.h     2009-03-16 20:58:59.000000000 -0400
311 @@ -0,0 +1,36 @@
312 +#ifndef __ARRAYS_H__
313 +#define __ARRAYS_H__
314 +#include <linux/list.h>
315 +
316 +#define SAMPLING_METHOD_DEFAULT 0
317 +#define SAMPLING_METHOD_LOG 1
318 +
319 +/* Every probe has an array handler */
320 +
321 +/* XXX - Optimize this structure */
322 +
323 +extern void (*rec_event)(void *,unsigned int);
324 +struct array_handler {
325 +       struct list_head link;
326 +       unsigned int (*hash_func)(void *);
327 +       unsigned int (*sampling_func)(void *,int,void *);
328 +       unsigned short size;
329 +       unsigned int threshold;
330 +       unsigned char **expcount;
331 +       unsigned int sampling_method;
332 +       unsigned int **arrays;
333 +       unsigned int arraysize;
334 +       unsigned int num_samples[2];
335 +       void **epoch_samples; /* size-sized lists of samples */
336 +       unsigned int (*serialize)(void *, void *);
337 +       unsigned char code[5];
338 +};
339 +
340 +struct event {
341 +       struct list_head link;
342 +       void *event_data;
343 +       unsigned int count;
344 +       unsigned int event_type;
345 +       struct task_struct *task;
346 +};
347 +#endif
348 --- linux-2.6.22-590/include/linux/mutex.h      2007-07-08 19:32:17.000000000 -0400
349 +++ linux-2.6.22-591/include/linux/mutex.h      2009-03-16 20:58:59.000000000 -0400
350 @@ -53,6 +53,10 @@
351         struct thread_info      *owner;
352         const char              *name;
353         void                    *magic;
354 +#else
355 +#ifdef CONFIG_CHOPSTIX
356 +       struct thread_info      *owner;
357 +#endif
358  #endif
359  #ifdef CONFIG_DEBUG_LOCK_ALLOC
360         struct lockdep_map      dep_map;
361 --- linux-2.6.22-590/include/linux/sched.h      2009-03-16 20:49:42.000000000 -0400
362 +++ linux-2.6.22-591/include/linux/sched.h      2009-03-16 20:58:59.000000000 -0400
363 @@ -850,6 +850,10 @@
364  #endif
365         unsigned long sleep_avg;
366         unsigned long long timestamp, last_ran;
367 +#ifdef CONFIG_CHOPSTIX
368 +       unsigned long last_interrupted, last_ran_j;
369 +#endif
370 +
371         unsigned long long sched_time; /* sched_clock time spent running */
372         enum sleep_type sleep_type;
373  
374 --- linux-2.6.22-590/kernel/mutex.c     2007-07-08 19:32:17.000000000 -0400
375 +++ linux-2.6.22-591/kernel/mutex.c     2009-03-16 20:58:59.000000000 -0400
376 @@ -18,6 +18,17 @@
377  #include <linux/spinlock.h>
378  #include <linux/interrupt.h>
379  #include <linux/debug_locks.h>
380 +#include <linux/arrays.h>
381 +
382 +#undef CONFIG_CHOPSTIX
383 +#ifdef CONFIG_CHOPSTIX
384 +struct event_spec {
385 +       unsigned long pc;
386 +       unsigned long dcookie;
387 +       unsigned count;
388 +       unsigned char reason;
389 +};
390 +#endif
391  
392  /*
393   * In the DEBUG case we are using the "NULL fastpath" for mutexes,
394 @@ -43,6 +54,9 @@
395  __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key)
396  {
397         atomic_set(&lock->count, 1);
398 +#ifdef CONFIG_CHOPSTIX
399 +       lock->owner=NULL;
400 +#endif
401         spin_lock_init(&lock->wait_lock);
402         INIT_LIST_HEAD(&lock->wait_list);
403  
404 @@ -88,6 +102,7 @@
405          * The locking fastpath is the 1->0 transition from
406          * 'unlocked' into 'locked' state.
407          */
408 +
409         __mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath);
410  }
411  
412 @@ -168,6 +183,27 @@
413                 }
414                 __set_task_state(task, state);
415  
416 +#ifdef CONFIG_CHOPSTIX
417 +               if (rec_event) {
418 +                       if (lock->owner) {
419 +                               struct event event;
420 +                               struct event_spec espec;
421 +                               struct task_struct *p = lock->owner->task;
422 +                               /*spin_lock(&p->alloc_lock);*/
423 +                               espec.reason = 0; /* lock */
424 +                               event.event_data=&espec;
425 +                               event.task = p;
426 +                               espec.pc=lock;
427 +                               event.event_type=5; 
428 +                               (*rec_event)(&event, 1);
429 +                               /*spin_unlock(&p->alloc_lock);*/
430 +
431 +                       }
432 +                       else 
433 +                               BUG();
434 +               }
435 +#endif
436 +
437                 /* didnt get the lock, go to sleep: */
438                 spin_unlock_mutex(&lock->wait_lock, flags);
439                 schedule();
440 @@ -177,6 +213,9 @@
441         /* got the lock - rejoice! */
442         mutex_remove_waiter(lock, &waiter, task_thread_info(task));
443         debug_mutex_set_owner(lock, task_thread_info(task));
444 +#ifdef CONFIG_CHOPSTIX
445 +       lock->owner = task_thread_info(task);
446 +#endif
447  
448         /* set it to 0 if there are no waiters left: */
449         if (likely(list_empty(&lock->wait_list)))
450 @@ -202,6 +241,7 @@
451  mutex_lock_nested(struct mutex *lock, unsigned int subclass)
452  {
453         might_sleep();
454 +
455         __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, subclass);
456  }
457  
458 @@ -211,6 +251,7 @@
459  mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass)
460  {
461         might_sleep();
462 +
463         return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, subclass);
464  }
465  
466 @@ -246,6 +287,23 @@
467  
468                 debug_mutex_wake_waiter(lock, waiter);
469  
470 +#ifdef CONFIG_CHOPSTIX
471 +               if (rec_event) {
472 +                       if (lock->owner) {
473 +                               struct event event;
474 +                               struct event_spec espec;
475 +
476 +                               espec.reason = 1; /* unlock */
477 +                               event.event_data=&espec;
478 +                               event.task = lock->owner->task;
479 +                               espec.pc=lock;
480 +                               event.event_type=5; 
481 +                               (*rec_event)(&event, 1);
482 +                       }
483 +                       else 
484 +                               BUG();
485 +               }
486 +#endif
487                 wake_up_process(waiter->task);
488         }
489  
490 --- linux-2.6.22-590/kernel/sched.c     2009-03-16 20:49:42.000000000 -0400
491 +++ linux-2.6.22-591/kernel/sched.c     2009-03-16 20:58:59.000000000 -0400
492 @@ -10,7 +10,7 @@
493   *  1998-11-19 Implemented schedule_timeout() and related stuff
494   *             by Andrea Arcangeli
495   *  2002-01-04 New ultra-scalable O(1) scheduler by Ingo Molnar:
496 - *             hybrid priority-list and round-robin design with
497 + *             hybrid priority-list and round-robin deventn with
498   *             an array-switch method of distributing timeslices
499   *             and per-CPU runqueues.  Cleanups and useful suggestions
500   *             by Davide Libenzi, preemptible kernel bits by Robert Love.
501 @@ -23,6 +23,7 @@
502  #include <linux/nmi.h>
503  #include <linux/init.h>
504  #include <asm/uaccess.h>
505 +#include <linux/arrays.h>
506  #include <linux/highmem.h>
507  #include <linux/smp_lock.h>
508  #include <asm/mmu_context.h>
509 @@ -59,6 +60,9 @@
510  #include <linux/vs_sched.h>
511  #include <linux/vs_cvirt.h>
512  
513 +#define INTERRUPTIBLE   -1
514 +#define RUNNING         0
515 +
516  /*
517   * Scheduler clock - returns current time in nanosec units.
518   * This is default implementation.
519 @@ -431,6 +435,7 @@
520  
521  repeat_lock_task:
522         rq = task_rq(p);
523 +
524         spin_lock(&rq->lock);
525         if (unlikely(rq != task_rq(p))) {
526                 spin_unlock(&rq->lock);
527 @@ -1741,6 +1746,21 @@
528          * event cannot wake it up and insert it on the runqueue either.
529          */
530         p->state = TASK_RUNNING;
531 +#ifdef CONFIG_CHOPSTIX
532 +    /* The jiffy of last interruption */
533 +    if (p->state & TASK_UNINTERRUPTIBLE) {
534 +                               p->last_interrupted=jiffies;
535 +       }
536 +    else
537 +    if (p->state & TASK_INTERRUPTIBLE) {
538 +                               p->last_interrupted=INTERRUPTIBLE;
539 +       }
540 +    else
541 +           p->last_interrupted=RUNNING;
542 +
543 +    /* The jiffy of last execution */ 
544 +       p->last_ran_j=jiffies;
545 +#endif
546  
547         /*
548          * Make sure we do not leak PI boosting priority to the child:
549 @@ -3608,6 +3628,7 @@
550  
551  #endif
552  
553 +
554  static inline int interactive_sleep(enum sleep_type sleep_type)
555  {
556         return (sleep_type == SLEEP_INTERACTIVE ||
557 @@ -3617,16 +3638,28 @@
558  /*
559   * schedule() is the main scheduler function.
560   */
561 +
562 +#ifdef CONFIG_CHOPSTIX
563 +extern void (*rec_event)(void *,unsigned int);
564 +struct event_spec {
565 +       unsigned long pc;
566 +       unsigned long dcookie;
567 +       unsigned int count;
568 +       unsigned int reason;
569 +};
570 +#endif
571 +
572  asmlinkage void __sched schedule(void)
573  {
574         struct task_struct *prev, *next;
575         struct prio_array *array;
576         struct list_head *queue;
577         unsigned long long now;
578 -       unsigned long run_time;
579 +       unsigned long run_time, diff;
580         int cpu, idx, new_prio;
581         long *switch_count;
582         struct rq *rq;
583 +       int sampling_reason;
584  
585         /*
586          * Test if we are atomic.  Since do_exit() needs to call into
587 @@ -3680,6 +3713,7 @@
588         switch_count = &prev->nivcsw;
589         if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
590                 switch_count = &prev->nvcsw;
591 +
592                 if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
593                                 unlikely(signal_pending(prev))))
594                         prev->state = TASK_RUNNING;
595 @@ -3689,6 +3723,17 @@
596                                 vx_uninterruptible_inc(prev);
597                         }
598                         deactivate_task(prev, rq);
599 +#ifdef CONFIG_CHOPSTIX
600 +            /* An uninterruptible process just yielded. Record the current jiffie */
601 +                       if (prev->state & TASK_UNINTERRUPTIBLE) {
602 +                               prev->last_interrupted=jiffies;
603 +                       }
604 +            /* An interruptible process just yielded, or it got preempted. 
605 +             * Mark it as interruptible */
606 +                       else if (prev->state & TASK_INTERRUPTIBLE) {
607 +                               prev->last_interrupted=INTERRUPTIBLE;
608 +                       }
609 +#endif
610                 }
611         }
612  
613 @@ -3765,6 +3810,40 @@
614                 prev->sleep_avg = 0;
615         prev->timestamp = prev->last_ran = now;
616  
617 +#ifdef CONFIG_CHOPSTIX
618 +       /* Run only if the Chopstix module so decrees it */
619 +       if (rec_event) {
620 +               prev->last_ran_j = jiffies;
621 +               if (next->last_interrupted!=INTERRUPTIBLE) {
622 +                       if (next->last_interrupted!=RUNNING) {
623 +                               diff = (jiffies-next->last_interrupted);
624 +                               sampling_reason = 0;/* BLOCKING */
625 +                       }
626 +                       else {
627 +                               diff = jiffies-next->last_ran_j; 
628 +                               sampling_reason = 1;/* PREEMPTION */
629 +                       }
630 +
631 +                       if (diff >= HZ/10) {
632 +                               struct event event;
633 +                               struct event_spec espec;
634 +                struct pt_regs *regs;
635 +                regs = task_pt_regs(current);
636 +
637 +                               espec.reason = sampling_reason;
638 +                               event.event_data=&espec;
639 +                               event.task=next;
640 +                               espec.pc=regs->eip;
641 +                               event.event_type=2; 
642 +                               /* index in the event array currently set up */
643 +                               /* make sure the counters are loaded in the order we want them to show up*/ 
644 +                               (*rec_event)(&event, diff);
645 +                       }
646 +               }
647 +        /* next has been elected to run */
648 +               next->last_interrupted=0;
649 +       }
650 +#endif
651         sched_info_switch(prev, next);
652         if (likely(prev != next)) {
653                 next->timestamp = next->last_ran = now;
654 @@ -4664,6 +4743,7 @@
655         get_task_struct(p);
656         read_unlock(&tasklist_lock);
657  
658 +
659         retval = -EPERM;
660         if ((current->euid != p->euid) && (current->euid != p->uid) &&
661                         !capable(CAP_SYS_NICE))
662 @@ -5032,6 +5112,7 @@
663         jiffies_to_timespec(p->policy == SCHED_FIFO ?
664                                 0 : task_timeslice(p), &t);
665         read_unlock(&tasklist_lock);
666 +
667         retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
668  out_nounlock:
669         return retval;
670 @@ -7275,3 +7356,20 @@
671  }
672  
673  #endif
674 +
675 +#ifdef CONFIG_CHOPSTIX
676 +void (*rec_event)(void *,unsigned int) = NULL;
677 +
678 +/* To support safe calling from asm */
679 +asmlinkage void rec_event_asm (struct event *event_signature_in, unsigned int count) {
680 +    struct pt_regs *regs;
681 +    struct event_spec *es = event_signature_in->event_data;
682 +    regs = task_pt_regs(current);
683 +       event_signature_in->task=current;
684 +       es->pc=regs->eip;
685 +    event_signature_in->count=1;
686 +    (*rec_event)(event_signature_in, count);
687 +}
688 +EXPORT_SYMBOL(rec_event);
689 +EXPORT_SYMBOL(in_sched_functions);
690 +#endif
691 --- linux-2.6.22-590/mm/memory.c        2009-03-16 20:49:42.000000000 -0400
692 +++ linux-2.6.22-591/mm/memory.c        2009-03-16 20:58:59.000000000 -0400
693 @@ -59,6 +59,7 @@
694  
695  #include <linux/swapops.h>
696  #include <linux/elf.h>
697 +#include <linux/arrays.h>
698  
699  #ifndef CONFIG_NEED_MULTIPLE_NODES
700  /* use the per-pgdat data instead for discontigmem - mbligh */
701 @@ -2601,6 +2602,15 @@
702         return ret;
703  }
704  
705 +extern void (*rec_event)(void *,unsigned int);
706 +struct event_spec {
707 +       unsigned long pc;
708 +       unsigned long dcookie; 
709 +       unsigned count;
710 +       unsigned char reason;
711 +};
712 +
713 +
714  /*
715   * By the time we get here, we already hold the mm semaphore
716   */
717 @@ -2630,6 +2640,24 @@
718         if (!pte)
719                 return VM_FAULT_OOM;
720  
721 +#ifdef CONFIG_CHOPSTIX
722 +       if (rec_event) {
723 +               struct event event;
724 +               struct event_spec espec;
725 +        struct pt_regs *regs;
726 +        unsigned int pc;
727 +        regs = task_pt_regs(current);
728 +        pc = regs->eip & (unsigned int) ~4095;
729 +
730 +               espec.reason = 0; /* alloc */
731 +               event.event_data=&espec;
732 +               event.task = current;
733 +               espec.pc=pc;
734 +               event.event_type=5; 
735 +               (*rec_event)(&event, 1);
736 +       }
737 +#endif
738 +
739         return handle_pte_fault(mm, vma, address, pte, pmd, write_access);
740  }
741  
742 --- linux-2.6.22-590/mm/slab.c  2009-03-16 20:49:42.000000000 -0400
743 +++ linux-2.6.22-591/mm/slab.c  2009-03-16 21:00:27.000000000 -0400
744 @@ -110,11 +110,13 @@
745  #include       <linux/fault-inject.h>
746  #include       <linux/rtmutex.h>
747  #include       <linux/reciprocal_div.h>
748 +#include <linux/arrays.h>
749  
750  #include       <asm/cacheflush.h>
751  #include       <asm/tlbflush.h>
752  #include       <asm/page.h>
753  
754 +
755  /*
756   * DEBUG       - 1 for kmem_cache_create() to honour; SLAB_RED_ZONE & SLAB_POISON.
757   *               0 for faster, smaller code (especially in the critical paths).
758 @@ -249,6 +251,14 @@
759         void *addr;
760  };
761  
762 +extern void (*rec_event)(void *,unsigned int);
763 +struct event_spec {
764 +       unsigned long pc;
765 +       unsigned long dcookie; 
766 +       unsigned count;
767 +       unsigned char reason;
768 +};
769 +
770  /*
771   * struct array_cache
772   *
773 @@ -3443,6 +3453,19 @@
774         local_irq_restore(save_flags);
775         objp = cache_alloc_debugcheck_after(cachep, flags, objp, caller);
776         prefetchw(objp);
777 +#ifdef CONFIG_CHOPSTIX
778 +       if (rec_event && objp) {
779 +               struct event event;
780 +               struct event_spec espec;
781 +
782 +               espec.reason = 0; /* alloc */
783 +               event.event_data=&espec;
784 +               event.task = current;
785 +               espec.pc=caller;
786 +               event.event_type=5; 
787 +               (*rec_event)(&event, cachep->buffer_size);
788 +       }
789 +#endif
790  
791         return objp;
792  }
793 @@ -3549,12 +3572,26 @@
794   * Release an obj back to its cache. If the obj has a constructed state, it must
795   * be in this state _before_ it is released.  Called with disabled ints.
796   */
797 -static inline void __cache_free(struct kmem_cache *cachep, void *objp)
798 +static inline void __cache_free(struct kmem_cache *cachep, void *objp, void *caller)
799  {
800         struct array_cache *ac = cpu_cache_get(cachep);
801  
802         check_irq_off();
803 -       objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
804 +       objp = cache_free_debugcheck(cachep, objp, caller);
805 + #ifdef CONFIG_CHOPSTIX
806 +       if (rec_event && objp) {
807 +               struct event event;
808 +               struct event_spec espec;
809 +  
810 +               espec.reason = 1; /* free */
811 +               event.event_data=&espec;
812 +               event.task = current;
813 +               espec.pc=caller;
814 +               event.event_type=4; 
815 +               (*rec_event)(&event, cachep->buffer_size);
816 +       }
817 + #endif
818 +
819         vx_slab_free(cachep);
820  
821         if (cache_free_alien(cachep, objp))
822 @@ -3651,16 +3688,19 @@
823                         __builtin_return_address(0));
824  }
825  EXPORT_SYMBOL(kmem_cache_alloc_node);
826 -
827  static __always_inline void *
828  __do_kmalloc_node(size_t size, gfp_t flags, int node, void *caller)
829  {
830         struct kmem_cache *cachep;
831 +       void *ret;
832 +
833  
834         cachep = kmem_find_general_cachep(size, flags);
835         if (unlikely(cachep == NULL))
836                 return NULL;
837 -       return kmem_cache_alloc_node(cachep, flags, node);
838 +       ret = kmem_cache_alloc_node(cachep, flags, node);
839 +       
840 +       return ret;
841  }
842  
843  #ifdef CONFIG_DEBUG_SLAB
844 @@ -3696,6 +3736,7 @@
845                                           void *caller)
846  {
847         struct kmem_cache *cachep;
848 +       void *ret;
849  
850         /* If you want to save a few bytes .text space: replace
851          * __ with kmem_.
852 @@ -3705,9 +3746,10 @@
853         cachep = __find_general_cachep(size, flags);
854         if (unlikely(cachep == NULL))
855                 return NULL;
856 -       return __cache_alloc(cachep, flags, caller);
857 -}
858 +       ret = __cache_alloc(cachep, flags, caller);
859  
860 +       return ret;
861 +}
862  
863  #ifdef CONFIG_DEBUG_SLAB
864  void *__kmalloc(size_t size, gfp_t flags)
865 @@ -3723,10 +3765,17 @@
866  EXPORT_SYMBOL(__kmalloc_track_caller);
867  
868  #else
869 +#ifdef CONFIG_CHOPSTIX
870 +void *__kmalloc(size_t size, gfp_t flags)
871 +{
872 +       return __do_kmalloc(size, flags, __builtin_return_address(0));
873 +}
874 +#else
875  void *__kmalloc(size_t size, gfp_t flags)
876  {
877         return __do_kmalloc(size, flags, NULL);
878  }
879 +#endif
880  EXPORT_SYMBOL(__kmalloc);
881  #endif
882  
883 @@ -3792,7 +3841,7 @@
884  
885         local_irq_save(flags);
886         debug_check_no_locks_freed(objp, obj_size(cachep));
887 -       __cache_free(cachep, objp);
888 +       __cache_free(cachep, objp,__builtin_return_address(0));
889         local_irq_restore(flags);
890  }
891  EXPORT_SYMBOL(kmem_cache_free);
892 @@ -3817,7 +3866,7 @@
893         kfree_debugcheck(objp);
894         c = virt_to_cache(objp);
895         debug_check_no_locks_freed(objp, obj_size(c));
896 -       __cache_free(c, (void *)objp);
897 +       __cache_free(c, (void *)objp,__builtin_return_address(0));
898         local_irq_restore(flags);
899  }
900  EXPORT_SYMBOL(kfree);