drivers/tty/tty_buffer.c
Source file repositories/reference/linux-study-clean/drivers/tty/tty_buffer.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/tty/tty_buffer.c- Extension
.c- Size
- 16707 bytes
- Lines
- 635
- Domain
- Driver Families
- Bucket
- drivers/tty
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/types.hlinux/errno.hlinux/minmax.hlinux/tty.hlinux/tty_buffer.hlinux/tty_driver.hlinux/tty_flip.hlinux/timer.hlinux/string.hlinux/slab.hlinux/sched.hlinux/wait.hlinux/bitops.hlinux/delay.hlinux/module.hlinux/ratelimit.htty.h
Detected Declarations
function tty_buffer_unlock_exclusivefunction tty_buffer_queue_workfunction tty_buffer_lock_exclusivefunction tty_buffer_space_availfunction tty_buffer_resetfunction tty_buffer_free_allfunction tty_buffer_freefunction tty_buffer_flushfunction __tty_buffer_request_roomfunction tty_buffer_request_roomfunction __tty_insert_flip_string_flagsfunction tty_prepare_flip_stringfunction flush_to_ldiscfunction lookahead_bufsfunction receive_buffunction receive_buffunction tty_flip_buffer_commitfunction tty_flip_buffer_pushfunction tty_insert_flip_stringfunction tty_buffer_initfunction tty_buffer_set_limitfunction tty_buffer_set_lock_subclassfunction tty_buffer_restart_workfunction tty_buffer_cancel_workfunction tty_buffer_flush_workexport tty_buffer_lock_exclusiveexport tty_buffer_unlock_exclusiveexport tty_buffer_space_availexport tty_buffer_request_roomexport __tty_insert_flip_string_flagsexport tty_prepare_flip_stringexport tty_ldisc_receive_bufexport tty_flip_buffer_pushexport tty_buffer_set_limit
Annotated Snippet
if (free) {
p = llist_entry(free, struct tty_buffer, free);
goto found;
}
}
/* Should possibly check if this fails for the largest buffer we
* have queued and recycle that ?
*/
if (atomic_read(&port->buf.mem_used) > port->buf.mem_limit)
return NULL;
p = kmalloc_flex(*p, data, 2 * size, GFP_ATOMIC | __GFP_NOWARN);
if (p == NULL)
return NULL;
found:
tty_buffer_reset(p, size);
atomic_add(size, &port->buf.mem_used);
return p;
}
/**
* tty_buffer_free - free a tty buffer
* @port: tty port owning the buffer
* @b: the buffer to free
*
* Free a tty buffer, or add it to the free list according to our internal
* strategy.
*/
static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b)
{
struct tty_bufhead *buf = &port->buf;
/* Dumb strategy for now - should keep some stats */
WARN_ON(atomic_sub_return(b->size, &buf->mem_used) < 0);
if (b->size > MIN_TTYB_SIZE)
kfree(b);
else if (b->size > 0)
llist_add(&b->free, &buf->free);
}
/**
* tty_buffer_flush - flush full tty buffers
* @tty: tty to flush
* @ld: optional ldisc ptr (must be referenced)
*
* Flush all the buffers containing receive data. If @ld != %NULL, flush the
* ldisc input buffer.
*
* Locking: takes buffer lock to ensure single-threaded flip buffer 'consumer'.
*/
void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld)
{
struct tty_port *port = tty->port;
struct tty_bufhead *buf = &port->buf;
struct tty_buffer *next;
atomic_inc(&buf->priority);
mutex_lock(&buf->lock);
/* paired w/ release in __tty_buffer_request_room; ensures there are
* no pending memory accesses to the freed buffer
*/
while ((next = smp_load_acquire(&buf->head->next)) != NULL) {
tty_buffer_free(port, buf->head);
buf->head = next;
}
buf->head->read = buf->head->commit;
buf->head->lookahead = buf->head->read;
if (ld && ld->ops->flush_buffer)
ld->ops->flush_buffer(tty);
atomic_dec(&buf->priority);
mutex_unlock(&buf->lock);
}
/**
* __tty_buffer_request_room - grow tty buffer if needed
* @port: tty port
* @size: size desired
* @flags: buffer has to store flags along character data
*
* Make at least @size bytes of linear space available for the tty buffer.
*
* Will change over to a new buffer if the current buffer is encoded as
* %TTY_NORMAL (so has no flags buffer) and the new buffer requires a flags
* buffer.
*
Annotation
- Immediate include surface: `linux/types.h`, `linux/errno.h`, `linux/minmax.h`, `linux/tty.h`, `linux/tty_buffer.h`, `linux/tty_driver.h`, `linux/tty_flip.h`, `linux/timer.h`.
- Detected declarations: `function tty_buffer_unlock_exclusive`, `function tty_buffer_queue_work`, `function tty_buffer_lock_exclusive`, `function tty_buffer_space_avail`, `function tty_buffer_reset`, `function tty_buffer_free_all`, `function tty_buffer_free`, `function tty_buffer_flush`, `function __tty_buffer_request_room`, `function tty_buffer_request_room`.
- Atlas domain: Driver Families / drivers/tty.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.