Hi,
I'm just trying to figure out how the wait&wake_up functions are working. As starting point I modified a 'hello world' modul that does only output "Hello World" so nothing special. Then I added one hrtimer and it's working. The point I'm stuck is the wake_up part :/
I had a look at and simply tried to imitate what's done there....but the condition "flag==1" seems always to be false. At first I used the counter variable 'counter' but it's condition was also never true...
Any ideas? Help?
I'm just trying to figure out how the wait&wake_up functions are working. As starting point I modified a 'hello world' modul that does only output "Hello World" so nothing special. Then I added one hrtimer and it's working. The point I'm stuck is the wake_up part :/
I had a look at and simply tried to imitate what's done there....but the condition "flag==1" seems always to be false. At first I used the counter variable 'counter' but it's condition was also never true...
Any ideas? Help?
#include <linux/wait.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/device.h> #include <asm/uaccess.h> /////////////////////////////////////////////////////////////////////////////// #include <linux/hrtimer.h> #include <linux/ktime.h> static struct hrtimer hr_timer; static int counter=0; static ktime_t interval; static atomic_t flag; static DECLARE_WAIT_QUEUE_HEAD(wait_queue_for_read); /////////////////////////////////////////////////////////////////////////////// static dev_t tim_dev_number; static struct cdev *driver_object; static struct class *tim_class; static struct device *tim_dev; enum hrtimer_restart my_hrtimer_callback(struct hrtimer *timer) { ktime_t now; printk(KERN_DEBUG "HR Timer callback function called, %d\n", counter); if(counter < 2) { now = hrtimer_cb_get_time(timer); hrtimer_forward(timer, now, interval); counter++; return HRTIMER_RESTART; } else { atomic_set(&flag, 1); wake_up_interruptible(&wait_queue_for_read); return HRTIMER_NORESTART; } } static int driver_open(struct inode *inode, struct file *filp) { ktime_t ktime; counter = 0; atomic_set(&flag, 0); printk(KERN_DEBUG "HR Timer fired up\n"); interval = ktime_set(1, 1000000000); hrtimer_init(&hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hr_timer.function = &my_hrtimer_callback; // printk( "Starting timer to fire in %ldms (%ld)\n", delay_in_ms, jiffies ); hrtimer_start(&hr_timer, ktime, HRTIMER_MODE_REL); // init_waitqueue_head(&wait_queue_for_read); return 0; } static int driver_close(struct inode *inode, struct file *filp) { int ret; ret = hrtimer_cancel(&hr_timer); if (ret) printk(KERN_DEBUG "The timer was still in use...\n"); printk(KERN_DEBUG "driver_close called\n"); return 0; } static ssize_t driver_read(struct file *filp, char __user *ubuf, size_t count, loff_t *offset) { unsigned long not_copied, to_copy; wait_event_interruptible(wait_queue_for_read, atomic_read(&flag)==1); // wait_event_interruptible(wait_queue_for_read, counter>1); to_copy = min( count, strlen("Hello World\n")+1); not_copied = copy_to_user(ubuf, "Hello World", to_copy); return to_copy - not_copied; } static struct file_operations fops = { .owner = THIS_MODULE, .read = driver_read, .open = driver_open, .release= driver_close, }; static int __init mod_init(void) { if(alloc_chrdev_region(&tim_dev_number,0,1,"Hello") < 0) return -EIO; driver_object = cdev_alloc(); if(driver_object == NULL) goto free_device_number; driver_object->owner = THIS_MODULE; driver_object->ops = &fops; if(cdev_add(driver_object, tim_dev_number,1)) goto free_cdev; tim_class = class_create(THIS_MODULE, "Hello"); if( IS_ERR(tim_class) ) { printk(KERN_ERR "no udev support\n"); goto free_cdev; } tim_dev = device_create(tim_class, NULL, tim_dev_number, NULL, "%s", "tim"); return 0; free_cdev: kobject_put(&driver_object->kobj); free_device_number: unregister_chrdev_region(tim_dev_number, 1); return -EIO; } static void __exit mod_exit(void) { device_destroy(tim_class, tim_dev_number); class_destroy(tim_class); cdev_del(driver_object); unregister_chrdev_region(tim_dev_number, 1); return; } module_init(mod_init); module_exit(mod_exit); MODULE_AUTHOR("me"); MODULE_LICENSE("GPL");