Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 33658
b: refs/heads/master
c: 01da5fd
h: refs/heads/master
v: v3
  • Loading branch information
Alan Cox authored and Linus Torvalds committed Aug 27, 2006
1 parent 1575173 commit 1ed60e8
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: af9b897ee639d96b2bd29b65b50cd0a1f2b6d6c9
refs/heads/master: 01da5fd83d6b2c5e36b77539f6cbdd8f49849225
89 changes: 79 additions & 10 deletions trunk/drivers/char/tty_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,17 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
*/


/**
* tty_buffer_free_all - free buffers used by a tty
* @tty: tty 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
*
* Locking: none
*/


/**
* tty_buffer_free_all - free buffers used by a tty
* @tty: tty to free from
Expand All @@ -287,19 +298,47 @@ static void tty_buffer_free_all(struct tty_struct *tty)
kfree(thead);
}
tty->buf.tail = NULL;
tty->buf.memory_used = 0;
}

/**
* tty_buffer_init - prepare a tty buffer structure
* @tty: tty 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.
*
* Locking: none
*/

static void tty_buffer_init(struct tty_struct *tty)
{
spin_lock_init(&tty->buf.lock);
tty->buf.head = NULL;
tty->buf.tail = NULL;
tty->buf.free = NULL;
tty->buf.memory_used = 0;
}

static struct tty_buffer *tty_buffer_alloc(size_t size)
/**
* tty_buffer_alloc - allocate a tty buffer
* @tty: tty device
* @size: desired size (characters)
*
* Allocate a new tty buffer to hold the desired number of characters.
* Return NULL if out of memory or the allocation would exceed the
* per device queue
*
* Locking: Caller must hold tty->buf.lock
*/

static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
{
struct tty_buffer *p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
struct tty_buffer *p;

if (tty->buf.memory_used + size > 65536)
return NULL;
p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
if(p == NULL)
return NULL;
p->used = 0;
Expand All @@ -309,17 +348,27 @@ static struct tty_buffer *tty_buffer_alloc(size_t size)
p->read = 0;
p->char_buf_ptr = (char *)(p->data);
p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
/* printk("Flip create %p\n", p); */
tty->buf.memory_used += size;
return p;
}

/* Must be called with the tty_read lock held. This needs to acquire strategy
code to decide if we should kfree or relink a given expired buffer */
/**
* tty_buffer_free - free a tty buffer
* @tty: tty owning the buffer
* @b: the buffer to free
*
* Free a tty buffer, or add it to the free list according to our
* internal strategy
*
* Locking: Caller must hold tty->buf.lock
*/

static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
{
/* Dumb strategy for now - should keep some stats */
/* printk("Flip dispose %p\n", b); */
tty->buf.memory_used -= b->size;
WARN_ON(tty->buf.memory_used < 0);

if(b->size >= 512)
kfree(b);
else {
Expand All @@ -328,6 +377,18 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
}
}

/**
* tty_buffer_find - find a free tty buffer
* @tty: tty owning the buffer
* @size: characters wanted
*
* Locate an existing suitable tty buffer or if we are lacking one then
* allocate a new one. We round our buffers off in 256 character chunks
* to get better allocation behaviour.
*
* Locking: Caller must hold tty->buf.lock
*/

static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
{
struct tty_buffer **tbh = &tty->buf.free;
Expand All @@ -339,20 +400,28 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
t->used = 0;
t->commit = 0;
t->read = 0;
/* DEBUG ONLY */
/* memset(t->data, '*', size); */
/* printk("Flip recycle %p\n", t); */
tty->buf.memory_used += t->size;
return t;
}
tbh = &((*tbh)->next);
}
/* Round the buffer size out */
size = (size + 0xFF) & ~ 0xFF;
return tty_buffer_alloc(size);
return tty_buffer_alloc(tty, size);
/* Should possibly check if this fails for the largest buffer we
have queued and recycle that ? */
}

/**
* tty_buffer_request_room - grow tty buffer if needed
* @tty: tty structure
* @size: size desired
*
* Make at least size bytes of linear space available for the tty
* buffer. If we fail return the size we managed to find.
*
* Locking: Takes tty->buf.lock
*/
int tty_buffer_request_room(struct tty_struct *tty, size_t size)
{
struct tty_buffer *b, *n;
Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/tty.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ struct tty_bufhead {
struct tty_buffer *head; /* Queue head */
struct tty_buffer *tail; /* Active buffer */
struct tty_buffer *free; /* Free queue head */
int memory_used; /* Buffer space used excluding free queue */
};
/*
* The pty uses char_buf and flag_buf as a contiguous buffer
Expand Down

0 comments on commit 1ed60e8

Please sign in to comment.