Quantcast
Channel: Linux Kernel Newbies Forum
Viewing all articles
Browse latest Browse all 7450

Blocking char device is not waking up (1 reply)

$
0
0
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?

#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");

Viewing all articles
Browse latest Browse all 7450

Trending Articles