0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/init.h>
0009 #include <linux/module.h>
0010 #include <linux/proc_fs.h>
0011 #include <linux/mutex.h>
0012 #include <linux/kfifo.h>
0013
0014
0015
0016
0017
0018
0019 #define FIFO_SIZE 32
0020
0021
0022 #define PROC_FIFO "bytestream-fifo"
0023
0024
0025 static DEFINE_MUTEX(read_access);
0026
0027
0028 static DEFINE_MUTEX(write_access);
0029
0030
0031
0032
0033
0034
0035 #if 0
0036 #define DYNAMIC
0037 #endif
0038
0039 #ifdef DYNAMIC
0040 static struct kfifo test;
0041 #else
0042 static DECLARE_KFIFO(test, unsigned char, FIFO_SIZE);
0043 #endif
0044
0045 static const unsigned char expected_result[FIFO_SIZE] = {
0046 3, 4, 5, 6, 7, 8, 9, 0,
0047 1, 20, 21, 22, 23, 24, 25, 26,
0048 27, 28, 29, 30, 31, 32, 33, 34,
0049 35, 36, 37, 38, 39, 40, 41, 42,
0050 };
0051
0052 static int __init testfunc(void)
0053 {
0054 unsigned char buf[6];
0055 unsigned char i, j;
0056 unsigned int ret;
0057
0058 printk(KERN_INFO "byte stream fifo test start\n");
0059
0060
0061 kfifo_in(&test, "hello", 5);
0062
0063
0064 for (i = 0; i != 10; i++)
0065 kfifo_put(&test, i);
0066
0067
0068 printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test));
0069
0070
0071 i = kfifo_out(&test, buf, 5);
0072 printk(KERN_INFO "buf: %.*s\n", i, buf);
0073
0074
0075 ret = kfifo_out(&test, buf, 2);
0076 printk(KERN_INFO "ret: %d\n", ret);
0077
0078 ret = kfifo_in(&test, buf, ret);
0079 printk(KERN_INFO "ret: %d\n", ret);
0080
0081
0082 printk(KERN_INFO "skip 1st element\n");
0083 kfifo_skip(&test);
0084
0085
0086 for (i = 20; kfifo_put(&test, i); i++)
0087 ;
0088
0089 printk(KERN_INFO "queue len: %u\n", kfifo_len(&test));
0090
0091
0092 if (kfifo_peek(&test, &i))
0093 printk(KERN_INFO "%d\n", i);
0094
0095
0096 j = 0;
0097 while (kfifo_get(&test, &i)) {
0098 printk(KERN_INFO "item = %d\n", i);
0099 if (i != expected_result[j++]) {
0100 printk(KERN_WARNING "value mismatch: test failed\n");
0101 return -EIO;
0102 }
0103 }
0104 if (j != ARRAY_SIZE(expected_result)) {
0105 printk(KERN_WARNING "size mismatch: test failed\n");
0106 return -EIO;
0107 }
0108 printk(KERN_INFO "test passed\n");
0109
0110 return 0;
0111 }
0112
0113 static ssize_t fifo_write(struct file *file, const char __user *buf,
0114 size_t count, loff_t *ppos)
0115 {
0116 int ret;
0117 unsigned int copied;
0118
0119 if (mutex_lock_interruptible(&write_access))
0120 return -ERESTARTSYS;
0121
0122 ret = kfifo_from_user(&test, buf, count, &copied);
0123
0124 mutex_unlock(&write_access);
0125 if (ret)
0126 return ret;
0127
0128 return copied;
0129 }
0130
0131 static ssize_t fifo_read(struct file *file, char __user *buf,
0132 size_t count, loff_t *ppos)
0133 {
0134 int ret;
0135 unsigned int copied;
0136
0137 if (mutex_lock_interruptible(&read_access))
0138 return -ERESTARTSYS;
0139
0140 ret = kfifo_to_user(&test, buf, count, &copied);
0141
0142 mutex_unlock(&read_access);
0143 if (ret)
0144 return ret;
0145
0146 return copied;
0147 }
0148
0149 static const struct proc_ops fifo_proc_ops = {
0150 .proc_read = fifo_read,
0151 .proc_write = fifo_write,
0152 .proc_lseek = noop_llseek,
0153 };
0154
0155 static int __init example_init(void)
0156 {
0157 #ifdef DYNAMIC
0158 int ret;
0159
0160 ret = kfifo_alloc(&test, FIFO_SIZE, GFP_KERNEL);
0161 if (ret) {
0162 printk(KERN_ERR "error kfifo_alloc\n");
0163 return ret;
0164 }
0165 #else
0166 INIT_KFIFO(test);
0167 #endif
0168 if (testfunc() < 0) {
0169 #ifdef DYNAMIC
0170 kfifo_free(&test);
0171 #endif
0172 return -EIO;
0173 }
0174
0175 if (proc_create(PROC_FIFO, 0, NULL, &fifo_proc_ops) == NULL) {
0176 #ifdef DYNAMIC
0177 kfifo_free(&test);
0178 #endif
0179 return -ENOMEM;
0180 }
0181 return 0;
0182 }
0183
0184 static void __exit example_exit(void)
0185 {
0186 remove_proc_entry(PROC_FIFO, NULL);
0187 #ifdef DYNAMIC
0188 kfifo_free(&test);
0189 #endif
0190 }
0191
0192 module_init(example_init);
0193 module_exit(example_exit);
0194 MODULE_LICENSE("GPL");
0195 MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>");