XenevaOS
Loading...
Searching...
No Matches
tty_buffer.h
Go to the documentation of this file.
1#ifndef _LINUX_TTY_BUFFER_H
2#define _LINUX_TTY_BUFFER_H
3
4/*
5 * DCL <linux/tty_buffer.h> -- struct tty_buffer and the byte/flag accessors.
6 *
7 * Ported from mainline include/linux/tty_buffer.h (v7.2), field for field.
8 *
9 * The layout is the part that cannot be reinterpreted: `data[]` is a flexible
10 * array holding *both* the characters and, when flags are in use, a parallel
11 * flag byte per character immediately after them -- flag_buf_ptr() finds the
12 * flag array by adding b->size (the character capacity) to char_buf_ptr().
13 * So `size` is not "how much is in use", it is the fixed stride separating
14 * the two arrays inside one allocation, and tty_buffer_reset() setting
15 * size = 0 on the sentinel is what makes an empty buffer claim no space at
16 * all.
17 *
18 * `used`/`commit`/`read`/`lookahead` are the producer/consumer cursor set:
19 * used -- bytes the driver has written (not yet visible to the ldisc)
20 * commit -- bytes made visible, published by tty_flip_buffer_commit()
21 * read -- bytes the ldisc has consumed
22 * lookahead-- the ldisc's next candidate position when a consumer stopped
23 * short (tty_buffer.c:404 walks the chain from here)
24 * The commit/read gap is what tty_flip_buffer_push() exists to close.
25 *
26 * The union is the point of the llist: a buffer is either on the live queue
27 * (->next) or on the free list (->free), never both, so the two share storage.
28 */
29
30#include <linux/atomic.h>
31#include <linux/llist.h>
32#include <linux/mutex.h>
33#include <linux/workqueue.h>
34
35struct tty_buffer {
36 union {
39 };
40 unsigned int used;
41 unsigned int size;
42 unsigned int commit;
43 unsigned int lookahead; /* Lazy update on recv, can become less than "read" */
44 unsigned int read;
45 bool flags;
46 /* Data points here */
47 u8 data[] __aligned(sizeof(unsigned long));
48};
49
50static inline u8* char_buf_ptr(struct tty_buffer* b, unsigned int ofs)
51{
52 return b->data + ofs;
53}
54
55static inline u8* flag_buf_ptr(struct tty_buffer* b, unsigned int ofs)
56{
57 return char_buf_ptr(b, ofs) + b->size;
58}
59
60/*
61 * struct tty_bufhead embeds a `sentinel` tty_buffer, and struct tty_buffer
62 * ends in a flexible array -- so a struct with a variable-sized member sits in
63 * the middle of another struct. That is a GNU extension and clang says so
64 * (-Wgnu-variable-sized-type-not-at-end), once per translation unit, because
65 * it comes from a header.
66 *
67 * mainline's layout is exactly this (include/linux/tty_buffer.h v7.2): the
68 * sentinel is what an empty buffer head points at, `size` reads 0 after
69 * tty_buffer_reset(&buf->sentinel, 0), and the fields after it (`free`,
70 * `mem_used`, `mem_limit`, `tail`) are what the sentinel's zero-length data[]
71 * leaves room for. It is deliberate, it is the whole design of the empty
72 * buffer, and it cannot be moved to the end without changing what
73 * tty_buffer_find() compares against. So the layout is kept and the notice is
74 * scoped to this struct: it says "extension", not "bug".
75 */
76#if defined(__clang__)
77#pragma clang diagnostic push
78#pragma clang diagnostic ignored "-Wgnu-variable-sized-type-not-at-end"
79#endif
81 struct tty_buffer* head; /* Queue head */
84 struct mutex lock;
87 struct llist_head free; /* Free queue head */
88 atomic_t mem_used; /* In-use buffers excluding free list */
90 struct tty_buffer* tail; /* Active buffer */
91};
92#if defined(__clang__)
93#pragma clang diagnostic pop
94#endif
95
96/*
97 * When a break, frame error, or parity error happens, these codes are
98 * stuffed into the flags buffer.
99 */
100#define TTY_NORMAL 0
101#define TTY_BREAK 1
102#define TTY_FRAME 2
103#define TTY_PARITY 3
104#define TTY_OVERRUN 4
105
106#endif /* _LINUX_TTY_BUFFER_H */
size_t b
Definition main.cpp:156
void * data
Definition kthread.h:30
uint8_t u8
Definition kernel.h:14
Definition atomic.h:31
Definition llist.h:46
Definition llist.h:42
Definition mutex.h:59
Definition tty_buffer.h:35
u8 data[] __aligned(sizeof(unsigned long))
unsigned int commit
Definition tty_buffer.h:42
unsigned int used
Definition tty_buffer.h:40
bool flags
Definition tty_buffer.h:45
struct tty_buffer * next
Definition tty_buffer.h:37
struct llist_node free
Definition tty_buffer.h:38
unsigned int lookahead
Definition tty_buffer.h:43
unsigned int size
Definition tty_buffer.h:41
unsigned int read
Definition tty_buffer.h:44
Definition tty_buffer.h:80
struct workqueue_struct * flip_wq
Definition tty_buffer.h:82
struct mutex lock
Definition tty_buffer.h:84
struct tty_buffer sentinel
Definition tty_buffer.h:86
atomic_t priority
Definition tty_buffer.h:85
struct tty_buffer * tail
Definition tty_buffer.h:90
atomic_t mem_used
Definition tty_buffer.h:88
struct tty_buffer * head
Definition tty_buffer.h:81
struct work_struct work
Definition tty_buffer.h:83
struct llist_head free
Definition tty_buffer.h:87
int mem_limit
Definition tty_buffer.h:89
Definition workqueue.h:44
Definition workqueue.h:50