2.6.13-rc6-rt9
Subsystems (5)
i have released the 2.6.13-rc6-rt9 tree, which can be downloaded from the usual place:
http://redhat.com/~mingo/realtime-preempt/
it's a fixes-only release. Changes since 2.6.13-rc6-rt3:
- USB irq flags use cleanups (Alan Stern)
- RCU tasklist-lock fixes (Paul McKenney, Thomas Gleixner)
- HR-timers waitqueue splitup, better HRT latencies (Thomas Gleixner)
- latency tracer fixes, irq flags tracing cleanups (Steven Rostedt, me)
- NFSd BKL unlock fix (Steven Rostedt)
- stackfootprint-max-printer fix (Steven Rostedt)
- stop_machine fix (Steven Rostedt)
- lpptest fix (me)
- turned off IOAPIC_POSTFLUSH when CONFIG_X86_IOAPIC_FAST. Now with Karsten's VIA fixes my testbox does not show PCI-POST weirnesses anymore. In case of IRQ problems please turn off IOAPIC_FAST. (me)
to build a 2.6.13-rc6-rt9 tree, the following patches should be applied:
http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.12.tar.bz2
http://kernel.org/pub/linux/kernel/v2.6/testing/patch-2.6.13-rc6.bz2
http://redhat.com/~mingo/realtime-preempt/patch-2.6.13-rc6-rt9
Ingo
Quoted 2 lines · Ingo Molnar
i have released the 2.6.13-rc6-rt9 tree, which can be downloaded from the usual place:
Hi Ingo,
finally found the deadlock. It was caused by IRQ flood, which was introduced by the end_irq() changes.
They change the semantics in two ways - both wrong.
1. The condition is different
2. ->end() can contain different code than ->enable()
That's the code in end_8259A_irq():
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) && irq_desc[irq].action) enable_8259A_irq(irq);
The code in end_irq():
if (!(desc->status & IRQ_DISABLED)) desc->handler->enable(irq);
What was the reason for those changes ?
tglx
diff -uprN --exclude-from=/usr/local/bin/diffit.exclude linux-2.6.13-rc6-rt8/kernel/irq/handle.c linux-2.6.13-rc6-rt-debug/kernel/irq/handle.c
--- linux-2.6.13-rc6-rt8/kernel/irq/handle.c 2005-08-17 17:53:13.000000000 +0200
+++ linux-2.6.13-rc6-rt-debug/kernel/irq/handle.c 2005-08-18 16:32:54.000000000 +0200
@@ -171,7 +171,7 @@ fastcall notrace unsigned int __do_IRQ(u */desc->handler->ack(irq);action_ret = handle_IRQ_event(irq, regs, desc->action);
- end_irq(desc, irq);
+ desc->handler->end(irq);
return 1;
}
@@ -241,7 +241,7 @@ out:
* The end-handler has to deal with interrupts which got
* disabled while the handler was running:
*/
- end_irq(desc, irq);
+ desc->handler->end(irq);out_no_end:spin_unlock(&desc->lock);
kernel/irq/internals.h +0 -15
@@ -6,21 +6,6 @@ extern int noirqdebug;void recalculate_desc_flags (struct irq_desc *desc); -/* -* On PREEMPT_HARDIRQS, the ->ack handler masks interrupts, so that -* they can be redirected to an IRQ thread, if needed. So here we -* have to unmask the interrupt line, if needed: -*/ -static inline void end_irq (irq_desc_t *desc,unsigned int irq) -{ -#ifdef CONFIG_PREEMPT_HARDIRQS -if (!(desc->status &IRQ_DISABLED )) - desc->handler->enable (irq); -#else - desc->handler->end (irq); -#endif -} -#ifdef CONFIG_PROC_FS extern void register_irq_proc (unsigned int irq);extern void register_handler_proc (unsigned int irq,struct irqaction *action);
kernel/irq/manage.c +1 -1
@@ -442,7 +442,7 @@ static void do_hardirq(struct irq_desc ** The end-handler has to deal with interrupts which got * disabled while the handler was running: */ -end_irq (desc, irq); + desc->handler->end (irq); }spin_unlock_irq (&desc->lock);
On Thu, 2005-08-18 at 17:24 +0200, Thomas Gleixner wrote:
Oops, mailer madness.
tglx
kernel/irq/handle.c +2 -2
@@ -171,7 +171,7 @@ fastcall notrace unsigned int __do_IRQ(u*/ desc->handler->ack (irq); action_ret =handle_IRQ_event (irq, regs, desc->action); -end_irq (desc, irq); + desc->handler->end (irq);return 1 ; }
@@ -241,7 +241,7 @@ out:* The end-handler has to deal with interrupts which got * disabled while the handler was running: */ -end_irq (desc, irq); + desc->handler->end (irq); out_no_end:spin_unlock (&desc->lock);
kernel/irq/internals.h +0 -15
@@ -6,21 +6,6 @@ extern int noirqdebug;void recalculate_desc_flags (struct irq_desc *desc); -/* -* On PREEMPT_HARDIRQS, the ->ack handler masks interrupts, so that -* they can be redirected to an IRQ thread, if needed. So here we -* have to unmask the interrupt line, if needed: -*/ -static inline void end_irq (irq_desc_t *desc,unsigned int irq) -{ -#ifdef CONFIG_PREEMPT_HARDIRQS -if (!(desc->status &IRQ_DISABLED )) - desc->handler->enable (irq); -#else - desc->handler->end (irq); -#endif -} -#ifdef CONFIG_PROC_FS extern void register_irq_proc (unsigned int irq);extern void register_handler_proc (unsigned int irq,struct irqaction *action);
kernel/irq/manage.c +1 -1
@@ -442,7 +442,7 @@ static void do_hardirq(struct irq_desc ** The end-handler has to deal with interrupts which got * disabled while the handler was running: */ -end_irq (desc, irq); + desc->handler->end (irq); }spin_unlock_irq (&desc->lock);
Quoted 2 lines · Thomas Gleixner
finally found the deadlock. It was caused by IRQ flood, which was introduced by the
end_irq()changes.
Found another one to back out. It creaped in with the same patch.
It's slow and just conceals bad configured PICs and crappy demux handlers.
tglx
arch/ppc/syslib/open_pic.c +0 -4
@@ -816,10 +816,6 @@ static void openpic_set_sense(u_int irq, }#endif /* notused */ -#ifdef CONFIG_PREEMPT_RT -#define __SLOW_VERSION__ -#endif -/* No spinlocks, should not be necessary with the OpenPIC * (1 register = 1 interrupt and we have the desc lock). */
PATCH 1/1 fix DECNET_ROUTER=y compile
In reply to Ingo MolnarIt doesn't compile with CONFIG_DECNET_ROUTER=y:
<-- snip -->
...
CC net/decnet/dn_dev.onet/decnet/dn_dev.c: In function 'dn_forwarding_proc':net/decnet/dn_dev.c:335: error: 'struct dn_dev_parms' has no member named 'down' net/decnet/dn_dev.c:336: error: syntax error before 'do' net/decnet/dn_dev.c:338: error: 'struct dn_dev_parms' has no member named 'up' net/decnet/dn_dev.c:339: error: syntax error before 'do' net/decnet/dn_dev.c:339: warning: control reaches end of non-void function net/decnet/dn_dev.c: In function 'dn_forwarding_sysctl':net/decnet/dn_dev.c:374: error: 'struct dn_dev_parms' has no member named 'down' net/decnet/dn_dev.c:375: error: syntax error before 'do' net/decnet/dn_dev.c:377: error: 'struct dn_dev_parms' has no member named 'up' net/decnet/dn_dev.c:378: error: syntax error before 'do' net/decnet/dn_dev.c:378: warning: control reaches end of non-void function make[2]: *** [net/decnet/dn_dev.o] Error 1
<-- snip -->
net/decnet/dn_dev.c renamed from net/decnet/dn_dev.c.old +8 -8
@@ -332,11 +332,11 @@*/ tmp = dn_db->parms.forwarding; dn_db->parms.forwarding = old; -if (dn_db->parms.down) - dn_db->parms.down (dev); +if (dn_db->parms.dn_down) + dn_db->parms.dn_down (dev); dn_db->parms.forwarding = tmp; -if (dn_db->parms.up) - dn_db->parms.up (dev); +if (dn_db->parms.dn_up) + dn_db->parms.dn_up (dev); }return err;
@@ -371,11 +371,11 @@if (value >2 )return -EINVAL ; -if (dn_db->parms.down) - dn_db->parms.down (dev); +if (dn_db->parms.dn_down) + dn_db->parms.dn_down (dev); dn_db->parms.forwarding = value; -if (dn_db->parms.up) - dn_db->parms.up (dev); +if (dn_db->parms.dn_up) + dn_db->parms.dn_up (dev); }return 0 ;
Ingo Molnar
AppliedRe: [2.6.13-rc6-rt9 patch] fix DECNET_ROUTER=y compile
Quoted 1 line · Adrian Bunk
It doesn't compile with
CONFIG_DECNET_ROUTER=y:
thanks, applied.
Ingo
2.6.13-rc6-rt9: compile errors
In reply to Ingo MolnarI'm getting the following compile errors:
<-- snip -->
...
LD .tmp_vmlinux1drivers/built-in.o: In function `pi_init':
: multiple definition of `pi_init'
kernel/built-in.o:(.bss+0x80f0): first defined here
ld: Warning: size of symbol `pi_init' changed from 4 in kernel/built-in.o to 675 in drivers/built-in.o
ld: Warning: type of symbol pi_init' changed from 1 to 2 in drivers/built-in.o fs/built-in.o: In function jffs2_do_crccheck_inode':
: undefined reference to there_is_no_init_MUTEX_LOCKED_for_RT_semaphores' fs/built-in.o: In function jffs2_i_init_once':
super.c:(.text+0x1d1137): undefined reference to there_is_no_init_MUTEX_LOCKED_for_RT_semaphores' drivers/built-in.o: In function si_restart_short_timer':
ipmi_si_intf.c:(.text+0x21f395): undefined reference to __bad_spinlock_type' drivers/built-in.o: In function smi_timeout':
ipmi_si_intf.c:(.text+0x21f5ca): undefined reference to __bad_spinlock_type' ipmi_si_intf.c:(.text+0x21f5fa): undefined reference to __bad_spinlock_type' drivers/built-in.o: In function `carm_init_one':
sx8.c:(.text+0x28ebcd): undefined reference to there_is_no_init_MUTEX_LOCKED_for_RT_semaphores' drivers/built-in.o: In function plip_close':
plip.c:(.text+0x2bae71): undefined reference to there_is_no_init_MUTEX_LOCKED_for_RT_semaphores' drivers/built-in.o: In function sixpack_open':
6pack.c:(.text+0x47640c): undefined reference to there_is_no_init_MUTEX_LOCKED_for_RT_semaphores' drivers/built-in.o: In function mc32_probe1':
3c527.c:(.init.text+0x333d9): undefined reference to `there_is_no_init_MUTEX_LOCKED_for_RT_semaphores'
make: *** [.tmp_vmlinux1] Error 1
<-- snip -->
Note: pi_init is a global function in drivers/block/paride/paride.c .
cu
Adrian
Signature · 4 lines
"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon SeedRe: 2.6.13-rc6-rt9: compile errors
Quoted 11 lines · Adrian Bunk
I'm getting the following compile errors:
<-- snip -->
...
LD .tmp_vmlinux1drivers/built-in.o: In function `pi_init':
: multiple definition of `pi_init' kernel/built-in.o:(.bss+0x80f0): first defined hereNote:
pi_initis a global function indrivers/block/paride/paride.c.
thanks - fixed it in my tree.
Ingo
Quoted 20 lines · Ingo Molnar
i have released the 2.6.13-rc6-rt9 tree, which can be downloaded from the usual place:
http://redhat.com/~mingo/realtime-preempt/
it's a fixes-only release. Changes since 2.6.13-rc6-rt3:
- USB irq flags use cleanups (Alan Stern)
- RCU tasklist-lock fixes (Paul McKenney, Thomas Gleixner)
- HR-timers waitqueue splitup, better HRT latencies (Thomas Gleixner)
- latency tracer fixes, irq flags tracing cleanups (Steven Rostedt, me)
- NFSd BKL unlock fix (Steven Rostedt)
- stackfootprint-max-printer fix (Steven Rostedt)
Quoted 7 lines
-
stop_machinefix (Steven Rostedt)- lpptest fix (me)
- turned off
IOAPIC_POSTFLUSHwhenCONFIG_X86_IOAPIC_FAST. Now with Karsten's VIA fixes my testbox does not show PCI-POST weirnesses anymore. In case of IRQ problems please turn offIOAPIC_FAST. (me)
I'm still getting the same oops when rebooting. the same process (reboot) similar call trace (some addresses are slightly different but the functions are the same:
disable_IO_APIC+0x5a/0x90 (8) machine_restart+0x5/0x9 (28) sys_reboot+0x147/0x156 (4) netdev_run_todo+0xa4/0x209 (4)
etc.
Another interesting data point is that I did a SysRq+B right after the machine came up and got a different oops.
Signature · 4 lines
Charles D. (Chuck) Harding <[email protected]> Voice: 925-423-8879 Senior Computer Associate ICCD Fax: 925-423-6961 Lawrence Livermore National Laboratory Computation Directorate Livermore, CA USA http://www.llnl.gov GPG Public Key ID: B9EB6601
Steven Rostedt
reviewerDeadlock finally found!!!
I've been debugging this all week. And at 2:30 in the morning I finally found where it is. It really sucks when you need to debug on something that doesn't have a serial, and netconsole doesn't work that reliably.
This also explains why this only happened on my laptop. It is caused by the dependent_sleeper, which is used quite a bit when you have SCHED_HT turned on. Although I wouldn't be surprised if this deadlock exists elsewhere.
The dependent_sleeper (used by SCHED_HT) grabs all the run queue locks for the physical CPU. Then it calls trace_stop_sched_switched. So this is the calling chain.
dependent_sleeper
+==> grabs CPU0 rq and CPU1 rq lock (saying CPU 0 and 1 are on the
same physical CPU)
-> trace_stop_sched_switched
-> check_wakeup_timing
-> down_trylock(max_mutex)
-> rt_down_trylock
-> __down_trylock
+==> grabs trace_lockNow lets look at something at the same time that is unlocking.
rt_up
-> __up_mutex_nosavestate_inline
-> ___up_mutex_nosavestate
-> ____up_mutex
+==> grabs trace_lock
-> __up_mutex_waiter_nosavestate
-> wake_up_process
-> try_to_wake_up
+==> grabs rq lockHere we can see that there's a reverse order here and we have a deadlock. I actually witness this using my logger to show the traces. All I needed was the last few lines, so the console was fine here.
Ingo, can't you get rt.c to be more confusing. I mean it is too simple. We need to add a few more underscores here and there :-) Seriously, that rt.c is mind boggling. It was nice before, now it is just screaming for a cleanup (come now, do we really need the four underscores?). Same with latency.c.
Well, there's the deadlock, I'm too tired to figure out all the paths, and what the heck is going on. So I'll give you the honour of writing the patch. ;-)
Thanks,
-- Steve
Steven Rostedt
reviewerQuoted 5 lines · Steven Rostedt
Ingo, can't you get
rt.cto be more confusing. I mean it is too simple. We need to add a few more underscores here and there :-) Seriously, thatrt.cis mind boggling. It was nice before, now it is just screaming for a cleanup (come now, do we really need the four underscores?). Same withlatency.c.
Ingo,
Here's one example of cleaning up rt.c. I like an extra parameter instead of having two functions that are exactly the same except for one line. I'll probably submit more.
I haven't thought of a good way yet to solve the race condition with dependent sleeper. (Except by turning off CONFIG_WAKEUP_TIMING :-)
-- Steve
kernel/rt.c +9 -44
@@ -1331,8 +1331,7 @@FREE_WAITER (&waiter); } -static void __up_mutex_waiter_savestate(struct rt_mutex *lock __EIP_DECL__); -static void __up_mutex_waiter_nosavestate(struct rt_mutex *lock __EIP_DECL__); +static void __up_mutex_waiter(struct rt_mutex *lock, int save_state __EIP_DECL__);/* * release the lock:
@@ -1361,12 +1360,9 @@if (plist_empty (&lock->wait_list))check_pi_list_empty (lock,lock_owner (lock));#endif -if (unlikely (!plist_empty (&lock->wait_list))) { -if (save_state) - __up_mutex_waiter_savestate(lock __EIP__); -else - __up_mutex_waiter_nosavestate(lock __EIP__); - }else +if (unlikely (!plist_empty (&lock->wait_list))) + __up_mutex_waiter(lock, save_state __EIP__); +else lock->owner =NULL ;__raw_spin_unlock (&pi_lock);__raw_spin_unlock (&lock->wait_lock);
@@ -1759,7 +1755,7 @@ return __down_trylock(&rwsem->lock __CALLER0__); } -static void __up_mutex_waiter_nosavestate(struct rt_mutex *lock __EIP_DECL__) +static void __up_mutex_waiter(struct rt_mutex *lock, int save_state __EIP_DECL__) {struct thread_info *old_owner_ti, *new_owner_ti;struct task_struct *old_owner, *new_owner;
@@ -1790,43 +1786,12 @@ new_owner->pending_owner = lock; }#endif -wake_up_process (new_owner); +if (save_state) +wake_up_process_mutex (new_owner); +else +wake_up_process (new_owner); } -static void __up_mutex_waiter_savestate(struct rt_mutex *lock __EIP_DECL__) -{ -struct thread_info *old_owner_ti, *new_owner_ti; -struct task_struct *old_owner, *new_owner; -struct rt_mutex_waiter *w; -int prio; - - old_owner_ti =lock_owner (lock); - old_owner = old_owner_ti->task; - new_owner_ti = pick_new_owner(lock, old_owner_ti, 1 __EIP__); - new_owner = new_owner_ti->task; - -/* -* If the owner got priority-boosted then restore it -* to the previous priority (or to the next highest prio -* waiter's priority): -*/ - prio = old_owner->normal_prio; -if (unlikely (!plist_empty (&old_owner->pi_waiters))) { - w = plist_first_entry(&old_owner->pi_waiters, struct rt_mutex_waiter, pi_list); -if (w->ti->task->prio < prio) - prio = w->ti->task->prio; - } -if (unlikely (prio != old_owner->prio)) -pi_setprio (lock, old_owner, prio); -#ifdef CAPTURE_LOCK -if (lock != &kernel_sem.lock) { - new_owner->rt_flags |=RT_PENDOWNER ; - new_owner->pending_owner = lock; - } -#endif -wake_up_process_mutex (new_owner); -} -/* * Do owner check too: */
Steven Rostedt
reviewerQuoted 5 lines · Steven Rostedt
On Fri, 2005-08-19 at 02:39 -0400, Steven Rostedt wrote:
I haven't thought of a good way yet to solve the race condition with dependent sleeper. (Except by turning off
CONFIG_WAKEUP_TIMING:-)
OK, I found one simple solution. The problem stems from max_mutex being grabbed. Since this uses the RT locks, and since tracing shouldn't really care about PI and all that, I switched this to a compat_semaphore, but only if CONFIG_WAKEUP_TIMING is set. This seems to get rid of this race condition that I have.
I found more bugs, but for now this message is about this specific race.
-- Steve
kernel/latency.c +12 -0
@@ -102,7 +102,19 @@/* * Track maximum latencies and save the trace: */ +#ifdef CONFIG_WAKEUP_TIMING +/* +* The WAKEUP_TIMING has a race condition, since +* trace_stop_sched_switched might be called with run queue locks held +* which eventually calls down_trylock. +* But the RT version of down_trylock grabs a bunch of locks that +* are used by rt_up. rt_up can call wake_up_process which +* eventually grabs a run queue lock. +*/ +static __cacheline_aligned_in_smp COMPAT_DECLARE_MUTEX (max_mutex ); +#else static __cacheline_aligned_in_smp DECLARE_MUTEX (max_mutex ); +#endif /* * Sequence count - we record it when starting a measurement and * skip the latency if the sequence has changed - some other section
Quoted 7 lines · Steven Rostedt
Quoted 5 lines · Steven Rostedt
On Fri, 2005-08-19 at 02:39 -0400, Steven Rostedt wrote:
I haven't thought of a good way yet to solve the race condition with dependent sleeper. (Except by turning off
CONFIG_WAKEUP_TIMING:-)
Quoted 5 lines
OK, I found one simple solution. The problem stems from
max_mutexbeing grabbed. Since this uses the RT locks, and since tracing shouldn't really care about PI and all that, I switched this to acompat_semaphore, but only ifCONFIG_WAKEUP_TIMINGis set. This seems to get rid of this race condition that I have.
ok, i have applied your patch and have done a small tweak: i made it a compat semaphore unconditionally. There's no point in #ifdefing it on WAKEUP_TIMING.
Quoted 2 lines
I found more bugs, but for now this message is about this specific race.
ok.
Ingo
Quoted 8 lines · Steven Rostedt
Quoted 5 lines · Steven Rostedt
Ingo, can't you get
rt.cto be more confusing. I mean it is too simple. We need to add a few more underscores here and there :-) Seriously, thatrt.cis mind boggling. It was nice before, now it is just screaming for a cleanup (come now, do we really need the four underscores?). Same withlatency.c.
Quoted 5 lines
Ingo,
Here's one example of cleaning up
rt.c. I like an extra parameter instead of having two functions that are exactly the same except for one line. I'll probably submit more.
it was done like that deliberately, so that the fastpath doesnt include conditional code. (when all debugging options are disabled)
Ingo
Quoted 5 lines · Steven Rostedt
Ingo, can't you get
rt.cto be more confusing. I mean it is too simple. We need to add a few more underscores here and there :-) Seriously, thatrt.cis mind boggling. It was nice before, now it is just screaming for a cleanup (come now, do we really need the four underscores?). Same withlatency.c.
i agree that it's ugly, but some of that ugliness is to achieve the 7-instructions fail-through codepath for the common acquire (and release) codepath:
c03a5320 <__down_mutex>:
c03a5320: 89 c1 mov %eax,%ecx c03a5322: 8b 15 08 76 3a c0 mov 0xc03a7608,%edx c03a5328: 31 c0 xor %eax,%eax c03a532a: 0f b1 51 14 cmpxchg %edx,0x14(%ecx) c03a532e: 85 c0 test %eax,%eax c03a5330: 75 01 jne c03a5333 <__down_mutex+0x13> c03a5332: c3 ret
that's how much it takes to acquire an RT lock, and i worked hard to get there. As long as the fastpath is kept this tight, feel free to do cleanups. But i really want to avoid having to write mutex_down/up in assembly for 24 architectures ...
Ingo
Steven Rostedt
reviewerQuoted 12 lines · Ingo Molnar
Quoted 5 lines · Steven Rostedt
Ingo, can't you get
rt.cto be more confusing. I mean it is too simple. We need to add a few more underscores here and there :-) Seriously, thatrt.cis mind boggling. It was nice before, now it is just screaming for a cleanup (come now, do we really need the four underscores?). Same withlatency.c.i agree that it's ugly, but some of that ugliness is to achieve the 7-instructions fail-through codepath for the common acquire (and release) codepath:
Quoted 9 lines
c03a5320<__down_mutex>:c03a5320: 89 c1 mov %eax,%ecx c03a5322: 8b 15 08 76 3a c0 mov 0xc03a7608,%edx c03a5328: 31 c0 xor %eax,%eax c03a532a: 0f b1 51 14 cmpxchg %edx,0x14(%ecx) c03a532e: 85 c0 test %eax,%eax c03a5330: 75 01 jne c03a5333 <__down_mutex+0x13> c03a5332: c3 ret
Impressive!
Quoted 4 lines
that's how much it takes to acquire an RT lock, and i worked hard to get there. As long as the fastpath is kept this tight, feel free to do cleanups. But i really want to avoid having to write mutex_down/up in assembly for 24 architectures ...
Warning! I'm hacking hard to get rid of the global pi_lock, and I'm not worrying now about efficiency. I figure that if I can get it to work, then we can speed it up afterwards. Since it's complex enough keeping all the locks straight, I just want it to work without deadlocking.
Once I get it to work, I'll let you figure out how get it back down to 7-instructions :-)
-- Steve
Quoted 30 lines · Steven Rostedt
Quoted 12 lines · Ingo Molnar
Quoted 5 lines · Steven Rostedt
Ingo, can't you get
rt.cto be more confusing. I mean it is too simple. We need to add a few more underscores here and there :-) Seriously, thatrt.cis mind boggling. It was nice before, now it is just screaming for a cleanup (come now, do we really need the four underscores?). Same withlatency.c.i agree that it's ugly, but some of that ugliness is to achieve the 7-instructions fail-through codepath for the common acquire (and release) codepath:
Quoted 9 lines
c03a5320<__down_mutex>:c03a5320: 89 c1 mov %eax,%ecx c03a5322: 8b 15 08 76 3a c0 mov 0xc03a7608,%edx c03a5328: 31 c0 xor %eax,%eax c03a532a: 0f b1 51 14 cmpxchg %edx,0x14(%ecx) c03a532e: 85 c0 test %eax,%eax c03a5330: 75 01 jne c03a5333 <__down_mutex+0x13> c03a5332: c3 retImpressive!
Quoted 4 lines
that's how much it takes to acquire an RT lock, and i worked hard to get there. As long as the fastpath is kept this tight, feel free to do cleanups. But i really want to avoid having to write mutex_down/up in assembly for 24 architectures ...
Quoted 7 lines
Warning! I'm hacking hard to get rid of the global
pi_lock, and I'm not worrying now about efficiency. I figure that if I can get it to work, then we can speed it up afterwards. Since it's complex enough keeping all the locks straight, I just want it to work without deadlocking.Once I get it to work, I'll let you figure out how get it back down to 7-instructions :-)
yeah. It can always be done after the fact - the basics wont change. (Note that the above disassembly is for UP, on SMP the fastpath is longer and around 10-15 instructions.)
Ingo
Hi Ingo, Paul, others,
I'm trying to run a user-mode-linux guest under the RT kernel however the uml process never gets out of the calibrate delay loop. It seems as if the signal never gets through.
A non -rt host kernel does work (with a similar .config).
Could this be related to pauls task list changes?
Kind regards,
Signature · 1 line
Peter Zijlstra <[email protected]>
Quoted 6 lines · Peter Zijlstra
Hi Ingo, Paul, others,
I'm trying to run a user-mode-linux guest under the RT kernel however the uml process never gets out of the calibrate delay loop. It seems as if the signal never gets through.
one clarification: the guest kernel is a non -rt kernel, a modified 2.6.13-rc6 in my case.
Quoted 6 lines
A non -rt host kernel does work (with a similar .config).
Could this be related to pauls task list changes?
Kind regards,
Signature · 1 line
Peter Zijlstra <[email protected]>
Quoted 13 lines · Peter Zijlstra
Quoted 6 lines · Peter Zijlstra
Hi Ingo, Paul, others,
I'm trying to run a user-mode-linux guest under the RT kernel however the uml process never gets out of the calibrate delay loop. It seems as if the signal never gets through.
one clarification: the guest kernel is a non -rt kernel, a modified 2.6.13-rc6 in my case.
Quoted 3 lines
A non -rt host kernel does work (with a similar .config).
Could this be related to pauls task list changes?
Possibly. What signal? This is a signal to a single process, right?
Thanx, Paul
Quoted 8 lines · Paul E. McKenney
Quoted 7 lines · Peter Zijlstra
Quoted 6 lines · Peter Zijlstra
Hi Ingo, Paul, others,
I'm trying to run a user-mode-linux guest under the RT kernel however the uml process never gets out of the calibrate delay loop. It seems as if the signal never gets through.
Quoted 9 lines
Quoted 6 lines
one clarification: the guest kernel is a non -rt kernel, a modified 2.6.13-rc6 in my case.
Quoted 3 lines
A non -rt host kernel does work (with a similar .config).
Could this be related to pauls task list changes?
Possibly. What signal? This is a signal to a single process, right?
Jeff, could you help us out here?
What exactly does uml need to get out of the calibrate delay loop?
Kind regards,
Peter Zijlstra
Quoted 2 lines · Peter Zijlstra
Jeff, could you help us out here?
What exactly does uml need to get out of the calibrate delay loop?
Interrupts, it's not too demanding :-)
If it's not seeing VTALRM, then it will never leave the calibration loop.
Try stracing it and see what it's getting.
Jeff
Quoted 9 lines · Jeff Dike
Quoted 2 lines · Peter Zijlstra
Jeff, could you help us out here?
What exactly does uml need to get out of the calibrate delay loop?Interrupts, it's not too demanding :-)
If it's not seeing VTALRM, then it will never leave the calibration loop.
Try stracing it and see what it's getting.
Sorry for the late reply.
Yes, that does seem to be the problem.
Even with a current -rt (2.6.14-rc2-rt5) UML does not run. The issue is indeed (as jeff pointed out) that VTALRM is never send. The small test programm below illustrates this.
On a non-rt kernel it completed in 1 second.
On a -rt kernel it waits at infinitum.
Kind regards,
Peter Zijlstra
---------------------------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <signal.h>
volatile int quit = 0;
void sig_vtalrm(int signr, siginfo_t * si, void * arg)
{
if (signr == SIGVTALRM) quit = 1;
}int main()
{
struct itimerval ival = {{0,0}, {1, 0}};
struct sigaction sa;
sa.sa_sigaction = sig_vtalrm;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGVTALRM, &sa, NULL);
setitimer(ITIMER_VIRTUAL, &ival, NULL);
printf("wait\n");
while (!quit) ;
printf("done\n");
}Signature · 1 line
Peter Zijlstra <[email protected]>
Quoted 13 lines · Peter Zijlstra
Quoted 9 lines · Jeff Dike
Quoted 2 lines · Peter Zijlstra
Jeff, could you help us out here?
What exactly does uml need to get out of the calibrate delay loop?Interrupts, it's not too demanding :-)
If it's not seeing VTALRM, then it will never leave the calibration loop.
Try stracing it and see what it's getting.
Sorry for the late reply.
Quoted 8 lines
Yes, that does seem to be the problem.
Even with a current -rt (2.6.14-rc2-rt5) UML does not run. The issue is indeed (as jeff pointed out) that VTALRM is never send. The small test programm below illustrates this.
On a non-rt kernel it completed in 1 second.
On a -rt kernel it waits at infinitum.
Will play with it and see what I broke...
Thanx, Paul
Quoted 41 lines
Kind regards,
Peter Zijlstra
---------------------------
#include <
stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <signal.h>volatile int quit = 0;
void
sig_vtalrm(int signr, siginfo_t * si, void * arg){ if (signr == SIGVTALRM) quit = 1; }int
main(){ struct itimerval ival = {{0,0}, {1, 0}}; struct sigaction sa; sa.sa_sigaction = sig_vtalrm; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGVTALRM, &sa, NULL); setitimer(ITIMER_VIRTUAL, &ival, NULL); printf("wait\n"); while (!quit) ; printf("done\n"); }Signature · 1 line
Peter Zijlstra <[email protected]>
Quoted 8 lines · Paul E. McKenney
Quoted 6 lines
Even with a current -rt (2.6.14-rc2-rt5) UML does not run. The issue is indeed (as jeff pointed out) that VTALRM is never send. The small test programm below illustrates this.
On a non-rt kernel it completed in 1 second.
On a -rt kernel it waits at infinitum.Will play with it and see what I broke...
Paul,
you are not the culprit :)
The run_posix_cpu_timers(p) call is #ifdef'd out with PREEMPT_RT.
Thats a hard to fix issue.
It can not be run from hardirq context, as it takes a lot of locks (especially our favorites: tasklist_lock and sighand->siglock). :(
Maybe another playground for rcu, but it might also be solved by some other mechanism for accounting and delayed execution in the PREEMPT_RT case.
tglx
Quoted 5 lines · Thomas Gleixner
Quoted 4 lines · Paul E. McKenney
Quoted 4 lines
Even with a current -rt (2.6.14-rc2-rt5) UML does not run. The issue is indeed (as jeff pointed out) that VTALRM is never send. The small test programm below illustrates this.
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
On a non-rt kernel it completed in 1 second.
On a -rt kernel it waits at infinitum.Will play with it and see what I broke...
Paul,
you are not the culprit :)
Woo-hoo!!! Exonerated!!! This time, anyway... ;-)
Quoted 10 lines
The
run_posix_cpu_timers(p)call is #ifdef'd out withPREEMPT_RT.Thats a hard to fix issue.
It can not be run from hardirq context, as it takes a lot of locks (especially our favorites:
tasklist_lockandsighand->siglock). :(Maybe another playground for rcu, but it might also be solved by some other mechanism for accounting and delayed execution in the
PREEMPT_RTcase.
Certainly check_thread_timers() and check_process_timers() are playing with a number of task_struct fields, so it is not immediately clear to me how to safely replace tasklist_lock with RCU, at least not with a simple and small patch.
What did you have in mind for delayed execution?
Thanx, Paul
Quoted 3 lines · Paul E. McKenney
Quoted 1 line
you are not the culprit :)
Woo-hoo!!! Exonerated!!! This time, anyway... ;-)
My pleasure :)
Quoted 7 lines
Quoted 6 lines
It can not be run from hardirq context, as it takes a lot of locks (especially our favorites:
tasklist_lockandsighand->siglock). :(Maybe another playground for rcu, but it might also be solved by some other mechanism for accounting and delayed execution in the
PREEMPT_RTcase.
Quoted 6 lines
Certainly
check_thread_timers()andcheck_process_timers()are playing with a number oftask_structfields, so it is not immediately clear to me how to safely replacetasklist_lockwith RCU, at least not with a simple and small patch.What did you have in mind for delayed execution?
Do only the time check in hard irq context and defer the lock protected operations to a softirq context. Have to look deeper at the details though.
tglx
Quoted 4 lines · Ingo Molnar
i have released the 2.6.13-rc6-rt9 tree, which can be downloaded from the usual place:
I'm looking into getting HRT and RT booting on a SUMMIT NUMA machine (cyclone timer), but after s/error/warning/ in arch/i386/timers/timer.c for the HRT cyclone ifdef, I still get the following link error:
LD .tmp_vmlinux1
net/built-in.o(.init.text+0xdae): In function `sock_ioctl':net/socket.c:868: undefined reference to `__you_cannot_kmalloc_that_much'
make: *** [.tmp_vmlinux1] Error 1
I was expecting to be able to build the kernel, and have it crash on boot (due to unsynched TSCs I'm guessing) and then start debugging/devel from there. But the the rt9 patch won't build (HRT standalone for 2.6.10 does build). Anyone else seeing this?
Quoted 36 lines
it's a fixes-only release. Changes since 2.6.13-rc6-rt3:
- USB irq flags use cleanups (Alan Stern)
- RCU tasklist-lock fixes (Paul McKenney, Thomas Gleixner)
- HR-timers waitqueue splitup, better HRT latencies (Thomas Gleixner)
- latency tracer fixes, irq flags tracing cleanups (Steven Rostedt, me)
- NFSd BKL unlock fix (Steven Rostedt)
- stackfootprint-max-printer fix (Steven Rostedt)
-
stop_machinefix (Steven Rostedt)- lpptest fix (me)
- turned off
IOAPIC_POSTFLUSHwhenCONFIG_X86_IOAPIC_FAST. Now with Karsten's VIA fixes my testbox does not show PCI-POST weirnesses anymore. In case of IRQ problems please turn offIOAPIC_FAST. (me)to build a 2.6.13-rc6-rt9 tree, the following patches should be applied:
http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.12.tar.bz2 http://kernel.org/pub/linux/kernel/v2.6/testing/patch-2.6.13-rc6.bz2 http://redhat.com/~mingo/realtime-preempt/patch-2.6.13-rc6-rt9 Ingo-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Signature · 5 lines
Darren Hart IBM Linux Technology Center Linux Kernel Team Phone: 503 578 3185 T/L: 775 3185
Quoted 11 lines · Darren Hart
Quoted 5 lines · Ingo Molnar
i have released the 2.6.13-rc6-rt9 tree, which can be downloaded from the usual place:
I'm looking into getting HRT and RT booting on a SUMMIT NUMA machine (cyclone timer), but after s/error/warning/ in
arch/i386/timers/timer.cfor the HRT cyclone ifdef, I still get the following link error:
should be fixed in 2.6.13-rc6-rt12 and later patches.
Ingo
Quoted 4 lines · Ingo Molnar
i have released the 2.6.13-rc6-rt9 tree, which can be downloaded from the usual place:
I was trying to use another HRT clock source and couldn't get menuconfig to let me select acpi-pm-timer, turns out it has been disabled in arch/i386/Kconfig, but the description is still in the help...
# config HIGH_RES_TIMER_ACPI_PM # bool "ACPI-pm-timer"
Is the pm timer incompatible with the RT portion of this patch?
Thanks,
--Darren
Quoted 36 lines
it's a fixes-only release. Changes since 2.6.13-rc6-rt3:
- USB irq flags use cleanups (Alan Stern)
- RCU tasklist-lock fixes (Paul McKenney, Thomas Gleixner)
- HR-timers waitqueue splitup, better HRT latencies (Thomas Gleixner)
- latency tracer fixes, irq flags tracing cleanups (Steven Rostedt, me)
- NFSd BKL unlock fix (Steven Rostedt)
- stackfootprint-max-printer fix (Steven Rostedt)
-
stop_machinefix (Steven Rostedt)- lpptest fix (me)
- turned off
IOAPIC_POSTFLUSHwhenCONFIG_X86_IOAPIC_FAST. Now with Karsten's VIA fixes my testbox does not show PCI-POST weirnesses anymore. In case of IRQ problems please turn offIOAPIC_FAST. (me)to build a 2.6.13-rc6-rt9 tree, the following patches should be applied:
http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.12.tar.bz2 http://kernel.org/pub/linux/kernel/v2.6/testing/patch-2.6.13-rc6.bz2 http://redhat.com/~mingo/realtime-preempt/patch-2.6.13-rc6-rt9 Ingo-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Signature · 5 lines
Darren Hart IBM Linux Technology Center Linux Kernel Team Phone: 503 578 3185 T/L: 775 3185
Quoted 9 lines · Darren Hart
I was trying to use another HRT clock source and couldn't get menuconfig to let me select acpi-pm-timer, turns out it has been disabled in
arch/i386/Kconfig, but the description is still in the help...# config HIGH_RES_TIMER_ACPI_PM # bool "ACPI-pm-timer"Is the pm timer incompatible with the RT portion of this patch?
The only timesource I came around to fixup is TSC in combination with PIT or preferred Local APIC. Add "lapic" to your kernel command line for UP boxen. Therefor it is disabled for now.
Quoted 3 lines
I'm looking into getting HRT and RT booting on a SUMMIT NUMA machine (cyclone timer), but after s/error/warning/ in
arch/i386/timers/timer.cfor the HRT cyclone ifdef, I still get the following link error:
It should be simple to fix this. Just not right now. I have no such box and restricted time resources. Can you test a patch when I find a slot? But of course you are heartely invited to fix it yourself :)
tglx
Quoted 16 lines · Thomas Gleixner
Quoted 7 lines · Darren Hart
I was trying to use another HRT clock source and couldn't get menuconfig to let me select acpi-pm-timer, turns out it has been disabled in
arch/i386/Kconfig, but the description is still in the help...# config HIGH_RES_TIMER_ACPI_PM # bool "ACPI-pm-timer"Is the pm timer incompatible with the RT portion of this patch?
The only timesource I came around to fixup is TSC in combination with PIT or preferred Local APIC. Add "lapic" to your kernel command line for UP boxen. Therefor it is disabled for now.
Quoted 5 lines
Quoted 1 line
I'm looking into getting HRT and RT booting on a SUMMIT NUMA machine (cyclone timer), but after s/error/warning/ in
arch/i386/timers/timer.cfor the HRT cyclone ifdef, I still get the following link error:It should be simple to fix this. Just not right now. I have no such box and restricted time resources. Can you test a patch when I find a slot?
Absolutely.
Quoted 1 line
But of course you are heartely invited to fix it yourself :)
As always :-)
Quoted 2 lines
tglx
Thanks for the response, I wanted to hear your take on this rather than making any assumptions as to the state of the patch.
Quoted 3 lines
Signature · 5 lines
Darren Hart IBM Linux Technology Center Linux Kernel Team Phone: 503 578 3185 T/L: 775 3185
PATCH 1/1 PI aware dynamic priority adjustment
In reply to Ingo MolnarHi all,
Quoted 2 lines · Ingo Molnar
i have released the 2.6.13-rc6-rt9 tree, which can be downloaded from the usual place:
I reworked the code for dynamically setting the priority of the hrtimer softirq to be aware of PI.
The current function "mutex_chprio()" in -rt9 is equivivalent to a static priority assigment of the hrtimer softirq. The new PI aware function resolves this nicely and the latency improvements are impressive (factor 2-3).
I stumbled over "//#define MUTEX_IRQS_OFF" in the first attempt. My assumption that all code protected by pi_lock (which is a raw lock) is irq save turned out to be wrong. I missed that commented define :( I guess it was introduced during the "IRQ latency contest" to squeeze out the last nsecs :)
Switching it back on is not really influencing system performance in a measurable way, but it allows to use the pi aware boosting function in irq context.
Quite contrary it makes the system more snappy and the overall test latencies go down.
Ingo ????
I assume you run with tracing enabled all the time, which conceals this regression.
This is not only a demand for HRT, I'm aware of a _real world_ application which requires such functionality depending on the status of the device. It runs on a low performance machine so avoiding task switches is really appreciated.
--------------------------------------------
Find attached my current config and a simple test program for cyclic scheduling. Read the top source comment what you need and where to get it.
Please use the -n option for now until we have sorted out following problems:
1. tasklist_lock contention
AFAICT tasklist_lock is the longest held lock in the kernel aside BKL, but this problem seems to be solved.
send_sigqueue is called from posix_timer_fn() and acquires tasklist_lock, which makes no sense to me.
send_sigqueue()s (l)onl(e)y user is the posix_timer function (posix_timer_fn(), calling posix_timer_event()).
Each posix timer blocks the task from vanishing away by get_task_struct(), which is protected by the held tasklist_lock.
The task can neither go away nor the signal handler can change until put_task_struct() is called inside release_posix_timer(), which removes any chance to do an invalid access to either task or sighand because the relevant timer is deleted before the call to put_task_struct(). Also this call is protected by tasklist_lock().
If I understand the code correctly then the tasklist_lock acquirement in send_sigqueue() is superfluous. If not then the "(un)register action" of put/get_task_struct() is just hot air action. AFAICS from kernel history this interface was introduced to provide lock free access to certain parts of the signaling code where the caller holds a reference to the task structure instead of running through the PITA of find_task_by_pid()
- of course with tasklist_lock held - for every signal to deliver.
I ran already extensive tests on a kernel with the lock acquirement removed without any problems - as expected by my shortsight :)
Can the experts please shed some light on me ?
Oleg, Paul, Roland ??? (Alphabetic order :)
If I'm not completely wrong, then this mechanism should be generalized to allow other users than posixtimers a simple un/registering of this protection. I know a couple of things where this would be useful. I'd be happy to write up the relevant patch for the general interface.
If I missed something important, feel free to call me an (over-worked) idiot :)
2. Drift of cyclic timers (armed by set_timer()):
Due to rounding errors and the drift adjustment code, the fixed increment which is precalculated when the timer is set up and added on rearm, I see creeping deviation from the timeline.
I have a patch lined up to base the rearm on human (nsac) units, so this effect will go away. But this is waste of time until (1.) is not solved.
George ???
Cheers,
tglx
-----------------------------------
Some numbers:
Test scenario:
PIII 666MHZ 128MB
Kernel command line: root=/dev/hda1 ro console=ttyS0,115200 lapic nmi_watchdog=2
Using lapic gives definitely better results than using the solely PIT based version. Make sure to add it to your command line, if you have a x86 box. PPC is fine without.
Load:
ssh1# while true; do hackbench 20; done
ssh2# while true; do find -type f | xargs grep kernel; done
(Over a large tree so caching is not relevant. The hd led is almost permanent on)
ping -f to the test box
All I(nterval)/Min/Act/Max values in usecs.
test1:/home/tglx/cyclictest# ./cyclictest -p 80 -n -i 1100 293.12 276.22 198.22 88/202 12270 <---- output from /proc/loadavg
T: 0 ( 5407) P:80 I: 1100 C: 2047066 Min: 7 Act: 15 Max: 59
test1:/home/tglx/cyclictest# ./cyclictest -p 80 -n -t 2 -d 10 296.17 275.21 193.82 52/202 22270
T: 0 ( 5407) P:80 I: 1000 C: 1047066 Min: 7 Act: 15 Max: 60
T: 1 ( 5408) P:79 I: 1010 C: 1036659 Min: 7 Act: 11 Max: 79
test1:/home/tglx/cyclictest# ./cyclictest -p 80 -n -t 5 130.31 124.17 148.68 3/525 19070
T: 0 ( 5473) P:80 I: 1000 C: 2631537 Min: 7 Act: 18 Max: 73
T: 1 ( 5474) P:79 I: 1500 C: 1754358 Min: 7 Act: 15 Max: 70
T: 2 ( 5475) P:78 I: 2000 C: 1315769 Min: 6 Act: 13 Max: 70
T: 3 ( 5476) P:77 I: 2500 C: 1052615 Min: 7 Act: 12 Max: 68
T: 4 ( 5477) P:76 I: 3000 C: 877179 Min: 6 Act: 10 Max: 66
test1:/home/tglx/cyclictest# ./cyclictest -p 80 -n -t 5 -i 800 -d 240 177.44 130.70 129.67 15/176 7217
T: 0 (21198) P:80 I: 800 C: 1578221 Min: 7 Act: 13 Max: 82
T: 1 (21199) P:79 I: 1040 C: 1214016 Min: 7 Act: 12 Max: 84
T: 2 (21200) P:78 I: 1280 C: 986388 Min: 7 Act: 13 Max: 60
T: 3 (21201) P:77 I: 1520 C: 830643 Min: 7 Act: 14 Max: 71
T: 4 (21202) P:76 I: 1760 C: 717373 Min: 7 Act: 13 Max: 66
test1:/home/tglx/cyclictest# ./cyclictest -p 80 -n -t 5 -i 666 -d 33 79.75 106.97 106.85 43/869 30355
T: 0 (25687) P:80 I: 666 C: 9329552 Min: 6 Act: 9 Max: 79
T: 1 (25688) P:79 I: 699 C: 8889101 Min: 6 Act: 12 Max: 80
T: 2 (25689) P:78 I: 732 C: 8488363 Min: 6 Act: 10 Max: 87
T: 3 (25690) P:77 I: 765 C: 8122198 Min: 6 Act: 12 Max: 83
T: 4 (25692) P:76 I: 798 C: 7786318 Min: 6 Act: 10 Max: 94
-----------------------------------
include/linux/sched.h +1 -1
@@ -1134,7 +1134,7 @@ extern int idle_cpu(int cpu);extern int sched_setscheduler (struct task_struct *,int ,struct sched_param *);extern task_t *idle_task (int cpu);extern void mutex_setprio (task_t *p,int prio); -extern void mutex_chprio (task_t *p,int prio); +extern void pi_changeprio (task_t *p,int prio);extern int normal_prio (task_t *p);void yield (void );
kernel/rt.c +46 -16
88 lines not on this page · raw message
kernel/sched.c +0 -52
58 lines not on this page · raw message
kernel/softirq.c +1 -1
@@ -314,7 +314,7 @@ void raise_softirq_prio(unsigned long nrif (prio > (MAX_RT_PRIO -1 )) prio =MAX_RT_PRIO -1 ; -mutex_chprio (tsk, prio); +pi_changeprio (tsk, prio); wake_up_process(tsk); }#endif
kernel/timer.c +1 -1
@@ -1731,7 +1731,7 @@ static inline void recalc_priority(tvec_if (prio == hrbase->hr_prio)return ; hrbase->hr_prio = prio; -mutex_chprio (current, prio); +pi_changeprio (current, prio);spin_unlock_irq (&hrbase->t_base.lock);cond_resched ();spin_lock_irq (&hrbase->t_base.lock);
Re: [PATCH 2.6.13-rc6-rt9] PI aware dynamic priority adjustment
Thomas Gleixner wrote:
~
Quoted 11 lines
2. Drift of cyclic timers (armed by
set_timer()):Due to rounding errors and the drift adjustment code, the fixed increment which is precalculated when the timer is set up and added on rearm, I see creeping deviation from the timeline.
I have a patch lined up to base the rearm on human (nsac) units, so this effect will go away. But this is waste of time until (1.) is not solved.
George ???
Could I (we) see what you have in mind?
Quoted 1 line
Signature · 2 lines
George Anzinger [email protected] HRT (High-res-timers): http://sourceforge.net/projects/high-res-timers/
Re: [PATCH 2.6.13-rc6-rt9] PI aware dynamic priority adjustment
George,
Quoted 6 lines · George Anzinger
Quoted 6 lines
2. Drift of cyclic timers (armed by
set_timer()):Due to rounding errors and the drift adjustment code, the fixed increment which is precalculated when the timer is set up and added on rearm, I see creeping deviation from the timeline.
Quoted 6 lines
Quoted 4 lines
I have a patch lined up to base the rearm on human (nsac) units, so this effect will go away. But this is waste of time until (1.) is not solved.
George ???
Could I (we) see what you have in mind?
Nothing which applies clean at the moment and I have no access to the box where the patch floats around.
It's simply explained.
Current code:
set_timer()
calc interval->jiffies / interval->arch_cycles; based on it.interval
rearm()
timer->expires += interval->jiffies; timer->arch_cycle_expires += interval->arch_cycles; normalize(timer);
Patched code:
set_timer()
timer.interval = it.interval; timer.next_expire = it.value; both stored as timespec
rearm()
next_expire += interval; calc timer->expires/arch_cycle_expires;
So on each rearm we eliminate the rounding errors and take the drift adjustment into account.
It adds some calculation overhead to each rearm, but ....
tglx
Re: [PATCH 2.6.13-rc6-rt9] PI aware dynamic priority adjustment
Quoted 41 lines · Thomas Gleixner
George,
Quoted 6 lines · George Anzinger
Quoted 6 lines
2. Drift of cyclic timers (armed by
set_timer()):Due to rounding errors and the drift adjustment code, the fixed increment which is precalculated when the timer is set up and added on rearm, I see creeping deviation from the timeline.
Quoted 6 lines
Quoted 4 lines
I have a patch lined up to base the rearm on human (nsac) units, so this effect will go away. But this is waste of time until (1.) is not solved.
George ???
Could I (we) see what you have in mind?
Nothing which applies clean at the moment and I have no access to the box where the patch floats around.
It's simply explained.
Current code:
set_timer()calc interval->jiffies / interval->arch_cycles; based on it.interval
rearm()timer->expires += interval->jiffies; timer->arch_cycle_expires += interval->arch_cycles; normalize(timer);Patched code:
set_timer()timer.interval = it.interval; timer.next_expire = it.value; both stored as timespec
Quoted 9 lines
rearm()next_expire += interval; calc timer->expires/arch_cycle_expires;So on each rearm we eliminate the rounding errors and take the drift adjustment into account.
It adds some calculation overhead to each rearm, but ....
I think the standard was written to eliminate the need for this. The notion is that we have a resolution which we use in the calculations so while there may be drift WRT his request, there should be no drift WRT the requested value rounded up to the next resolution.
Still, if we can't keep that resolution in arch_cycles...
On another issue along this line, I have been thinking of changing the x86 TSC arch cycle size to 1ns. (NOT the resolution, the units for the arch cycle.) The reason to do this is to correctly track changes in cpu frequency as it is today, we would need to track down and update all pending HR timers when ever the frequency changed. By using a common unit all we need to do is change the conversion constants (well I guess they would not be constants any more :). I REALLY don't want to do this as it does add conversion overhead, but I can not think of another clean way to track TSC frequency changes.
Signature · 2 lines
George Anzinger [email protected] HRT (High-res-timers): http://sourceforge.net/projects/high-res-timers/
Re: [PATCH 2.6.13-rc6-rt9] PI aware dynamic priority adjustment
Quoted 9 lines
On another issue along this line, I have been thinking of changing the x86 TSC arch cycle size to 1ns. (NOT the resolution, the units for the arch cycle.) The reason to do this is to correctly track changes in cpu frequency as it is today, we would need to track down and update all pending HR timers when ever the frequency changed. By using a common unit all we need to do is change the conversion constants (well I guess they would not be constants any more :). I REALLY don't want to do this as it does add conversion overhead, but I can not think of another clean way to track TSC frequency changes.
sched_clock does this conversion at sampling time, too.
Re: [PATCH 2.6.13-rc6-rt9] PI aware dynamic priority adjustment
In reply to Thomas GleixnerQuoted 7 lines · Thomas Gleixner
send_sigqueueis called fromposix_timer_fn()and acquirestasklist_lock, which makes no sense to me.send_sigqueue()s (l)onl(e)y user is the
posix_timerfunction (posix_timer_fn(), callingposix_timer_event()).
Quoted 8 lines
Each posix timer blocks the task from vanishing away by
get_task_struct(), which is protected by the heldtasklist_lock.The task can neither go away nor the signal handler can change until
put_task_struct()is called insiderelease_posix_timer(), which removes any chance to do an invalid access to either task or sighand because the relevant timer is deleted before the call toput_task_struct(). Also this call is protected bytasklist_lock().
Yes, the task_struct can't go away, but if process exited this task_struct is just chunk of garbage. I think the intent was to protect against this case.
However, I agree with you, locking the tasklist_lock can't help, and the code is wrong.
posix_timer_event() first checks that the thread (SIGEV_THREAD_ID case) does not have PF_EXITING flag, then it calls send_sigqueue() which locks task list. But if the thread exits in between the kernel will oops.
posix_timer_event() runs under k_itimer.it_lock, but this does not help if that thread was not the only one in thread group, in this case we don't call exit_itimers().
The comment is wrong too. ->sighand can't change, we are clearing posix timer on exec, and tasklist can't prevent ->sighand from going away..
Ingo, Roland, George, am I wrong?
Oleg.
Re: [PATCH 2.6.13-rc6-rt9] PI aware dynamic priority adjustment
Quoted 8 lines · Oleg Nesterov
posix_timer_event()first checks that the thread (SIGEV_THREAD_IDcase) does not havePF_EXITINGflag, then it callssend_sigqueue()which locks task list. But if the thread exits in between the kernel will oops.
posix_timer_event()runs under k_itimer.it_lock, but this does not help if that thread was not the only one in thread group, in this case we don't callexit_itimers().
I added exit_notify_itimers() for that case. It is synchronized vs. posix_timer_event() via the timer lock and therefor protects against the race described above.
It solves the problem for the only user of send_sigqueue for now, but I think we should have a more general interface to such functionality to allow simple usage.
tglx
include/linux/sched.h +1 -0
@@ -1051,6 +1051,7 @@ extern void __exit_signal(struct task_stextern void exit_sighand (struct task_struct *);extern void __exit_sighand (struct task_struct *);extern void exit_itimers (struct signal_struct *); +extern void exit_notify_itimers (struct signal_struct *); extern NORET_TYPE void do_group_exit(int);
kernel/posix-timers.c +27 -0
@@ -1169,6 +1169,33 @@ void exit_itimers(struct signal_struct * }/* +* This is called by __exit_signal, when there are still references to +* the shared signal_struct +*/ +void exit_notify_itimers (struct signal_struct *sig) +{ +struct k_itimer *timer; +struct list_head *tmp; +unsigned long flags; + +list_for_each (tmp, &sig->posix_timers) { + + timer = list_entry(tmp, struct k_itimer, list); + +/* Protect against posix_timer_fn */ +spin_lock_irqsave (&timer->it_lock, flags); +if (timer->it_process == current) { + +if (timer->it_sigev_notify == (SIGEV_SIGNAL |SIGEV_THREAD_ID )) + timer->it_sigev_notify =SIGEV_SIGNAL ; + + timer->it_process = timer->it_process->group_leader; + } +spin_lock_irqrestore (&timer->it_lock, flags); + } +} + +/* * And now for the "clock" calls * * These functions are called both from timer functions (with the timer
kernel/signal.c +5 -6
@@ -390,6 +390,7 @@ void __exit_signal(struct task_struct *t sig->nvcsw += tsk->nvcsw; sig->nivcsw += tsk->nivcsw; sig->sched_time += tsk->sched_time; +exit_notify_itimers (sig);spin_unlock (&sighand->siglock); sig =NULL ;/* Marker for below. */ }
@@ -1381,13 +1382,12 @@ send_sigqueue(int sig, struct sigqueue *int ret =0 ;/* -* We need the tasklist lock even for the specific -* thread case (when we don't need to follow the group -* lists) in order to avoid races with "p->sighand" -* going away or changing from under us. +* No need to hold tasklist lock here. +* posix_timer_event() is synchronized via +* exit_itimers() and exit_notify_itimers() to +* be protected against p->sighand == NULL */ BUG_ON (!(q->flags &SIGQUEUE_PREALLOC )); -read_lock (&tasklist_lock);spin_lock_irqsave (&p->sighand->siglock, flags);if (unlikely (!list_empty (&q->list))) {
@@ -1414,7 +1414,6 @@ send_sigqueue(int sig, struct sigqueue * out:spin_unlock_irqrestore (&p->sighand->siglock, flags); -read_unlock (&tasklist_lock);return (ret); }
Re: [PATCH 2.6.13-rc6-rt9] PI aware dynamic priority adjustment
Quoted 47 lines · Thomas Gleixner
Quoted 8 lines · Oleg Nesterov
posix_timer_event()first checks that the thread (SIGEV_THREAD_IDcase) does not havePF_EXITINGflag, then it callssend_sigqueue()which locks task list. But if the thread exits in between the kernel will oops.
posix_timer_event()runs under k_itimer.it_lock, but this does not help if that thread was not the only one in thread group, in this case we don't callexit_itimers().I added
exit_notify_itimers()for that case. It is synchronized vs.posix_timer_event()via the timer lock and therefor protects against the race described above.It solves the problem for the only user of
send_sigqueuefor now, but I think we should have a more general interface to such functionality to allow simple usage.tglx
Signed-off-by Thomas Gleixner <[email protected]>diff -uprN --exclude-from=/usr/local/bin/diffit.exclude
linux-2.6.13-rc6/include/linux/sched.hlinux-2.6.13-rc6.work/include/linux/sched.hinclude/linux/sched.h 2005-08-20 17:43:36.000000000 +0200 renamed from include/linux/sched.h 2005-08-13 12:25:56.000000000 +0200 +1
-0@@ -1051,6 +1051,7 @@ extern void __exit_signal(struct task_st extern void exit_sighand(struct task_struct *); extern void __exit_sighand(struct task_struct *); extern void exit_itimers(struct signal_struct *); +extern void exit_notify_itimers(struct signal_struct *); extern NORET_TYPE void do_group_exit(int);diff -uprN --exclude-from=/usr/local/bin/diffit.exclude
linux-2.6.13-rc6/kernel/posix-timers.clinux-2.6.13-rc6.work/kernel/posix-timers.ckernel/posix-timers.c 2005-08-20 17:43:36.000000000 +0200 renamed from kernel/posix-timers.c 2005-08-13 12:25:58.000000000 +0200 +5
-0@@ -1169,6 +1169,33 @@ void exit_itimers(struct signal_struct * } /* + * This is called by __exit_signal, when there are still references to + * the shared signal_struct + */ +void exit_notify_itimers(struct signal_struct *sig) +{
kernel/posix-timers.c 2005-08-20 17:43:36.000000000 +0200 void exit_itimers(struct signal_struct * · line 1186
Quoted 10 lines
kernel/posix-timers.c 2005-08-20 17:43:36.000000000 +0200 renamed from kernel/posix-timers.c 2005-08-13 12:25:58.000000000 +0200 +10
-0+ struct k_itimer *timer; + struct list_head *tmp; + unsigned long flags; + + list_for_each(tmp, &sig->posix_timers) { + + timer = list_entry(tmp, struct k_itimer, list); + + /* Protect against posix_timer_fn */ + spin_lock_irqsave(&timer->it_lock, flags);
I think this is deadlockable. We already (release_task) hold tasklist_lock here. What if this timer has no SIGEV_THREAD_ID ?
posix_timer_fn locks timer->it_lock first, then locks tasklist_lock in send_group_sigqueue().
Also, sys_timer_delete() locks ->it_lock, then ->sighand.lock.
I think the better fix would be re-check ->sighand in send_sigqueue, like Paul's patches do.
Oleg.
Re: [PATCH 2.6.13-rc6-rt9] PI aware dynamic priority adjustment
In reply to Thomas GleixnerQuoted 9 lines · Thomas Gleixner
Quoted 4 lines · Oleg Nesterov
posix_timer_event()first checks that the thread (SIGEV_THREAD_IDcase) does not havePF_EXITINGflag, then it callssend_sigqueue()which locks task list. But if the thread exits in between the kernel will oops.
Quoted 8 lines
Quoted 3 lines
posix_timer_event()runs under k_itimer.it_lock, but this does not help if that thread was not the only one in thread group, in this case we don't callexit_itimers().I added
exit_notify_itimers()for that case. It is synchronized vs.posix_timer_event()via the timer lock and therefor protects against the race described above.
It seems to me that exit (or exec) calling the timer release code covered this. I haven't gone through the exact sequence being discussed, however. In any case, I don't think we should send the signal to the group leader instead, but rather should release the timer and cancel any pending signal. AFAIKT there is no reason the group leader can not exit prior to other threads, but I may have missed this...
George
Quoted 103 lines
It solves the problem for the only user of
send_sigqueuefor now, but I think we should have a more general interface to such functionality to allow simple usage.tglx
Signed-off-by Thomas Gleixner <[email protected]>diff -uprN --exclude-from=/usr/local/bin/diffit.exclude
linux-2.6.13-rc6/include/linux/sched.hlinux-2.6.13-rc6.work/include/linux/sched.hinclude/linux/sched.h +1
-0@@ -1051,6 +1051,7 @@ extern void __exit_signal(struct task_stextern void exit_sighand (struct task_struct *);extern void __exit_sighand (struct task_struct *);extern void exit_itimers (struct signal_struct *); +extern void exit_notify_itimers (struct signal_struct *); extern NORET_TYPE void do_group_exit(int);diff -uprN --exclude-from=/usr/local/bin/diffit.exclude
linux-2.6.13-rc6/kernel/posix-timers.clinux-2.6.13-rc6.work/kernel/posix-timers.ckernel/posix-timers.c +27
-0@@ -1169,6 +1169,33 @@ void exit_itimers(struct signal_struct * }/* +* This is called by __exit_signal, when there are still references to +* the shared signal_struct +*/ +void exit_notify_itimers (struct signal_struct *sig) +{ +struct k_itimer *timer; +struct list_head *tmp; +unsigned long flags; + +list_for_each (tmp, &sig->posix_timers) { + + timer = list_entry(tmp, struct k_itimer, list); + +/* Protect against posix_timer_fn */ +spin_lock_irqsave (&timer->it_lock, flags); +if (timer->it_process == current) { + +if (timer->it_sigev_notify == (SIGEV_SIGNAL |SIGEV_THREAD_ID )) + timer->it_sigev_notify =SIGEV_SIGNAL ; + + timer->it_process = timer->it_process->group_leader; + } +spin_lock_irqrestore (&timer->it_lock, flags); + } +} + +/* * And now for the "clock" calls * * These functions are called both from timer functions (with the timer diff -uprN --exclude-from=/usr/local/bin/diffit.exclude
linux-2.6.13-rc6/kernel/signal.clinux-2.6.13-rc6.work/kernel/signal.ckernel/signal.c +5
-7@@ -390,6 +390,7 @@ void __exit_signal(struct task_struct *t sig->nvcsw += tsk->nvcsw; sig->nivcsw += tsk->nivcsw; sig->sched_time += tsk->sched_time; +exit_notify_itimers (sig);spin_unlock (&sighand->siglock); sig =NULL ;/* Marker for below. */ }@@ -1381,13 +1382,12 @@ send_sigqueue(int sig, struct sigqueue *int ret =0 ;/* -* We need the tasklist lock even for the specific -* thread case (when we don't need to follow the group -* lists) in order to avoid races with "p->sighand" -* going away or changing from under us. +* No need to hold tasklist lock here. +* posix_timer_event() is synchronized via +* exit_itimers() and exit_notify_itimers() to +* be protected against p->sighand == NULL */ BUG_ON (!(q->flags &SIGQUEUE_PREALLOC )); -read_lock (&tasklist_lock);spin_lock_irqsave (&p->sighand->siglock, flags);if (unlikely (!list_empty (&q->list))) {@@ -1414,7 +1414,6 @@ send_sigqueue(int sig, struct sigqueue * out:spin_unlock_irqrestore (&p->sighand->siglock, flags); -read_unlock (&tasklist_lock);return (ret); } -To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Signature · 2 lines
George Anzinger [email protected] HRT (High-res-timers): http://sourceforge.net/projects/high-res-timers/
PATCH 1/1 fix send_sigqueue() vs thread exit race
In reply to Thomas Gleixner[PATCH] fix send_sigqueue() vs thread exit race
posix_timer_event() first checks that the thread (SIGEV_THREAD_ID case) does not have PF_EXITING flag, then it calls send_sigqueue() which locks task list. But if the thread exits in between the kernel will oops (->sighand == NULL after __exit_sighand).
This patch moves the PF_EXITING check into the send_sigqueue(), it must be done atomically under tasklist_lock. When send_sigqueue() detects exiting thread it returns -1. In that case posix_timer_event will send the signal to thread group.
Also, this patch fixes task_struct use-after-free in posix_timer_event.
kernel/signal.c renamed from kernel/signal.c~ +12 -10
@@ -1366,16 +1366,16 @@ send_sigqueue(int sig, struct sigqueue *unsigned long flags;int ret =0 ; -/* -* We need the tasklist lock even for the specific -* thread case (when we don't need to follow the group -* lists) in order to avoid races with "p->sighand" -* going away or changing from under us. -*/ BUG_ON (!(q->flags &SIGQUEUE_PREALLOC )); -read_lock (&tasklist_lock); +read_lock (&tasklist_lock); + +if (unlikely (p->flags &PF_EXITING )) { + ret =-1 ; + goto out_err; + } +spin_lock_irqsave (&p->sighand->siglock, flags); - +if (unlikely (!list_empty (&q->list))) {/* * If an SI_TIMER entry is already queue just increment
@@ -1385,7 +1385,7 @@ send_sigqueue(int sig, struct sigqueue *BUG (); q->info.si_overrun++; goto out; - } + }/* Short-circuit ignored signals. */ if (sig_ignored (p, sig)) { ret =1 ;
@@ -1400,8 +1400,10 @@ send_sigqueue(int sig, struct sigqueue * out:spin_unlock_irqrestore (&p->sighand->siglock, flags); +out_err:read_unlock (&tasklist_lock); -return (ret); + +return ret; }int
kernel/posix-timers.c renamed from kernel/posix-timers.c~ +15 -13
@@ -427,21 +427,23 @@ int posix_timer_event(struct k_itimer *t timr->sigq->info.si_code =SI_TIMER ; timr->sigq->info.si_tid = timr->it_id; timr->sigq->info.si_value = timr->it_sigev_value; +if (timr->it_sigev_notify &SIGEV_THREAD_ID ) { -if (unlikely (timr->it_process->flags &PF_EXITING )) { - timr->it_sigev_notify =SIGEV_SIGNAL ; -put_task_struct (timr->it_process); - timr->it_process = timr->it_process->group_leader; - goto group; - } -return send_sigqueue (timr->it_sigev_signo, timr->sigq, - timr->it_process); - } -else { - group: -return send_group_sigqueue (timr->it_sigev_signo, timr->sigq, - timr->it_process); +struct task_struct *leader; +int ret =send_sigqueue (timr->it_sigev_signo, timr->sigq, + timr->it_process); + +if (likely (ret >=0 )) +return ret; + + timr->it_sigev_notify =SIGEV_SIGNAL ; + leader = timr->it_process->group_leader; +put_task_struct (timr->it_process); + timr->it_process = leader; } + +return send_group_sigqueue (timr->it_sigev_signo, timr->sigq, + timr->it_process); }EXPORT_SYMBOL_GPL (posix_timer_event);
Re: [PATCH] fix send_sigqueue() vs thread exit race
Quoted 27 lines · Oleg Nesterov
[PATCH] fix
send_sigqueue()vs thread exit race
posix_timer_event()first checks that the thread (SIGEV_THREAD_IDcase) does not havePF_EXITINGflag, then it callssend_sigqueue()which locks task list. But if the thread exits in between the kernel will oops (->sighand == NULL after__exit_sighand).This patch moves the
PF_EXITINGcheck into thesend_sigqueue(), it must be done atomically undertasklist_lock. Whensend_sigqueue()detects exiting thread it returns -1. In that caseposix_timer_eventwill send the signal to thread group.Also, this patch fixes
task_structuse-after-free inposix_timer_event.Signed-off-by Oleg Nesterov <[email protected]>kernel/signal.c renamed from kernel/signal.c~ +0
-5@@ -1366,16 +1366,16 @@ send_sigqueue(int sig, struct sigqueue *unsigned long flags;int ret =0 ; -/* -* We need the tasklist lock even for the specific -* thread case (when we don't need to follow the group -* lists) in order to avoid races with "p->sighand" -* going away or changing from under us.
kernel/signal.c send_sigqueue(int sig, struct sigqueue * · line 1376
Quoted 10 lines
kernel/signal.c renamed from kernel/signal.c~ +7
-2-*/ BUG_ON (!(q->flags &SIGQUEUE_PREALLOC )); -read_lock (&tasklist_lock); +read_lock (&tasklist_lock); + +if (unlikely (p->flags &PF_EXITING )) { + ret =-1 ; + goto out_err; + } +
It's still racy. tasklist_lock does not protect anything here.
arm timer
exit
timer event
timr->it_process references a freed structure
tglx
Re: [PATCH] fix send_sigqueue() vs thread exit race
Quoted 4 lines · Thomas Gleixner
Quoted 2 lines · Oleg Nesterov
[PATCH] fix
send_sigqueue()vs thread exit race
Quoted 11 lines
kernel/signal.c send_sigqueue(int sig, struct sigqueue * · line 1376
Quoted 9 lines
.....
kernel/signal.c renamed from kernel/signal.c~ +7
-1-read_lock (&tasklist_lock); +read_lock (&tasklist_lock); + +if (unlikely (p->flags &PF_EXITING )) { + ret =-1 ; + goto out_err; + } +It's still racy.
tasklist_lockdoes not protect anything here.
I hope no, but please clarify if I am wrong.
tasklist_lock protects against release_task()->__exit_sigxxx() here.
Quoted 2 lines
arm timer
exit
If this is the last thread in thread group, exit_itimers() will stop and clear ->posix_timers.
If not:
Quoted 3 lines
timer event
timr->it_process references a freed structure
No, create_timer() does get_task_struct(timr->it_process), this task may be EXIT_DEAD now, but the task_struct itself is valid, and it's ->flags has PF_EXITING flag.
Oleg.
Re: [PATCH] fix send_sigqueue() vs thread exit race
Quoted 9 lines · Oleg Nesterov
If not:
Quoted 3 lines
timer event
timr->it_process references a freed structureNo,
create_timer()doesget_task_struct(timr->it_process), this task may beEXIT_DEADnow, but thetask_structitself is valid, and it's ->flags hasPF_EXITINGflag.
Right, did not think about that.
tglx
Re: [PATCH] fix send_sigqueue() vs thread exit race
In reply to Thomas GleixnerQuoted 4 lines · Thomas Gleixner
arm timer
exit
timer event
I think there is another bug here.
CPU_0 CPU_1
release_task: posix_timer_fn:
write_lock(tasklist); lock(timer->it_lock); exit_timers: send_sigxxx(); lock(timer->it_lock) read_lock(tasklist);
Deadlock.
Dear cc-list, what do you think?
Oleg.
Re: [PATCH] fix send_sigqueue() vs thread exit race
Oleg,
Quoted 11 lines · Oleg Nesterov
CPU_0CPU_1
release_task:posix_timer_fn:write_lock(tasklist); lock(timer->it_lock); exit_timers: send_sigxxx(); lock(timer->it_lock) read_lock(tasklist);Deadlock.
Dear cc-list, what do you think?
The patch below on top of your patch should solve this. We don't need tasklist_lock to check p->flags. As you pointed out p cannot be invalid in send_sigqueue as it's protected by get_task_struct() in create_timer()
For send_group_sigqueue it's protected by exit_itimers() waiting for k_itimer.it_lock.
It still does not solve the ugly dependency on tasklist_lock but at least the race and the deadlock are fixed.
tglx
kernel/signal.c renamed from kernel/signal.oleg.c +15 -6
@@ -1381,11 +1381,14 @@ send_sigqueue(int sig, struct sigqueue *int ret =0 ;BUG_ON (!(q->flags &SIGQUEUE_PREALLOC )); -read_lock (&tasklist_lock); -if (unlikely (p->flags &PF_EXITING )) { - ret =-1 ; - goto out_err; +retry: +if (unlikely (p->flags &PF_EXITING )) +return -1 ; + + if ((unlikely(!read_trylock(&tasklist_lock))) { +cpu_relax (); + goto retry; }spin_lock_irqsave (&p->sighand->siglock, flags);
@@ -1414,7 +1417,6 @@ send_sigqueue(int sig, struct sigqueue * out:spin_unlock_irqrestore (&p->sighand->siglock, flags); -out_err:read_unlock (&tasklist_lock);return ret;
@@ -1427,7 +1429,14 @@ send_group_sigqueue(int sig, struct sigqint ret =0 ;BUG_ON (!(q->flags &SIGQUEUE_PREALLOC )); -read_lock (&tasklist_lock); +retry: +if (unlikely (p->flags &PF_EXITING )) +return -1 ; + +if (unlikely (!read_trylock (&tasklist_lock))) { +cpu_relax (); + goto retry; + }spin_lock_irqsave (&p->sighand->siglock, flags);handle_stop_signal (sig, p);
kernel/posix-timers.c renamed from kernel/posix-timers.oleg.c +2 -1
@@ -501,7 +501,8 @@ static void posix_timer_fn(unsigned longremove_from_abslist (timr); } -if (posix_timer_event (timr, si_private)) +/* Do not rearm the timer, when we are exiting */ +if (posix_timer_event (timr, si_private) >0 )/* * signal was not sent because of sig_ignor * we will not get a call back to restart it AND
Re: [PATCH] fix send_sigqueue() vs thread exit race
Quoted 1 line · Thomas Gleixner
Oleg,
Sorry for making noise. I introduced the race again.
tglx
kernel/signal.c renamed from kernel/signal.oleg.c +22 -3
@@ -1381,8 +1381,15 @@ send_sigqueue(int sig, struct sigqueue *int ret =0 ;BUG_ON (!(q->flags &SIGQUEUE_PREALLOC )); -read_lock (&tasklist_lock); +retry: +if (unlikely (p->flags &PF_EXITING )) +return -1 ; + +if (unlikely (!read_trylock (&tasklist_lock))) { +cpu_relax (); + goto retry; + }if (unlikely (p->flags &PF_EXITING )) { ret =-1 ; goto out_err;
@@ -1427,7 +1434,18 @@ send_group_sigqueue(int sig, struct sigqint ret =0 ;BUG_ON (!(q->flags &SIGQUEUE_PREALLOC )); -read_lock (&tasklist_lock); +retry: +if (unlikely (p->flags &PF_EXITING )) +return -1 ; + +if (unlikely (!read_trylock (&tasklist_lock))) { +cpu_relax (); + goto retry; + } +if (unlikely (p->flags &PF_EXITING )) { + ret =-1 ; + goto out_err; + }spin_lock_irqsave (&p->sighand->siglock, flags);handle_stop_signal (sig, p);
@@ -1461,8 +1479,9 @@ send_group_sigqueue(int sig, struct sigq__group_complete_signal (sig, p); out:spin_unlock_irqrestore (&p->sighand->siglock, flags); +out_err:read_unlock (&tasklist_lock); -return (ret); +return ret; }/*
kernel/posix-timers.c renamed from kernel/posix-timers.oleg.c +2 -1
@@ -501,7 +501,8 @@ static void posix_timer_fn(unsigned longremove_from_abslist (timr); } -if (posix_timer_event (timr, si_private)) +/* Do not rearm the timer, when we are exiting */ +if (posix_timer_event (timr, si_private) >0 )/* * signal was not sent because of sig_ignor * we will not get a call back to restart it AND
Re: [PATCH] fix send_sigqueue() vs thread exit race
kernel/signal.c send_group_sigqueue(int sig, struct sigq · line 1440
Quoted 10 lines · Thomas Gleixner
kernel/signal.c renamed from kernel/signal.oleg.c +4
-1@@ -1427,7 +1434,18 @@ send_group_sigqueue(int sig, struct sigqint ret =0 ;BUG_ON (!(q->flags &SIGQUEUE_PREALLOC )); -read_lock (&tasklist_lock); +retry: +if (unlikely (p->flags &PF_EXITING )) +return -1 ; +
I don't think this is correct. p == ->group_leader, it may have been exited and in EXIT_ZOMBIE state. But the thread group (process) is live, we should not stop posix timers.
Oleg.
Re: [PATCH] fix send_sigqueue() vs thread exit race
Quoted 5 lines · Oleg Nesterov
Quoted 4 lines · Thomas Gleixner
(quoted diff) +0
-0@@ -1427,7 +1434,18 @@ send_group_sigqueue(int sig, struct sigq int ret = 0;
Quoted 10 lines
kernel/signal.c send_sigqueue(int sig, struct sigqueue * · line 1388
Quoted 6 lines
kernel/signal.c renamed from kernel/signal.oleg.c +4
-1BUG_ON (!(q->flags &SIGQUEUE_PREALLOC )); -read_lock (&tasklist_lock); +retry: +if (unlikely (p->flags &PF_EXITING )) +return -1 ; +I don't think this is correct. p == ->group_leader, it may have been exited and in
EXIT_ZOMBIEstate. But the thread group (process) is live, we should not stop posix timers.
Hmm, true. release_task() is not called in this case, so p->sighand is still there.
But we can not check for p->sighand == NULL, as sighand is released after exit_itimers() so we are still deadlock prone. So I think __exit_sighand() should be called before exit_itimers(). Then we can do
retry:
if (unlikely(!p->sighand)) return -1;
instead of checking for PF_EXITING.
tglx
Re: [PATCH] fix send_sigqueue() vs thread exit race
Quoted 10 lines · Thomas Gleixner
But we can not check for
p->sighand== NULL, as sighand is released afterexit_itimers()so we are still deadlock prone. So I think__exit_sighand()should be called beforeexit_itimers(). Then we can doretry:
if (unlikely(!p->sighand)) return -1;instead of checking for
PF_EXITING.
I think yes, and this is closely related to your and Paul "Use RCU to protect tasklist for unicast signals" patches.
We don't need RCU here, but we do need this hypothetical lock_task_sighand() (and __exit_sighand from __exit_signal change).
We still need tasklist_lock in send_group_queue for __group_complete_signal though. I hope Paul will solve this, it is needed for group_send_info() anyway.
But for the near future I don't see simple and non-intrusive fix for this deadlock. I am waiting for George to confirm that the bug exists and we are not crazy :)
Oleg.
Re: [PATCH] fix send_sigqueue() vs thread exit race
Oleg,
Quoted 8 lines · Oleg Nesterov
Thomas Gleixner wrote:
I think yes, and this is closely related to your and Paul "Use RCU to protect tasklist for unicast signals" patches.We don't need RCU here, but we do need this hypothetical
lock_task_sighand()(and__exit_sighandfrom__exit_signalchange).
Quoted 7 lines
We still need
tasklist_lockinsend_group_queuefor__group_complete_signalthough. I hope Paul will solve this, it is needed forgroup_send_info()anyway.But for the near future I don't see simple and non-intrusive fix for this deadlock. I am waiting for George to confirm that the bug exists and we are not crazy :)
It exists. It triggers on preempt-RT and I can trigger it on vanilla SMP by waiting for the timer expiry in release_task() before the __exit_signal() call. That's reasonable, as it can happen that way by chance too. It requires that the timer expires on a different CPU, but I don't see a reason why this should not happen.
The patch below solves it for me.
tglx
kernel/exit.c +0 -1
@@ -71,7 +71,6 @@ repeat:__ptrace_unlink (p);BUG_ON (!list_empty (&p->ptrace_list) || !list_empty (&p->ptrace_children));__exit_signal (p); -__exit_sighand (p);/* * Note that the fastpath in sys_times depends on __exit_signal having * updated the counters before a task is removed from the tasklist of
kernel/fork.c +2 -1
@@ -1132,7 +1132,8 @@ bad_fork_cleanup_mm: bad_fork_cleanup_signal:exit_signal (p); bad_fork_cleanup_sighand: -exit_sighand (p); +if (p->sighand) +exit_sighand (p); bad_fork_cleanup_fs:exit_fs (p);/* blocking */ bad_fork_cleanup_files:
kernel/posix-timers.c +17 -14
@@ -427,21 +427,23 @@ int posix_timer_event(struct k_itimer *t timr->sigq->info.si_code =SI_TIMER ; timr->sigq->info.si_tid = timr->it_id; timr->sigq->info.si_value = timr->it_sigev_value; +if (timr->it_sigev_notify &SIGEV_THREAD_ID ) { -if (unlikely (timr->it_process->flags &PF_EXITING )) { - timr->it_sigev_notify =SIGEV_SIGNAL ; -put_task_struct (timr->it_process); - timr->it_process = timr->it_process->group_leader; - goto group; - } -return send_sigqueue (timr->it_sigev_signo, timr->sigq, - timr->it_process); - } -else { - group: -return send_group_sigqueue (timr->it_sigev_signo, timr->sigq, - timr->it_process); +struct task_struct *leader; +int ret =send_sigqueue (timr->it_sigev_signo, timr->sigq, + timr->it_process); + +if (likely (ret >=0 )) +return ret; + + timr->it_sigev_notify =SIGEV_SIGNAL ; + leader = timr->it_process->group_leader; +put_task_struct (timr->it_process); + timr->it_process = leader; } + +return send_group_sigqueue (timr->it_sigev_signo, timr->sigq, + timr->it_process); }EXPORT_SYMBOL_GPL (posix_timer_event);
@@ -499,7 +501,8 @@ static void posix_timer_fn(unsigned longremove_from_abslist (timr); } -if (posix_timer_event (timr, si_private)) +/* Do not rearm the timer, when we are exiting */ +if (posix_timer_event (timr, si_private) >0 )/* * signal was not sent because of sig_ignor * we will not get a call back to restart it AND
kernel/signal.c +29 -12
81 lines not on this page · raw message
Re: [PATCH] fix send_sigqueue() vs thread exit race
Quoted 6 lines · Thomas Gleixner
It exists. It triggers on preempt-RT and I can trigger it on vanilla SMP by waiting for the timer expiry in
release_task()before the__exit_signal()call. That's reasonable, as it can happen that way by chance too. It requires that the timer expires on a different CPU, but I don't see a reason why this should not happen.
Ok, exit_itimers()->itimer_delete() called when the last thread exits or does exec.
kernel/posix-timers.c:common_timer_del() calls del_timer_sync(), after that nobody can access this timer, so we don't need to lock timer->it_lock at all in this case. No lock - no deadlock.
But I know nothing about kernel/posix-cpu-timers.c, I doubt it will work for posix_cpu_timer_del(). I don't have time to study posix-cpu-timers now. However, I see that __exit_signal() calls posix_cpu_timers_exit_xxx(), so may be it can work?
380 int posix_cpu_timer_del(struct k_itimer *timer)
381 {
382 struct task_struct *p = timer->it.cpu.task;
383
384 if (timer->it.cpu.firing)
385 return TIMER_RETRY;
386
387 if (unlikely(p == NULL))
388 return 0;
389
390 if (!list_empty(&timer->it.cpu.entry)) {
391 read_lock(&tasklist_lock);Surely, it should be impossible to happen when process exists, otherwise it would deadlock immediately, we did write_lock(tasklist).
Thomas, do you know something about posix-cpu-timers.c?
Oleg.
Re: [PATCH] fix send_sigqueue() vs thread exit race
Quoted 7 lines · Oleg Nesterov
Thomas Gleixner wrote:
Ok, exit_itimers()->itimer_delete() called when the last thread exits or does exec.kernel/posix-timers.c:common_timer_del() calls
del_timer_sync(), after that nobody can access this timer, so we don't need to locktimer->it_lockat all in this case. No lock - no deadlock.
It still deadlocks:
CPU 0 CPU 1write_lock(&tasklist_lock);__exit_signal()
timer expires
base->running_timer = timer
send_group_sigqueue()
read_lock(&tasklist_lock();exit_itimers()
del_timer_sync(timer)
waits for ever because waits for ever on tasklist_lock
base->running_timer == timer
I still think the last patch I sent is still necessary.
Quoted 18 lines
But I know nothing about
kernel/posix-cpu-timers.c, I doubt it will work forposix_cpu_timer_del(). I don't have time to study posix-cpu-timers now. However, I see that__exit_signal()callsposix_cpu_timers_exit_xxx(), so may be it can work?380 int posix_cpu_timer_del(struct k_itimer *timer) 381 { 382 struct task_struct *p = timer->it.cpu.task; 383 384 if (timer->it.cpu.firing) 385 return TIMER_RETRY; 386 387 if (unlikely(p == NULL)) 388 return 0; 389 390 if (!list_empty(&timer->it.cpu.entry)) { 391 read_lock(&tasklist_lock);
Quoted 4 lines
Surely, it should be impossible to happen when process exists, otherwise it would deadlock immediately, we did
write_lock(tasklist).Thomas, do you know something about
posix-cpu-timers.c?
Not much. I look into this
tglx
Re: [PATCH] fix send_sigqueue() vs thread exit race
Quoted 12 lines · Thomas Gleixner
Quoted 4 lines · Oleg Nesterov
kernel/posix-timers.c:common_timer_del() calls
del_timer_sync(), after that nobody can access this timer, so we don't need to locktimer->it_lockat all in this case. No lock - no deadlock.It still deadlocks:
CPU 0 CPU 1
write_lock(&tasklist_lock);__exit_signal()
Quoted 8 lines
timer expires base->running_timer = timer send_group_sigqueue() read_lock(&tasklist_lock();
exit_itimers()
del_timer_sync(timer)
waits for ever because waits for ever ontasklist_lock
base->running_timer== timer
Silly me.
Quoted 1 line
I still think the last patch I sent is still necessary.
Thomas, you know that I like this change in __exit_{signal,sighand}, but i think this change is dangerous, should go in a separate patch, and needs a lot of testing. But the decision is up to Ingo and Roland.
I am looking at your previous patch:
kernel/signal.c send_sigqueue(int sig, struct sigqueue * · line 1393
Quoted 12 lines
kernel/signal.c +11
-1-read_lock (&tasklist_lock); +retry: +if (unlikely (p->flags &PF_EXITING )) +return -1 ; + +if (unlikely (!read_trylock (&tasklist_lock))) { +cpu_relax (); + goto retry; + } +if (unlikely (p->flags &PF_EXITING )) { + ret =-1 ; + goto out_err;
What do you think about this:
int try_to_lock_this_beep_tasklist_lock(struct task_struct *group_leader)
{
while (unlikely(!read_trylock(&tasklist_lock))) {
if (group_leader->flags & PF_EXITING) {
smp_rmb();
if (thread_group_empty(group_leader))
return 0;
}
cpu_relax();
}
return 1;
}No need to re-check after we got tasklist, the signal will be flushed. I think it's better to move the locking into the posix_timer_event, btw. In that case we can drop my patch.
What is your opinion, can it work?
P.S.
Thomas, thanks for explanation about posix-cpu-timers.
Oleg.
Re: [PATCH] fix send_sigqueue() vs thread exit race
Quoted 6 lines · Oleg Nesterov
Quoted 1 line · Thomas Gleixner
I still think the last patch I sent is still necessary.
Thomas, you know that I like this change in __exit_{signal,sighand}, but i think this change is dangerous, should go in a separate patch, and needs a lot of testing. But the decision is up to Ingo and Roland.
Maybe it makes more sense in context of Pauls RCU stuff.
Quoted 16 lines
What do you think about this:
int
try_to_lock_this_beep_tasklist_lock(struct task_struct *group_leader){ while (unlikely(!read_trylock(&tasklist_lock))) { if (group_leader->flags & PF_EXITING) { smp_rmb(); if (thread_group_empty(group_leader)) return 0; } cpu_relax(); } return 1; }
Quoted 1 line
No need to re-check after we got tasklist, the signal will be flushed.
Makes sense, though I'm not sure if its safe to call thread_group_empty() without tasklist lock held. I might be in case of PF_EXITING, but it needs a comment at least.
Quoted 1 line
I think it's better to move the locking into the
posix_timer_event, btw.
Hmm, not sure. I've seen similar stuff in the AIO patches. I guess this should be solved safe at one place rather than all around the kernel.
tglx
PATCH 1/1 fix exit_itimers() vs posix_timer_event() AB-BA deadlock
In reply to Oleg NesterovCPU_0 CPU_1
release_task: posix_timer_fn:
write_lock(tasklist); spin_lock(timer->it_lock);
exit_timers: send_sigqueue:
spin_lock(timer->it_lock) read_lock(tasklist);Actually, it is a bit worse. If posix timer starts between tasklist locking and del_timer_sync() call this deadlock will happen because of TIMER_RETRY logic.
With this patch posix_timer_event() detects the exiting thread group and aborts the sending of signal (taking tasklist_lock). To simplify the code tasklist locking moved from send_{,group_}sigqueue to the posix_timer_event().
kernel/posix-timers.c renamed from kernel/posix-timers.c~1_DLOCK +38 -16
@@ -411,6 +411,10 @@ exit:int posix_timer_event (struct k_itimer *timr,int si_private) { +struct task_struct *leader, *zombie; +int (*send_actor)(int ,struct sigqueue *,struct task_struct *); +int ret; +memset (&timr->sigq->info,0 ,sizeof (siginfo_t)); timr->sigq->info.si_sys_private = si_private;/*
@@ -428,22 +432,40 @@ int posix_timer_event(struct k_itimer *t timr->sigq->info.si_tid = timr->it_id; timr->sigq->info.si_value = timr->it_sigev_value; -if (timr->it_sigev_notify &SIGEV_THREAD_ID ) { -struct task_struct *leader; -int ret =send_sigqueue (timr->it_sigev_signo, timr->sigq, - timr->it_process); - -if (likely (ret >=0 )) -return ret; - - timr->it_sigev_notify =SIGEV_SIGNAL ; - leader = timr->it_process->group_leader; -put_task_struct (timr->it_process); - timr->it_process = leader; - } - -return send_group_sigqueue (timr->it_sigev_signo, timr->sigq, - timr->it_process); +/* +* We are locking ->it_lock + tasklist_lock backwards +* from release_task()->exit_itimers(), beware deadlock. +*/ + leader = timr->it_process->group_leader; +while (unlikely (!read_trylock (&tasklist_lock))) { +if (leader->flags &PF_EXITING ) { +smp_rmb (); +if (thread_group_empty (leader)) +return 0 ; + } +cpu_relax (); + } + + zombie =NULL ; + send_actor = send_group_sigqueue; +if (timr->it_sigev_notify &SIGEV_THREAD_ID ) { +if (unlikely (timr->it_process->flags &PF_EXITING )) { + zombie = timr->it_process; + timr->it_process = leader; + timr->it_sigev_notify =SIGEV_SIGNAL ; + }else + send_actor = send_sigqueue; + } + + ret =send_actor (timr->it_sigev_signo, timr->sigq, + timr->it_process); + +read_unlock (&tasklist_lock); + +if (unlikely (zombie !=NULL )) +put_task_struct (zombie); + +return ret; }EXPORT_SYMBOL_GPL (posix_timer_event);
kernel/signal.c renamed from kernel/signal.c~1_DLOCK +3 -17
@@ -1367,22 +1367,14 @@ send_sigqueue(int sig, struct sigqueue *int ret =0 ;BUG_ON (!(q->flags &SIGQUEUE_PREALLOC )); -read_lock (&tasklist_lock); - -if (unlikely (p->flags &PF_EXITING )) { - ret =-1 ; - goto out_err; - } -spin_lock_irqsave (&p->sighand->siglock, flags);if (unlikely (!list_empty (&q->list))) { +BUG_ON (q->info.si_code !=SI_TIMER );/* * If an SI_TIMER entry is already queue just increment * the overrun count. */ -if (q->info.si_code !=SI_TIMER ) -BUG (); q->info.si_overrun++; goto out; }
@@ -1400,9 +1392,6 @@ send_sigqueue(int sig, struct sigqueue * out:spin_unlock_irqrestore (&p->sighand->siglock, flags); -out_err: -read_unlock (&tasklist_lock); -return ret; }
@@ -1413,7 +1402,6 @@ send_group_sigqueue(int sig, struct sigqint ret =0 ;BUG_ON (!(q->flags &SIGQUEUE_PREALLOC )); -read_lock (&tasklist_lock);spin_lock_irqsave (&p->sighand->siglock, flags);handle_stop_signal (sig, p);
@@ -1424,13 +1412,12 @@ send_group_sigqueue(int sig, struct sigq }if (unlikely (!list_empty (&q->list))) { +BUG_ON (q->info.si_code !=SI_TIMER );/* * If an SI_TIMER entry is already queue just increment * the overrun count. Other uses should not try to * send the signal multiple times. */ -if (q->info.si_code !=SI_TIMER ) -BUG (); q->info.si_overrun++; goto out; }
@@ -1447,8 +1434,7 @@ send_group_sigqueue(int sig, struct sigq__group_complete_signal (sig, p); out:spin_unlock_irqrestore (&p->sighand->siglock, flags); -read_unlock (&tasklist_lock); -return (ret); +return ret; }/*
Re: [PATCH] fix exit_itimers() vs posix_timer_event() AB-BA deadlock
Quoted 4 lines · Oleg Nesterov
(quoted diff) +1
-0+ /* + * We are locking ->it_lock + tasklist_lock backwards + * from release_task()->exit_itimers(), beware deadlock.
Review
Quoted 10 lines
(quoted diff) +0
-0+ */ + leader = timr->it_process->group_leader; + while (unlikely(!read_trylock(&tasklist_lock))) { + if (leader->flags & PF_EXITING) { + smp_rmb(); + if (thread_group_empty(leader)) + return 0; + } + cpu_relax(); + }
Oh dear. Is there no way to fix this up by taking the locks in the correct order? (Whatever that is).
Re: [PATCH] fix exit_itimers() vs posix_timer_event() AB-BAdeadlock
Quoted 17 lines · Andrew Morton
Quoted 5 lines · Oleg Nesterov
+ /*
+ * We are locking ->it_lock + tasklist_lock backwards + * from release_task()->exit_itimers(), beware deadlock. + */Quoted 9 lines
+ leader =
timr->it_process->group_leader;
+ while (unlikely(!read_trylock(&tasklist_lock))) {
+ if (leader->flags&PF_EXITING) {
+smp_rmb();
+ if (thread_group_empty(leader))
+ return 0;
+ }
+cpu_relax();
+ }
Quoted 2 lines
Oh dear. Is there no way to fix this up by taking the locks in the correct order? (Whatever that is).
Yes, this is ugly and that is why I hesitated so long before posting this patch.
But I don't see the simple and correct fix. The lock ordering is not the only problem. In fact we don't need to take the ->it_lock in the itimer_delete() at all. The problem is that itimer_delete() can't delete k_itimer.it.real.timer while holding tasklist_lock, because this lock will prevent (without this patch) the completition of posix_timer_fn(). It is unsafe to unlock tasklist in __exit_signal() before calling exit_itimers(), and it is too late to call exit_itimers() after unlock_irq(&tasklist_lock) in release_task(), at this moment we don't have ->signal/->sighand already.
I beleive the only sane fix would be to eliminate tasklist_lock from signal sending path (see the patches from Paul and Thomas), but this is hard and (I think) needs more working/testing.
Oleg.
Re: [PATCH] fix exit_itimers() vs posix_timer_event() AB-BAdeadlock
Quoted 19 lines · Oleg Nesterov
Quoted 17 lines · Andrew Morton
Quoted 14 lines · Oleg Nesterov
+ /*
+ * We are locking ->it_lock + tasklist_lock backwards + * from release_task()->exit_itimers(), beware deadlock. + */+ leader =
timr->it_process->group_leader;
+ while (unlikely(!read_trylock(&tasklist_lock))) {
+ if (leader->flags&PF_EXITING) {
+smp_rmb();
+ if (thread_group_empty(leader))
+ return 0;
+ }
+cpu_relax();
+ }
Quoted 2 lines
Quoted 2 lines
Oh dear. Is there no way to fix this up by taking the locks in the correct order? (Whatever that is).
Andrew, please drop this patch. It is obsoleted by Roland's "[PATCH] Call exit_itimers from do_exit, not __exit_signal".
Oleg.
Re: [PATCH] fix send_sigqueue() vs thread exit race
In reply to Oleg NesterovQuoted 4 lines · Oleg Nesterov
But I know nothing about
kernel/posix-cpu-timers.c, I doubt it will work forposix_cpu_timer_del(). I don't have time to study posix-cpu-timers now. However, I see that__exit_signal()callsposix_cpu_timers_exit_xxx(), so may be it can work?
timer->it.cpu.task is set to NULL by posix_cpu_timers_exit(), so the code in posix_cpu_timer_del returns before accessing tasklist_lock.
The exit functions do not take any locks, but it is not necessary there.
posix_run_cpu_timers(p) is called with p=current() and we have interrupts disabled, so the timer interrupt can not run on this CPU. The current exiting process can not run at the same time on a different CPU, so no race and lockup possible here.
tglx
Re: [PATCH 2.6.13-rc6-rt9] PI aware dynamic priority adjustment
In reply to Thomas GleixnerQuoted 8 lines · Thomas Gleixner
Hi all,
Quoted 2 lines · Ingo Molnar
i have released the 2.6.13-rc6-rt9 tree, which can be downloaded from the usual place:
I reworked the code for dynamically setting the priority of the hrtimer softirq to be aware of PI.
looks mostly good to me. I'm uneasy about the fact that we touch p->normal_prio without taking the runqueue lock. Best would be to clean these things up by introducing a wake_up_process_prio() and wake_up_process_chprio() method that does these things embedded in try_to_wake_up().
Quoted 6 lines
I stumbled over "//#define
MUTEX_IRQS_OFF" in the first attempt. My assumption that all code protected bypi_lock(which is a raw lock) is irq save turned out to be wrong. I missed that commented define :( I guess it was introduced during the "IRQ latency contest" to squeeze out the last nsecs :)
Quoted 6 lines
Switching it back on is not really influencing system performance in a measurable way, but it allows to use the pi aware boosting function in irq context.
Quite contrary it makes the system more snappy and the overall test latencies go down.
we can undo that flag - it's indeed only a couple of cycles worth of optimization, which wont count for most workloads. I've applied your patch, but we need to do those cleanups and the fact needs to be documented that !MUTEX_IRQS_OFF is not safe anymore. (most likely this means that the MUTEX_IRQS_OFF flag and all related changes needs to be gotten rid of)
Ingo
Re: [PATCH 2.6.13-rc6-rt9] PI aware dynamic priority adjustment
Quoted 9 lines · Ingo Molnar
Quoted 2 lines
Quite contrary it makes the system more snappy and the overall test latencies go down.
we can undo that flag - it's indeed only a couple of cycles worth of optimization, which wont count for most workloads. I've applied your patch, but we need to do those cleanups and the fact needs to be documented that !MUTEX_IRQS_OFF is not safe anymore. (most likely this means that the
MUTEX_IRQS_OFFflag and all related changes needs to be gotten rid of)
your patch gets rid of the flag, but not of all side-effects: e.g. trace_local_irq_enable(ti) only takes a 'ti' parameter for !MUTEX_IRQS_OFF - which does not exist anymore.
Ingo