Re: [patch] uninline init_waitqueue_*() functions

Andrew Morton
2006-07-05T17:11:08Z

On Wed, 5 Jul 2006 13:46:30 +0200
Ingo Molnar <mingo@elte.hu> wrote:

>
> * Ingo Molnar <mingo@elte.hu> wrote:
>
> > > true. I redid my tests with both lockdep and debug-spinlocks turned off:
> > >
> > > text data bss dec filename
> > > 21172153 6077270 3081864 30331287 vmlinux.x32.after
> > > 21198222 6077106 3081864 30357192 vmlinux.x32.before
> > >
> > > with 851 callsites that's a 30.6 bytes win per call site (total 26K) -
> > > still not bad at all.
> >
> > and that was with CONFIG_CC_OPTIMIZE_FOR_SIZE enabled. With
> > optimize-for-size disabled the win goes up to 32.6 bytes (total 28K).
>
> i also tried a config with the best size settings (disabling
> FRAME_POINTER, enabling CC_OPTIMIZE_FOR_SIZE), and this gives:
>
> text data bss dec filename
> 20777768 6076042 3081864 29935674 vmlinux.x32.size.before
> 20748140 6076178 3081864 29906182 vmlinux.x32.size.after
>
> or a 34.8 bytes win per callsite (29K total).
>

With gcc-4.1.0 on i686, uninlining those three functions as per the below
patch _increases_ the allnoconfig vmlinux's .text from 833456 bytes to
833728.

Which maybe means it's still worth doing, because a lot of people run with
some debug options nowadays.

But it's a more believable result, and an inexplicable one given your
numbers. Something's up.

include/linux/wait.h | 24 +++---------------------
kernel/fork.c | 21 +++++++++++++++++++++
2 files changed, 24 insertions(+), 21 deletions(-)

diff -puN include/linux/wait.h~a include/linux/wait.h
--- a/include/linux/wait.h~a
+++ a/include/linux/wait.h
@@ -82,27 +82,9 @@ struct task_struct;
*/
extern struct lock_class_key waitqueue_lock_key;

-static inline void init_waitqueue_head(wait_queue_head_t *q)
-{
- spin_lock_init(&q->lock);
- lockdep_set_class(&q->lock, &waitqueue_lock_key);
- INIT_LIST_HEAD(&q->task_list);
-}
-
-static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p)
-{
- q->flags = 0;
- q->private = p;
- q->func = default_wake_function;
-}
-
-static inline void init_waitqueue_func_entry(wait_queue_t *q,
- wait_queue_func_t func)
-{
- q->flags = 0;
- q->private = NULL;
- q->func = func;
-}
+void init_waitqueue_head(wait_queue_head_t *q);
+void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p);
+void init_waitqueue_func_entry(wait_queue_t *q, wait_queue_func_t func);

static inline int waitqueue_active(wait_queue_head_t *q)
{
diff -puN fs/aio.c~a fs/aio.c
diff -puN kernel/fork.c~a kernel/fork.c
--- a/kernel/fork.c~a
+++ a/kernel/fork.c
@@ -153,6 +153,27 @@ void __init fork_init(unsigned long memp
init_task.signal->rlim[RLIMIT_NPROC];
}

+void init_waitqueue_head(wait_queue_head_t *q)
+{
+ spin_lock_init(&q->lock);
+ lockdep_set_class(&q->lock, &waitqueue_lock_key);
+ INIT_LIST_HEAD(&q->task_list);
+}
+
+void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p)
+{
+ q->flags = 0;
+ q->private = p;
+ q->func = default_wake_function;
+}
+
+void init_waitqueue_func_entry(wait_queue_t *q, wait_queue_func_t func)
+{
+ q->flags = 0;
+ q->private = NULL;
+ q->func = func;
+}
+
static struct task_struct *dup_task_struct(struct task_struct *orig)
{
struct task_struct *tsk;
_