plist: shrink plist_head
PATCH 3/3 plist: shrink plist_head
struct plist_head is too big, and the field prio_list in the struct plist_head is used seldom. So it can be removed and we use the first plist_node's prio_list when needed.
The size of struct rtmutex and struct task_struct will also decreased after struct plist_head shrinked.
--- include/linux/plist.h | 47 ++++++++++++++++++++++--------------------- lib/plist.c | 54 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 59 insertions(+), 42 deletions(-)
include/linux/plist.h +24 -23
@@ -31,15 +31,17 @@* * Simple ASCII art explanation: * -* |HEAD | -* | | -* |prio_list.prev|<------------------------------------| -* |prio_list.next|<->|pl|<->|pl|<--------------->|pl|<-| -* |10 | |10| |21| |21| |21| |40| (prio) -* | | | | | | | | | | | | -* | | | | | | | | | | | | -* |node_list.next|<->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<-| -* |node_list.prev|<------------------------------------| +* pl:prio_list (only for plist_node) +* nl:node_list +* HEAD| NODE(S) +* | +* ||------------------------------------| +* ||->|pl|<->|pl|<--------------->|pl|<-| +* | |10| |21| |21| |21| |40| (prio) +* | | | | | | | | | | | +* | | | | | | | | | | | +* |->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<-| +* |-------------------------------------------| * * The nodes on the prio_list list are sorted by priority to simplify * the insertion of new nodes. There are no nodes with duplicate
@@ -78,7 +80,6 @@#include <linux/spinlock_types.h> struct plist_head { -struct list_head prio_list;struct list_head node_list;#ifdef CONFIG_DEBUG_PI_LIST raw_spinlock_t *rawlock;
@@ -88,7 +89,8 @@ struct plist_head {struct plist_node {int prio; -struct plist_head plist; +struct list_head prio_list; +struct list_head node_list; };#ifdef CONFIG_DEBUG_PI_LIST
@@ -100,7 +102,6 @@ struct plist_node {#endif #define _PLIST_HEAD_INIT (head) \ - .prio_list = LIST_HEAD_INIT((head).prio_list), \ .node_list = LIST_HEAD_INIT((head).node_list)/**
@@ -133,7 +134,8 @@ struct plist_node {#define PLIST_NODE_INIT (node, __prio) \ { \ .prio = (__prio), \ - .plist = { _PLIST_HEAD_INIT((node).plist) }, \ + .prio_list = LIST_HEAD_INIT((node).prio_list), \ + .node_list = LIST_HEAD_INIT((node).node_list), \ }/**
@@ -144,7 +146,6 @@ struct plist_node {static inline void plist_head_init (struct plist_head *head,spinlock_t *lock) { -INIT_LIST_HEAD (&head->prio_list);INIT_LIST_HEAD (&head->node_list);#ifdef CONFIG_DEBUG_PI_LIST head->spinlock = lock;
@@ -160,7 +161,6 @@ plist_head_init(struct plist_head *head, spinlock_t *lock)static inline void plist_head_init_raw (struct plist_head *head,raw_spinlock_t *lock) { -INIT_LIST_HEAD (&head->prio_list);INIT_LIST_HEAD (&head->node_list);#ifdef CONFIG_DEBUG_PI_LIST head->rawlock = lock;
@@ -176,7 +176,8 @@ plist_head_init_raw(struct plist_head *head, raw_spinlock_t *lock)static inline void plist_node_init (struct plist_node *node,int prio) { node->prio = prio; -plist_head_init (&node->plist,NULL ); +INIT_LIST_HEAD (&node->prio_list); +INIT_LIST_HEAD (&node->node_list); }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);* @head: the head for your list */ #define plist_for_each (pos, head) \ - list_for_each_entry(pos, &(head)->node_list, plist.node_list) + list_for_each_entry(pos, &(head)->node_list, node_list)/** * 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);* Iterate over a plist of given type, safe against removal of list entry. */ #define plist_for_each_safe (pos, n, head) \ - list_for_each_entry_safe(pos, n, &(head)->node_list, plist.node_list) + list_for_each_entry_safe(pos, n, &(head)->node_list, node_list)/** * 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);* @mem: the name of the list_struct within the struct */ #define plist_for_each_entry (pos, head, mem) \ - list_for_each_entry(pos, &(head)->node_list, mem.plist.node_list) + list_for_each_entry(pos, &(head)->node_list, mem.node_list)/** * 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);* Iterate over list of given type, safe against removal of list entry. */ #define plist_for_each_entry_safe (pos, n, head, m) \ - list_for_each_entry_safe(pos, n, &(head)->node_list, m.plist.node_list) + list_for_each_entry_safe(pos, n, &(head)->node_list, m.node_list)/** * 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)*/ static inline int plist_node_empty (const struct plist_node *node) { -return plist_head_empty (&node->plist); +return list_empty (&node->node_list); }/* 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)static inline struct plist_node *plist_first (const struct plist_head *head) {return list_entry (head->node_list.next, - struct plist_node, plist.node_list); + struct plist_node, node_list); }/**
@@ -297,7 +298,7 @@ static inline struct plist_node *plist_first(const struct plist_head *head)static inline struct plist_node *plist_last (const struct plist_head *head) {return list_entry (head->node_list.prev, - struct plist_node, plist.node_list); + struct plist_node, node_list); }#endif
lib/plist.c +35 -19
81 lines not on this page · raw message
Quoted 33 lines · Lai Jiangshan
struct
plist_headis too big, and the fieldprio_listin the structplist_headis used seldom. So it can be removed and we use the first plist_node'sprio_listwhen needed.The size of struct rtmutex and struct
task_structwill also decreased after structplist_headshrinked.Signed-off-by Lai Jiangshan <[email protected]>--- include/linux/plist.h | 47 ++++++++++++++++++++++--------------------- lib/plist.c | 54 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 59 insertions(+), 42 deletions(-)include/linux/plist.h +2
-9@@ -31,15 +31,17 @@* * Simple ASCII art explanation: * -* |HEAD | -* | | -* |prio_list.prev|<------------------------------------| -* |prio_list.next|<->|pl|<->|pl|<--------------->|pl|<-| -* |10 | |10| |21| |21| |21| |40| (prio) -* | | | | | | | | | | | | -* | | | | | | | | | | | | -* |node_list.next|<->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<-| -* |node_list.prev|<------------------------------------| +* pl:prio_list (only for plist_node) +* nl:node_list
include/linux/plist.h line 45
Quoted 10 lines
include/linux/plist.h +9
-0+* HEAD| NODE(S) +* | +* ||------------------------------------| +* ||->|pl|<->|pl|<--------------->|pl|<-| +* | |10| |21| |21| |21| |40| (prio) +* | | | | | | | | | | | +* | | | | | | | | | | | +* |->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<-| +* |-------------------------------------------| *
This is the test code for this new plist.
After my careful review and the tests, I trust this plist.
Subject: [PATCH] plist: test for plist
Add test code for checking plist when kernel is booting.
---
lib/plist.c +80 -1
@@ -28,6 +28,8 @@#ifdef CONFIG_DEBUG_PI_LIST +static struct plist_head test_head; +static void plist_check_prev_next (struct list_head *t,struct list_head *p,struct list_head *n) {
@@ -54,7 +56,7 @@ static void plist_check_list(struct list_head *top)static void plist_check_head (struct plist_head *head) { -WARN_ON (!head->rawlock && !head->spinlock); +WARN_ON (head != &test_head && !head->rawlock && !head->spinlock);if (head->rawlock)WARN_ON_SMP (!raw_spin_is_locked (head->rawlock));if (head->spinlock)
@@ -135,3 +137,80 @@ void plist_del(struct plist_node *node, struct plist_head *head)plist_check_head (head); } + +#ifdef CONFIG_DEBUG_PI_LIST +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/init.h> + +static struct plist_node __initdata test_node[241 ]; + +static void __init plist_test_check (int nr_expect) +{ +struct plist_node *first, *prio_pos, *node_pos; + +if (plist_head_empty (&test_head)) { +BUG_ON (nr_expect !=0 ); +return ; + } + + prio_pos = first =plist_first (&test_head); +plist_for_each (node_pos, &test_head) { +if (nr_expect-- <0 ) +break ; +if (node_pos == first) +continue ; +if (node_pos->prio == prio_pos->prio) { +BUG_ON (!list_empty (&node_pos->prio_list)); +continue ; + } + +BUG_ON (prio_pos->prio > node_pos->prio); +BUG_ON (prio_pos->prio_list.next != &node_pos->prio_list); + prio_pos = node_pos; + } + +BUG_ON (nr_expect !=0 ); +BUG_ON (prio_pos->prio_list.next != &first->prio_list); +} + +static int __init plist_test (void ) +{ +int nr_expect =0 , i, loop; +unsigned int r =local_clock (); + +printk (KERN_INFO "start plist test\n" ); +plist_head_init (&test_head,NULL ); +for (i =0 ; i <ARRAY_SIZE (test_node); i++) +plist_node_init (test_node + i,0 ); + +for (loop =0 ; loop <1000 ; loop++) { + r = r *193939 %47629 ; + i = r %ARRAY_SIZE (test_node); +if (plist_node_empty (test_node + i)) { + r = r *193939 %47629 ; + test_node[i].prio = r %99 ; +plist_add (test_node + i, &test_head); + nr_expect++; + }else { +plist_del (test_node + i, &test_head); + nr_expect--; + } +plist_test_check (nr_expect); + } + +for (i =0 ; i <ARRAY_SIZE (test_node); i++) { +if (plist_node_empty (test_node + i)) +continue ; +plist_del (test_node + i, &test_head); + nr_expect--; +plist_test_check (nr_expect); + } + +printk (KERN_INFO "end plist test\n" ); +return 0 ; +} + +module_init (plist_test); + +#endif
PATCH 4/4 plist: priority list test
In reply to Lai JiangshanAdd test code for checking plist when the kernel is booting.
---
lib/plist.c +80 -1
@@ -28,6 +28,8 @@#ifdef CONFIG_DEBUG_PI_LIST +static struct plist_head test_head; +static void plist_check_prev_next (struct list_head *t,struct list_head *p,struct list_head *n) {
@@ -54,7 +56,7 @@ static void plist_check_list(struct list_head *top)static void plist_check_head (struct plist_head *head) { -WARN_ON (!head->rawlock && !head->spinlock); +WARN_ON (head != &test_head && !head->rawlock && !head->spinlock);if (head->rawlock)WARN_ON_SMP (!raw_spin_is_locked (head->rawlock));if (head->spinlock)
@@ -135,3 +137,80 @@ void plist_del(struct plist_node *node, struct plist_head *head)plist_check_head (head); } + +#ifdef CONFIG_DEBUG_PI_LIST +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/init.h> + +static struct plist_node __initdata test_node[241 ]; + +static void __init plist_test_check (int nr_expect) +{ +struct plist_node *first, *prio_pos, *node_pos; + +if (plist_head_empty (&test_head)) { +BUG_ON (nr_expect !=0 ); +return ; + } + + prio_pos = first =plist_first (&test_head); +plist_for_each (node_pos, &test_head) { +if (nr_expect-- <0 ) +break ; +if (node_pos == first) +continue ; +if (node_pos->prio == prio_pos->prio) { +BUG_ON (!list_empty (&node_pos->prio_list)); +continue ; + } + +BUG_ON (prio_pos->prio > node_pos->prio); +BUG_ON (prio_pos->prio_list.next != &node_pos->prio_list); + prio_pos = node_pos; + } + +BUG_ON (nr_expect !=0 ); +BUG_ON (prio_pos->prio_list.next != &first->prio_list); +} + +static int __init plist_test (void ) +{ +int nr_expect =0 , i, loop; +unsigned int r =local_clock (); + +printk (KERN_INFO "start plist test\n" ); +plist_head_init (&test_head,NULL ); +for (i =0 ; i <ARRAY_SIZE (test_node); i++) +plist_node_init (test_node + i,0 ); + +for (loop =0 ; loop <1000 ; loop++) { + r = r *193939 %47629 ; + i = r %ARRAY_SIZE (test_node); +if (plist_node_empty (test_node + i)) { + r = r *193939 %47629 ; + test_node[i].prio = r %99 ; +plist_add (test_node + i, &test_head); + nr_expect++; + }else { +plist_del (test_node + i, &test_head); + nr_expect--; + } +plist_test_check (nr_expect); + } + +for (i =0 ; i <ARRAY_SIZE (test_node); i++) { +if (plist_node_empty (test_node + i)) +continue ; +plist_del (test_node + i, &test_head); + nr_expect--; +plist_test_check (nr_expect); + } + +printk (KERN_INFO "end plist test\n" ); +return 0 ; +} + +module_init (plist_test); + +#endif
[tip:core/futexes] plist: Add priority list test
Commit-ID: 6d55da53db3d9b911f69f2ce1e5fb8943eafe057 Gitweb: http://git.kernel.org/tip/6d55da53db3d9b911f69f2ce1e5fb8943eafe057 Author: Lai Jiangshan <[email protected]> AuthorDate: Tue, 21 Dec 2010 17:55:18 +0800 Committer: Steven Rostedt <[email protected]> CommitDate: Fri, 11 Mar 2011 15:14:48 -0500
plist: Add priority list test
Add test code for checking plist when the kernel is booting.
LKML-Reference: <[email protected]>
--- lib/plist.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 80 insertions(+), 1 deletions(-)
lib/plist.c +80 -1
@@ -28,6 +28,8 @@#ifdef CONFIG_DEBUG_PI_LIST +static struct plist_head test_head; +static void plist_check_prev_next (struct list_head *t,struct list_head *p,struct list_head *n) {
@@ -54,7 +56,7 @@ static void plist_check_list(struct list_head *top)static void plist_check_head (struct plist_head *head) { -WARN_ON (!head->rawlock && !head->spinlock); +WARN_ON (head != &test_head && !head->rawlock && !head->spinlock);if (head->rawlock)WARN_ON_SMP (!raw_spin_is_locked (head->rawlock));if (head->spinlock)
@@ -135,3 +137,80 @@ void plist_del(struct plist_node *node, struct plist_head *head)plist_check_head (head); } + +#ifdef CONFIG_DEBUG_PI_LIST +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/init.h> + +static struct plist_node __initdata test_node[241 ]; + +static void __init plist_test_check (int nr_expect) +{ +struct plist_node *first, *prio_pos, *node_pos; + +if (plist_head_empty (&test_head)) { +BUG_ON (nr_expect !=0 ); +return ; + } + + prio_pos = first =plist_first (&test_head); +plist_for_each (node_pos, &test_head) { +if (nr_expect-- <0 ) +break ; +if (node_pos == first) +continue ; +if (node_pos->prio == prio_pos->prio) { +BUG_ON (!list_empty (&node_pos->prio_list)); +continue ; + } + +BUG_ON (prio_pos->prio > node_pos->prio); +BUG_ON (prio_pos->prio_list.next != &node_pos->prio_list); + prio_pos = node_pos; + } + +BUG_ON (nr_expect !=0 ); +BUG_ON (prio_pos->prio_list.next != &first->prio_list); +} + +static int __init plist_test (void ) +{ +int nr_expect =0 , i, loop; +unsigned int r =local_clock (); + +printk (KERN_INFO "start plist test\n" ); +plist_head_init (&test_head,NULL ); +for (i =0 ; i <ARRAY_SIZE (test_node); i++) +plist_node_init (test_node + i,0 ); + +for (loop =0 ; loop <1000 ; loop++) { + r = r *193939 %47629 ; + i = r %ARRAY_SIZE (test_node); +if (plist_node_empty (test_node + i)) { + r = r *193939 %47629 ; + test_node[i].prio = r %99 ; +plist_add (test_node + i, &test_head); + nr_expect++; + }else { +plist_del (test_node + i, &test_head); + nr_expect--; + } +plist_test_check (nr_expect); + } + +for (i =0 ; i <ARRAY_SIZE (test_node); i++) { +if (plist_node_empty (test_node + i)) +continue ; +plist_del (test_node + i, &test_head); + nr_expect--; +plist_test_check (nr_expect); + } + +printk (KERN_INFO "end plist test\n" ); +return 0 ; +} + +module_init (plist_test); + +#endif