aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/init_task.h
diff options
context:
space:
mode:
authorGregory Haskins <ghaskins@novell.com>2008-12-29 09:39:53 -0500
committerGregory Haskins <ghaskins@novell.com>2008-12-29 09:39:53 -0500
commit917b627d4d981dc614519d7b34ea31a976b14e12 (patch)
treeedb1744bd3f943ee79ee4f6c995c48a28421504c /include/linux/init_task.h
parent4075134e40804821f90866d7de56802e4dcecb1e (diff)
sched: create "pushable_tasks" list to limit pushing to one attempt
The RT scheduler employs a "push/pull" design to actively balance tasks within the system (on a per disjoint cpuset basis). When a task is awoken, it is immediately determined if there are any lower priority cpus which should be preempted. This is opposed to the way normal SCHED_OTHER tasks behave, which will wait for a periodic rebalancing operation to occur before spreading out load. When a particular RQ has more than 1 active RT task, it is said to be in an "overloaded" state. Once this occurs, the system enters the active balancing mode, where it will try to push the task away, or persuade a different cpu to pull it over. The system will stay in this state until the system falls back below the <= 1 queued RT task per RQ. However, the current implementation suffers from a limitation in the push logic. Once overloaded, all tasks (other than current) on the RQ are analyzed on every push operation, even if it was previously unpushable (due to affinity, etc). Whats more, the operation stops at the first task that is unpushable and will not look at items lower in the queue. This causes two problems: 1) We can have the same tasks analyzed over and over again during each push, which extends out the fast path in the scheduler for no gain. Consider a RQ that has dozens of tasks that are bound to a core. Each one of those tasks will be encountered and skipped for each push operation while they are queued. 2) There may be lower-priority tasks under the unpushable task that could have been successfully pushed, but will never be considered until either the unpushable task is cleared, or a pull operation succeeds. The net result is a potential latency source for mid priority tasks. This patch aims to rectify these two conditions by introducing a new priority sorted list: "pushable_tasks". A task is added to the list each time a task is activated or preempted. It is removed from the list any time it is deactivated, made current, or fails to push. This works because a task only needs to be attempted to push once. After an initial failure to push, the other cpus will eventually try to pull the task when the conditions are proper. This also solves the problem that we don't completely analyze all tasks due to encountering an unpushable tasks. Now every task will have a push attempted (when appropriate). This reduces latency both by shorting the critical section of the rq->lock for certain workloads, and by making sure the algorithm considers all eligible tasks in the system. [ rostedt: added a couple more BUG_ONs ] Signed-off-by: Gregory Haskins <ghaskins@novell.com> Acked-by: Steven Rostedt <srostedt@redhat.com>
Diffstat (limited to 'include/linux/init_task.h')
-rw-r--r--include/linux/init_task.h1
1 files changed, 1 insertions, 0 deletions
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 23fd8909b9e..6851225f44a 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -140,6 +140,7 @@ extern struct group_info init_groups;
140 .nr_cpus_allowed = NR_CPUS, \ 140 .nr_cpus_allowed = NR_CPUS, \
141 }, \ 141 }, \
142 .tasks = LIST_HEAD_INIT(tsk.tasks), \ 142 .tasks = LIST_HEAD_INIT(tsk.tasks), \
143 .pushable_tasks = PLIST_NODE_INIT(tsk.pushable_tasks, MAX_PRIO), \
143 .ptraced = LIST_HEAD_INIT(tsk.ptraced), \ 144 .ptraced = LIST_HEAD_INIT(tsk.ptraced), \
144 .ptrace_entry = LIST_HEAD_INIT(tsk.ptrace_entry), \ 145 .ptrace_entry = LIST_HEAD_INIT(tsk.ptrace_entry), \
145 .real_parent = &tsk, \ 146 .real_parent = &tsk, \