diff options
| author | Peter Hurley <peter@hurleysoftware.com> | 2013-06-15 09:36:06 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-07-23 19:47:08 -0400 |
| commit | 809850b7a5fcc0a96d023e1171a7944c60fd5a71 (patch) | |
| tree | 5c6a22458a7d756cbfe948bfb6b7d331af01610f /include/linux | |
| parent | 2cf7b67e87f0d8db025cff12b5d29c0663bbcd87 (diff) | |
tty: Use lockless flip buffer free list
In preparation for lockless flip buffers, make the flip buffer
free list lockless.
NB: using llist is not the optimal solution, as the driver and
buffer work may contend over the llist head unnecessarily. However,
test measurements indicate this contention is low.
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/llist.h | 23 | ||||
| -rw-r--r-- | include/linux/tty.h | 8 |
2 files changed, 29 insertions, 2 deletions
diff --git a/include/linux/llist.h b/include/linux/llist.h index cdaa7f023899..8828a78dec9a 100644 --- a/include/linux/llist.h +++ b/include/linux/llist.h | |||
| @@ -125,6 +125,29 @@ static inline void init_llist_head(struct llist_head *list) | |||
| 125 | (pos) = llist_entry((pos)->member.next, typeof(*(pos)), member)) | 125 | (pos) = llist_entry((pos)->member.next, typeof(*(pos)), member)) |
| 126 | 126 | ||
| 127 | /** | 127 | /** |
| 128 | * llist_for_each_entry_safe - iterate over some deleted entries of lock-less list of given type | ||
| 129 | * safe against removal of list entry | ||
| 130 | * @pos: the type * to use as a loop cursor. | ||
| 131 | * @n: another type * to use as temporary storage | ||
| 132 | * @node: the first entry of deleted list entries. | ||
| 133 | * @member: the name of the llist_node with the struct. | ||
| 134 | * | ||
| 135 | * In general, some entries of the lock-less list can be traversed | ||
| 136 | * safely only after being removed from list, so start with an entry | ||
| 137 | * instead of list head. | ||
| 138 | * | ||
| 139 | * If being used on entries deleted from lock-less list directly, the | ||
| 140 | * traverse order is from the newest to the oldest added entry. If | ||
| 141 | * you want to traverse from the oldest to the newest, you must | ||
| 142 | * reverse the order by yourself before traversing. | ||
| 143 | */ | ||
| 144 | #define llist_for_each_entry_safe(pos, n, node, member) \ | ||
| 145 | for (pos = llist_entry((node), typeof(*pos), member); \ | ||
| 146 | &pos->member != NULL && \ | ||
| 147 | (n = llist_entry(pos->member.next, typeof(*n), member), true); \ | ||
| 148 | pos = n) | ||
| 149 | |||
| 150 | /** | ||
| 128 | * llist_empty - tests whether a lock-less list is empty | 151 | * llist_empty - tests whether a lock-less list is empty |
| 129 | * @head: the list to test | 152 | * @head: the list to test |
| 130 | * | 153 | * |
diff --git a/include/linux/tty.h b/include/linux/tty.h index 87bbaa31ebf5..5043b12f23ea 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/tty_flags.h> | 11 | #include <linux/tty_flags.h> |
| 12 | #include <uapi/linux/tty.h> | 12 | #include <uapi/linux/tty.h> |
| 13 | #include <linux/rwsem.h> | 13 | #include <linux/rwsem.h> |
| 14 | #include <linux/llist.h> | ||
| 14 | 15 | ||
| 15 | 16 | ||
| 16 | 17 | ||
| @@ -30,7 +31,10 @@ | |||
| 30 | #define __DISABLED_CHAR '\0' | 31 | #define __DISABLED_CHAR '\0' |
| 31 | 32 | ||
| 32 | struct tty_buffer { | 33 | struct tty_buffer { |
| 33 | struct tty_buffer *next; | 34 | union { |
| 35 | struct tty_buffer *next; | ||
| 36 | struct llist_node free; | ||
| 37 | }; | ||
| 34 | int used; | 38 | int used; |
| 35 | int size; | 39 | int size; |
| 36 | int commit; | 40 | int commit; |
| @@ -65,7 +69,7 @@ struct tty_bufhead { | |||
| 65 | spinlock_t lock; | 69 | spinlock_t lock; |
| 66 | struct tty_buffer *head; /* Queue head */ | 70 | struct tty_buffer *head; /* Queue head */ |
| 67 | struct tty_buffer *tail; /* Active buffer */ | 71 | struct tty_buffer *tail; /* Active buffer */ |
| 68 | struct tty_buffer *free; /* Free queue head */ | 72 | struct llist_head free; /* Free queue head */ |
| 69 | int memory_used; /* Buffer space used excluding | 73 | int memory_used; /* Buffer space used excluding |
| 70 | free queue */ | 74 | free queue */ |
| 71 | }; | 75 | }; |
