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