Re: Problem with "wait_event_interruptible"

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Feb 26, 2003 at 05:09:50AM +0000, Anticipating a Reply wrote:
> Hello Jan ,
> 
>   Thanks for the reply .
> 
>  I understood that we need to do both ,i.e. 
> satisfy condition & also wakeup , to come out
> of "wait_event_interruptible()".
>  
>  But this can be achieved using 
> "sleep_on_interruptible" and doing a
> "wakeup_interruptible" after checking 
> the condition .

The difference between wake_up and wake_up_interruptible is a bit
strange. You should mostly use plain wake_up, which wakes up both
TASK_INTERRUPTIBLE and TASK_UNINTERRUPTIBLE processes.
wake_up_interruptible is for special purposes where you need to wake the
interruptible sleepers only.

>  Does "wait_event_interruptible" 
> need to be used in any specific 
> scenario or in any particular 
> situation ?

wait_on[_interruptible] is a simple macro around sleep_on!

It merely does the three things - puting yourself to the queue, seting
TASK_[UN]INTERRUPTIBLE state, checking the condition and actualy calling
schedule() in correct order so you can't miss a wake up. So for the
common case it saves you some thinking (note that there is no lock - you
must assure "atomicity" with correct oredering).

Note, that it you use the _interruptible variant, you MUST check the
return value and if it returns -ERESTARTSYS, you must return to userland
either with -EINTR, -ERESTARTSYS or -ERESTARTNOHAND so pendings signals
can be handled.  If you return -EINTR, the value is simply propagated to
userland. If you return -ERESTARTSYS, signal is handled and your syscall
is restarted (unless the signal terminated or the handler exited via
a longjump). If you return -ERESTARTNOHAND, your syscall is restarted
if the signal was ignored (that is if there is no handler and the action
is not to terminate the process (poll uses this)).

Other note: in kernel thread, there is no userland to handle signals. So
there is no point in interruptible sleep.

Important note: you can only sleep in process context. That is, not in
interrupts, bottom halves and tasklets.

>   Kindly explain ,where specifically
> do we need to use each of these variants
> of wait-sleeps  ?
> 
>   Thanks in advance .
> 
> Regards !
> 
>  --- Jan Hudec <bulb@ucw.cz> wrote: > On Mon, Feb 24,
> 2003 at 11:45:55AM +0000,
> > Anticipating a Reply wrote:
> > > Hello All ,
> > > 
> > >     I'am facing a problem in the following 
> > > kernel module for a 2.4.16 kernel .
> > >  Here I'am not getting 
> > > the expected behaviour of
> > "wait_event_interruptible".
> > 
> > You are geting the expected behaviour. You are not
> > waking up the queue!
> > 
> > The wait_event_interruptible goes to sleep while the
> > condition is false.
> > When it goes to sleep, you need to wake it up. You
> > need to:
> > flag = 1;
> > wake_up(my_queue);
> > 
> > Note: You should use atomic operations for the flag
> > ;-).
> > 
> > >   Basically I'am trying to sleep on a 
> > > a condition (.i.e. a flag value is 0 ) in 
> > > "read "implementation . I have implemented 
> > > the unlocking mechanism in "write" implementation
> > > (.ie. flag=1 ).
> > > 
> > >   But the "read" implementation continues
> > > to remain blocked , even if the condition
> > > is satisfied when a "write" to the device
> > >  is done . 
> > > 
> > >   Kindly suggest me if I'am doing something 
> > > wrong . I have the code of the driver and 
> > > test routines below .
> > >   
> > >    Thank you in Advance .
> > > 
> > > Regards
> > > 
> > >
> > /***************************************************
> > > 
> > >     Trying to write a Kernel module 
> > >     which shows the usage of kernel waitqueue
> > > 
> > > The device acessed is having major=222 minor=0
> > > 
> > > This module is compiled as :
> > >  
> > >   cc -c my.c -I/usr/src/linux/include
> > > 
> > > and inserted as module using :
> > > 
> > >   insmod my.o my_major=222
> > > 	
> > >
> >
> ****************************************************/
> > > 
> > > #ifndef __KERNEL__
> > > #  define __KERNEL__
> > > #endif
> > > 
> > > #ifndef MODULE
> > > #  define MODULE
> > > #endif
> > > 
> > > #include <linux/config.h>
> > > #include <linux/module.h>
> > > 
> > > #include <linux/kernel.h>   /* printk() */
> > > #include <linux/slab.h>     /* kmalloc() */
> > > #include <linux/fs.h>       /* everything... */
> > > #include <linux/errno.h>    /* error codes */
> > > #include <linux/types.h>    /* size_t */
> > > #include <linux/wait.h>
> > > #include <asm/page.h>
> > > 
> > > /* Device Major Number */
> > > static int my_major = 0;
> > > 
> > > MODULE_PARM(my_major, "i");
> > > MODULE_AUTHOR("learner");
> > > 
> > > int flag ;
> > > 
> > > /* Wait queue for this device */
> > > wait_queue_head_t my_queue ;
> > > 
> > > /*
> > >  * Forwards for our methods.
> > >  */
> > > int my_open (struct inode *inode, struct file
> > *filp);
> > > ssize_t my_read(struct file *filp, char *buf,
> > size_t
> > > count, loff_t *f_pos);
> > > ssize_t my_write(struct file *filp, const char
> > *buf,
> > > size_t count, loff_t *f_pos);
> > > int my_release(struct inode *inode, struct file
> > > *filp);
> > > 
> > > 
> > > struct file_operations my_ops = {
> > > 	read:    my_read,
> > > 	write:   my_write,
> > >     open:    my_open,
> > > 	release: my_release,
> > > };
> > > 
> > > 
> > > /*
> > >  * Open the device; all we have to do here is to
> > up
> > > the usage count and
> > >  * set the right fops.
> > >  */
> > > int my_open(struct inode *inode, struct file
> > *filp)
> > > {
> > >     MOD_INC_USE_COUNT;
> > > 	return 0;
> > > }
> > > 
> > > /*
> > >  * Reading the Device 
> > >  */
> > > ssize_t my_read(struct file *filp, char *buf,
> > size_t
> > > count,loff_t *f_pos)
> > > {
> > >     printk( KERN_WARNING "read: Going to sleep on
> > wait
> > > queue" );  
> > > 	wait_event_interruptible( my_queue, flag );
> > >     printk( KERN_WARNING "read: Come out of sleep
> > in
> > > wait queue" );  
> > >     printk( KERN_WARNING "read: Data Value %d \n",
> > > flag );  
> > > 	return 0;
> > > }
> > > 
> > > /*
> > >  * Writing the Device 
> > >  */
> > > ssize_t my_write(struct file *filp, const char
> > *buf,
> > > size_t count,loff_t *f_pos)
> > > {
> > >    printk( KERN_WARNING "write: Going to wake up
> > > sleeping processes");  
> > >    flag=1 ;	
> > >    return 0;
> > > }
> > > 
> > > /*
> > >  * Closing the Device 
> > >  */
> > > int my_release(struct inode *inode, struct file
> > *filp)
> > > {
> > >     MOD_DEC_USE_COUNT;
> > >     return 0;
> > > }
> > > 
> > > /*
> > >  * Module housekeeping.
> > >  */
> > > static int my_init(void)
> > > {
> > >     int result;
> > > 
> > >     SET_MODULE_OWNER(&my_ops);
> > > 
> > >     result = register_chrdev(my_major, "my",
> > &my_ops);
> > >     if (result < 0)
> > >     {
> > >         printk(KERN_WARNING "my: unable to get
> > major
> > > %d\n", my_major);
> > >         return result;
> > >     }
> > > 	
> > >     if (my_major == 0)
> > >         my_major = result;
> > >     
> > > 	init_waitqueue_head( &my_queue );
> > >     printk(KERN_WARNING "init: Initialised Wait
> > queue
> > > \n");
> > >     
> > > 	/* Initializing condition Flag to zero */
> > > 	flag = 0 ;
> > > 
> > >     return 0;
> > > }
> > > 
> > > static void my_cleanup(void)
> > > {
> > >     unregister_chrdev(my_major, "my");
> > > }
> > > 
> > > module_init(my_init);
> > > module_exit(my_cleanup);
> > > 
> > >
> >
> *******************************************************
> > > TEST ROUTINES 
> > >
> > ****************************************************
> > > 
> > > /* rtest : Program to read device 
> > >    ---------- it should block till the device
> > writes
> > > to device
> > > */
> > > 
> > > #include<fcntl.h>
> > > 
> > > main()
> > > {
> > > 
> > >   int fd ;
> > > 
> > >   int data ;
> > > 
> > >   fd = open("mydev",O_RDONLY );
> > > 
> > >   read( fd, &data, sizeof(data) ); 
> > > 
> > > 
> > >  }
> > > 
> > > /* wtest : Program to write device
> > >     ---------- it should unblocks device blocked
> > on
> > > read
> > >  */
> > > 
> > > #include<fcntl.h>
> > > 
> > > main()
> > > {
> > > 
> > >   int fd ;
> > > 
> > >   int data =0 ;
> > > 
> > >   fd = open("mydev",O_WRONLY );
> > > 
> > >   write( fd, &data, sizeof(data) ); 
> > > 
> > >  }
> > > ********************************************
> > > 
> > > 
> > >
> >
> ________________________________________________________________________
> > > Missed your favourite TV serial last night? Try
> > the new, Yahoo! TV.
> > >        visit http://in.tv.yahoo.com
> > > --
> > > Kernelnewbies: Help each other learn about the
> > Linux kernel.
> > > Archive:      
> > http://mail.nl.linux.org/kernelnewbies/
> > > FAQ:           http://kernelnewbies.org/faq/
> > > 
> >
> -------------------------------------------------------------------------------
> > 						 Jan 'Bulb' Hudec <bulb@ucw.cz>
> > --
> > Kernelnewbies: Help each other learn about the Linux
> > kernel.
> > Archive:      
> > http://mail.nl.linux.org/kernelnewbies/
> > FAQ:           http://kernelnewbies.org/faq/
> > 
> 
> ________________________________________________________________________
> Missed your favourite TV serial last night? Try the new, Yahoo! TV.
>        visit http://in.tv.yahoo.com
> 
-------------------------------------------------------------------------------
						 Jan 'Bulb' Hudec <bulb@ucw.cz>
--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
FAQ:           http://kernelnewbies.org/faq/


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux