Skip to content

Commit b8a2162

Browse files
Peter ZijlstraIngo Molnar
authored andcommitted
sched: Move completion code from core.c to completion.c
Completions already have their own header file: linux/completion.h Move the implementation out of kernel/sched/core.c and into its own file: kernel/sched/completion.c. Signed-off-by: Peter Zijlstra <peterz@infradead.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> Link: http://lkml.kernel.org/n/tip-x2y49rmxu5dljt66ai2lcfuw@git.kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent b414587 commit b8a2162

File tree

4 files changed

+301
-286
lines changed

4 files changed

+301
-286
lines changed

include/linux/completion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* (C) Copyright 2001 Linus Torvalds
66
*
77
* Atomic wait-for-completion handler data structures.
8-
* See kernel/sched/core.c for details.
8+
* See kernel/sched/completion.c for details.
99
*/
1010

1111
#include <linux/wait.h>

kernel/sched/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ CFLAGS_core.o := $(PROFILING) -fno-omit-frame-pointer
1212
endif
1313

1414
obj-y += core.o proc.o clock.o cputime.o idle_task.o fair.o rt.o stop_task.o
15-
obj-y += wait.o
15+
obj-y += wait.o completion.o
1616
obj-$(CONFIG_SMP) += cpupri.o
1717
obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o
1818
obj-$(CONFIG_SCHEDSTATS) += stats.o

kernel/sched/completion.c

Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
/*
2+
* Generic wait-for-completion handler;
3+
*
4+
* It differs from semaphores in that their default case is the opposite,
5+
* wait_for_completion default blocks whereas semaphore default non-block. The
6+
* interface also makes it easy to 'complete' multiple waiting threads,
7+
* something which isn't entirely natural for semaphores.
8+
*
9+
* But more importantly, the primitive documents the usage. Semaphores would
10+
* typically be used for exclusion which gives rise to priority inversion.
11+
* Waiting for completion is a typically sync point, but not an exclusion point.
12+
*/
13+
14+
#include <linux/sched.h>
15+
#include <linux/completion.h>
16+
17+
/**
18+
* complete: - signals a single thread waiting on this completion
19+
* @x: holds the state of this particular completion
20+
*
21+
* This will wake up a single thread waiting on this completion. Threads will be
22+
* awakened in the same order in which they were queued.
23+
*
24+
* See also complete_all(), wait_for_completion() and related routines.
25+
*
26+
* It may be assumed that this function implies a write memory barrier before
27+
* changing the task state if and only if any tasks are woken up.
28+
*/
29+
void complete(struct completion *x)
30+
{
31+
unsigned long flags;
32+
33+
spin_lock_irqsave(&x->wait.lock, flags);
34+
x->done++;
35+
__wake_up_locked(&x->wait, TASK_NORMAL, 1);
36+
spin_unlock_irqrestore(&x->wait.lock, flags);
37+
}
38+
EXPORT_SYMBOL(complete);
39+
40+
/**
41+
* complete_all: - signals all threads waiting on this completion
42+
* @x: holds the state of this particular completion
43+
*
44+
* This will wake up all threads waiting on this particular completion event.
45+
*
46+
* It may be assumed that this function implies a write memory barrier before
47+
* changing the task state if and only if any tasks are woken up.
48+
*/
49+
void complete_all(struct completion *x)
50+
{
51+
unsigned long flags;
52+
53+
spin_lock_irqsave(&x->wait.lock, flags);
54+
x->done += UINT_MAX/2;
55+
__wake_up_locked(&x->wait, TASK_NORMAL, 0);
56+
spin_unlock_irqrestore(&x->wait.lock, flags);
57+
}
58+
EXPORT_SYMBOL(complete_all);
59+
60+
static inline long __sched
61+
do_wait_for_common(struct completion *x,
62+
long (*action)(long), long timeout, int state)
63+
{
64+
if (!x->done) {
65+
DECLARE_WAITQUEUE(wait, current);
66+
67+
__add_wait_queue_tail_exclusive(&x->wait, &wait);
68+
do {
69+
if (signal_pending_state(state, current)) {
70+
timeout = -ERESTARTSYS;
71+
break;
72+
}
73+
__set_current_state(state);
74+
spin_unlock_irq(&x->wait.lock);
75+
timeout = action(timeout);
76+
spin_lock_irq(&x->wait.lock);
77+
} while (!x->done && timeout);
78+
__remove_wait_queue(&x->wait, &wait);
79+
if (!x->done)
80+
return timeout;
81+
}
82+
x->done--;
83+
return timeout ?: 1;
84+
}
85+
86+
static inline long __sched
87+
__wait_for_common(struct completion *x,
88+
long (*action)(long), long timeout, int state)
89+
{
90+
might_sleep();
91+
92+
spin_lock_irq(&x->wait.lock);
93+
timeout = do_wait_for_common(x, action, timeout, state);
94+
spin_unlock_irq(&x->wait.lock);
95+
return timeout;
96+
}
97+
98+
static long __sched
99+
wait_for_common(struct completion *x, long timeout, int state)
100+
{
101+
return __wait_for_common(x, schedule_timeout, timeout, state);
102+
}
103+
104+
static long __sched
105+
wait_for_common_io(struct completion *x, long timeout, int state)
106+
{
107+
return __wait_for_common(x, io_schedule_timeout, timeout, state);
108+
}
109+
110+
/**
111+
* wait_for_completion: - waits for completion of a task
112+
* @x: holds the state of this particular completion
113+
*
114+
* This waits to be signaled for completion of a specific task. It is NOT
115+
* interruptible and there is no timeout.
116+
*
117+
* See also similar routines (i.e. wait_for_completion_timeout()) with timeout
118+
* and interrupt capability. Also see complete().
119+
*/
120+
void __sched wait_for_completion(struct completion *x)
121+
{
122+
wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE);
123+
}
124+
EXPORT_SYMBOL(wait_for_completion);
125+
126+
/**
127+
* wait_for_completion_timeout: - waits for completion of a task (w/timeout)
128+
* @x: holds the state of this particular completion
129+
* @timeout: timeout value in jiffies
130+
*
131+
* This waits for either a completion of a specific task to be signaled or for a
132+
* specified timeout to expire. The timeout is in jiffies. It is not
133+
* interruptible.
134+
*
135+
* Return: 0 if timed out, and positive (at least 1, or number of jiffies left
136+
* till timeout) if completed.
137+
*/
138+
unsigned long __sched
139+
wait_for_completion_timeout(struct completion *x, unsigned long timeout)
140+
{
141+
return wait_for_common(x, timeout, TASK_UNINTERRUPTIBLE);
142+
}
143+
EXPORT_SYMBOL(wait_for_completion_timeout);
144+
145+
/**
146+
* wait_for_completion_io: - waits for completion of a task
147+
* @x: holds the state of this particular completion
148+
*
149+
* This waits to be signaled for completion of a specific task. It is NOT
150+
* interruptible and there is no timeout. The caller is accounted as waiting
151+
* for IO.
152+
*/
153+
void __sched wait_for_completion_io(struct completion *x)
154+
{
155+
wait_for_common_io(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE);
156+
}
157+
EXPORT_SYMBOL(wait_for_completion_io);
158+
159+
/**
160+
* wait_for_completion_io_timeout: - waits for completion of a task (w/timeout)
161+
* @x: holds the state of this particular completion
162+
* @timeout: timeout value in jiffies
163+
*
164+
* This waits for either a completion of a specific task to be signaled or for a
165+
* specified timeout to expire. The timeout is in jiffies. It is not
166+
* interruptible. The caller is accounted as waiting for IO.
167+
*
168+
* Return: 0 if timed out, and positive (at least 1, or number of jiffies left
169+
* till timeout) if completed.
170+
*/
171+
unsigned long __sched
172+
wait_for_completion_io_timeout(struct completion *x, unsigned long timeout)
173+
{
174+
return wait_for_common_io(x, timeout, TASK_UNINTERRUPTIBLE);
175+
}
176+
EXPORT_SYMBOL(wait_for_completion_io_timeout);
177+
178+
/**
179+
* wait_for_completion_interruptible: - waits for completion of a task (w/intr)
180+
* @x: holds the state of this particular completion
181+
*
182+
* This waits for completion of a specific task to be signaled. It is
183+
* interruptible.
184+
*
185+
* Return: -ERESTARTSYS if interrupted, 0 if completed.
186+
*/
187+
int __sched wait_for_completion_interruptible(struct completion *x)
188+
{
189+
long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_INTERRUPTIBLE);
190+
if (t == -ERESTARTSYS)
191+
return t;
192+
return 0;
193+
}
194+
EXPORT_SYMBOL(wait_for_completion_interruptible);
195+
196+
/**
197+
* wait_for_completion_interruptible_timeout: - waits for completion (w/(to,intr))
198+
* @x: holds the state of this particular completion
199+
* @timeout: timeout value in jiffies
200+
*
201+
* This waits for either a completion of a specific task to be signaled or for a
202+
* specified timeout to expire. It is interruptible. The timeout is in jiffies.
203+
*
204+
* Return: -ERESTARTSYS if interrupted, 0 if timed out, positive (at least 1,
205+
* or number of jiffies left till timeout) if completed.
206+
*/
207+
long __sched
208+
wait_for_completion_interruptible_timeout(struct completion *x,
209+
unsigned long timeout)
210+
{
211+
return wait_for_common(x, timeout, TASK_INTERRUPTIBLE);
212+
}
213+
EXPORT_SYMBOL(wait_for_completion_interruptible_timeout);
214+
215+
/**
216+
* wait_for_completion_killable: - waits for completion of a task (killable)
217+
* @x: holds the state of this particular completion
218+
*
219+
* This waits to be signaled for completion of a specific task. It can be
220+
* interrupted by a kill signal.
221+
*
222+
* Return: -ERESTARTSYS if interrupted, 0 if completed.
223+
*/
224+
int __sched wait_for_completion_killable(struct completion *x)
225+
{
226+
long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_KILLABLE);
227+
if (t == -ERESTARTSYS)
228+
return t;
229+
return 0;
230+
}
231+
EXPORT_SYMBOL(wait_for_completion_killable);
232+
233+
/**
234+
* wait_for_completion_killable_timeout: - waits for completion of a task (w/(to,killable))
235+
* @x: holds the state of this particular completion
236+
* @timeout: timeout value in jiffies
237+
*
238+
* This waits for either a completion of a specific task to be
239+
* signaled or for a specified timeout to expire. It can be
240+
* interrupted by a kill signal. The timeout is in jiffies.
241+
*
242+
* Return: -ERESTARTSYS if interrupted, 0 if timed out, positive (at least 1,
243+
* or number of jiffies left till timeout) if completed.
244+
*/
245+
long __sched
246+
wait_for_completion_killable_timeout(struct completion *x,
247+
unsigned long timeout)
248+
{
249+
return wait_for_common(x, timeout, TASK_KILLABLE);
250+
}
251+
EXPORT_SYMBOL(wait_for_completion_killable_timeout);
252+
253+
/**
254+
* try_wait_for_completion - try to decrement a completion without blocking
255+
* @x: completion structure
256+
*
257+
* Return: 0 if a decrement cannot be done without blocking
258+
* 1 if a decrement succeeded.
259+
*
260+
* If a completion is being used as a counting completion,
261+
* attempt to decrement the counter without blocking. This
262+
* enables us to avoid waiting if the resource the completion
263+
* is protecting is not available.
264+
*/
265+
bool try_wait_for_completion(struct completion *x)
266+
{
267+
unsigned long flags;
268+
int ret = 1;
269+
270+
spin_lock_irqsave(&x->wait.lock, flags);
271+
if (!x->done)
272+
ret = 0;
273+
else
274+
x->done--;
275+
spin_unlock_irqrestore(&x->wait.lock, flags);
276+
return ret;
277+
}
278+
EXPORT_SYMBOL(try_wait_for_completion);
279+
280+
/**
281+
* completion_done - Test to see if a completion has any waiters
282+
* @x: completion structure
283+
*
284+
* Return: 0 if there are waiters (wait_for_completion() in progress)
285+
* 1 if there are no waiters.
286+
*
287+
*/
288+
bool completion_done(struct completion *x)
289+
{
290+
unsigned long flags;
291+
int ret = 1;
292+
293+
spin_lock_irqsave(&x->wait.lock, flags);
294+
if (!x->done)
295+
ret = 0;
296+
spin_unlock_irqrestore(&x->wait.lock, flags);
297+
return ret;
298+
}
299+
EXPORT_SYMBOL(completion_done);

0 commit comments

Comments
 (0)