wake_up_interruptible problem

From: Juergen Oberhofer
Date: Mon Dec 01 2003 - 11:26:06 EST


Hi,
I'm trying to implement a timer, which on each timer interrupt wakes up
every process that got blocked by a read call.
My problem is the following: if I'm insmod'ing the module (I've attached the
file) the execution gets
blocked on the wake_up_interruptible(&timer_queue); call. If I'm
uncommenting this line everything
goes smooth and the timer counts without problems. Does somebody have a
hint? Some ideas?
Regards
Juergen

void timerEvent(unsigned long arg)
{
tick_count++;
wake_up_interruptible(&timer_queue);
timer.expires= jiffies + timer_delay;
add_timer(&timer);
}

int __init init_timer_module(void)
{
/* Create the proc entry and make it readable and writeable by all -
0666 */
timer_file = create_proc_entry("timer", 0666, NULL);
if (timer_file == NULL) {
return -ENOMEM;
}

/* Set timer_file fields */
timer_file->read_proc = &proc_read_timer;
timer_file->write_proc = &proc_write_timer;
timer_file->owner = THIS_MODULE;

SET_MODULE_OWNER(&timer_fops);

/* register /dev/tick */
register_chrdev(TICK_MAJOR, "tick", &timer_fops);

init_timer(&timer);
timer.expires= jiffies + timer_delay;
timer.function=timerEvent;
timer.data=42;
add_timer(&timer);

/* everything initialized */
printk(KERN_INFO "%s %s initialized\n", MODULE_NAME, MODULE_VERSION);
return 0;
}

--
HoHoHo! Seid Ihr auch alle schön brav gewesen?

GMX Weihnachts-Special: Die 1. Adresse für Weihnachts-
männer und -frauen! http://www.gmx.net/de/cgi/specialmail

+++ GMX - die erste Adresse für Mail, Message, More! +++/*
* amu_module.c is based on procfs_example.c by Erik Mouw.
* For more information, please see The Linux Kernel Procfs Guide,
* http://kernelnewbies.org/documents/kdoc/procfs-guide/lkprocfsguide.html
*
* J.J. Boor, AimSys bv
* http://www.aimsys.nl
* jjboor@xxxxxxxxx
*/

/*
${CROSS_COMPILE}gcc -O2 -D__KERNEL__ -DMODULE amu_timer.c -o amu_timer.o

*/


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/fs.h>
#include <asm/uaccess.h>

#define TICK_MAJOR 241

#define MODULE_VERSION "0.1"
#define MODULE_NAME "timer"

static struct proc_dir_entry *timer_file;

static struct timer_list timer;
static unsigned long tick_count = 0;
static int timer_delay = 1;

DECLARE_WAIT_QUEUE_HEAD(timer_queue);

int timer_open(struct inode* inode, struct file* filp);
ssize_t timer_read (struct file *filp, char *buf, size_t count, loff_t *f_pos);
int timer_release(struct inode* inode, struct file* filp);

static struct file_operations timer_fops = {
open: timer_open,
read: timer_read,
release: timer_release
};

static int proc_read_timer(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len;
len = sprintf(page, "nr of timer ticks: %lu\n", tick_count);
return len;
}


static int proc_write_timer(struct file *file, const char *buffer,
unsigned long count, void *data)
{
return 0;
}

void timerEvent(unsigned long arg)
{
tick_count++;
wake_up_interruptible(&timer_queue);
timer.expires= jiffies + timer_delay;
add_timer(&timer);
}

int __init init_timer_module(void)
{
/* Create the proc entry and make it readable and writeable by all - 0666 */
timer_file = create_proc_entry("timer", 0666, NULL);
if (timer_file == NULL) {
return -ENOMEM;
}

/* Set timer_file fields */
timer_file->read_proc = &proc_read_timer;
timer_file->write_proc = &proc_write_timer;
timer_file->owner = THIS_MODULE;

SET_MODULE_OWNER(&timer_fops);

/* register /dev/tick */
register_chrdev(TICK_MAJOR, "tick", &timer_fops);

init_timer(&timer);
timer.expires= jiffies + timer_delay;
timer.function=timerEvent;
timer.data=42;
add_timer(&timer);

/* everything initialized */
printk(KERN_INFO "%s %s initialized\n", MODULE_NAME, MODULE_VERSION);
return 0;
}

static void __exit cleanup_timer_module(void)
{
del_timer(&timer);
remove_proc_entry("timer", NULL);
unregister_chrdev(TICK_MAJOR, "tick");

printk(KERN_INFO "%s %s removed\n", MODULE_NAME, MODULE_VERSION);
}

int timer_open(struct inode* inode, struct file* filp)
{
return 0;
}

int timer_release(struct inode* inode, struct file* filp)
{
return 0;
}

ssize_t timer_read (struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
/* dummy read to wait on kernel timer */
while (1) {
interruptible_sleep_on(&timer_queue);
if (signal_pending (current)) /* a signal arrived */
return -ERESTARTSYS; /* tell the fs layer to handle it */
else break;
}
return 0;
}

#ifdef MODULE
/* here are the compiler macros for module operation */
module_init(init_timer_module);
module_exit(cleanup_timer_module);
#endif

MODULE_AUTHOR("J.J. Boor, AimSys bv");
MODULE_DESCRIPTION("timer module");
MODULE_LICENSE("GPL");

EXPORT_NO_SYMBOLS;