#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/spinlock.h>
#include <asm/io.h>

static int major;
static char *name = "foo";
static volatile int count = 0;

spinlock_t lock_a = SPIN_LOCK_UNLOCKED;
spinlock_t lock_b = SPIN_LOCK_UNLOCKED;

int 
foo_open(struct inode* inode, struct file *filp)
{
	return 0;
}
	
ssize_t 
foo_read(struct file *filp, char *buf, 
	size_t n, loff_t *offp)
{
	spin_lock(&lock_b);
	spin_lock(&lock_a);
	/* Dummy critical section */
	count++;	
	spin_unlock(&lock_b);
	spin_unlock(&lock_a);
	return 0;
}

ssize_t 
foo_write(struct file *filp, const char *buf, 
	size_t n, loff_t *offp)
{
	spin_lock(&lock_a);
	spin_lock(&lock_b);
	/* Dummy critical section */
	count++;
	spin_unlock(&lock_a);
	spin_unlock(&lock_b);
	
	return n;
}

struct file_operations fops = {
		.open = foo_open, 
		.read = foo_read, 
		.write = foo_write
};

static int hello_init(void)
{
	count = 0;
	printk("loading..count = %u\n", count);
	major = register_chrdev(0,name, &fops);
	printk("got major = %d\n", major);
	if (major < 0) return major;
	return 0;
}

static void hello_exit(void)
{
	unregister_chrdev(major, name);
	printk("Hello cleaning up...\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");