Merge tag 'for-linus-v3.10-rc1-2' of git://oss.sgi.com/xfs/xfs
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / samples / kfifo / bytestream-example.c
CommitLineData
5bf2b193
SS
1/*
2 * Sample kfifo byte stream implementation
3 *
4 * Copyright (C) 2010 Stefani Seibold <stefani@seibold.net>
5 *
6 * Released under the GPL version 2 only.
7 *
8 */
9
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/proc_fs.h>
13#include <linux/mutex.h>
14#include <linux/kfifo.h>
15
16/*
17 * This module shows how to create a byte stream fifo.
18 */
19
20/* fifo size in elements (bytes) */
21#define FIFO_SIZE 32
22
23/* name of the proc entry */
24#define PROC_FIFO "bytestream-fifo"
25
26/* lock for procfs read access */
27static DEFINE_MUTEX(read_lock);
28
29/* lock for procfs write access */
30static DEFINE_MUTEX(write_lock);
31
32/*
33 * define DYNAMIC in this example for a dynamically allocated fifo.
34 *
35 * Otherwise the fifo storage will be a part of the fifo structure.
36 */
37#if 0
38#define DYNAMIC
39#endif
40
41#ifdef DYNAMIC
42static struct kfifo test;
43#else
44static DECLARE_KFIFO(test, unsigned char, FIFO_SIZE);
45#endif
46
a25effa4 47static const unsigned char expected_result[FIFO_SIZE] = {
2aaf2092
AR
48 3, 4, 5, 6, 7, 8, 9, 0,
49 1, 20, 21, 22, 23, 24, 25, 26,
50 27, 28, 29, 30, 31, 32, 33, 34,
51 35, 36, 37, 38, 39, 40, 41, 42,
52};
53
5bf2b193
SS
54static int __init testfunc(void)
55{
56 unsigned char buf[6];
2aaf2092 57 unsigned char i, j;
5bf2b193
SS
58 unsigned int ret;
59
60 printk(KERN_INFO "byte stream fifo test start\n");
61
62 /* put string into the fifo */
63 kfifo_in(&test, "hello", 5);
64
65 /* put values into the fifo */
66 for (i = 0; i != 10; i++)
67 kfifo_put(&test, &i);
68
69 /* show the number of used elements */
70 printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test));
71
72 /* get max of 5 bytes from the fifo */
73 i = kfifo_out(&test, buf, 5);
74 printk(KERN_INFO "buf: %.*s\n", i, buf);
75
76 /* get max of 2 elements from the fifo */
77 ret = kfifo_out(&test, buf, 2);
78 printk(KERN_INFO "ret: %d\n", ret);
79 /* and put it back to the end of the fifo */
80 ret = kfifo_in(&test, buf, ret);
81 printk(KERN_INFO "ret: %d\n", ret);
82
5ddf8391
AR
83 /* skip first element of the fifo */
84 printk(KERN_INFO "skip 1st element\n");
85 kfifo_skip(&test);
86
5bf2b193
SS
87 /* put values into the fifo until is full */
88 for (i = 20; kfifo_put(&test, &i); i++)
89 ;
90
91 printk(KERN_INFO "queue len: %u\n", kfifo_len(&test));
92
a25effa4
AR
93 /* show the first value without removing from the fifo */
94 if (kfifo_peek(&test, &i))
95 printk(KERN_INFO "%d\n", i);
96
2aaf2092
AR
97 /* check the correctness of all values in the fifo */
98 j = 0;
99 while (kfifo_get(&test, &i)) {
a25effa4 100 printk(KERN_INFO "item = %d\n", i);
2aaf2092
AR
101 if (i != expected_result[j++]) {
102 printk(KERN_WARNING "value mismatch: test failed\n");
103 return -EIO;
104 }
105 }
106 if (j != ARRAY_SIZE(expected_result)) {
107 printk(KERN_WARNING "size mismatch: test failed\n");
108 return -EIO;
109 }
110 printk(KERN_INFO "test passed\n");
5bf2b193
SS
111
112 return 0;
113}
114
115static ssize_t fifo_write(struct file *file, const char __user *buf,
116 size_t count, loff_t *ppos)
117{
118 int ret;
119 unsigned int copied;
120
121 if (mutex_lock_interruptible(&write_lock))
122 return -ERESTARTSYS;
123
124 ret = kfifo_from_user(&test, buf, count, &copied);
125
126 mutex_unlock(&write_lock);
127
128 return ret ? ret : copied;
129}
130
131static ssize_t fifo_read(struct file *file, char __user *buf,
132 size_t count, loff_t *ppos)
133{
134 int ret;
135 unsigned int copied;
136
137 if (mutex_lock_interruptible(&read_lock))
138 return -ERESTARTSYS;
139
140 ret = kfifo_to_user(&test, buf, count, &copied);
141
142 mutex_unlock(&read_lock);
143
144 return ret ? ret : copied;
145}
146
147static const struct file_operations fifo_fops = {
148 .owner = THIS_MODULE,
149 .read = fifo_read,
150 .write = fifo_write,
6038f373 151 .llseek = noop_llseek,
5bf2b193
SS
152};
153
154static int __init example_init(void)
155{
156#ifdef DYNAMIC
157 int ret;
158
159 ret = kfifo_alloc(&test, FIFO_SIZE, GFP_KERNEL);
160 if (ret) {
161 printk(KERN_ERR "error kfifo_alloc\n");
162 return ret;
163 }
164#else
165 INIT_KFIFO(test);
166#endif
2aaf2092
AR
167 if (testfunc() < 0) {
168#ifdef DYNAMIC
169 kfifo_free(&test);
170#endif
171 return -EIO;
172 }
5bf2b193
SS
173
174 if (proc_create(PROC_FIFO, 0, NULL, &fifo_fops) == NULL) {
175#ifdef DYNAMIC
176 kfifo_free(&test);
177#endif
178 return -ENOMEM;
179 }
180 return 0;
181}
182
183static void __exit example_exit(void)
184{
185 remove_proc_entry(PROC_FIFO, NULL);
186#ifdef DYNAMIC
187 kfifo_free(&test);
188#endif
189}
190
191module_init(example_init);
192module_exit(example_exit);
193MODULE_LICENSE("GPL");
194MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>");