Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Sample kfifo int type 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 int type fifo.
0016  */
0017 
0018 /* fifo size in elements (ints) */
0019 #define FIFO_SIZE   32
0020 
0021 /* name of the proc entry */
0022 #define PROC_FIFO   "int-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 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     /* put values into the fifo */
0061     for (i = 0; i != 10; i++)
0062         kfifo_put(&test, i);
0063 
0064     /* show the number of used elements */
0065     printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test));
0066 
0067     /* get max of 2 elements from the fifo */
0068     ret = kfifo_out(&test, buf, 2);
0069     printk(KERN_INFO "ret: %d\n", ret);
0070     /* and put it back to the end of the fifo */
0071     ret = kfifo_in(&test, buf, ret);
0072     printk(KERN_INFO "ret: %d\n", ret);
0073 
0074     /* skip first element of the fifo */
0075     printk(KERN_INFO "skip 1st element\n");
0076     kfifo_skip(&test);
0077 
0078     /* put values into the fifo until is full */
0079     for (i = 20; kfifo_put(&test, i); i++)
0080         ;
0081 
0082     printk(KERN_INFO "queue len: %u\n", kfifo_len(&test));
0083 
0084     /* show the first value without removing from the fifo */
0085     if (kfifo_peek(&test, &i))
0086         printk(KERN_INFO "%d\n", i);
0087 
0088     /* check the correctness of all values in the fifo */
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>");