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 "int-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 DECLARE_KFIFO_PTR(test, int);
0041 #else
0042 static DEFINE_KFIFO(test, int, FIFO_SIZE);
0043 #endif
0044
0045 static const int 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 int buf[6];
0055 int i, j;
0056 unsigned int ret;
0057
0058 printk(KERN_INFO "int fifo test start\n");
0059
0060
0061 for (i = 0; i != 10; i++)
0062 kfifo_put(&test, i);
0063
0064
0065 printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test));
0066
0067
0068 ret = kfifo_out(&test, buf, 2);
0069 printk(KERN_INFO "ret: %d\n", ret);
0070
0071 ret = kfifo_in(&test, buf, ret);
0072 printk(KERN_INFO "ret: %d\n", ret);
0073
0074
0075 printk(KERN_INFO "skip 1st element\n");
0076 kfifo_skip(&test);
0077
0078
0079 for (i = 20; kfifo_put(&test, i); i++)
0080 ;
0081
0082 printk(KERN_INFO "queue len: %u\n", kfifo_len(&test));
0083
0084
0085 if (kfifo_peek(&test, &i))
0086 printk(KERN_INFO "%d\n", i);
0087
0088
0089 j = 0;
0090 while (kfifo_get(&test, &i)) {
0091 printk(KERN_INFO "item = %d\n", i);
0092 if (i != expected_result[j++]) {
0093 printk(KERN_WARNING "value mismatch: test failed\n");
0094 return -EIO;
0095 }
0096 }
0097 if (j != ARRAY_SIZE(expected_result)) {
0098 printk(KERN_WARNING "size mismatch: test failed\n");
0099 return -EIO;
0100 }
0101 printk(KERN_INFO "test passed\n");
0102
0103 return 0;
0104 }
0105
0106 static ssize_t fifo_write(struct file *file, const char __user *buf,
0107 size_t count, loff_t *ppos)
0108 {
0109 int ret;
0110 unsigned int copied;
0111
0112 if (mutex_lock_interruptible(&write_access))
0113 return -ERESTARTSYS;
0114
0115 ret = kfifo_from_user(&test, buf, count, &copied);
0116
0117 mutex_unlock(&write_access);
0118 if (ret)
0119 return ret;
0120
0121 return copied;
0122 }
0123
0124 static ssize_t fifo_read(struct file *file, char __user *buf,
0125 size_t count, loff_t *ppos)
0126 {
0127 int ret;
0128 unsigned int copied;
0129
0130 if (mutex_lock_interruptible(&read_access))
0131 return -ERESTARTSYS;
0132
0133 ret = kfifo_to_user(&test, buf, count, &copied);
0134
0135 mutex_unlock(&read_access);
0136 if (ret)
0137 return ret;
0138
0139 return copied;
0140 }
0141
0142 static const struct proc_ops fifo_proc_ops = {
0143 .proc_read = fifo_read,
0144 .proc_write = fifo_write,
0145 .proc_lseek = noop_llseek,
0146 };
0147
0148 static int __init example_init(void)
0149 {
0150 #ifdef DYNAMIC
0151 int ret;
0152
0153 ret = kfifo_alloc(&test, FIFO_SIZE, GFP_KERNEL);
0154 if (ret) {
0155 printk(KERN_ERR "error kfifo_alloc\n");
0156 return ret;
0157 }
0158 #endif
0159 if (testfunc() < 0) {
0160 #ifdef DYNAMIC
0161 kfifo_free(&test);
0162 #endif
0163 return -EIO;
0164 }
0165
0166 if (proc_create(PROC_FIFO, 0, NULL, &fifo_proc_ops) == NULL) {
0167 #ifdef DYNAMIC
0168 kfifo_free(&test);
0169 #endif
0170 return -ENOMEM;
0171 }
0172 return 0;
0173 }
0174
0175 static void __exit example_exit(void)
0176 {
0177 remove_proc_entry(PROC_FIFO, NULL);
0178 #ifdef DYNAMIC
0179 kfifo_free(&test);
0180 #endif
0181 }
0182
0183 module_init(example_init);
0184 module_exit(example_exit);
0185 MODULE_LICENSE("GPL");
0186 MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>");