[patch 2/4] KMON - kmon core implementation ...

From: Davide Libenzi
Date: Sun May 06 2007 - 19:49:46 EST


This is the core implementation of the kmon interface.



Signed-off-by: Davide Libenzi <davidel@xxxxxxxxxxxxxxx>


- Davide


Index: linux-2.6.21.scdev/include/linux/kmon.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.21.scdev/include/linux/kmon.h 2007-05-06 14:10:51.000000000 -0700
@@ -0,0 +1,77 @@
+/*
+ * include/linux/kmon.h
+ *
+ * Copyright (C) 2007 Davide Libenzi <davidel@xxxxxxxxxxxxxxx>
+ *
+ */
+
+#ifndef _LINUX_KMON_H
+#define _LINUX_KMON_H
+
+#define KMON_START _IO('K', 1)
+#define KMON_STOP _IO('K', 2)
+#define KMON_BUFFSIZE _IOR('K', 3, long)
+
+
+#ifdef __KERNEL__
+
+struct kmon_ring {
+ unsigned long head, tail;
+ unsigned long size;
+ void *data;
+};
+
+struct kmon_buffer {
+ void *data;
+ unsigned long size;
+};
+
+struct kmon_notifier {
+ struct list_head lnk;
+ void (*write)(struct kmon_notifier *, const struct kmon_buffer *, int);
+};
+
+int kmon_ring_write(struct kmon_ring *rng, const struct kmon_buffer *kbuf, int n);
+unsigned long kmon_ring_read(struct kmon_ring *rng, struct kmon_buffer *kbuf);
+void kmon_ring_commit_read(struct kmon_ring *rng, unsigned long size);
+int kmon_add_data(const void *data, unsigned long size);
+void kmon_notify_add(struct kmon_notifier *knfy);
+void kmon_notify_remove(struct kmon_notifier *knfy);
+int kmon_setup(void);
+void kmon_cleanup(void);
+
+unsigned long kmon_ring_avail(const struct kmon_ring *rng)
+{
+ return (rng->head - rng->tail) & (rng->size - 1);
+}
+
+static inline void kmon_put16(unsigned char *buf, u16 v)
+{
+ *buf++ = (unsigned char) v;
+ *buf = (unsigned char) (v >> 8);
+}
+
+static inline void kmon_put32(unsigned char *buf, u32 v)
+{
+ *buf++ = (unsigned char) v;
+ *buf++ = (unsigned char) (v >> 8);
+ *buf++ = (unsigned char) (v >> 16);
+ *buf = (unsigned char) (v >> 24);
+}
+
+static inline void kmon_put64(unsigned char *buf, u64 v)
+{
+ *buf++ = (unsigned char) v;
+ *buf++ = (unsigned char) (v >> 8);
+ *buf++ = (unsigned char) (v >> 16);
+ *buf++ = (unsigned char) (v >> 24);
+ *buf++ = (unsigned char) (v >> 32);
+ *buf++ = (unsigned char) (v >> 40);
+ *buf++ = (unsigned char) (v >> 48);
+ *buf = (unsigned char) (v >> 56);
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_KMON_H */
+
Index: linux-2.6.21.scdev/drivers/char/kmon-dev.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.21.scdev/drivers/char/kmon-dev.c 2007-05-06 14:10:51.000000000 -0700
@@ -0,0 +1,268 @@
+/*
+ * drivers/char/kmon-dev.c
+ *
+ * Copyright (C) 2007 Davide Libenzi <davidel@xxxxxxxxxxxxxxx>
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/fcntl.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+#include <linux/log2.h>
+#include <linux/kmon.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#define KMON_BUFSIZE_DEFAULT (1024 * 1024)
+#define KMON "kmon v0.17"
+
+#define KMON_FL_OVERFLOW (1 << 0)
+
+struct kmon_ctx {
+ struct kmon_notifier knfy;
+ struct mutex mtx;
+ wait_queue_head_t wqh;
+ struct kmon_ring rng;
+ unsigned long flags;
+};
+
+static int kmon_alloc_ring(struct kmon_ring *rng, unsigned long size)
+{
+ size = roundup_pow_of_two(size);
+ rng->data = vmalloc(size);
+ if (rng->data == NULL)
+ return -ENOMEM;
+ rng->head = rng->tail = 0;
+ rng->size = size;
+
+ return 0;
+}
+
+static void kmon_nfy_write(struct kmon_notifier *knfy, const struct kmon_buffer *kbuf,
+ int n)
+{
+ struct kmon_ctx *ctx = container_of(knfy, struct kmon_ctx, knfy);
+ int error;
+
+ mutex_lock(&ctx->mtx);
+ if (likely((ctx->flags & KMON_FL_OVERFLOW) == 0)) {
+ error = kmon_ring_write(&ctx->rng, kbuf, n);
+ if (unlikely(error))
+ ctx->flags |= KMON_FL_OVERFLOW;
+ }
+ if (waitqueue_active(&ctx->wqh))
+ wake_up_locked(&ctx->wqh);
+ mutex_unlock(&ctx->mtx);
+}
+
+static int kmon_open(struct inode *inode, struct file *file)
+{
+ int error;
+ struct kmon_ctx *ctx;
+
+ ctx = (struct kmon_ctx *) kzalloc(sizeof(struct kmon_ctx), GFP_KERNEL);
+ if (ctx == NULL)
+ return -ENOMEM;
+ error = kmon_alloc_ring(&ctx->rng, KMON_BUFSIZE_DEFAULT);
+ if (error) {
+ kfree(ctx);
+ return error;
+ }
+ init_waitqueue_head(&ctx->wqh);
+ mutex_init(&ctx->mtx);
+
+ file->private_data = ctx;
+
+ return 0;
+}
+
+static int kmon_release(struct inode *inode, struct file *file)
+{
+ struct kmon_ctx *ctx = file->private_data;
+
+ if (ctx->knfy.write != NULL)
+ kmon_notify_remove(&ctx->knfy);
+ vfree(ctx->rng.data);
+ mutex_destroy(&ctx->mtx);
+ kfree(ctx);
+
+ return 0;
+}
+
+static unsigned int kmon_poll(struct file *file, poll_table *wait)
+{
+ struct kmon_ctx *ctx = file->private_data;
+ unsigned int events = 0;
+
+ poll_wait(file, &ctx->wqh, wait);
+
+ mutex_lock(&ctx->mtx);
+ if (ctx->flags & KMON_FL_OVERFLOW)
+ events |= POLLERR;
+ if (ctx->rng.head != ctx->rng.tail)
+ events |= POLLIN;
+ mutex_unlock(&ctx->mtx);
+
+ return events;
+}
+
+static ssize_t kmon_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ struct kmon_ctx *ctx = file->private_data;
+ ssize_t res, i;
+ unsigned long size, bcnt;
+ DECLARE_WAITQUEUE(wait, current);
+ struct kmon_buffer kbuf[2];
+
+ mutex_lock(&ctx->mtx);
+ res = -EAGAIN;
+ size = kmon_ring_read(&ctx->rng, kbuf);
+ if (size == 0 && !(file->f_flags & O_NONBLOCK)) {
+ __add_wait_queue(&ctx->wqh, &wait);
+ for (res = 0;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ size = kmon_ring_read(&ctx->rng, kbuf);
+ if (size != 0) {
+ res = 0;
+ break;
+ }
+ if (signal_pending(current)) {
+ res = -ERESTARTSYS;
+ break;
+ }
+ mutex_unlock(&ctx->mtx);
+ schedule();
+ mutex_lock(&ctx->mtx);
+ }
+ __remove_wait_queue(&ctx->wqh, &wait);
+ __set_current_state(TASK_RUNNING);
+ }
+ if (size != 0) {
+ res = -EFAULT;
+ for (i = 0, size = 0; size < (unsigned long) count &&
+ i < 2; i++) {
+ bcnt = min(kbuf[i].size, (unsigned long) count - size);
+ if (bcnt != 0 &&
+ copy_to_user(buf + size, kbuf[i].data, bcnt))
+ goto out_unlock;
+ size += bcnt;
+ }
+ kmon_ring_commit_read(&ctx->rng, size);
+ res = (ssize_t) size;
+ }
+out_unlock:
+ mutex_unlock(&ctx->mtx);
+
+ return res;
+}
+
+static int kmon_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct kmon_ctx *ctx = file->private_data;
+ int error = -EINVAL;
+ unsigned long size;
+
+ switch (cmd) {
+ case KMON_START:
+ mutex_lock(&ctx->mtx);
+ error = -ENOBUFS;
+ if (ctx->rng.data != NULL) {
+ if (ctx->knfy.write == NULL) {
+ ctx->rng.head = ctx->rng.tail = 0;
+ ctx->flags &= ~KMON_FL_OVERFLOW;
+ ctx->knfy.write = kmon_nfy_write;
+ kmon_notify_add(&ctx->knfy);
+ error = 0;
+ } else
+ error = -EALREADY;
+ }
+ mutex_unlock(&ctx->mtx);
+ break;
+
+ case KMON_STOP:
+ mutex_lock(&ctx->mtx);
+ if (ctx->knfy.write != NULL) {
+ kmon_notify_remove(&ctx->knfy);
+ ctx->knfy.write = NULL;
+ error = 0;
+ } else
+ error = -EALREADY;
+ mutex_unlock(&ctx->mtx);
+ break;
+
+ case KMON_BUFFSIZE:
+ if (copy_from_user(&size, (void __user *) arg, sizeof(size)))
+ return -EFAULT;
+ mutex_lock(&ctx->mtx);
+ if (ctx->knfy.write == NULL) {
+ vfree(ctx->rng.data);
+ ctx->rng.data = NULL;
+ error = kmon_alloc_ring(&ctx->rng, size);
+ } else
+ error = -EBUSY;
+ mutex_unlock(&ctx->mtx);
+ break;
+ }
+
+ return error;
+}
+
+static const struct file_operations kmon_fops = {
+ .poll = kmon_poll,
+ .read = kmon_read,
+ .ioctl = kmon_ioctl,
+ .open = kmon_open,
+ .release = kmon_release,
+};
+
+static struct miscdevice kmon_dev = {
+ MISC_DYNAMIC_MINOR,
+ "kmon",
+ &kmon_fops
+};
+
+static int __init kmon_init(void)
+{
+ int error;
+
+ error = kmon_setup();
+ if (error)
+ return error;
+
+ error = misc_register(&kmon_dev);
+ if (error) {
+ printk(KERN_ERR KMON " - unable to register misc device.\n");
+ goto out_kmon_cleanup;
+ }
+
+ return 0;
+
+out_kmon_cleanup:
+ kmon_cleanup();
+ return error;
+}
+module_init(kmon_init);
+
+static void __exit kmon_exit(void)
+{
+ misc_deregister(&kmon_dev);
+ kmon_cleanup();
+}
+module_exit(kmon_exit);
+
+MODULE_AUTHOR("Davide Libenzi");
+MODULE_LICENSE("GPL");
+
Index: linux-2.6.21.scdev/kernel/kmon.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.21.scdev/kernel/kmon.c 2007-05-06 14:10:51.000000000 -0700
@@ -0,0 +1,310 @@
+/*
+ * kernel/kmon.c
+ *
+ * Copyright (C) 2007 Davide Libenzi <davidel@xxxxxxxxxxxxxxx>
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/fcntl.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/rcupdate.h>
+#include <linux/workqueue.h>
+#include <linux/log2.h>
+#include <linux/cpu.h>
+#include <linux/ktime.h>
+#include <linux/kmon.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#define DEF_CPUBUF_SIZE (1024 * 16)
+#define DEF_SYNCBUF_FREQ (HZ / 20)
+#define CPUBUF_CPU(p) ((int) ((p) - cpubuf))
+
+struct kmon_cpubuf {
+ struct delayed_work work;
+ struct kmon_ring rng;
+ u64 base_time;
+};
+
+static unsigned long cpubuf_size = DEF_CPUBUF_SIZE;
+static unsigned long flush_freq = DEF_SYNCBUF_FREQ;
+static struct kmon_cpubuf cpubuf[NR_CPUS] __cacheline_aligned;
+static struct list_head kmon_nfylist = LIST_HEAD_INIT(kmon_nfylist);
+static struct mutex kmon_mtx;
+static struct mutex setup_mtx;
+static long usecnt;
+
+int kmon_ring_write(struct kmon_ring *rng, const struct kmon_buffer *kbuf, int n)
+{
+ int i;
+ unsigned long head, rspace, dwrt;
+
+ head = rng->head;
+ rspace = (rng->size - 1) - ((head - rng->tail) & (rng->size - 1));
+ for (i = 0; i < n; i++, kbuf++) {
+ if (rspace < kbuf->size)
+ return -EAGAIN;
+ dwrt = min(kbuf->size, rng->size - head);
+ if (likely(dwrt))
+ memcpy(rng->data + head, kbuf->data, dwrt);
+ if (kbuf->size > dwrt)
+ memcpy(rng->data, kbuf->data + dwrt, kbuf->size - dwrt);
+ rspace -= kbuf->size;
+ head = (head + kbuf->size) & (rng->size - 1);
+ }
+ smp_wmb();
+ rng->head = head;
+
+ return 0;
+}
+EXPORT_SYMBOL(kmon_ring_write);
+
+unsigned long kmon_ring_read(struct kmon_ring *rng, struct kmon_buffer *kbuf)
+{
+ unsigned long size;
+
+ size = kmon_ring_avail(rng);
+ kbuf[0].size = min(size, rng->size - rng->tail);
+ kbuf[0].data = rng->data + rng->tail;
+ kbuf[1].size = size - kbuf[0].size;
+ kbuf[1].data = rng->data;
+
+ return size;
+}
+EXPORT_SYMBOL(kmon_ring_read);
+
+void kmon_ring_commit_read(struct kmon_ring *rng, unsigned long size)
+{
+ rng->tail = (rng->tail + size) & (rng->size - 1);
+}
+EXPORT_SYMBOL(kmon_ring_commit_read);
+
+static unsigned int kmon_prepare_buf(unsigned char *buf, int cpu, u64 time,
+ unsigned long size)
+{
+ buf[0] = (unsigned char) cpu;
+ kmon_put64(buf + 1, time);
+ kmon_put16(buf + 9, (u16) size);
+ return 11;
+}
+
+int kmon_add_data(const void *data, unsigned long size)
+{
+ int cpu, error = -EAGAIN;
+ u64 ctime;
+ struct kmon_cpubuf *cpub;
+ unsigned char buf[16];
+ struct kmon_buffer kbuf[2];
+
+ rcu_read_lock();
+ cpu = smp_processor_id();
+ cpub = &cpubuf[cpu];
+ if (cpub->rng.data != NULL) {
+ ctime = ktime_to_ns(ktime_get());
+ kbuf[0].data = buf;
+ kbuf[0].size = kmon_prepare_buf(buf, cpu, ctime, size);
+ kbuf[1].data = (void *) data;
+ kbuf[1].size = size;
+ error = kmon_ring_write(&cpub->rng, kbuf, 2);
+ }
+ rcu_read_unlock();
+
+ return error;
+}
+EXPORT_SYMBOL(kmon_add_data);
+
+void kmon_notify_add(struct kmon_notifier *knfy)
+{
+ mutex_lock(&kmon_mtx);
+ list_add_tail(&knfy->lnk, &kmon_nfylist);
+ mutex_unlock(&kmon_mtx);
+}
+EXPORT_SYMBOL(kmon_notify_add);
+
+void kmon_notify_remove(struct kmon_notifier *knfy)
+{
+ mutex_lock(&kmon_mtx);
+ list_del_init(&knfy->lnk);
+ mutex_unlock(&kmon_mtx);
+}
+EXPORT_SYMBOL(kmon_notify_remove);
+
+static void kmon_sync_buffer(struct work_struct *work)
+{
+ unsigned long size;
+ struct kmon_cpubuf *cpub;
+ struct kmon_notifier *knfy;
+ struct kmon_buffer kbuf[2];
+
+ cpub = container_of(work, struct kmon_cpubuf, work.work);
+ mutex_lock(&kmon_mtx);
+ if (likely(cpub->rng.data != NULL)) {
+ size = kmon_ring_read(&cpub->rng, kbuf);
+ if (likely(size)) {
+ list_for_each_entry(knfy, &kmon_nfylist, lnk) {
+ (*knfy->write)(knfy, kbuf, 2);
+ }
+ kmon_ring_commit_read(&cpub->rng, size);
+ }
+ schedule_delayed_work(&cpub->work, flush_freq);
+ }
+ mutex_unlock(&kmon_mtx);
+}
+
+static int kmon_cpu_prepare(int cpu)
+{
+ unsigned long size;
+ void *data;
+ struct kmon_cpubuf *cpub;
+
+ size = roundup_pow_of_two(cpubuf_size);
+ cpub = &cpubuf[cpu];
+ mutex_lock(&kmon_mtx);
+ if (cpub->rng.data == NULL) {
+ data = vmalloc_node(size, cpu_to_node(cpu));
+ if (data == NULL) {
+ mutex_unlock(&kmon_mtx);
+ return -ENOMEM;
+ }
+ cpub->rng.head = cpub->rng.tail = 0;
+ cpub->rng.size = size;
+ rcu_assign_pointer(cpub->rng.data, data);
+ INIT_DELAYED_WORK(&cpub->work, kmon_sync_buffer);
+ schedule_delayed_work_on(cpu, &cpub->work, flush_freq + cpu);
+ }
+ mutex_unlock(&kmon_mtx);
+
+ return 0;
+}
+
+static void kmon_cpu_cleanup(int cpu)
+{
+ void *data = NULL;
+ struct kmon_cpubuf *cpub;
+
+ cpub = &cpubuf[cpu];
+ mutex_lock(&kmon_mtx);
+ if (cpub->rng.data != NULL) {
+ data = cpub->rng.data;
+ cpub->rng.data = NULL;
+ }
+ mutex_unlock(&kmon_mtx);
+
+ if (data != NULL) {
+ cancel_delayed_work(&cpub->work);
+ synchronize_rcu();
+ vfree(data);
+ }
+}
+
+static int kmon_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
+ void *v)
+{
+ int cpu = (long) v;
+
+ switch (val) {
+ case CPU_UP_PREPARE:
+ kmon_cpu_prepare(cpu);
+ break;
+ case CPU_UP_CANCELED:
+ case CPU_DEAD:
+ kmon_cpu_cleanup(cpu);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block kmon_cpu_notifier = {
+ .notifier_call = kmon_cpu_hotplug,
+};
+
+static void kmon_free_cpubufs(void)
+{
+ int cpu;
+
+ for_each_online_cpu(cpu)
+ kmon_cpu_cleanup(cpu);
+}
+
+static int kmon_alloc_cpubufs(void)
+{
+ int cpu, error;
+
+ for_each_online_cpu(cpu) {
+ error = kmon_cpu_prepare(cpu);
+ if (error) {
+ kmon_free_cpubufs();
+ return error;
+ }
+ }
+
+ return 0;
+}
+
+int kmon_setup(void)
+{
+ int error;
+
+ mutex_lock(&setup_mtx);
+ if (usecnt > 0)
+ goto setup_done;
+
+ error = register_cpu_notifier(&kmon_cpu_notifier);
+ if (error)
+ goto out_unlock;
+
+ error = kmon_alloc_cpubufs();
+ if (error)
+ goto out_unreg_cpuntfy;
+
+setup_done:
+ usecnt++;
+ mutex_unlock(&setup_mtx);
+
+ return 0;
+
+out_unreg_cpuntfy:
+ unregister_cpu_notifier(&kmon_cpu_notifier);
+ kmon_free_cpubufs();
+out_unlock:
+ mutex_unlock(&setup_mtx);
+ return error;
+}
+EXPORT_SYMBOL(kmon_setup);
+
+void kmon_cleanup(void)
+{
+ mutex_lock(&setup_mtx);
+ usecnt--;
+ if (usecnt == 0) {
+ unregister_cpu_notifier(&kmon_cpu_notifier);
+ kmon_free_cpubufs();
+ }
+ mutex_unlock(&setup_mtx);
+}
+EXPORT_SYMBOL(kmon_cleanup);
+
+static int __init kmon_init(void)
+{
+ mutex_init(&kmon_mtx);
+ mutex_init(&setup_mtx);
+
+ return 0;
+}
+fs_initcall(kmon_init);
+
Index: linux-2.6.21.scdev/kernel/kmon-stats.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.21.scdev/kernel/kmon-stats.c 2007-05-06 14:10:51.000000000 -0700
@@ -0,0 +1,62 @@
+/*
+ * kernel/kmon-stats.c
+ *
+ * Copyright (C) 2007 Davide Libenzi <davidel@xxxxxxxxxxxxxxx>
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/fcntl.h>
+#include <linux/sched.h>
+#include <linux/kmon.h>
+#include <linux/kmon-stats.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+void kmon_st_task_enqueue(struct task_struct *tsk)
+{
+ unsigned char buf[8];
+
+ buf[0] = KMON_DT_TSKQUEUE;
+ kmon_put16(buf + 1, (u16) tsk->pid);
+ kmon_add_data(buf, 3);
+}
+
+void kmon_st_task_dequeue(struct task_struct *tsk)
+{
+ unsigned char buf[8];
+
+ buf[0] = KMON_DT_TSKDEQUEUE;
+ kmon_put16(buf + 1, (u16) tsk->pid);
+ kmon_add_data(buf, 3);
+}
+
+void kmon_st_task_switch(struct task_struct *prev, struct task_struct *next)
+{
+ unsigned char buf[8];
+
+ buf[0] = KMON_DT_TSKSWITCH;
+ kmon_put16(buf + 1, (u16) prev->pid);
+ kmon_put16(buf + 3, (u16) next->pid);
+ kmon_add_data(buf, 5);
+}
+
+void kmon_st_task_wakeup(struct task_struct *from, struct task_struct *to)
+{
+ unsigned char buf[8];
+
+ buf[0] = KMON_DT_TSKWAKEUP;
+ kmon_put16(buf + 1, from ? (u16) from->pid: 0);
+ kmon_put16(buf + 3, (u16) to->pid);
+ kmon_add_data(buf, 5);
+}
+
Index: linux-2.6.21.scdev/include/linux/kmon-stats.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.21.scdev/include/linux/kmon-stats.h 2007-05-06 14:10:51.000000000 -0700
@@ -0,0 +1,37 @@
+/*
+ * include/linux/kmon-stats.h
+ *
+ * Copyright (C) 2007 Davide Libenzi <davidel@xxxxxxxxxxxxxxx>
+ *
+ */
+
+#ifndef _LINUX_KMON_STATS_H
+#define _LINUX_KMON_STATS_H
+
+#define KMON_DT_TSKQUEUE 1
+#define KMON_DT_TSKDEQUEUE 2
+#define KMON_DT_TSKSWITCH 3
+#define KMON_DT_TSKWAKEUP 4
+
+#ifdef __KERNEL__
+
+#ifdef CONFIG_KMON
+
+void kmon_st_task_enqueue(struct task_struct *tsk);
+void kmon_st_task_dequeue(struct task_struct *tsk);
+void kmon_st_task_switch(struct task_struct *prev, struct task_struct *next);
+void kmon_st_task_wakeup(struct task_struct *from, struct task_struct *to);
+
+#else /* CONFIG_KMON */
+
+#define kmon_st_task_enqueue(p) do { } while (0)
+#define kmon_st_task_dequeue(p) do { } while (0)
+#define kmon_st_task_switch(p, n) do { } while (0)
+#define kmon_st_task_wakeup(f, t) do { } while (0)
+
+#endif /* CONFIG_KMON */
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_KMON_STATS_H */
+

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/