Initial commit
authorBryn M. Reeves <bmr@redhat.com>
Mon, 1 Oct 2012 08:27:44 +0000 (09:27 +0100)
committerBryn M. Reeves <bmr@redhat.com>
Mon, 1 Oct 2012 08:27:44 +0000 (09:27 +0100)
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
conbench.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..7c6d9db
--- /dev/null
+++ b/Makefile
@@ -0,0 +1 @@
+obj-m += conbench.o
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..8e12400
--- /dev/null
+++ b/README
@@ -0,0 +1,12 @@
+Conbench - a simple kernel console benchmark
+
+Conbench is a simple load generator / benchmark tool for testing the 
+performance of the Linux kernel console subsystem. When loaded the
+module will attempt to write out the configured number of log
+messages using asynchronous workqueue tasks.
+
+TODO:
+
+- sync/async control
+- automatic worker scaling
+
diff --git a/conbench.c b/conbench.c
new file mode 100644 (file)
index 0000000..b8d3d4c
--- /dev/null
@@ -0,0 +1,95 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+
+static unsigned int lines = 20000;
+
+atomic_t todo, done;
+
+static const char *fmtstr= KERN_WARNING "log message %5d of %5d (%p) [done %5d / todo %5d]\n";
+
+LIST_HEAD(work_items);
+
+struct cb_work_item {
+       struct work_struct printer;
+       struct list_head printers;
+       int start;
+       int end;
+};
+
+void cb_log_msgs_fn(struct work_struct *work)
+{
+       int i;
+       struct cb_work_item *this =
+               container_of(work, struct cb_work_item, printer);
+
+       for (i = this->start; i < this->end; i++)
+               printk(fmtstr, i + 1, lines, this,
+                       atomic_read(&done),
+                       atomic_read(&todo));
+       atomic_sub((this->end - this->start + 1), &todo);
+       atomic_add((this->end - this->start + 1), &done);
+}
+
+int conbench_init(void)
+{
+       int ret = 0, i, lines_each, workers = 4;
+       struct list_head *pos, *next;
+
+       atomic_set(&todo, lines);
+       atomic_set(&done, 0);
+
+       lines_each = lines / workers;
+
+       for (i = 0; i < workers; i++) {
+               struct cb_work_item *item;
+               item = kzalloc(sizeof(*item), GFP_KERNEL);
+               if (!item) {
+                       ret = -1;
+                       goto out_free;
+               }
+               INIT_WORK(&item->printer, cb_log_msgs_fn);
+               item->start = i * lines_each;
+               item->end = (i + 1) * lines_each - 1;
+               list_add(&item->printers, &work_items);
+               printk(KERN_ERR "created work item for %5d to %5d (%p)",
+                       item->start, item->end, item);
+       }
+
+       list_for_each(pos, &work_items) {
+               printk(KERN_ERR "conbench: scheduling printer\n");
+               schedule_work(&list_entry(pos, struct cb_work_item, printers)->printer);
+       }
+
+       //while (atomic_read(&todo) && (atomic_read(&done) != lines))
+               //msleep(5000);
+
+       flush_scheduled_work();
+
+out_free:
+       list_for_each_safe(pos, next, &work_items) {
+               struct cb_work_item *wi;
+               wi = list_entry(pos, struct cb_work_item, printers);
+               list_del(&wi->printers);
+               kfree(wi);
+       }
+       return ret;
+}
+
+void conbench_exit(void)
+{
+       return;
+}
+
+module_init(conbench_init);
+module_exit(conbench_exit);
+
+module_param(lines, uint, 0644);
+MODULE_PARM_DESC(lines, "number of log lines to write");
+MODULE_DESCRIPTION("console benchmark");
+MODULE_AUTHOR("Bryn M. Reeves");
+MODULE_LICENSE("GPL");
+