diff options
Diffstat (limited to 'samples/kfifo/record-example.c')
| -rw-r--r-- | samples/kfifo/record-example.c | 167 | 
1 files changed, 167 insertions, 0 deletions
diff --git a/samples/kfifo/record-example.c b/samples/kfifo/record-example.c new file mode 100644 index 00000000000..32c6e0bda74 --- /dev/null +++ b/samples/kfifo/record-example.c @@ -0,0 +1,167 @@ +/* + * Sample dynamic sized record fifo implementation + * + * Copyright (C) 2010 Stefani Seibold <stefani@seibold.net> + * + * Released under the GPL version 2 only. + * + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/proc_fs.h> +#include <linux/mutex.h> +#include <linux/kfifo.h> + +/* + * This module shows how to create a variable sized record fifo. + */ + +/* fifo size in elements (bytes) */ +#define FIFO_SIZE	128 + +/* name of the proc entry */ +#define	PROC_FIFO	"record-fifo" + +/* lock for procfs read access */ +static DEFINE_MUTEX(read_lock); + +/* lock for procfs write access */ +static DEFINE_MUTEX(write_lock); + +/* + * define DYNAMIC in this example for a dynamically allocated fifo. + * + * Otherwise the fifo storage will be a part of the fifo structure. + */ +#if 0 +#define DYNAMIC +#endif + +/* + * struct kfifo_rec_ptr_1 and  STRUCT_KFIFO_REC_1 can handle records of a + * length between 0 and 255 bytes. + * + * struct kfifo_rec_ptr_2 and  STRUCT_KFIFO_REC_2 can handle records of a + * length between 0 and 65535 bytes. + */ + +#ifdef DYNAMIC +struct kfifo_rec_ptr_1 test; + +#else +typedef STRUCT_KFIFO_REC_1(FIFO_SIZE) mytest; + +static mytest test; +#endif + +static int __init testfunc(void) +{ +	char		buf[100]; +	unsigned int	i; +	unsigned int	ret; +	struct { unsigned char buf[6]; } hello = { "hello" }; + +	printk(KERN_INFO "record fifo test start\n"); + +	kfifo_in(&test, &hello, sizeof(hello)); + +	/* show the size of the next record in the fifo */ +	printk(KERN_INFO "fifo peek len: %u\n", kfifo_peek_len(&test)); + +	/* put in variable length data */ +	for (i = 0; i < 10; i++) { +		memset(buf, 'a' + i, i + 1); +		kfifo_in(&test, buf, i + 1); +	} + +	printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test)); + +	/* show the first record without removing from the fifo */ +	ret = kfifo_out_peek(&test, buf, sizeof(buf)); +	if (ret) +		printk(KERN_INFO "%.*s\n", ret, buf); + +	/* print out all records in the fifo */ +	while (!kfifo_is_empty(&test)) { +		ret = kfifo_out(&test, buf, sizeof(buf)); +		printk(KERN_INFO "%.*s\n", ret, buf); +	} + +	return 0; +} + +static ssize_t fifo_write(struct file *file, const char __user *buf, +						size_t count, loff_t *ppos) +{ +	int ret; +	unsigned int copied; + +	if (mutex_lock_interruptible(&write_lock)) +		return -ERESTARTSYS; + +	ret = kfifo_from_user(&test, buf, count, &copied); + +	mutex_unlock(&write_lock); + +	return ret ? ret : copied; +} + +static ssize_t fifo_read(struct file *file, char __user *buf, +						size_t count, loff_t *ppos) +{ +	int ret; +	unsigned int copied; + +	if (mutex_lock_interruptible(&read_lock)) +		return -ERESTARTSYS; + +	ret = kfifo_to_user(&test, buf, count, &copied); + +	mutex_unlock(&read_lock); + +	return ret ? ret : copied; +} + +static const struct file_operations fifo_fops = { +	.owner		= THIS_MODULE, +	.read		= fifo_read, +	.write		= fifo_write, +}; + +static int __init example_init(void) +{ +#ifdef DYNAMIC +	int ret; + +	ret = kfifo_alloc(&test, FIFO_SIZE, GFP_KERNEL); +	if (ret) { +		printk(KERN_ERR "error kfifo_alloc\n"); +		return ret; +	} +#else +	INIT_KFIFO(test); +#endif +	testfunc(); + +	if (proc_create(PROC_FIFO, 0, NULL, &fifo_fops) == NULL) { +#ifdef DYNAMIC +		kfifo_free(&test); +#endif +		return -ENOMEM; +	} +	return 0; +} + +static void __exit example_exit(void) +{ +	remove_proc_entry(PROC_FIFO, NULL); +#ifdef DYNAMIC +	kfifo_free(&test); +#endif +} + +module_init(example_init); +module_exit(example_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>");  |