XenevaOS
Loading...
Searching...
No Matches
kfifo.h
Go to the documentation of this file.
1#ifndef __LINUX_KFIFO_H__
2#define __LINUX_KFIFO_H__
3
4/*
5 * DCL <linux/kfifo.h> -- the byte ring behind a tty port's transmit buffer.
6 *
7 * serial_core.c keeps everything waiting to go out the UART in one of these:
8 * tty_port_alloc_xmit_buf() hands it a PAGE_SIZE buffer (serial_core.c:262),
9 * uart_write() pushes bytes in, and the driver's start_tx pulls them out and
10 * writes them to the shift register. 8250_port.c:1722 decides when to raise a
11 * write wakeup by comparing kfifo_len() against WAKEUP_CHARS, so the length
12 * has to be exact or the tty never learns the port drained.
13 *
14 * Deliberate simplification: mainline's kfifo is a macro-generated type-safe
15 * family with a __kfifo core, a mask for power-of-two indexing, and record
16 * variants for framed data. None of that is needed for a byte ring -- and
17 * mainline's own `size` must be a power of two, which a macro cannot check.
18 * This implementation indexes with `% size` instead: one division per byte on
19 * a 115200-baud transmit path is nothing, and it cannot be wrong if a future
20 * caller passes a size that is not a power of two. The `in`/`out` counters
21 * free-run and wrap, so occupancy is `in - out` in plain unsigned arithmetic.
22 *
23 * The subset is exactly what the staged set calls: kfifo_init, kfifo_reset,
24 * kfifo_is_empty, kfifo_len, kfifo_avail, kfifo_put, kfifo_in. kfifo_get and
25 * kfifo_out were absent for two stages on the grounds that nothing read
26 * through this ring; stage 3 changed that, and serial_core.h now reads it
27 * three ways (uart_fifo_out, uart_fifo_get, uart_xmit_advance), so all three
28 * are at the bottom of this file.
29 */
30
31#include <linux/kernel.h> /* u8, size_t */
32#include <linux/string.h> /* memcpy */
33
34struct kfifo {
35 unsigned char* buf;
36 unsigned int size; /* capacity in bytes */
37 unsigned int in; /* free-running write counter */
38 unsigned int out; /* free-running read counter */
39};
40
41/* tty_port.h's spelling: `DECLARE_KFIFO_PTR(xmit_fifo, u8)` */
42#define DECLARE_KFIFO_PTR(fifo, type) struct kfifo fifo
43
44/* buffer is supplied later (or never: serial_core allocates it on demand) */
45#define kfifo_init(f, buffer, sz) \
46 do { \
47 (f)->buf = (unsigned char*)(buffer); \
48 (f)->size = (unsigned int)(sz); \
49 (f)->in = 0; \
50 (f)->out = 0; \
51 } while (0)
52
53/* Takes the object, not a pointer -- serial_core.c:293's spelling. */
54#define INIT_KFIFO(fifo) kfifo_init(&(fifo), NULL, 0)
55
56#define kfifo_reset(fifo) \
57 do { (fifo)->in = 0; (fifo)->out = 0; } while (0)
58
59#define kfifo_is_empty(fifo) ((fifo)->in == (fifo)->out)
60
61#define kfifo_len(fifo) ((fifo)->in - (fifo)->out)
62
63#define kfifo_avail(fifo) ((fifo)->size - (fifo)->in + (fifo)->out)
64
65static inline unsigned int kfifo_put(struct kfifo* f, unsigned char val)
66{
67 if (!f->buf || kfifo_avail(f) == 0)
68 return 0;
69 f->buf[f->in % f->size] = val;
70 f->in++;
71 return 1;
72}
73
74static inline unsigned int kfifo_in(struct kfifo* f, const void* buf,
75 unsigned int len)
76{
77 unsigned int avail;
78 unsigned int i;
79
80 if (!f->buf)
81 return 0;
82
83 avail = kfifo_avail(f);
84 if (len > avail)
85 len = avail;
86
87 for (i = 0; i < len; i++)
88 f->buf[(f->in + i) % f->size] = ((const unsigned char*)buf)[i];
89 f->in += len;
90 return len;
91}
92
93
94/*
95 * The three reads serial_core.h asks for and this header did not have.
96 *
97 * mainline spells all three as macros built on __kfifo_out with an element
98 * size; DCL's struct kfifo is byte-oriented (no esize field, `size` is a byte
99 * capacity), so the bodies are plain byte loops below -- same three
100 * behaviours, which is what the callers actually depend on:
101 *
102 * kfifo_out(f, buf, n) copy out and *consume* up to n bytes
103 * kfifo_get(f, val) copy out and consume exactly one byte; the count
104 * it returns is 0 or 1, which is why
105 * uart_fifo_get() can add it straight to
106 * icount.tx as "one more byte left the fifo"
107 * kfifo_skip_count(f, n) consume without copying, for
108 * uart_xmit_advance() -- the transmit path has
109 * already accounted for the bytes it handed to the
110 * UART and only needs the ring to move on
111 *
112 * The clamp to kfifo_len() matters in all three: mainline's variants return
113 * short rather than reading past the consumer mark, and a ring that could be
114 * asked for more than it holds would otherwise wrap and re-deliver bytes.
115 *
116 * out is a free-running counter here (kfifo_len is `in - out`, taken mod
117 * `size` on access), so advancing it needs no mask -- the same convention the
118 * two writers above already use for `in`.
119 */
120static inline unsigned int kfifo_out(struct kfifo* f, void* buf,
121 unsigned int n)
122{
123 unsigned int i;
124
125 if (!f->buf)
126 return 0;
127 if (n > kfifo_len(f))
128 n = kfifo_len(f);
129
130 for (i = 0; i < n; i++)
131 ((unsigned char*)buf)[i] = f->buf[(f->out + i) % f->size];
132 f->out += n;
133 return n;
134}
135
136static inline unsigned int kfifo_get(struct kfifo* f, unsigned char* val)
137{
138 return kfifo_out(f, val, 1);
139}
140
141static inline void kfifo_skip_count(struct kfifo* f, unsigned int n)
142{
143 if (!f->buf)
144 return;
145 if (n > kfifo_len(f))
146 n = kfifo_len(f);
147 f->out += n;
148}
149
150#endif /* __LINUX_KFIFO_H__ */
const char * f
Definition drm_print.h:205
size_t len
Definition initial.c:23
#define kfifo_avail(fifo)
Definition kfifo.h:63
#define kfifo_len(fifo)
Definition kfifo.h:61
Definition kfifo.h:34
unsigned int size
Definition kfifo.h:36
unsigned int out
Definition kfifo.h:38
unsigned char * buf
Definition kfifo.h:35
unsigned int in
Definition kfifo.h:37