public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] fix loop with disabled tasklets
@ 2001-11-11 15:56 Momchil Velikov
  2001-11-12  7:46 ` Mathijs Mohlmann
  0 siblings, 1 reply; 26+ messages in thread
From: Momchil Velikov @ 2001-11-11 15:56 UTC (permalink / raw)
  To: Mathijs Mohlmann; +Cc: linux-kernel


Mathijs,

You may want to have a look at the following patches (tested by visual
inspection):

--- softirq.c.orig	Sun Nov 11 16:42:14 2001
+++ softirq.c	Sun Nov 11 16:59:44 2001
@@ -188,22 +188,17 @@ static void tasklet_action(struct softir
 
 		list = list->next;
 
+		if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
+			BUG();
+
 		if (tasklet_trylock(t)) {
-			if (!atomic_read(&t->count)) {
-				if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
-					BUG();
+			if (!atomic_read(&t->count))
 				t->func(t->data);
-				tasklet_unlock(t);
-				continue;
-			}
 			tasklet_unlock(t);
+			continue;
 		}
 
-		local_irq_disable();
-		t->next = tasklet_vec[cpu].list;
-		tasklet_vec[cpu].list = t;
-		__cpu_raise_softirq(cpu, TASKLET_SOFTIRQ);
-		local_irq_enable();
+		tasklet_schedule(t);
 	}
 }
 
@@ -222,22 +217,17 @@ static void tasklet_hi_action(struct sof
 
 		list = list->next;
 
+		if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
+			BUG();
+
 		if (tasklet_trylock(t)) {
-			if (!atomic_read(&t->count)) {
-				if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
-					BUG();
+			if (!atomic_read(&t->count))
 				t->func(t->data);
-				tasklet_unlock(t);
-				continue;
-			}
 			tasklet_unlock(t);
+			continue;
 		}
 
-		local_irq_disable();
-		t->next = tasklet_hi_vec[cpu].list;
-		tasklet_hi_vec[cpu].list = t;
-		__cpu_raise_softirq(cpu, HI_SOFTIRQ);
-		local_irq_enable();
+		tasklet_hi_schedule(t);
 	}
 }
 

--- interrupt.h.orig	Sun Nov 11 16:49:05 2001
+++ interrupt.h	Sun Nov 11 17:28:08 2001
@@ -185,13 +185,15 @@ static inline void tasklet_disable(struc
 static inline void tasklet_enable(struct tasklet_struct *t)
 {
 	smp_mb__before_atomic_dec();
-	atomic_dec(&t->count);
+	if (atomic_dec_and_test(&t->count))
+		tasklet_schedule(t);
 }
 
 static inline void tasklet_hi_enable(struct tasklet_struct *t)
 {
 	smp_mb__before_atomic_dec();
-	atomic_dec(&t->count);
+	if (atomic_dec_and_test(&t->count))
+		tasklet_hi_schedule(t);
 }
 
 extern void tasklet_kill(struct tasklet_struct *t);

Regards,
-velco

^ permalink raw reply	[flat|nested] 26+ messages in thread
* Re: [PATCH] fix loop with disabled tasklets
@ 2001-11-12 15:33 Petr Vandrovec
  2001-11-12 14:48 ` Andrea Arcangeli
  0 siblings, 1 reply; 26+ messages in thread
From: Petr Vandrovec @ 2001-11-12 15:33 UTC (permalink / raw)
  To: Andrea Arcangeli
  Cc: mathijs, jgarzik, linux-kernel, torvalds, kuznet, Thorsten Kukuk

On 12 Nov 01 at 15:20, Andrea Arcangeli wrote:

Hi Andrea,
  does it compile? It looks to me like that you are using ret_from_fork,
ret_from_smp and ret_from_smpfork interchangably in the patch. You renamed
ret_from_smpfork to ret_from_fork, changed extern ret_from_smpfork
to ret_from_smp, and you still call ret_from_smpfork ;-)

  Or do I miss something?
                                                Thanks,
                                                    Petr Vandrovec
                                                    vandrove@vc.cvut.cz
                                                    

> --- 2.4.15pre2aa1/arch/sparc/kernel/entry.S.~1~ Sat Feb 10 02:34:05 2001
> +++ 2.4.15pre2aa1/arch/sparc/kernel/entry.S Mon Nov 12 15:17:32 2001
> @@ -1466,8 +1466,7 @@
>     b   C_LABEL(ret_sys_call)
>      ld [%sp + REGWIN_SZ + PT_I0], %o0
>  
> -#ifdef CONFIG_SMP
> -   .globl  C_LABEL(ret_from_smpfork)
> +   .globl  C_LABEL(ret_from_fork)
>  C_LABEL(ret_from_smpfork):
>     wr  %l0, PSR_ET, %psr
>     WRITE_PAUSE
> @@ -1475,7 +1474,6 @@
>      mov    %g3, %o0
>     b   C_LABEL(ret_sys_call)
>      ld [%sp + REGWIN_SZ + PT_I0], %o0
> -#endif
>  
>     /* Linux native and SunOS system calls enter here... */
>     .align  4
> --- 2.4.15pre2aa1/arch/sparc/kernel/process.c.~1~   Thu Oct 11 10:41:52 2001
> +++ 2.4.15pre2aa1/arch/sparc/kernel/process.c   Mon Nov 12 15:18:21 2001
> @@ -455,11 +455,7 @@
>   *       allocate the task_struct and kernel stack in
>   *       do_fork().
>   */
> -#ifdef CONFIG_SMP
> -extern void ret_from_smpfork(void);
> -#else
> -extern void ret_from_syscall(void);
> -#endif
> +extern void ret_from_smp(void);
>  
>  int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
>         unsigned long unused,
> @@ -493,13 +489,8 @@
>     copy_regwin(new_stack, (((struct reg_window *) regs) - 1));
>  
>     p->thread.ksp = (unsigned long) new_stack;
> -#ifdef CONFIG_SMP
>     p->thread.kpc = (((unsigned long) ret_from_smpfork) - 0x8);
>     p->thread.kpsr = current->thread.fork_kpsr | PSR_PIL;
> -#else
> -   p->thread.kpc = (((unsigned long) ret_from_syscall) - 0x8);
> -   p->thread.kpsr = current->thread.fork_kpsr;
> -#endif
>     p->thread.kwim = current->thread.fork_kwim;
>  
>     /* This is used for sun4c only */

^ permalink raw reply	[flat|nested] 26+ messages in thread
* [PATCH] fix loop with disabled tasklets
@ 2001-11-10 12:21 Mathijs Mohlmann
  2001-11-10 13:37 ` David S. Miller
  0 siblings, 1 reply; 26+ messages in thread
From: Mathijs Mohlmann @ 2001-11-10 12:21 UTC (permalink / raw)
  To: andrea, jgarzik; +Cc: linux-kernel, torvalds


	I have a questions about the current softirq implementation.

Looking at kernel/softirq.c:418 and futher. When the tasklet is disabled it 
is rescheduled. This is fine, but __cpu_raise_softirq is also called. This 
means that ksoftirqd will loop until the tasklet is enabled. 
Normaly this is no biggy, because user processes still come through.
But during boot -when the tasklet_enable is yet to be called by "the idle 
thread"- the system will lockup. This happens during the boot of my sun4m 
with the keyboard tasklet.

To demonstrate, i wrote a module. Inserting this will result in 0% idle time. 
Inserting this with the below patch, the system simply goes on.

If this really is an issue, this patch fixes it. It does change the current
behavior a bit though. Currently when a tasklet is run while it is already
running on a different cpu, the task is rescheduled. This results in the 
tasklet being executed two times. With this patch applied, it will not. (this 
is still good according to kernel/include/interrups.h:83 and futher).

	i'm not sure about the enable_tasklet bit. I think it will prevent
people from calling tasklet_enable from within an interrupt handler. But then
again, why do you want to do that? Thanx, velco and
	
	Any comments?

	me

#define MODULE
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/interrupt.h>

MODULE_LICENSE("GPL");

void
dummy_lockit(unsigned long nill)
{
	printk("doing the lockit\n");
	return;
}

DECLARE_TASKLET_DISABLED(lockit, dummy_lockit, 0);
int
init_module(void)
{
	printk("going to lock\n");
	tasklet_schedule(&lockit);
	return(0);
}

void
cleanup_module(void)
{
	tasklet_enable(&lockit);
	set_current_state(TASK_INTERRUPTIBLE);
	schedule_timeout(HZ); /* some time to do dummy_lockit */

	printk("bye\n");
}


diff -ruN linux-2.4.14/include/linux/interrupt.h 
linux/include/linux/interrupt.h
--- linux-2.4.14/include/linux/interrupt.h	Sat Nov  3 11:20:41 2001
+++ linux/include/linux/interrupt.h	Sat Nov 10 12:28:14 2001
@@ -185,13 +185,15 @@
 static inline void tasklet_enable(struct tasklet_struct *t)
 {
 	smp_mb__before_atomic_dec();
-	atomic_dec(&t->count);
+	if (atomic_dec_and_test(&t->count))
+		__cpu_raise_softirq(smp_processor_id(), TASKLET_SOFTIRQ);
 }
 
 static inline void tasklet_hi_enable(struct tasklet_struct *t)
 {
 	smp_mb__before_atomic_dec();
-	atomic_dec(&t->count);
+	if (atomic_dec_and_test(&t->count))
+		__cpu_raise_softirq(smp_processor_id(), HI_SOFTIRQ);
 }
 
 extern void tasklet_kill(struct tasklet_struct *t);
diff -ruN linux-2.4.14/kernel/softirq.c linux/kernel/softirq.c
--- linux-2.4.14/kernel/softirq.c	Thu Nov  8 15:58:24 2001
+++ linux/kernel/softirq.c	Sat Nov 10 12:27:24 2001
@@ -188,21 +188,19 @@
 
 		list = list->next;
 
-		if (tasklet_trylock(t)) {
-			if (!atomic_read(&t->count)) {
+		if (!atomic_read(&t->count)) {
+			if (tasklet_trylock(t)) {
 				if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
 					BUG();
 				t->func(t->data);
 				tasklet_unlock(t);
-				continue;
 			}
-			tasklet_unlock(t);
+			continue;
 		}
 
 		local_irq_disable();
 		t->next = tasklet_vec[cpu].list;
 		tasklet_vec[cpu].list = t;
-		__cpu_raise_softirq(cpu, TASKLET_SOFTIRQ);
 		local_irq_enable();
 	}
 }
@@ -222,21 +220,19 @@
 
 		list = list->next;
 
-		if (tasklet_trylock(t)) {
-			if (!atomic_read(&t->count)) {
+		if (!atomic_read(&t->count)) {
+			if (tasklet_trylock(t)) {
 				if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
 					BUG();
 				t->func(t->data);
 				tasklet_unlock(t);
-				continue;
 			}
-			tasklet_unlock(t);
+			continue;
 		}
 
 		local_irq_disable();
 		t->next = tasklet_hi_vec[cpu].list;
 		tasklet_hi_vec[cpu].list = t;
-		__cpu_raise_softirq(cpu, HI_SOFTIRQ);
 		local_irq_enable();
 	}
 }

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2001-11-12 19:03 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-11-11 15:56 [PATCH] fix loop with disabled tasklets Momchil Velikov
2001-11-12  7:46 ` Mathijs Mohlmann
2001-11-12  8:00   ` David S. Miller
2001-11-12  8:07   ` Momchil Velikov
2001-11-12  9:11     ` Mathijs Mohlmann
2001-11-12  9:41       ` Momchil Velikov
2001-11-12  9:54         ` Mathijs Mohlmann
  -- strict thread matches above, loose matches on Subject: below --
2001-11-12 15:33 Petr Vandrovec
2001-11-12 14:48 ` Andrea Arcangeli
2001-11-10 12:21 Mathijs Mohlmann
2001-11-10 13:37 ` David S. Miller
2001-11-10 15:03   ` Andrea Arcangeli
2001-11-10 15:29     ` Mathijs Mohlmann
2001-11-10 16:02       ` Alan Cox
2001-11-10 16:37       ` Andrea Arcangeli
2001-11-12  1:11         ` Andrea Arcangeli
2001-11-12  7:42           ` Mathijs Mohlmann
2001-11-12  7:59             ` David S. Miller
2001-11-12 14:03               ` Andrea Arcangeli
2001-11-12 13:57             ` Andrea Arcangeli
2001-11-12  8:03           ` David S. Miller
2001-11-12 14:04             ` Andrea Arcangeli
2001-11-12 14:20               ` Andrea Arcangeli
2001-11-12 17:10                 ` Thorsten Kukuk
2001-11-12 19:03                 ` Mathijs Mohlmann
2001-11-11  2:32     ` Mathijs Mohlmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox