Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Sample kfifo byte stream implementation
0004  *
0005  * Copyright (C) 2010 Stefani Seibold <stefani@seibold.net>
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  * This module shows how to create a byte stream fifo.
0016  */
0017 
0018 /* fifo size in elements (bytes) */
0019 #define FIFO_SIZE   32
0020 
0021 /* name of the proc entry */
0022 #define PROC_FIFO   "bytestream-fifo"
0023 
0024 /* lock for procfs read access */
0025 static DEFINE_MUTEX(read_access);
0026 
0027 /* lock for procfs write access */
0028 static DEFINE_MUTEX(write_access);
0029 
0030 /*
0031  * define DYNAMIC in this example for a dynamically allocated fifo.
0032  *
0033  * Otherwise the fifo storage will be a part of the fifo structure.
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     /* put string into the fifo */
0061     kfifo_in(&test, "hello", 5);
0062 
0063     /* put values into the fifo */
0064     for (i = 0; i != 10; i++)
0065         kfifo_put(&test, i);
0066 
0067     /* show the number of used elements */
0068     printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test));
0069 
0070     /* get max of 5 bytes from the fifo */
0071     i = kfifo_out(&test, buf, 5);
0072     printk(KERN_INFO "buf: %.*s\n", i, buf);
0073 
0074     /* get max of 2 elements from the fifo */
0075     ret = kfifo_out(&test, buf, 2);
0076     printk(KERN_INFO "ret: %d\n", ret);
0077     /* and put it back to the end of the fifo */
0078     ret = kfifo_in(&test, buf, ret);
0079     printk(KERN_INFO "ret: %d\n", ret);
0080 
0081     /* skip first element of the fifo */
0082     printk(KERN_INFO "skip 1st element\n");
0083     kfifo_skip(&test);
0084 
0085     /* put values into the fifo until is full */
0086     for (i = 20; kfifo_put(&test, i); i++)
0087         ;
0088 
0089     printk(KERN_INFO "queue len: %u\n", kfifo_len(&test));
0090 
0091     /* show the first value without removing from the fifo */
0092     if (kfifo_peek(&test, &i))
0093         printk(KERN_INFO "%d\n", i);
0094 
0095     /* check the correctness of all values in the fifo */
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>");