diff -uprN -X /tmp/dontdiff linux-2.6.9_vanilla/arch/i386/kernel/irq.c /usr/src/linux_lttng/arch/i386/kernel/irq.c
--- linux-2.6.9_vanilla/arch/i386/kernel/irq.c	2005-12-01 11:48:23.000000000 -0500
+++ /usr/src/linux_lttng/arch/i386/kernel/irq.c	2005-11-25 16:38:08.000000000 -0500
@@ -34,6 +34,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/kallsyms.h>
+#include <linux/ltt/ltt-facility-kernel.h>
 
 #include <asm/atomic.h>
 #include <asm/io.h>
@@ -222,6 +223,8 @@ asmlinkage int handle_IRQ_event(unsigned
 	int status = 1;	/* Force the "do bottom halves" bit */
 	int ret, retval = 0;
 
+        trace_kernel_irq_entry(irq, !(user_mode(regs)));
+        
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
@@ -235,6 +238,9 @@ asmlinkage int handle_IRQ_event(unsigned
 	if (status & SA_SAMPLE_RANDOM)
 		add_interrupt_randomness(irq);
 	local_irq_disable();
+
+        trace_kernel_irq_exit();
+        
 	return retval;
 }
 
diff -uprN -X /tmp/dontdiff linux-2.6.9_vanilla/arch/i386/kernel/process.c /usr/src/linux_lttng/arch/i386/kernel/process.c
--- linux-2.6.9_vanilla/arch/i386/kernel/process.c	2005-12-01 14:33:48.000000000 -0500
+++ /usr/src/linux_lttng/arch/i386/kernel/process.c	2005-11-28 12:21:22.000000000 -0500
@@ -12,6 +12,7 @@
  */
 
 #include <stdarg.h>
+#include <linux/ltt/ltt-facility-process.h>
 
 #include <linux/errno.h>
 #include <linux/sched.h>
diff -uprN -X /tmp/dontdiff linux-2.6.9_vanilla/arch/i386/kernel/traps.c /usr/src/linux_lttng/arch/i386/kernel/traps.c
--- linux-2.6.9_vanilla/arch/i386/kernel/traps.c	2005-12-01 14:33:48.000000000 -0500
+++ /usr/src/linux_lttng/arch/i386/kernel/traps.c	2005-11-28 13:06:25.000000000 -0500
@@ -403,6 +403,10 @@ void die(const char * str, struct pt_reg
 #endif
 		if (nl)
 			printk("\n");
+#ifdef CONFIG_LTT
+                printk("LTT NESTING LEVEL : %u ", ltt_nesting[smp_processor_id()]);
+                printk("\n");
+#endif                
 	notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
 		show_registers(regs);
 		try_crashdump(regs);
@@ -503,6 +507,7 @@ static inline void do_trap(int trapnr, i
 			force_sig_info(signr, info, tsk);
 		else
 			force_sig(signr, tsk);
+                trace_kernel_trap_exit();
 		return;
 	}
 
@@ -510,6 +515,7 @@ static inline void do_trap(int trapnr, i
 		if (!fixup_exception(regs)) {
 		die:
 			die(str, regs, error_code);
+                trace_kernel_trap_exit();        
 		}
 		else if (is_iret(regs)) {
 			if (!iret_to_user(regs))
@@ -523,8 +529,10 @@ static inline void do_trap(int trapnr, i
 	vm86_trap: {
 		int ret = handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr);
 		if (ret) goto trap_signal;
+                trace_kernel_trap_exit();
 		return;
 	}
+        trace_kernel_trap_exit();
 }
 
 #define DO_ERROR(trapnr, signr, str, name) \
@@ -765,7 +773,11 @@ void die_nmi (struct pt_regs *regs, cons
 static void default_do_nmi(struct pt_regs * regs)
 {
 	unsigned char reason = get_nmi_reason();
- 
+#ifndef CONFIG_X86_LOCAL_APIC
+  /* On machines with APIC enabled, NMIs are used to implement a watchdog
+      and will hang the machine if traced. */
+        trace_kernel_trap_entry(2, (void*)regs->eip);
+#endif        
 	if (!(reason & 0xc0)) {
 		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
 							== NOTIFY_STOP)
@@ -935,8 +947,10 @@ asmlinkage void do_debug(struct pt_regs 
 	 */
 	info.si_addr = ((regs->xcs & 3) == 0) ? (void __user *)tsk->thread.eip
 	                                      : (void __user *)regs->eip;
+        trace_kernel_trap_entry(1, (void*)regs->eip);
 	force_sig_info(SIGTRAP, &info, tsk);
+        trace_kernel_trap_exit();
 
 	/* Disable additional traps. They'll be re-enabled when
 	 * the signal is delivered.
--- linux-2.6.9_vanilla/fs/buffer.c	2005-12-01 14:33:48.000000000 -0500
+++ /usr/src/linux_lttng/fs/buffer.c	2005-11-25 16:01:56.000000000 -0500
@@ -156,7 +156,7 @@ void __wait_on_buffer(struct buffer_head
 {
 	wait_queue_head_t *wqh = bh_waitq_head(bh);
 	DEFINE_BH_WAIT(wait, bh);
-
+        trace_fs_buf_wait_start((void*)bh);
 	do {
 		prepare_to_wait(wqh, &wait.wait, TASK_UNINTERRUPTIBLE);
 		if (buffer_locked(bh)) {
@@ -165,6 +165,7 @@ void __wait_on_buffer(struct buffer_head
 		}
 	} while (buffer_locked(bh));
 	finish_wait(wqh, &wait.wait);
+        trace_fs_buf_wait_end((void*)bh);
 }
 
 static void
diff -uprN -X /tmp/dontdiff linux-2.6.9_vanilla/fs/open.c /usr/src/linux_lttng/fs/open.c
--- linux-2.6.9_vanilla/fs/open.c	2005-12-01 14:33:48.000000000 -0500
+++ /usr/src/linux_lttng/fs/open.c	2005-11-25 16:03:23.000000000 -0500
@@ -962,6 +962,9 @@ asmlinkage long sys_open(const char __us
 			error = PTR_ERR(f);
 			if (IS_ERR(f))
 				goto out_error;
+                        trace_fs_open(f->f_dentry->d_name.len,
+                           f->f_dentry->d_name.name,
+                           fd);
 			fd_install(fd, f);
 		}
 out:
diff -uprN -X /tmp/dontdiff linux-2.6.9_vanilla/fs/relayfs/inode.c /usr/src/linux_lttng/fs/relayfs/inode.c
--- linux-2.6.9_vanilla/fs/relayfs/inode.c	2005-12-01 14:33:21.000000000 -0500
+++ /usr/src/linux_lttng/fs/relayfs/inode.c	2005-11-28 13:16:26.000000000 -0500
@@ -94,6 +94,7 @@ static struct dentry *relayfs_create_ent
 					   int mode,
 					   struct rchan *chan)
 {
+	struct qstr qname;
 	struct dentry *d;
 	struct inode *inode;
 	int error = 0;
@@ -106,6 +107,10 @@ static struct dentry *relayfs_create_ent
 		return NULL;
 	}
 
+	qname.name = name;
+	qname.len = strlen(name);
+	qname.hash = full_name_hash(name, qname.len);
+
 	if (!parent && relayfs_mount && relayfs_mount->mnt_sb)
 		parent = relayfs_mount->mnt_sb->s_root;
 
@@ -116,7 +121,7 @@ static struct dentry *relayfs_create_ent
 
 	parent = dget(parent);
 	down(&parent->d_inode->i_sem);
-	d = lookup_one_len(name, parent, strlen(name));
+	d = lookup_hash(&qname, parent);
 	if (IS_ERR(d)) {
 		d = NULL;
 		goto release_mount;
@@ -235,6 +240,12 @@ int relayfs_remove_dir(struct dentry *de
 int relayfs_open(struct inode *inode, struct file *filp)
 {
 	struct rchan_buf *buf = RELAYFS_I(inode)->buf;
+
+	if(!atomic_dec_and_test(&buf->open_count)) {
+		atomic_inc(&buf->open_count);
+		return -EACCES;
+	}
+	
 	kref_get(&buf->kref);
 
 	return 0;
@@ -266,19 +277,97 @@ unsigned int relayfs_poll(struct file *f
 	struct inode *inode = filp->f_dentry->d_inode;
 	struct rchan_buf *buf = RELAYFS_I(inode)->buf;
 
-	if (buf->finalized)
-		return POLLERR;
-
 	if (filp->f_mode & FMODE_READ) {
 		poll_wait(filp, &buf->read_wait, wait);
-		if (!relay_buf_empty(buf))
-			mask |= POLLIN | POLLRDNORM;
+
+		if(relay_buf_empty(buf)) {
+			if(buf->finalized)
+				return POLLHUP;
+			else
+				return 0;
+		} else {
+			if((atomic_read(&buf->current_subbuf)+1) % buf->chan->n_subbufs
+					== atomic_read(&buf->current_read_subbuf)) /* If full */
+				return POLLPRI | POLLRDBAND;
+			else
+				return POLLIN | POLLRDNORM;
+		}
 	}
 
 	return mask;
 }
 
 /**
+ *	relayfs_ioctl - ioctl control on the relayfs file
+ *
+ *	@inode: the inode
+ *	@filp: the file
+ *	@cmd: the command
+ *	@arg: command arg
+ *
+ *	This ioctl implements three commands necessary for a minimal
+ *	producer/consumer implementation :
+ *	RELAYFS_GET_SUBBUF
+ *		Get the next sub buffer that can be read. It never blocks.
+ *	RELAYFS_PUT_SUBBUF
+ *		Release the oldest reserved (by "get") sub buffer.
+ *	RELAYFS_GET_N_BUBBUFS
+ *		returns the number of sub buffers in the per cpu channel.
+ *	RELAYFS_GET_SUBBUF_SIZE
+ *		returns the size of the sub buffers.
+ *
+ */
+int relayfs_ioctl(struct inode *inode, struct file *filp,
+		unsigned int cmd, unsigned long arg)
+{
+	struct rchan_buf *buf = RELAYFS_I(inode)->buf;
+	u32 __user    *argp = (u32 __user *)arg;
+
+	switch(cmd) {
+		case RELAYFS_GET_SUBBUF:
+			if(!relay_buf_empty(buf)) {
+				return put_user((u32)atomic_read(&buf->current_read_subbuf), argp);
+			} else {
+				return -EAGAIN;
+			}
+			break;
+		case RELAYFS_PUT_SUBBUF:
+			if(!relay_buf_empty(buf)) {
+				if(atomic_read(&buf->current_read_subbuf) >=
+						buf->chan->n_subbufs-1) {
+					atomic_set(&buf->current_read_subbuf, 0);
+				} else {
+					atomic_inc(&buf->current_read_subbuf);
+				}
+
+				if(unlikely(atomic_read(&buf->full))) {
+					int index;
+					void *data;
+					index = atomic_read(&buf->current_subbuf);
+					data = buf->start + index * buf->chan->subbuf_size;
+					
+					buf->chan->cb->buf_unfull(buf, index, data);
+					atomic_set(&buf->full, 0);
+				}
+				return 0;
+			} else {
+				return -EPERM;
+			}
+			break;
+		case RELAYFS_GET_N_SUBBUFS:
+			return put_user((u32)buf->chan->n_subbufs, argp);
+			break;
+		case RELAYFS_GET_SUBBUF_SIZE:
+			return put_user((u32)buf->chan->subbuf_size, argp);
+			break;
+		default:
+			return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+
+/**
  *	relayfs_release - release file op for relayfs files
  *	@inode: the inode
  *	@filp: the file
@@ -289,11 +378,17 @@ unsigned int relayfs_poll(struct file *f
 int relayfs_release(struct inode *inode, struct file *filp)
 {
 	struct rchan_buf *buf = RELAYFS_I(inode)->buf;
+
+	atomic_inc(&buf->open_count);
+	
 	kref_put(&buf->kref, relay_remove_buf);
 
 	return 0;
 }
 
+
+
+
 /**
  *	relayfs alloc_inode() implementation
  */
@@ -330,6 +425,7 @@ struct file_operations relayfs_file_oper
 	.poll		= relayfs_poll,
 	.mmap		= relayfs_mmap,
 	.release	= relayfs_release,
+	.ioctl		= relayfs_ioctl,
 };
 
 static struct super_operations relayfs_ops = {
@@ -382,6 +478,7 @@ static int __init init_relayfs_fs(void)
 {
 	int err;
 
+	printk(KERN_DEBUG "relayfs init\n");
 	relayfs_inode_cachep = kmem_cache_create("relayfs_inode_cache",
 				sizeof(struct relayfs_inode_info), 0,
 				0, init_once, NULL);
@@ -395,13 +492,14 @@ static int __init init_relayfs_fs(void)
 	return err;
 }
 
+
 static void __exit exit_relayfs_fs(void)
 {
 	unregister_filesystem(&relayfs_fs_type);
 	kmem_cache_destroy(relayfs_inode_cachep);
 }
 
-module_init(init_relayfs_fs)
+fs_initcall(init_relayfs_fs);
 module_exit(exit_relayfs_fs)
 
 EXPORT_SYMBOL_GPL(relayfs_open);
diff -uprN -X /tmp/dontdiff linux-2.6.9_vanilla/fs/relayfs/relay.c /usr/src/linux_lttng/fs/relayfs/relay.c
--- linux-2.6.9_vanilla/fs/relayfs/relay.c	2005-12-01 14:33:23.000000000 -0500
+++ /usr/src/linux_lttng/fs/relayfs/relay.c	2005-11-28 12:14:24.000000000 -0500
@@ -26,10 +26,8 @@
  */
 int relay_buf_empty(struct rchan_buf *buf)
 {
-	int produced = atomic_read(&buf->subbufs_produced);
-	int consumed = atomic_read(&buf->subbufs_consumed);
-
-	return (produced - consumed) ? 0 : 1;
+	return atomic_read(&buf->current_subbuf) ==
+						atomic_read(&buf->current_read_subbuf);
 }
 
 /**
@@ -40,15 +38,8 @@ int relay_buf_empty(struct rchan_buf *bu
  */
 static inline int relay_buf_full(struct rchan_buf *buf)
 {
-	int produced, consumed;
-
-	if (buf->chan->overwrite)
-		return 0;
-
-	produced = atomic_read(&buf->subbufs_produced);
-	consumed = atomic_read(&buf->subbufs_consumed);
-
-	return (produced - consumed > buf->chan->n_subbufs - 1) ? 1 : 0;
+	return (atomic_read(&buf->current_subbuf)+1) % buf->chan->n_subbufs
+							== atomic_read(&buf->current_read_subbuf);
 }
 
 /*
@@ -105,6 +96,15 @@ static void buf_full_default_callback(st
 {
 }
 
+/*
+ * buf_unfull() default callback.  Does nothing.
+ */
+static void buf_unfull_default_callback(struct rchan_buf *buf,
+				      unsigned subbuf_idx,
+				      void *subbuf)
+{
+}
+
 /* relay channel default callbacks */
 static struct rchan_callbacks default_channel_callbacks = {
 	.subbuf_start = subbuf_start_default_callback,
@@ -112,6 +112,7 @@ static struct rchan_callbacks default_ch
 	.buf_mapped = buf_mapped_default_callback,
 	.buf_unmapped = buf_unmapped_default_callback,
 	.buf_full = buf_full_default_callback,
+	.buf_unfull = buf_unfull_default_callback,
 };
 
 /**
@@ -145,6 +146,7 @@ static inline void *get_next_subbuf(stru
  *	__relay_reset - reset a channel buffer
  *	@buf: the channel buffer
  *	@init: 1 if this is a first-time initialization
+ *	@subbufs_count number of subbuffers
  *
  *	See relay_reset for description of effect.
  */
@@ -155,18 +157,15 @@ static inline void __relay_reset(struct 
 	if (init) {
 		init_waitqueue_head(&buf->read_wait);
 		kref_init(&buf->kref);
-		INIT_WORK(&buf->wake_readers, NULL, NULL);
-	} else {
-		cancel_delayed_work(&buf->wake_readers);
-		flush_scheduled_work();
 	}
 
-	atomic_set(&buf->subbufs_produced, 0);
-	atomic_set(&buf->subbufs_consumed, 0);
-	atomic_set(&buf->unfull, 0);
+	atomic_set(&buf->full, 0);
+	atomic_set(&buf->current_subbuf, 0);
+	atomic_set(&buf->current_read_subbuf, 0);
 	buf->finalized = 0;
 	buf->data = buf->start;
 	buf->offset = 0;
+	atomic_set(&buf->open_count, 1);
 
 	for (i = 0; i < buf->chan->n_subbufs; i++) {
 		buf->padding[i] = 0;
@@ -175,6 +174,8 @@ static inline void __relay_reset(struct 
 
 	buf->offset = buf->chan->cb->subbuf_start(buf, buf->data, 0, NULL);
 	buf->commit[0] = buf->offset;
+
+	INIT_WORK(&buf->wake_readers, NULL, NULL);
 }
 
 /**
@@ -211,7 +212,8 @@ void relay_reset(struct rchan *chan)
  */
 static struct rchan_buf *relay_open_buf(struct rchan *chan,
 					const char *filename,
-					struct dentry *parent)
+					struct dentry *parent,
+					int cpu)
 {
 	struct rchan_buf *buf;
 	struct dentry *dentry;
@@ -223,6 +225,7 @@ static struct rchan_buf *relay_open_buf(
 
 	buf = RELAYFS_I(dentry->d_inode)->buf;
 	buf->dentry = dentry;
+	buf->cpu = cpu;
 	__relay_reset(buf, 1);
 
 	return buf;
@@ -240,8 +243,6 @@ static inline void relay_close_buf(struc
 {
 	buf->finalized = 1;
 	buf->chan->cb = &default_channel_callbacks;
-	cancel_delayed_work(&buf->wake_readers);
-	flush_scheduled_work();
 	kref_put(&buf->kref, relay_remove_buf);
 }
 
@@ -263,6 +264,8 @@ static inline void setup_callbacks(struc
 		cb->buf_unmapped = buf_unmapped_default_callback;
 	if (!cb->buf_full)
 		cb->buf_full = buf_full_default_callback;
+	if (!cb->buf_unfull)
+		cb->buf_unfull = buf_unfull_default_callback;
 	chan->cb = cb;
 }
 
@@ -287,7 +290,8 @@ struct rchan *relay_open(const char *bas
 			 unsigned subbuf_size,
 			 unsigned n_subbufs,
 			 int overwrite,
-			 struct rchan_callbacks *cb)
+			 struct rchan_callbacks *cb,
+			 void *client_data)
 {
 	int i;
 	struct rchan *chan;
@@ -308,6 +312,7 @@ struct rchan *relay_open(const char *bas
 	chan->n_subbufs = n_subbufs;
 	chan->subbuf_size = subbuf_size;
 	chan->alloc_size = FIX_SIZE(subbuf_size * n_subbufs);
+	chan->client_data = client_data;
 	setup_callbacks(chan, cb);
 	kref_init(&chan->kref);
 
@@ -316,8 +321,8 @@ struct rchan *relay_open(const char *bas
 		goto free_chan;
 
 	for_each_online_cpu(i) {
-		sprintf(tmpname, "%s%d", base_filename, i);
-		chan->buf[i] = relay_open_buf(chan, tmpname, parent);
+		sprintf(tmpname, "%s_%d", base_filename, i);
+		chan->buf[i] = relay_open_buf(chan, tmpname, parent, i);
 		if (!chan->buf[i])
 			goto free_bufs;
 	}
@@ -347,12 +352,28 @@ static inline void deliver_check(struct 
 	void *subbuf;
 	unsigned full = buf->chan->subbuf_size - buf->padding[subbuf_idx];
 
+	//printk("Deliver check : %u, %u\n", full, buf->commit[subbuf_idx]);
+	if (buf->commit[subbuf_idx] == full) {
+		subbuf = buf->start + subbuf_idx * buf->chan->subbuf_size;
+		buf->chan->cb->deliver(buf, subbuf_idx, subbuf);
+	}
+	//printk("Deliver check end\n");
+}
+
+static inline void deliver_check_in_commit(struct rchan_buf *buf,
+				 unsigned subbuf_idx)
+{
+	void *subbuf;
+	unsigned full = buf->chan->subbuf_size - buf->padding[subbuf_idx];
+
 	if (buf->commit[subbuf_idx] == full) {
+		//printk("Deliver check in commit : %u, %u\n", full, buf->commit[subbuf_idx]);
 		subbuf = buf->start + subbuf_idx * buf->chan->subbuf_size;
 		buf->chan->cb->deliver(buf, subbuf_idx, subbuf);
 	}
 }
 
+
 /**
  *	do_switch - change subbuf pointer and do related bookkeeping
  */
@@ -361,10 +382,13 @@ static inline void do_switch(struct rcha
 	unsigned start = 0;
 	void *old_data = buf->start + old * buf->chan->subbuf_size;
 
+	//printk("do_switch begin\n");
 	buf->data = get_next_subbuf(buf);
 	buf->padding[new] = 0;
 	start = buf->chan->cb->subbuf_start(buf, buf->data, old, old_data);
+	//printk("Start : %u\n", start);
 	buf->offset = buf->commit[new] = start;
+	//printk("do_switch end\n");
 }
 
 /**
@@ -379,51 +403,68 @@ static inline void do_switch(struct rcha
  */
 unsigned relay_switch_subbuf(struct rchan_buf *buf, unsigned length)
 {
-	int new, old, produced = atomic_read(&buf->subbufs_produced);
+	int new, old;
 	unsigned padding;
 
+	//printk("relay_switch_subbuf begin\n");
 	if (unlikely(length > buf->chan->subbuf_size))
 		goto toobig;
 
-	if (unlikely(atomic_read(&buf->unfull))) {
-		atomic_set(&buf->unfull, 0);
-		new = produced % buf->chan->n_subbufs;
-		old = (produced - 1) % buf->chan->n_subbufs;
-		do_switch(buf, new, old);
-		return 0;
-	}
+	old = atomic_read(&buf->current_subbuf);
 
-	if (unlikely(relay_buf_full(buf)))
+	if (unlikely(!buf->chan->overwrite && relay_buf_full(buf))) {
+		if(likely(!atomic_read(&buf->full))) {
+			void *old_data = buf->start + old * buf->chan->subbuf_size;
+			
+			buf->chan->cb->buf_full(buf, old, old_data);
+			atomic_set(&buf->full, 1);
+		}
+
+		//printk("relay_switch_subbuf full end\n");
 		return 0;
+	}
+	/* Here, either the buffer is not full, or we have the possibility
+	 * to overwrite unread subbuffers.
+	 */
 
-	old = produced % buf->chan->n_subbufs;
 	padding = buf->chan->subbuf_size - buf->offset;
 	buf->padding[old] = padding;
 	deliver_check(buf, old);
 	buf->offset = buf->chan->subbuf_size;
-	atomic_inc(&buf->subbufs_produced);
-
+	
 	if (waitqueue_active(&buf->read_wait)) {
 		PREPARE_WORK(&buf->wake_readers, wakeup_readers, buf);
 		schedule_delayed_work(&buf->wake_readers, 1);
 	}
 
-	if (unlikely(relay_buf_full(buf))) {
-		void *old_data = buf->start + old * buf->chan->subbuf_size;
-		buf->chan->cb->buf_full(buf, old, old_data);
-		return 0;
+	/* In overwrite mode, we can push the read position : these *should*
+	 * be no reader active while there are writers */
+	if(buf->chan->overwrite && relay_buf_full(buf)) {
+		
+		if(atomic_read(&buf->current_read_subbuf) >=
+				buf->chan->n_subbufs-1) {
+			atomic_set(&buf->current_read_subbuf, 0);
+		} else {
+			atomic_inc(&buf->current_read_subbuf);
+		}
 	}
 
-	new = (produced + 1) % buf->chan->n_subbufs;
+	new = (old + 1) % buf->chan->n_subbufs;
+	atomic_set(&buf->current_subbuf, new);
+
 	do_switch(buf, new, old);
 
 	if (unlikely(length + buf->offset > buf->chan->subbuf_size))
 		goto toobig;
 
+	//printk("relay_switch_subbuf end\n");
 	return length;
 
 toobig:
-	printk(KERN_WARNING "relayfs: event too large (%u)\n", length);
+	/* Fixme : we cannot, never ever, call a printk from LTT schedule and
+	 * wakeup instrumentation! A deadlock would occur. We must find another
+	 * way to print debug messages. */
+	//printk(KERN_WARNING "relayfs: event too large (%u)\n", length);
 	WARN_ON(1);
 	return 0;
 }
@@ -445,42 +486,7 @@ void relay_commit(struct rchan_buf *buf,
 	offset = reserved - buf->start;
 	subbuf_idx = offset / buf->chan->subbuf_size;
 	buf->commit[subbuf_idx] += count;
-	deliver_check(buf, subbuf_idx);
-}
-
-/**
- *	relay_subbufs_consumed - update the buffer's sub-buffers-consumed count
- *	@chan: the channel
- *	@cpu: the cpu associated with the channel buffer to update
- *	@subbufs_consumed: number of sub-buffers to add to current buf's count
- *
- *	Adds to the channel buffer's consumed sub-buffer count.
- *	subbufs_consumed should be the number of sub-buffers newly consumed,
- *	not the total consumed.
- *
- *	NOTE: kernel clients don't need to call this function if the channel
- *	mode is 'overwrite'.
- */
-void relay_subbufs_consumed(struct rchan *chan, int cpu, int subbufs_consumed)
-{
-	int produced, consumed;
-	struct rchan_buf *buf;
-
-	if (!chan)
-		return;
-
-	if (cpu >= NR_CPUS || !chan->buf[cpu])
-		return;
-
-	buf = chan->buf[cpu];
-	if (relay_buf_full(buf))
-		atomic_set(&buf->unfull, 1);
-
-	atomic_add(subbufs_consumed, &buf->subbufs_consumed);
-	produced = atomic_read(&buf->subbufs_produced);
-	consumed = atomic_read(&buf->subbufs_consumed);
-	if (consumed > produced)
-		atomic_set(&buf->subbufs_consumed, produced);
+	deliver_check_in_commit(buf, subbuf_idx);
 }
 
 /**
@@ -540,6 +546,5 @@ EXPORT_SYMBOL_GPL(relay_open);
 EXPORT_SYMBOL_GPL(relay_close);
 EXPORT_SYMBOL_GPL(relay_flush);
 EXPORT_SYMBOL_GPL(relay_reset);
-EXPORT_SYMBOL_GPL(relay_subbufs_consumed);
 EXPORT_SYMBOL_GPL(relay_commit);
 EXPORT_SYMBOL_GPL(relay_switch_subbuf);
diff -uprN -X /tmp/dontdiff linux-2.6.9_vanilla/fs/select.c /usr/src/linux_lttng/fs/select.c
--- linux-2.6.9_vanilla/fs/select.c	2005-12-01 14:33:48.000000000 -0500
+++ /usr/src/linux_lttng/fs/select.c	2005-11-25 16:11:23.000000000 -0500
@@ -16,6 +16,7 @@
 
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/ltt/ltt-facility-fs.h>
 #include <linux/smp_lock.h>
 #include <linux/poll.h>
 #include <linux/personality.h> /* for STICKY_TIMEOUTS */
diff -uprN -X /tmp/dontdiff linux-2.6.9_vanilla/include/linux/relayfs_fs.h /usr/src/linux_lttng/include/linux/relayfs_fs.h
--- linux-2.6.9_vanilla/include/linux/relayfs_fs.h	2005-12-01 14:33:18.000000000 -0500
+++ /usr/src/linux_lttng/include/linux/relayfs_fs.h	2005-11-28 12:14:24.000000000 -0500
@@ -18,6 +18,10 @@
 #include <linux/fs.h>
 #include <linux/poll.h>
 #include <linux/kref.h>
+#include <linux/percpu.h>
+#include <linux/preempt.h>
+#include <linux/err.h>
+#include <asm/system.h> //for cmpxchg
 
 /*
  * Tracks changes to rchan_buf struct
@@ -32,19 +36,21 @@ struct rchan_buf
 	void *start;			/* start of channel buffer */
 	void *data;			/* start of current sub-buffer */
 	unsigned offset;		/* current offset into sub-buffer */
-	atomic_t subbufs_produced;	/* count of sub-buffers produced */
-	atomic_t subbufs_consumed;	/* count of sub-buffers consumed */
-	atomic_t unfull;		/* state has gone from full to not */
+	atomic_t full;		/* buffer is in full state */
+	atomic_t current_subbuf; /* Index of the subbuf currently written to */
+	atomic_t current_read_subbuf; /* Index of the subbuf to read next */
 	struct rchan *chan;		/* associated channel */
 	wait_queue_head_t read_wait;	/* reader wait queue */
 	struct work_struct wake_readers; /* reader wake-up work struct */
 	struct dentry *dentry;		/* channel file dentry */
 	struct kref kref;		/* channel buffer refcount */
+	atomic_t open_count;			/* file open count */
 	struct page **page_array;	/* array of current buffer pages */
 	int page_count;			/* number of current buffer pages */
 	unsigned *padding;		/* padding counts per sub-buffer */
 	unsigned *commit;		/* commit counts per sub-buffer */
 	int finalized;			/* buffer has been finalized */
+	int	cpu;						/* CPU number associated with the channel */
 } ____cacheline_aligned;
 
 /*
@@ -58,8 +64,8 @@ struct rchan
 	unsigned alloc_size;		/* total buffer size allocated */
 	int overwrite;			/* overwrite buffer when full? */
 	struct rchan_callbacks *cb;	/* client callbacks */
+	void *client_data; /* client data associated with the client callbacks */
 	struct kref kref;		/* channel refcount */
-	void *private_data;		/* for user-defined data */
 	struct rchan_buf *buf[NR_CPUS]; /* per-cpu channel buffers */
 };
 
@@ -89,8 +95,7 @@ struct rchan_callbacks
 	 * @prev_subbuf_idx: the previous sub-buffer's index
 	 * @prev_subbuf: the start of the previous sub-buffer
 	 *
-	 * The client should return the number of bytes it reserves at
-	 * the beginning of the sub-buffer, 0 if none.
+	 * returns the padding size at the beginning of the buffer.
 	 *
 	 * NOTE: subbuf_start will also be invoked when the buffer is
 	 *       created, so that the first sub-buffer can be initialized
@@ -120,8 +125,8 @@ struct rchan_callbacks
 	 *
 	 * Called when a relayfs file is successfully mmapped
 	 */
-        void (*buf_mapped)(struct rchan_buf *buf,
-			   struct file *filp);
+	void (*buf_mapped)(struct rchan_buf *buf,
+					struct file *filp);
 
 	/*
 	 * buf_unmapped - relayfs buffer unmap notification
@@ -130,8 +135,8 @@ struct rchan_callbacks
 	 *
 	 * Called when a relayfs file is successfully unmapped
 	 */
-        void (*buf_unmapped)(struct rchan_buf *buf,
-			     struct file *filp);
+	void (*buf_unmapped)(struct rchan_buf *buf,
+					struct file *filp);
 
 	/*
 	 * buf_full - relayfs buffer full notification
@@ -141,9 +146,22 @@ struct rchan_callbacks
 	 *
 	 * Called when a relayfs buffer becomes full
 	 */
-        void (*buf_full)(struct rchan_buf *buf,
-			 unsigned subbuf_idx,
-			 void *subbuf);
+	void (*buf_full)(struct rchan_buf *buf,
+				unsigned subbuf_idx,
+				void *subbuf);
+
+	/*
+	 * buf_unfull - relayfs buffer unfull notification
+	 * @buf: the channel channel buffer
+	 * @subbuf_idx: the current sub-buffer's index
+	 * @subbuf: the start of the current sub-buffer
+	 *
+	 * Called when a relayfs buffer passes from full to not full
+	 */
+	void (*buf_unfull)(struct rchan_buf *buf,
+				unsigned subbuf_idx,
+				void *subbuf);
+
 };
 
 /*
@@ -155,7 +173,8 @@ struct rchan *relay_open(const char *bas
 			 unsigned subbuf_size,
 			 unsigned n_subbufs,
 			 int overwrite,
-			 struct rchan_callbacks *cb);
+			 struct rchan_callbacks *cb,
+			 void *client_data);
 extern void relay_close(struct rchan *chan);
 extern void relay_flush(struct rchan *chan);
 extern void relay_subbufs_consumed(struct rchan *chan,
@@ -198,6 +217,7 @@ static inline void relay_write(struct rc
 	memcpy(buf->data + buf->offset, data, length);
 	buf->offset += length;
 	local_irq_restore(flags);
+//	preempt_check_resched();
 }
 
 /**
@@ -230,16 +250,22 @@ static inline void __relay_write(struct 
  *	relay_reserve - reserve slot in channel buffer
  *	@chan: relay channel
  *	@length: number of bytes to reserve
+ *	@old_offset : old offset in the buffer, used to insure atomicity of buffer
+ *	content (timestamp) vs the slot reserved.
  *
- *	Returns pointer to reserved slot, NULL if full.
+ *	Returns pointer to reserved slot, NULL if full, or -EAGAIN.
  *
  *	Reserves a slot in the current cpu's channel buffer.
  *	Does not protect the buffer at all - caller must provide
  *	appropriate synchronization.
+ *
+ *	If the old_offset does not match the current offset address,
+ *	the operation fails and returns a -EAGAIN error (use PTR_ERR).
  */
-static inline void *relay_reserve(struct rchan *chan, unsigned length)
+static inline void *relay_reserve(struct rchan *chan, unsigned length, 
+																	unsigned old_offset)
 {
-	void *reserved;
+	unsigned new_offset;
 	struct rchan_buf *buf = chan->buf[smp_processor_id()];
 
 	if (unlikely(buf->offset + length > buf->chan->subbuf_size)) {
@@ -247,10 +273,16 @@ static inline void *relay_reserve(struct
 		if (!length)
 			return NULL;
 	}
-	reserved = buf->data + buf->offset;
-	buf->offset += length;
 
-	return reserved;
+ // reserved = buf->data + buf->offset;
+	new_offset = buf->offset + length;
+
+	//cmpxchg(reserved, old_address, new_address);
+  //if(reserved == old_address)
+	if(cmpxchg(&buf->offset, old_offset, new_offset) == old_offset) {
+		return buf->data + old_offset;
+  }	else
+		return ERR_PTR(-EAGAIN);
 }
 
 /*
@@ -262,6 +294,24 @@ extern int relayfs_open(struct inode *in
 extern unsigned int relayfs_poll(struct file *filp, poll_table *wait);
 extern int relayfs_mmap(struct file *filp, struct vm_area_struct *vma);
 extern int relayfs_release(struct inode *inode, struct file *filp);
+extern int relayfs_ioctl(struct inode *inode, struct file *filp,
+							unsigned int cmd, unsigned long arg);
+extern void relay_subbufs_reserved(struct rchan *chan, int cpu,
+		int subbufs_reserved);
+extern void relay_subbufs_consumed(struct rchan *chan, int cpu,
+		int subbufs_consumed);
+
+/* Relayfs IOCTL */
+
+/* Get the next sub buffer that can be read. */
+#define RELAYFS_GET_SUBBUF				_IOR(0xF4, 0x00,__u32)
+/* Release the oldest reserved (by "get") sub buffer. */
+#define RELAYFS_PUT_SUBBUF				_IO(0xF4, 0x01)
+/* returns the number of sub buffers in the per cpu channel. */
+#define RELAYFS_GET_N_SUBBUFS			_IOR(0xF4, 0x02,__u32)
+/* returns the size of the sub buffers. */
+#define RELAYFS_GET_SUBBUF_SIZE		_IOR(0xF4, 0x03,__u32)
+
 
 #endif /* _LINUX_RELAYFS_FS_H */
 
diff -uprN -X /tmp/dontdiff linux-2.6.9_vanilla/kernel/exit.c /usr/src/linux_lttng/kernel/exit.c
--- linux-2.6.9_vanilla/kernel/exit.c	2005-12-01 14:33:48.000000000 -0500
+++ /usr/src/linux_lttng/kernel/exit.c	2005-11-25 16:21:42.000000000 -0500
@@ -1330,7 +1330,8 @@ static long do_wait(pid_t pid, int optio
 	DECLARE_WAITQUEUE(wait, current);
 	struct task_struct *tsk;
 	int flag, retval;
-
+        
+        trace_process_wait(current->pid, pid);
 	add_wait_queue(&current->wait_chldexit,&wait);
 repeat:
 	flag = 0;
diff -uprN -X /tmp/dontdiff linux-2.6.9_vanilla/kernel/itimer.c /usr/src/linux_lttng/kernel/itimer.c
--- linux-2.6.9_vanilla/kernel/itimer.c	2005-12-01 14:33:54.000000000 -0500
+++ /usr/src/linux_lttng/kernel/itimer.c	2005-11-25 16:44:57.000000000 -0500
@@ -17,7 +17,11 @@
 int do_getitimer(int which, struct itimerval *value)
 {
 	register unsigned long val, interval;
-
+        trace_timer_set_itimer(which,
+                   value->it_interval.tv_sec,
+                   value->it_interval.tv_usec,
+                   value->it_value.tv_sec,
+                   value->it_value.tv_usec);
 	switch (which) {
 	case ITIMER_REAL:
 		interval = current->it_real_incr;
diff -uprN -X /tmp/dontdiff linux-2.6.9_vanilla/kernel/sched.c /usr/src/linux_lttng/kernel/sched.c
--- linux-2.6.9_vanilla/kernel/sched.c	2005-12-01 14:33:54.000000000 -0500
+++ /usr/src/linux_lttng/kernel/sched.c	2005-11-25 16:45:52.000000000 -0500
@@ -2765,6 +2765,7 @@ switch_tasks:
 		++*switch_count;
 
 		prepare_arch_switch(rq, next);
+                trace_process_schedchange(prev->pid, next->pid, prev->state);
 		prev = context_switch(rq, prev, next);
 		barrier();
 
diff -uprN -X /tmp/dontdiff linux-2.6.9_vanilla/kernel/softirq.c /usr/src/linux_lttng/kernel/softirq.c
--- linux-2.6.9_vanilla/kernel/softirq.c	2005-12-01 14:33:54.000000000 -0500
+++ /usr/src/linux_lttng/kernel/softirq.c	2005-11-25 16:47:13.000000000 -0500
@@ -243,7 +243,9 @@ static void tasklet_action(struct softir
 			if (!atomic_read(&t->count)) {
 				if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
 					BUG();
+                                trace_kernel_tasklet_entry(LTT_ENUM_HIGH, t->func, t->data);
 				t->func(t->data);
+                                trace_kernel_tasklet_exit(LTT_ENUM_HIGH, t->func, t->data);
 				tasklet_unlock(t);
 				continue;
 			}
diff -uprN -X /tmp/dontdiff linux-2.6.9_vanilla/Makefile /usr/src/linux_lttng/Makefile
--- linux-2.6.9_vanilla/Makefile	2005-12-01 14:32:22.000000000 -0500
+++ /usr/src/linux_lttng/Makefile	2005-11-29 13:24:50.000000000 -0500
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 9
-EXTRAVERSION = -prep
+EXTRAVERSION = lltng
 NAME=AC 1
 
 # *DOCUMENTATION*
diff -uprN -X /tmp/dontdiff linux-2.6.9_vanilla/mm/filemap.c /usr/src/linux_lttng/mm/filemap.c
--- linux-2.6.9_vanilla/mm/filemap.c	2005-12-01 14:33:54.000000000 -0500
+++ /usr/src/linux_lttng/mm/filemap.c	2005-11-25 16:53:26.000000000 -0500
@@ -436,7 +436,7 @@ void fastcall wait_on_page_bit(struct pa
 {
 	wait_queue_head_t *waitqueue = page_waitqueue(page);
 	DEFINE_PAGE_WAIT(wait, page, bit_nr);
-
+        trace_memory_page_wait_start(page_address(page));
 	do {
 		prepare_to_wait(waitqueue, &wait.wait, TASK_UNINTERRUPTIBLE);
 		if (test_bit(bit_nr, &page->flags)) {
@@ -445,6 +445,7 @@ void fastcall wait_on_page_bit(struct pa
 		}
 	} while (test_bit(bit_nr, &page->flags));
 	finish_wait(waitqueue, &wait.wait);
+        trace_memory_page_wait_end(page_address(page));
 }
 
 EXPORT_SYMBOL(wait_on_page_bit);
diff -uprN -X /tmp/dontdiff linux-2.6.9_vanilla/mm/vmalloc.c /usr/src/linux_lttng/mm/vmalloc.c

