From 102a0743326a03cd1a1202ceda21e175b7d3575c Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Tue, 20 Feb 2024 01:20:52 +0000 Subject: [PATCH] add new system file --- kernel/drivers/tty/tty_buffer.c | 92 ++++++++++++++++++++++++++++++---------------- 1 files changed, 60 insertions(+), 32 deletions(-) diff --git a/kernel/drivers/tty/tty_buffer.c b/kernel/drivers/tty/tty_buffer.c index 6b0cb63..9f23798 100644 --- a/kernel/drivers/tty/tty_buffer.c +++ b/kernel/drivers/tty/tty_buffer.c @@ -17,7 +17,7 @@ #include <linux/delay.h> #include <linux/module.h> #include <linux/ratelimit.h> - +#include "tty.h" #define MIN_TTYB_SIZE 256 #define TTYB_ALIGN_MASK 255 @@ -42,7 +42,7 @@ * tty_buffer_lock_exclusive - gain exclusive access to buffer * tty_buffer_unlock_exclusive - release exclusive access * - * @port - tty_port owning the flip buffer + * @port: tty port owning the flip buffer * * Guarantees safe use of the line discipline's receive_buf() method by * excluding the buffer work and any pending flush from using the flip @@ -78,7 +78,7 @@ /** * tty_buffer_space_avail - return unused buffer space - * @port - tty_port owning the flip buffer + * @port: tty port owning the flip buffer * * Returns the # of bytes which can be written by the driver without * reaching the buffer limit. @@ -107,7 +107,7 @@ /** * tty_buffer_free_all - free buffers used by a tty - * @tty: tty to free from + * @port: tty port to free from * * Remove all the buffers pending on a tty whether queued with data * or in the free ring. Must be called when the tty is no longer in use @@ -118,9 +118,12 @@ struct tty_bufhead *buf = &port->buf; struct tty_buffer *p, *next; struct llist_node *llist; + unsigned int freed = 0; + int still_used; while ((p = buf->head) != NULL) { buf->head = p->next; + freed += p->size; if (p->size > 0) kfree(p); } @@ -132,12 +135,14 @@ buf->head = &buf->sentinel; buf->tail = &buf->sentinel; - atomic_set(&buf->mem_used, 0); + still_used = atomic_xchg(&buf->mem_used, 0); + WARN(still_used != freed, "we still have not freed %d bytes!", + still_used - freed); } /** * tty_buffer_alloc - allocate a tty buffer - * @tty: tty device + * @port: tty port * @size: desired size (characters) * * Allocate a new tty buffer to hold the desired number of characters. @@ -167,7 +172,8 @@ have queued and recycle that ? */ if (atomic_read(&port->buf.mem_used) > port->buf.mem_limit) return NULL; - p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); + p = kmalloc(sizeof(struct tty_buffer) + 2 * size, + GFP_ATOMIC | __GFP_NOWARN); if (p == NULL) return NULL; @@ -179,7 +185,7 @@ /** * tty_buffer_free - free a tty buffer - * @tty: tty owning the 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 @@ -238,7 +244,7 @@ /** * tty_buffer_request_room - grow tty buffer if needed - * @tty: tty structure + * @port: tty port * @size: size desired * @flags: buffer flags if new buffer allocated (default = 0) * @@ -389,27 +395,6 @@ EXPORT_SYMBOL(__tty_insert_flip_char); /** - * tty_schedule_flip - push characters to ldisc - * @port: tty port to push from - * - * Takes any pending buffers and transfers their ownership to the - * ldisc side of the queue. It then schedules those characters for - * processing by the line discipline. - */ - -void tty_schedule_flip(struct tty_port *port) -{ - struct tty_bufhead *buf = &port->buf; - - /* paired w/ acquire in flush_to_ldisc(); ensures - * flush_to_ldisc() sees buffer data. - */ - smp_store_release(&buf->tail->commit, buf->tail->used); - queue_work(system_unbound_wq, &buf->work); -} -EXPORT_SYMBOL(tty_schedule_flip); - -/** * tty_prepare_flip_string - make room for characters * @port: tty port * @chars: return pointer for character write area @@ -538,6 +523,15 @@ } +static inline void tty_flip_buffer_commit(struct tty_buffer *tail) +{ + /* + * Paired w/ acquire in flush_to_ldisc(); ensures flush_to_ldisc() sees + * buffer data. + */ + smp_store_release(&tail->commit, tail->used); +} + /** * tty_flip_buffer_push - terminal * @port: tty port to push @@ -551,13 +545,47 @@ void tty_flip_buffer_push(struct tty_port *port) { - tty_schedule_flip(port); + struct tty_bufhead *buf = &port->buf; + + tty_flip_buffer_commit(buf->tail); + queue_work(system_unbound_wq, &buf->work); } EXPORT_SYMBOL(tty_flip_buffer_push); /** + * tty_insert_flip_string_and_push_buffer - add characters to the tty buffer and + * push + * @port: tty port + * @chars: characters + * @size: size + * + * The function combines tty_insert_flip_string() and tty_flip_buffer_push() + * with the exception of properly holding the @port->lock. + * + * To be used only internally (by pty currently). + * + * Returns: the number added. + */ +int tty_insert_flip_string_and_push_buffer(struct tty_port *port, + const unsigned char *chars, size_t size) +{ + struct tty_bufhead *buf = &port->buf; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + size = tty_insert_flip_string(port, chars, size); + if (size) + tty_flip_buffer_commit(buf->tail); + spin_unlock_irqrestore(&port->lock, flags); + + queue_work(system_unbound_wq, &buf->work); + + return size; +} + +/** * tty_buffer_init - prepare a tty buffer structure - * @tty: tty to initialise + * @port: tty port to initialise * * Set up the initial state of the buffer management for a tty device. * Must be called before the other tty buffer functions are used. -- Gitblit v1.6.2