mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* Unusually long delay in the kernel
@ 2005-09-16 16:42 Alan Stern
  2005-09-16 17:58 ` Fawad Lateef
  2005-09-17  6:52 ` Andrew Morton
  0 siblings, 2 replies; 9+ messages in thread
From: Alan Stern @ 2005-09-16 16:42 UTC (permalink / raw)
  To: Kernel development list

This code excerpt is taken from the start of the control thread for the 
usb-storage driver in 2.6.14-rc1:


static int usb_stor_control_thread(void * __us)
{
	struct us_data *us = (struct us_data *)__us;
	struct Scsi_Host *host = us_to_host(us);

printk(KERN_INFO "Before thread start\n");
	lock_kernel();

	/*
	 * This thread doesn't need any user-level access,
	 * so get rid of all our resources.
	 */
	daemonize("usb-storage");
	current->flags |= PF_NOFREEZE;
	unlock_kernel();
printk(KERN_INFO "After thread start\n");


The code between the two printk's takes a long time to run.  I don't have 
precise numbers, but it feels like more than 1 second.

(1) Can anyone explain why, or indicate how to speed it up?

(2) Are the {un}lock_kernel calls really needed?

Thanks,

Alan Stern


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

* Re: Unusually long delay in the kernel
  2005-09-16 16:42 Unusually long delay in the kernel Alan Stern
@ 2005-09-16 17:58 ` Fawad Lateef
  2005-09-17  6:52 ` Andrew Morton
  1 sibling, 0 replies; 9+ messages in thread
From: Fawad Lateef @ 2005-09-16 17:58 UTC (permalink / raw)
  To: Alan Stern; +Cc: Kernel development list

On 9/16/05, Alan Stern <stern@rowland.harvard.edu> wrote:
> This code excerpt is taken from the start of the control thread for the
> usb-storage driver in 2.6.14-rc1:
> 
> 
> static int usb_stor_control_thread(void * __us)
> {
>         struct us_data *us = (struct us_data *)__us;
>         struct Scsi_Host *host = us_to_host(us);
> 
> printk(KERN_INFO "Before thread start\n");
>         lock_kernel();
> 
>         /*
>          * This thread doesn't need any user-level access,
>          * so get rid of all our resources.
>          */
>         daemonize("usb-storage");
>         current->flags |= PF_NOFREEZE;
>         unlock_kernel();
> printk(KERN_INFO "After thread start\n");
> 
> 
> The code between the two printk's takes a long time to run.  I don't have
> precise numbers, but it feels like more than 1 second.
> 
> (1) Can anyone explain why, or indicate how to speed it up?
> 
> (2) Are the {un}lock_kernel calls really needed?
> 

AFAIR the article on the lwn.net in the driver porting porting to 2.6
kernel mentioned that big kernel locks lock_kernel and unlock_kernel
gone, but as I searched into the kernel's drivers directory for the
kernel_thread functions (drivers creating threads), I found some of
them using lock_kernel and some not .... So I also wants to know are
they really needed ??

By the way I havn't saw/felt any long delay when starting thread in
this way using lock_kernel !!!!


-- 
Fawad Lateef

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

* Re: Unusually long delay in the kernel
  2005-09-16 16:42 Unusually long delay in the kernel Alan Stern
  2005-09-16 17:58 ` Fawad Lateef
@ 2005-09-17  6:52 ` Andrew Morton
  2005-09-17 22:15   ` Alan Stern
  1 sibling, 1 reply; 9+ messages in thread
From: Andrew Morton @ 2005-09-17  6:52 UTC (permalink / raw)
  To: Alan Stern; +Cc: linux-kernel

Alan Stern <stern@rowland.harvard.edu> wrote:
>
> This code excerpt is taken from the start of the control thread for the 
>  usb-storage driver in 2.6.14-rc1:
> 
> 
>  static int usb_stor_control_thread(void * __us)
>  {
>  	struct us_data *us = (struct us_data *)__us;
>  	struct Scsi_Host *host = us_to_host(us);
> 
>  printk(KERN_INFO "Before thread start\n");
>  	lock_kernel();
> 
>  	/*
>  	 * This thread doesn't need any user-level access,
>  	 * so get rid of all our resources.
>  	 */
>  	daemonize("usb-storage");
>  	current->flags |= PF_NOFREEZE;
>  	unlock_kernel();
>  printk(KERN_INFO "After thread start\n");
> 
> 
>  The code between the two printk's takes a long time to run.  I don't have 
>  precise numbers, but it feels like more than 1 second.
> 
>  (1) Can anyone explain why, or indicate how to speed it up?

What's it doing at the time?  (kgdb is great for this sort of thing: hit
^C, go for a wander through the thread callchains).

Presumably it's spinning on the bkl.  Is this actually an SMP machine?  If
so, perhaps some other process is holding the bkl for a long time.  Perhaps
a netdevice spending a long time diddling hardware in an ioctl, something
like that.

>  (2) Are the {un}lock_kernel calls really needed?

Definitely not.

That code could be converted to the kthread API btw.

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

* Re: Unusually long delay in the kernel
  2005-09-17  6:52 ` Andrew Morton
@ 2005-09-17 22:15   ` Alan Stern
  2005-09-17 23:41     ` Andrew Morton
  0 siblings, 1 reply; 9+ messages in thread
From: Alan Stern @ 2005-09-17 22:15 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel

On Fri, 16 Sep 2005, Andrew Morton wrote:

> Alan Stern <stern@rowland.harvard.edu> wrote:
> >
> > This code excerpt is taken from the start of the control thread for the 
> >  usb-storage driver in 2.6.14-rc1:
> > 
> > 
> >  static int usb_stor_control_thread(void * __us)
> >  {
> >  	struct us_data *us = (struct us_data *)__us;
> >  	struct Scsi_Host *host = us_to_host(us);
> > 
> >  printk(KERN_INFO "Before thread start\n");
> >  	lock_kernel();
> > 
> >  	/*
> >  	 * This thread doesn't need any user-level access,
> >  	 * so get rid of all our resources.
> >  	 */
> >  	daemonize("usb-storage");
> >  	current->flags |= PF_NOFREEZE;
> >  	unlock_kernel();
> >  printk(KERN_INFO "After thread start\n");
> > 
> > 
> >  The code between the two printk's takes a long time to run.  I don't have 
> >  precise numbers, but it feels like more than 1 second.
> > 
> >  (1) Can anyone explain why, or indicate how to speed it up?
> 
> What's it doing at the time?  (kgdb is great for this sort of thing: hit
> ^C, go for a wander through the thread callchains).
> 
> Presumably it's spinning on the bkl.  Is this actually an SMP machine?  If
> so, perhaps some other process is holding the bkl for a long time.  Perhaps
> a netdevice spending a long time diddling hardware in an ioctl, something
> like that.

I need to do more precise tests.  Some quick informal tests indicated that 
the lock_kernel call and the daemonize call each took a noticeable time.  
I'll respond later with more details.

> >  (2) Are the {un}lock_kernel calls really needed?
> 
> Definitely not.

Good; I'll take them out.

> That code could be converted to the kthread API btw.

Hmph.  Near as I can tell, the only changes that would involve are:

	Converting the thread creation call from kernel_thread to
	kthread_run.

	Adding another call to wake the thread up once it has been
	created.

	Removing the call to daemonize.

There wouldn't be any need to call kthread_stop -- and in fact it wouldn't 
work, as the thread waits on a semaphore while it is idle (kthread_stop 
can't cope with things like that).

So overall, it appears that converting to the kthread API would add the
overhead of an extra context switch at startup and synchronous
termination, without bringing any advantages at all.


That reminds me, I've got another question.  Once a thread has called
daemonize, or if it was started using kthread_run, all its signals are
blocked.  Is it still possible that through some extraordinary
circumstance the thread could receive a signal, or are we absolutely
guaranteed that no signals will arrive until the thread enables them?  
It's important to know the answer, because normally a thread spends its
idle time waiting on down_interruptible or something similar.  If a signal
managed to get through somehow, the thread would never be able to go back
to sleep unless it explicitly flushed its signals.

(I ask because I once noticed, looking through the signal-processing code, 
that the kernel itself could send an unblockable signal.  Don't recall 
where or when, though.)

Alan Stern


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

* Re: Unusually long delay in the kernel
  2005-09-17 22:15   ` Alan Stern
@ 2005-09-17 23:41     ` Andrew Morton
  2005-09-18 15:05       ` Alan Stern
  2005-09-19 18:06       ` Unusually long delay in the kernel Alan Stern
  0 siblings, 2 replies; 9+ messages in thread
From: Andrew Morton @ 2005-09-17 23:41 UTC (permalink / raw)
  To: Alan Stern; +Cc: linux-kernel

Alan Stern <stern@rowland.harvard.edu> wrote:
>
> > Presumably it's spinning on the bkl.  Is this actually an SMP machine?  If
> > so, perhaps some other process is holding the bkl for a long time.  Perhaps
> > a netdevice spending a long time diddling hardware in an ioctl, something
> > like that.
> 
> I need to do more precise tests.  Some quick informal tests indicated that 
> the lock_kernel call and the daemonize call each took a noticeable time.  

Something odd is happening.

> > That code could be converted to the kthread API btw.
> 
> Hmph.  Near as I can tell, the only changes that would involve are:
> 
> 	Converting the thread creation call from kernel_thread to
> 	kthread_run.
> 
> 	Adding another call to wake the thread up once it has been
> 	created.
> 
> 	Removing the call to daemonize.
> 
> There wouldn't be any need to call kthread_stop -- and in fact it wouldn't 
> work, as the thread waits on a semaphore while it is idle (kthread_stop 
> can't cope with things like that).

Well I was assuming that the semaphore would go away as well.  Kernel
threads normally use waitqueues to await more work.

> 
> That reminds me, I've got another question.  Once a thread has called
> daemonize, or if it was started using kthread_run, all its signals are
> blocked.  Is it still possible that through some extraordinary
> circumstance the thread could receive a signal, or are we absolutely
> guaranteed that no signals will arrive until the thread enables them?  

Kernel threads should sleep in state TASK_INTERRUPTIBLE, with all signals
blocked.  Because they don't want to contribute to the load average, and
because they shouldn't use signals.

So if it was possible to deliver a signal to an all-signals-blocked kernel
thread, that kernel thread would go into a busy loop, because all of its
sleep attempts will fall straight through (signal_pending() is true).  So I
think it's safe to assume that nobody ever does force_sig() on a kenrel
thread.

> It's important to know the answer, because normally a thread spends its
> idle time waiting on down_interruptible or something similar.  If a signal
> managed to get through somehow, the thread would never be able to go back
> to sleep unless it explicitly flushed its signals.

Yup.

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

* Re: Unusually long delay in the kernel
  2005-09-17 23:41     ` Andrew Morton
@ 2005-09-18 15:05       ` Alan Stern
  2005-09-18 20:09         ` Andrew Morton
  2005-09-19 18:06       ` Unusually long delay in the kernel Alan Stern
  1 sibling, 1 reply; 9+ messages in thread
From: Alan Stern @ 2005-09-18 15:05 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Rusty Russell, Kernel development list

On Sat, 17 Sep 2005, Andrew Morton wrote:

> > > That code could be converted to the kthread API btw.
> > 
> > Hmph.  Near as I can tell, the only changes that would involve are:
> > 
> > 	Converting the thread creation call from kernel_thread to
> > 	kthread_run.
> > 
> > 	Adding another call to wake the thread up once it has been
> > 	created.
> > 
> > 	Removing the call to daemonize.
> > 
> > There wouldn't be any need to call kthread_stop -- and in fact it wouldn't 
> > work, as the thread waits on a semaphore while it is idle (kthread_stop 
> > can't cope with things like that).
> 
> Well I was assuming that the semaphore would go away as well.  Kernel
> threads normally use waitqueues to await more work.

Some kernel threads have a producer-consumer relationship with their
clients, and it's important that they wake exactly once each time they are
invoked.  A semaphore is the natural way to manage such a thread, but the
kthread API isn't set up to handle such things.  It's possible to make
this work, by using a manual poor-man's semaphore implementation, but that
seems ridiculous.

Would this patch be acceptable?

Alan Stern



Enhance the kthread API so that it can be used with threads that wait on a 
semaphore when they are idle.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>

--- a/include/linux/kthread.h	Mon Sep 12 23:12:09 2005
+++ b/include/linux/kthread.h	Sat Sep 17 23:24:59 2005
@@ -67,7 +67,19 @@
  *
  * Returns the result of threadfn(), or -EINTR if wake_up_process()
  * was never called. */
-int kthread_stop(struct task_struct *k);
+#define kthread_stop(k)		kthread_stop_sem(k, NULL)
+
+/**
+ * kthread_stop_sem: stop a thread created by kthread_create().
+ * @k: thread created by kthread_create().
+ * @s: semaphore that @k waits on while idle.
+ *
+ * Does essentially the same thing as kthread_stop() above, but wakes
+ * @k by calling up(@s).
+ *
+ * Returns the result of threadfn(), or -EINTR if wake_up_process()
+ * was never called. */
+int kthread_stop_sem(struct task_struct *k, struct semaphore *s);
 
 /**
  * kthread_should_stop: should this kthread return now?
--- a/kernel/kthread.c	Mon Sep 12 23:12:09 2005
+++ b/kernel/kthread.c	Sat Sep 17 23:19:08 2005
@@ -163,7 +163,7 @@
 }
 EXPORT_SYMBOL(kthread_bind);
 
-int kthread_stop(struct task_struct *k)
+int kthread_stop_sem(struct task_struct *k, struct semaphore *s)
 {
 	int ret;
 
@@ -178,7 +178,10 @@
 
 	/* Now set kthread_should_stop() to true, and wake it up. */
 	kthread_stop_info.k = k;
-	wake_up_process(k);
+	if (s)
+		up(s);
+	else
+		wake_up_process(k);
 	put_task_struct(k);
 
 	/* Once it dies, reset stop ptr, gather result and we're done. */
@@ -189,7 +192,7 @@
 
 	return ret;
 }
-EXPORT_SYMBOL(kthread_stop);
+EXPORT_SYMBOL(kthread_stop_sem);
 
 static __init int helper_init(void)
 {


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

* Re: Unusually long delay in the kernel
  2005-09-18 15:05       ` Alan Stern
@ 2005-09-18 20:09         ` Andrew Morton
  2005-09-19 14:40           ` [Proposed PATCH] Add kthread_stop_sem Alan Stern
  0 siblings, 1 reply; 9+ messages in thread
From: Andrew Morton @ 2005-09-18 20:09 UTC (permalink / raw)
  To: Alan Stern; +Cc: rusty, linux-kernel

Alan Stern <stern@rowland.harvard.edu> wrote:
>
> On Sat, 17 Sep 2005, Andrew Morton wrote:
> 
>  > > > That code could be converted to the kthread API btw.
>  > > 
>  > > Hmph.  Near as I can tell, the only changes that would involve are:
>  > > 
>  > > 	Converting the thread creation call from kernel_thread to
>  > > 	kthread_run.
>  > > 
>  > > 	Adding another call to wake the thread up once it has been
>  > > 	created.
>  > > 
>  > > 	Removing the call to daemonize.
>  > > 
>  > > There wouldn't be any need to call kthread_stop -- and in fact it wouldn't 
>  > > work, as the thread waits on a semaphore while it is idle (kthread_stop 
>  > > can't cope with things like that).
>  > 
>  > Well I was assuming that the semaphore would go away as well.  Kernel
>  > threads normally use waitqueues to await more work.
> 
>  Some kernel threads have a producer-consumer relationship with their
>  clients, and it's important that they wake exactly once each time they are
>  invoked.  A semaphore is the natural way to manage such a thread, but the
>  kthread API isn't set up to handle such things.  It's possible to make
>  this work, by using a manual poor-man's semaphore implementation, but that
>  seems ridiculous.

OK.

>  Would this patch be acceptable?

Well it makes all kthread_stop() callers pass an additional (unused)
argument.  I'd make kthread_stop() and kthread_stop_sem() real C functions,
hide the code sharing within kthread.c.


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

* [Proposed PATCH] Add kthread_stop_sem
  2005-09-18 20:09         ` Andrew Morton
@ 2005-09-19 14:40           ` Alan Stern
  0 siblings, 0 replies; 9+ messages in thread
From: Alan Stern @ 2005-09-19 14:40 UTC (permalink / raw)
  To: Andrew Morton; +Cc: rusty, linux-kernel

On Sun, 18 Sep 2005, Andrew Morton wrote:

> >  Would this patch be acceptable?
> 
> Well it makes all kthread_stop() callers pass an additional (unused)
> argument.  I'd make kthread_stop() and kthread_stop_sem() real C functions,
> hide the code sharing within kthread.c.

This may not be needed anywhere, since James Bottomley has said that the
SCSI error handler thread doesn't need a strict one-invocation <->
one-iteration relation.  I'll post it anyway just in case someone thinks
it may come in handy later.  At the moment the new routine has no callers.

Alan Stern



Signed-off-by: Alan Stern <stern@rowland.harvard.edu>

Enlarge the kthread API by adding kthread_stop_sem, for use in stopping 
threads that spend their idle time waiting on a semaphore.

Index: usb-2.6/include/linux/kthread.h
===================================================================
--- usb-2.6.orig/include/linux/kthread.h
+++ usb-2.6/include/linux/kthread.h
@@ -70,6 +70,18 @@ void kthread_bind(struct task_struct *k,
 int kthread_stop(struct task_struct *k);
 
 /**
+ * kthread_stop_sem: stop a thread created by kthread_create().
+ * @k: thread created by kthread_create().
+ * @s: semaphore that @k waits on while idle.
+ *
+ * Does essentially the same thing as kthread_stop() above, but wakes
+ * @k by calling up(@s).
+ *
+ * Returns the result of threadfn(), or -EINTR if wake_up_process()
+ * was never called. */
+int kthread_stop_sem(struct task_struct *k, struct semaphore *s);
+
+/**
  * kthread_should_stop: should this kthread return now?
  *
  * When someone calls kthread_stop on your kthread, it will be woken
Index: usb-2.6/kernel/kthread.c
===================================================================
--- usb-2.6.orig/kernel/kthread.c
+++ usb-2.6/kernel/kthread.c
@@ -165,6 +165,12 @@ EXPORT_SYMBOL(kthread_bind);
 
 int kthread_stop(struct task_struct *k)
 {
+	return kthread_stop_sem(k, NULL);
+}
+EXPORT_SYMBOL(kthread_stop);
+
+int kthread_stop_sem(struct task_struct *k, struct semaphore *s)
+{
 	int ret;
 
 	down(&kthread_stop_lock);
@@ -178,7 +184,10 @@ int kthread_stop(struct task_struct *k)
 
 	/* Now set kthread_should_stop() to true, and wake it up. */
 	kthread_stop_info.k = k;
-	wake_up_process(k);
+	if (s)
+		up(s);
+	else
+		wake_up_process(k);
 	put_task_struct(k);
 
 	/* Once it dies, reset stop ptr, gather result and we're done. */
@@ -189,7 +198,7 @@ int kthread_stop(struct task_struct *k)
 
 	return ret;
 }
-EXPORT_SYMBOL(kthread_stop);
+EXPORT_SYMBOL(kthread_stop_sem);
 
 static __init int helper_init(void)
 {


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

* Re: Unusually long delay in the kernel
  2005-09-17 23:41     ` Andrew Morton
  2005-09-18 15:05       ` Alan Stern
@ 2005-09-19 18:06       ` Alan Stern
  1 sibling, 0 replies; 9+ messages in thread
From: Alan Stern @ 2005-09-19 18:06 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel

On Sat, 17 Sep 2005, Andrew Morton wrote:

> Alan Stern <stern@rowland.harvard.edu> wrote:
> >
> > > Presumably it's spinning on the bkl.  Is this actually an SMP machine?  If
> > > so, perhaps some other process is holding the bkl for a long time.  Perhaps
> > > a netdevice spending a long time diddling hardware in an ioctl, something
> > > like that.
> > 
> > I need to do more precise tests.  Some quick informal tests indicated that 
> > the lock_kernel call and the daemonize call each took a noticeable time.  
> 
> Something odd is happening.

Forget about this.  It turned out to be an unexpected side effect from the 
problems with the SCSI error handler.  Once that was fixed, the delay went 
away.

Alan Stern


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

end of thread, other threads:[~2005-09-19 18:06 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-09-16 16:42 Unusually long delay in the kernel Alan Stern
2005-09-16 17:58 ` Fawad Lateef
2005-09-17  6:52 ` Andrew Morton
2005-09-17 22:15   ` Alan Stern
2005-09-17 23:41     ` Andrew Morton
2005-09-18 15:05       ` Alan Stern
2005-09-18 20:09         ` Andrew Morton
2005-09-19 14:40           ` [Proposed PATCH] Add kthread_stop_sem Alan Stern
2005-09-19 18:06       ` Unusually long delay in the kernel Alan Stern

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

Powered by JetHome