Re: Problem with "wait_event_interruptible"

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

 



On Wed, Feb 26, 2003 at 11:47:19AM +0000, Anticipating a Reply wrote:
> Hello Jan ,
> 
>   Thanks again .
> 
>   But maybe you missed telling me how 
> 
> int wait_event_interruptible(wait_head_queue_t qu,
> int condition ); 
< 
>    is different from 
> 
> int interruptible_sleep_on(wait_head_queue_t *queue );
>   
>   I presume both are different in the 
> way they work . 

They work the same way. But wait_event[_interruptible] checks
a condition while [interruptible_]sleep_on does not.

>   So I wanted to know what are the specific 
> situations in which each of them will be used ?

If a sleep is conditional on some condition, you need wait_event. If you
want to uncodnitionaly put yourself to sleep on a wait queue, you use
sleep_on. (and respective interruptible variants).

And note, that
while(condition) sleep_on(queue);
is not the same as wait_event and is usualy WRONG.
(because there is a race condition).

I strongly suggest you take a look at the real primitives
- set_current_state and wait_queue_add.

>   I'am sorry if I could not understand the
> difference from the nice explanation you 
> have given earlier.
>
>   Thank you in advance .
> 
> Regards !
> 
> 
> 
> 
> --- Jan Hudec <bulb@ucw.cz> wrote: > 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/
> > 
> 
> ________________________________________________________________________
> 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