From: Oleg Nesterov <oleg@redhat.com>
To: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@kernel.org>,
Linus Torvalds <torvalds@linux-foundation.org>
Cc: Paul McKenney <paulmck@linux.vnet.ibm.com>,
Thomas Gleixner <tglx@linutronix.de>,
Andrew Morton <akpm@linux-foundation.org>,
linux-kernel@vger.kernel.org
Subject: [RFC] introduce prepare_to_wait_event()
Date: Tue, 1 Oct 2013 19:01:37 +0200 [thread overview]
Message-ID: <20131001170137.GA8560@redhat.com> (raw)
In-Reply-To: <20130930152242.207382649@infradead.org>
I didn't test is yet, and I did write the changelog.
But let me show the patch for review right now, before we all
forget the details... On top of Peter's "wait: Collapse __wait_event
macros -v4".
This patch moves the signal-pending checks and part of DEFINE_WAIT's
code into the new helper: prepare_to_wait_event().
Yes, sure, prepare_to_wait_event() becomes a little bit slower than
prepare_to_wait/prepare_to_wait_exclusive. But this is the slow path
anyway, we are likely going to sleep. IMO, it is better to shrink
.text, and on my build the difference is
- 5124686 2955056 10117120 18196862 115a97e vmlinux
+ 5123212 2955088 10117120 18195420 115a3dc vmlinux
The code with the patch is
#define ___wait_is_interruptible(state) \
(!__builtin_constant_p(state) || \
state == TASK_INTERRUPTIBLE || state == TASK_KILLABLE) \
#define ___wait_event(wq, condition, state, exclusive, ret, cmd) \
({ \
__label__ __out; \
wait_queue_t __wait; \
long __ret = ret; \
\
INIT_LIST_HEAD(&__wait.task_list); \
if (exclusive) \
__wait.flags = WQ_FLAG_EXCLUSIVE; \
else \
__wait.flags = 0; \
\
for (;;) { \
long intr = prepare_to_wait_event(&wq, &__wait, state); \
\
if (condition) \
break; \
\
if (___wait_is_interruptible(state) && intr) { \
__ret = intr; \
if (exclusive) { \
abort_exclusive_wait(&wq, &__wait, \
state, NULL); \
goto __out; \
} \
break; \
} \
\
cmd; \
} \
finish_wait(&wq, &__wait); \
__out: __ret; \
})
Compiler should optimize out "long intr" if !interruptible/killable.
What do you think?
Oleg.
---
diff --git a/include/linux/wait.h b/include/linux/wait.h
index bd4bd7b..aa758d3 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -187,27 +187,30 @@ wait_queue_head_t *bit_waitqueue(void *, int);
__cond || !__ret; \
})
-#define ___wait_signal_pending(state) \
- ((state == TASK_INTERRUPTIBLE && signal_pending(current)) || \
- (state == TASK_KILLABLE && fatal_signal_pending(current)))
+#define ___wait_is_interruptible(state) \
+ (!__builtin_constant_p(state) || \
+ state == TASK_INTERRUPTIBLE || state == TASK_KILLABLE) \
#define ___wait_event(wq, condition, state, exclusive, ret, cmd) \
({ \
__label__ __out; \
- DEFINE_WAIT(__wait); \
+ wait_queue_t __wait; \
long __ret = ret; \
\
+ INIT_LIST_HEAD(&__wait.task_list); \
+ if (exclusive) \
+ __wait.flags = WQ_FLAG_EXCLUSIVE; \
+ else \
+ __wait.flags = 0; \
+ \
for (;;) { \
- if (exclusive) \
- prepare_to_wait_exclusive(&wq, &__wait, state); \
- else \
- prepare_to_wait(&wq, &__wait, state); \
+ long intr = prepare_to_wait_event(&wq, &__wait, state); \
\
if (condition) \
break; \
\
- if (___wait_signal_pending(state)) { \
- __ret = -ERESTARTSYS; \
+ if (___wait_is_interruptible(state) && intr) { \
+ __ret = intr; \
if (exclusive) { \
abort_exclusive_wait(&wq, &__wait, \
state, NULL); \
@@ -794,6 +797,7 @@ extern long interruptible_sleep_on_timeout(wait_queue_head_t *q,
*/
void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state);
void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state);
+long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state);
void finish_wait(wait_queue_head_t *q, wait_queue_t *wait);
void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait,
unsigned int mode, void *key);
diff --git a/kernel/wait.c b/kernel/wait.c
index d550920..de21c63 100644
--- a/kernel/wait.c
+++ b/kernel/wait.c
@@ -92,6 +92,30 @@ prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state)
}
EXPORT_SYMBOL(prepare_to_wait_exclusive);
+long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state)
+{
+ unsigned long flags;
+
+ if (signal_pending_state(state, current))
+ return -ERESTARTSYS;
+
+ wait->private = current;
+ wait->func = autoremove_wake_function;
+
+ spin_lock_irqsave(&q->lock, flags);
+ if (list_empty(&wait->task_list)) {
+ if (wait->flags & WQ_FLAG_EXCLUSIVE)
+ __add_wait_queue_tail(q, wait);
+ else
+ __add_wait_queue(q, wait);
+ }
+ set_current_state(state);
+ spin_unlock_irqrestore(&q->lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(prepare_to_wait_event);
+
/**
* finish_wait - clean up after waiting in a queue
* @q: waitqueue waited on
next prev parent reply other threads:[~2013-10-01 17:08 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-09-30 15:22 [PATCH 0/6] sched, wait: Collapse __wait_event macros -v4 Peter Zijlstra
2013-09-30 15:22 ` [PATCH 1/6] sched, wait: Make the signal_pending() checks consistent Peter Zijlstra
2013-09-30 15:22 ` [PATCH 2/6] sched, wait: Change timeout logic Peter Zijlstra
2013-09-30 15:48 ` Linus Torvalds
2013-09-30 16:09 ` Peter Zijlstra
2013-09-30 15:22 ` [PATCH 3/6] sched, wait: Change the wait_exclusive control flow Peter Zijlstra
2013-09-30 15:22 ` [PATCH 4/6] sched, wait: Collapse __wait_event macros Peter Zijlstra
2013-09-30 15:22 ` [PATCH 5/6] sched, wait: Also use ___wait_event() for __wait_event_hrtimeout Peter Zijlstra
2013-09-30 15:22 ` [PATCH 6/6] sched, wait: Make the __wait_event*() interface more friendly Peter Zijlstra
2013-10-01 6:39 ` Ingo Molnar
2013-09-30 15:50 ` [PATCH 0/6] sched, wait: Collapse __wait_event macros -v4 Linus Torvalds
2013-09-30 16:11 ` Peter Zijlstra
2013-09-30 17:40 ` Oleg Nesterov
2013-09-30 18:00 ` Oleg Nesterov
2013-09-30 18:09 ` Peter Zijlstra
2013-09-30 18:13 ` Oleg Nesterov
2013-10-01 14:09 ` Oleg Nesterov
2013-10-01 14:39 ` Peter Zijlstra
2013-10-01 15:16 ` Oleg Nesterov
2013-10-01 17:01 ` Oleg Nesterov [this message]
2013-10-01 17:25 ` [RFC] introduce prepare_to_wait_event() Peter Zijlstra
2013-10-01 17:33 ` Oleg Nesterov
2013-10-01 17:44 ` Peter Zijlstra
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20131001170137.GA8560@redhat.com \
--to=oleg@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=paulmck@linux.vnet.ibm.com \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.