diff options
author | Lai Jiangshan <laijs@cn.fujitsu.com> | 2011-01-14 04:09:41 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2011-01-27 21:13:51 -0500 |
commit | 8161239a8bcce9ad6b537c04a1fa3b5c68bae693 (patch) | |
tree | a30738ef6e6be053e3604d7ca966a4805ef0039b /kernel/rtmutex_common.h | |
parent | 6fb1b304255efc5c4c93874ac8c066272e257e28 (diff) |
rtmutex: Simplify PI algorithm and make highest prio task get lock
In current rtmutex, the pending owner may be boosted by the tasks
in the rtmutex's waitlist when the pending owner is deboosted
or a task in the waitlist is boosted. This boosting is unrelated,
because the pending owner does not really take the rtmutex.
It is not reasonable.
Example.
time1:
A(high prio) onwers the rtmutex.
B(mid prio) and C (low prio) in the waitlist.
time2
A release the lock, B becomes the pending owner
A(or other high prio task) continues to run. B's prio is lower
than A, so B is just queued at the runqueue.
time3
A or other high prio task sleeps, but we have passed some time
The B and C's prio are changed in the period (time2 ~ time3)
due to boosting or deboosting. Now C has the priority higher
than B. ***Is it reasonable that C has to boost B and help B to
get the rtmutex?
NO!! I think, it is unrelated/unneed boosting before B really
owns the rtmutex. We should give C a chance to beat B and
win the rtmutex.
This is the motivation of this patch. This patch *ensures*
only the top waiter or higher priority task can take the lock.
How?
1) we don't dequeue the top waiter when unlock, if the top waiter
is changed, the old top waiter will fail and go to sleep again.
2) when requiring lock, it will get the lock when the lock is not taken and:
there is no waiter OR higher priority than waiters OR it is top waiter.
3) In any time, the top waiter is changed, the top waiter will be woken up.
The algorithm is much simpler than before, no pending owner, no
boosting for pending owner.
Other advantage of this patch:
1) The states of a rtmutex are reduced a half, easier to read the code.
2) the codes become shorter.
3) top waiter is not dequeued until it really take the lock:
they will retain FIFO when it is stolen.
Not advantage nor disadvantage
1) Even we may wakeup multiple waiters(any time when top waiter changed),
we hardly cause "thundering herd",
the number of wokenup task is likely 1 or very little.
2) two APIs are changed.
rt_mutex_owner() will not return pending owner, it will return NULL when
the top waiter is going to take the lock.
rt_mutex_next_owner() always return the top waiter.
will not return NULL if we have waiters
because the top waiter is not dequeued.
I have fixed the code that use these APIs.
need updated after this patch is accepted
1) Document/*
2) the testcase scripts/rt-tester/t4-l2-pi-deboost.tst
Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
LKML-Reference: <4D3012D5.4060709@cn.fujitsu.com>
Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/rtmutex_common.h')
-rw-r--r-- | kernel/rtmutex_common.h | 16 |
1 files changed, 2 insertions, 14 deletions
diff --git a/kernel/rtmutex_common.h b/kernel/rtmutex_common.h index 97a2f81866af..53a66c85261b 100644 --- a/kernel/rtmutex_common.h +++ b/kernel/rtmutex_common.h | |||
@@ -91,9 +91,8 @@ task_top_pi_waiter(struct task_struct *p) | |||
91 | /* | 91 | /* |
92 | * lock->owner state tracking: | 92 | * lock->owner state tracking: |
93 | */ | 93 | */ |
94 | #define RT_MUTEX_OWNER_PENDING 1UL | 94 | #define RT_MUTEX_HAS_WAITERS 1UL |
95 | #define RT_MUTEX_HAS_WAITERS 2UL | 95 | #define RT_MUTEX_OWNER_MASKALL 1UL |
96 | #define RT_MUTEX_OWNER_MASKALL 3UL | ||
97 | 96 | ||
98 | static inline struct task_struct *rt_mutex_owner(struct rt_mutex *lock) | 97 | static inline struct task_struct *rt_mutex_owner(struct rt_mutex *lock) |
99 | { | 98 | { |
@@ -101,17 +100,6 @@ static inline struct task_struct *rt_mutex_owner(struct rt_mutex *lock) | |||
101 | ((unsigned long)lock->owner & ~RT_MUTEX_OWNER_MASKALL); | 100 | ((unsigned long)lock->owner & ~RT_MUTEX_OWNER_MASKALL); |
102 | } | 101 | } |
103 | 102 | ||
104 | static inline struct task_struct *rt_mutex_real_owner(struct rt_mutex *lock) | ||
105 | { | ||
106 | return (struct task_struct *) | ||
107 | ((unsigned long)lock->owner & ~RT_MUTEX_HAS_WAITERS); | ||
108 | } | ||
109 | |||
110 | static inline unsigned long rt_mutex_owner_pending(struct rt_mutex *lock) | ||
111 | { | ||
112 | return (unsigned long)lock->owner & RT_MUTEX_OWNER_PENDING; | ||
113 | } | ||
114 | |||
115 | /* | 103 | /* |
116 | * PI-futex support (proxy locking functions, etc.): | 104 | * PI-futex support (proxy locking functions, etc.): |
117 | */ | 105 | */ |