diff options
author | Lai Jiangshan <laijs@cn.fujitsu.com> | 2010-12-21 04:55:14 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2011-03-11 15:13:26 -0500 |
commit | bf6a9b8336ba12672755c2ae898b0abe42c7a5ac (patch) | |
tree | c85f2b2acac9bf9b88e0c19d90d252b1780e0d35 | |
parent | 017f2b239dabb2740b91df162e004371b861f371 (diff) |
plist: Shrink struct plist_head
struct plist_head is used in struct task_struct as well as struct
rtmutex. If we can make it smaller, it will also make these structures
smaller as well.
The field prio_list in struct plist_head is seldom used and we can get
its information from the plist_nodes. Removing this field will decrease
the size of plist_head by half.
Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
LKML-Reference: <4D107982.9090700@cn.fujitsu.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | include/linux/plist.h | 47 | ||||
-rw-r--r-- | lib/plist.c | 54 |
2 files changed, 59 insertions, 42 deletions
diff --git a/include/linux/plist.h b/include/linux/plist.h index 7254eda078e5..c9b9f322c8d8 100644 --- a/include/linux/plist.h +++ b/include/linux/plist.h | |||
@@ -31,15 +31,17 @@ | |||
31 | * | 31 | * |
32 | * Simple ASCII art explanation: | 32 | * Simple ASCII art explanation: |
33 | * | 33 | * |
34 | * |HEAD | | 34 | * pl:prio_list (only for plist_node) |
35 | * | | | 35 | * nl:node_list |
36 | * |prio_list.prev|<------------------------------------| | 36 | * HEAD| NODE(S) |
37 | * |prio_list.next|<->|pl|<->|pl|<--------------->|pl|<-| | 37 | * | |
38 | * |10 | |10| |21| |21| |21| |40| (prio) | 38 | * ||------------------------------------| |
39 | * | | | | | | | | | | | | | 39 | * ||->|pl|<->|pl|<--------------->|pl|<-| |
40 | * | | | | | | | | | | | | | 40 | * | |10| |21| |21| |21| |40| (prio) |
41 | * |node_list.next|<->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<-| | 41 | * | | | | | | | | | | | |
42 | * |node_list.prev|<------------------------------------| | 42 | * | | | | | | | | | | | |
43 | * |->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<-| | ||
44 | * |-------------------------------------------| | ||
43 | * | 45 | * |
44 | * The nodes on the prio_list list are sorted by priority to simplify | 46 | * The nodes on the prio_list list are sorted by priority to simplify |
45 | * the insertion of new nodes. There are no nodes with duplicate | 47 | * the insertion of new nodes. There are no nodes with duplicate |
@@ -78,7 +80,6 @@ | |||
78 | #include <linux/spinlock_types.h> | 80 | #include <linux/spinlock_types.h> |
79 | 81 | ||
80 | struct plist_head { | 82 | struct plist_head { |
81 | struct list_head prio_list; | ||
82 | struct list_head node_list; | 83 | struct list_head node_list; |
83 | #ifdef CONFIG_DEBUG_PI_LIST | 84 | #ifdef CONFIG_DEBUG_PI_LIST |
84 | raw_spinlock_t *rawlock; | 85 | raw_spinlock_t *rawlock; |
@@ -88,7 +89,8 @@ struct plist_head { | |||
88 | 89 | ||
89 | struct plist_node { | 90 | struct plist_node { |
90 | int prio; | 91 | int prio; |
91 | struct plist_head plist; | 92 | struct list_head prio_list; |
93 | struct list_head node_list; | ||
92 | }; | 94 | }; |
93 | 95 | ||
94 | #ifdef CONFIG_DEBUG_PI_LIST | 96 | #ifdef CONFIG_DEBUG_PI_LIST |
@@ -100,7 +102,6 @@ struct plist_node { | |||
100 | #endif | 102 | #endif |
101 | 103 | ||
102 | #define _PLIST_HEAD_INIT(head) \ | 104 | #define _PLIST_HEAD_INIT(head) \ |
103 | .prio_list = LIST_HEAD_INIT((head).prio_list), \ | ||
104 | .node_list = LIST_HEAD_INIT((head).node_list) | 105 | .node_list = LIST_HEAD_INIT((head).node_list) |
105 | 106 | ||
106 | /** | 107 | /** |
@@ -133,7 +134,8 @@ struct plist_node { | |||
133 | #define PLIST_NODE_INIT(node, __prio) \ | 134 | #define PLIST_NODE_INIT(node, __prio) \ |
134 | { \ | 135 | { \ |
135 | .prio = (__prio), \ | 136 | .prio = (__prio), \ |
136 | .plist = { _PLIST_HEAD_INIT((node).plist) }, \ | 137 | .prio_list = LIST_HEAD_INIT((node).prio_list), \ |
138 | .node_list = LIST_HEAD_INIT((node).node_list), \ | ||
137 | } | 139 | } |
138 | 140 | ||
139 | /** | 141 | /** |
@@ -144,7 +146,6 @@ struct plist_node { | |||
144 | static inline void | 146 | static inline void |
145 | plist_head_init(struct plist_head *head, spinlock_t *lock) | 147 | plist_head_init(struct plist_head *head, spinlock_t *lock) |
146 | { | 148 | { |
147 | INIT_LIST_HEAD(&head->prio_list); | ||
148 | INIT_LIST_HEAD(&head->node_list); | 149 | INIT_LIST_HEAD(&head->node_list); |
149 | #ifdef CONFIG_DEBUG_PI_LIST | 150 | #ifdef CONFIG_DEBUG_PI_LIST |
150 | head->spinlock = lock; | 151 | head->spinlock = lock; |
@@ -160,7 +161,6 @@ plist_head_init(struct plist_head *head, spinlock_t *lock) | |||
160 | static inline void | 161 | static inline void |
161 | plist_head_init_raw(struct plist_head *head, raw_spinlock_t *lock) | 162 | plist_head_init_raw(struct plist_head *head, raw_spinlock_t *lock) |
162 | { | 163 | { |
163 | INIT_LIST_HEAD(&head->prio_list); | ||
164 | INIT_LIST_HEAD(&head->node_list); | 164 | INIT_LIST_HEAD(&head->node_list); |
165 | #ifdef CONFIG_DEBUG_PI_LIST | 165 | #ifdef CONFIG_DEBUG_PI_LIST |
166 | head->rawlock = lock; | 166 | head->rawlock = lock; |
@@ -176,7 +176,8 @@ plist_head_init_raw(struct plist_head *head, raw_spinlock_t *lock) | |||
176 | static inline void plist_node_init(struct plist_node *node, int prio) | 176 | static inline void plist_node_init(struct plist_node *node, int prio) |
177 | { | 177 | { |
178 | node->prio = prio; | 178 | node->prio = prio; |
179 | plist_head_init(&node->plist, NULL); | 179 | INIT_LIST_HEAD(&node->prio_list); |
180 | INIT_LIST_HEAD(&node->node_list); | ||
180 | } | 181 | } |
181 | 182 | ||
182 | extern void plist_add(struct plist_node *node, struct plist_head *head); | 183 | extern void plist_add(struct plist_node *node, struct plist_head *head); |
@@ -188,7 +189,7 @@ extern void plist_del(struct plist_node *node, struct plist_head *head); | |||
188 | * @head: the head for your list | 189 | * @head: the head for your list |
189 | */ | 190 | */ |
190 | #define plist_for_each(pos, head) \ | 191 | #define plist_for_each(pos, head) \ |
191 | list_for_each_entry(pos, &(head)->node_list, plist.node_list) | 192 | list_for_each_entry(pos, &(head)->node_list, node_list) |
192 | 193 | ||
193 | /** | 194 | /** |
194 | * plist_for_each_safe - iterate safely over a plist of given type | 195 | * plist_for_each_safe - iterate safely over a plist of given type |
@@ -199,7 +200,7 @@ extern void plist_del(struct plist_node *node, struct plist_head *head); | |||
199 | * Iterate over a plist of given type, safe against removal of list entry. | 200 | * Iterate over a plist of given type, safe against removal of list entry. |
200 | */ | 201 | */ |
201 | #define plist_for_each_safe(pos, n, head) \ | 202 | #define plist_for_each_safe(pos, n, head) \ |
202 | list_for_each_entry_safe(pos, n, &(head)->node_list, plist.node_list) | 203 | list_for_each_entry_safe(pos, n, &(head)->node_list, node_list) |
203 | 204 | ||
204 | /** | 205 | /** |
205 | * plist_for_each_entry - iterate over list of given type | 206 | * plist_for_each_entry - iterate over list of given type |
@@ -208,7 +209,7 @@ extern void plist_del(struct plist_node *node, struct plist_head *head); | |||
208 | * @mem: the name of the list_struct within the struct | 209 | * @mem: the name of the list_struct within the struct |
209 | */ | 210 | */ |
210 | #define plist_for_each_entry(pos, head, mem) \ | 211 | #define plist_for_each_entry(pos, head, mem) \ |
211 | list_for_each_entry(pos, &(head)->node_list, mem.plist.node_list) | 212 | list_for_each_entry(pos, &(head)->node_list, mem.node_list) |
212 | 213 | ||
213 | /** | 214 | /** |
214 | * plist_for_each_entry_safe - iterate safely over list of given type | 215 | * plist_for_each_entry_safe - iterate safely over list of given type |
@@ -220,7 +221,7 @@ extern void plist_del(struct plist_node *node, struct plist_head *head); | |||
220 | * Iterate over list of given type, safe against removal of list entry. | 221 | * Iterate over list of given type, safe against removal of list entry. |
221 | */ | 222 | */ |
222 | #define plist_for_each_entry_safe(pos, n, head, m) \ | 223 | #define plist_for_each_entry_safe(pos, n, head, m) \ |
223 | list_for_each_entry_safe(pos, n, &(head)->node_list, m.plist.node_list) | 224 | list_for_each_entry_safe(pos, n, &(head)->node_list, m.node_list) |
224 | 225 | ||
225 | /** | 226 | /** |
226 | * plist_head_empty - return !0 if a plist_head is empty | 227 | * plist_head_empty - return !0 if a plist_head is empty |
@@ -237,7 +238,7 @@ static inline int plist_head_empty(const struct plist_head *head) | |||
237 | */ | 238 | */ |
238 | static inline int plist_node_empty(const struct plist_node *node) | 239 | static inline int plist_node_empty(const struct plist_node *node) |
239 | { | 240 | { |
240 | return plist_head_empty(&node->plist); | 241 | return list_empty(&node->node_list); |
241 | } | 242 | } |
242 | 243 | ||
243 | /* All functions below assume the plist_head is not empty. */ | 244 | /* All functions below assume the plist_head is not empty. */ |
@@ -285,7 +286,7 @@ static inline int plist_node_empty(const struct plist_node *node) | |||
285 | static inline struct plist_node *plist_first(const struct plist_head *head) | 286 | static inline struct plist_node *plist_first(const struct plist_head *head) |
286 | { | 287 | { |
287 | return list_entry(head->node_list.next, | 288 | return list_entry(head->node_list.next, |
288 | struct plist_node, plist.node_list); | 289 | struct plist_node, node_list); |
289 | } | 290 | } |
290 | 291 | ||
291 | /** | 292 | /** |
@@ -297,7 +298,7 @@ static inline struct plist_node *plist_first(const struct plist_head *head) | |||
297 | static inline struct plist_node *plist_last(const struct plist_head *head) | 298 | static inline struct plist_node *plist_last(const struct plist_head *head) |
298 | { | 299 | { |
299 | return list_entry(head->node_list.prev, | 300 | return list_entry(head->node_list.prev, |
300 | struct plist_node, plist.node_list); | 301 | struct plist_node, node_list); |
301 | } | 302 | } |
302 | 303 | ||
303 | #endif | 304 | #endif |
diff --git a/lib/plist.c b/lib/plist.c index 1471988d9190..8c614d0e6c35 100644 --- a/lib/plist.c +++ b/lib/plist.c | |||
@@ -59,7 +59,8 @@ static void plist_check_head(struct plist_head *head) | |||
59 | WARN_ON_SMP(!raw_spin_is_locked(head->rawlock)); | 59 | WARN_ON_SMP(!raw_spin_is_locked(head->rawlock)); |
60 | if (head->spinlock) | 60 | if (head->spinlock) |
61 | WARN_ON_SMP(!spin_is_locked(head->spinlock)); | 61 | WARN_ON_SMP(!spin_is_locked(head->spinlock)); |
62 | plist_check_list(&head->prio_list); | 62 | if (!plist_head_empty(head)) |
63 | plist_check_list(&plist_first(head)->prio_list); | ||
63 | plist_check_list(&head->node_list); | 64 | plist_check_list(&head->node_list); |
64 | } | 65 | } |
65 | 66 | ||
@@ -75,25 +76,33 @@ static void plist_check_head(struct plist_head *head) | |||
75 | */ | 76 | */ |
76 | void plist_add(struct plist_node *node, struct plist_head *head) | 77 | void plist_add(struct plist_node *node, struct plist_head *head) |
77 | { | 78 | { |
78 | struct plist_node *iter; | 79 | struct plist_node *first, *iter, *prev = NULL; |
80 | struct list_head *node_next = &head->node_list; | ||
79 | 81 | ||
80 | plist_check_head(head); | 82 | plist_check_head(head); |
81 | WARN_ON(!plist_node_empty(node)); | 83 | WARN_ON(!plist_node_empty(node)); |
84 | WARN_ON(!list_empty(&node->prio_list)); | ||
82 | 85 | ||
83 | list_for_each_entry(iter, &head->prio_list, plist.prio_list) { | 86 | if (plist_head_empty(head)) |
84 | if (node->prio < iter->prio) | 87 | goto ins_node; |
85 | goto lt_prio; | 88 | |
86 | else if (node->prio == iter->prio) { | 89 | first = iter = plist_first(head); |
87 | iter = list_entry(iter->plist.prio_list.next, | 90 | |
88 | struct plist_node, plist.prio_list); | 91 | do { |
89 | goto eq_prio; | 92 | if (node->prio < iter->prio) { |
93 | node_next = &iter->node_list; | ||
94 | break; | ||
90 | } | 95 | } |
91 | } | ||
92 | 96 | ||
93 | lt_prio: | 97 | prev = iter; |
94 | list_add_tail(&node->plist.prio_list, &iter->plist.prio_list); | 98 | iter = list_entry(iter->prio_list.next, |
95 | eq_prio: | 99 | struct plist_node, prio_list); |
96 | list_add_tail(&node->plist.node_list, &iter->plist.node_list); | 100 | } while (iter != first); |
101 | |||
102 | if (!prev || prev->prio != node->prio) | ||
103 | list_add_tail(&node->prio_list, &iter->prio_list); | ||
104 | ins_node: | ||
105 | list_add_tail(&node->node_list, node_next); | ||
97 | 106 | ||
98 | plist_check_head(head); | 107 | plist_check_head(head); |
99 | } | 108 | } |
@@ -108,14 +117,21 @@ void plist_del(struct plist_node *node, struct plist_head *head) | |||
108 | { | 117 | { |
109 | plist_check_head(head); | 118 | plist_check_head(head); |
110 | 119 | ||
111 | if (!list_empty(&node->plist.prio_list)) { | 120 | if (!list_empty(&node->prio_list)) { |
112 | struct plist_node *next = plist_first(&node->plist); | 121 | if (node->node_list.next != &head->node_list) { |
122 | struct plist_node *next; | ||
123 | |||
124 | next = list_entry(node->node_list.next, | ||
125 | struct plist_node, node_list); | ||
113 | 126 | ||
114 | list_move_tail(&next->plist.prio_list, &node->plist.prio_list); | 127 | /* add the next plist_node into prio_list */ |
115 | list_del_init(&node->plist.prio_list); | 128 | if (list_empty(&next->prio_list)) |
129 | list_add(&next->prio_list, &node->prio_list); | ||
130 | } | ||
131 | list_del_init(&node->prio_list); | ||
116 | } | 132 | } |
117 | 133 | ||
118 | list_del_init(&node->plist.node_list); | 134 | list_del_init(&node->node_list); |
119 | 135 | ||
120 | plist_check_head(head); | 136 | plist_check_head(head); |
121 | } | 137 | } |