0

I am trying to build e kernel module which will be used by userspace program to setup timers. I am implementing it as a character device. What is the best way to implement multiple timers in the kernel module?

Currently I have one 'timer_list*', sat 'timer'. I am assigning memory from the heap everytime I get a new request for timer and then use setup_timer() and mod_timer() to set the timer everytime I assign memory. But I am only using one pointer to the timer_list struct. But my concern here is that how to free the memory assigned to 'timer' once the callback function is called because the current value of 'timer' might not be pointing to the structure whose callback function is called.

So, I thought about passing the address of the structure in as an argument to the callback function and then call kfree() on that address.

struct timer_list *timer;
timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
setup_timer(timer, my_callback, (unsigend long)timer);

My callback function looks like this:

void my_callback (unsigned long data)
{
      struct timer_list *timer = (struct timer_list*)data;
      printk("%d\n", timer->data);
      kfree(timer);
}

In this case I am getting a segmentation fault when I try to print timer->data saying there is no page for that particular address. So, is the the memoery allocated to timer_list freed when the callback function is called. In that case I dont need to worry about freeing the memory.

Also, is there a better way to implement this thing. Also, to keep a track of all the timers (like checking like existence of a timer), is it adivasable to maintain something like a linked-list or there is some kernel function to check this?

Poojan
  • 3,312
  • 4
  • 20
  • 23
  • Maybe look at http://stackoverflow.com/questions/9662193/how-to-access-kernel-space-from-user-spacein-linux . I think you will have to copy your data from kernel to user space as the user-space code cannot access kernel memory. – JimmyB Oct 09 '13 at 14:27
  • @HannoBinder thanks, but I did not really find anything that answers my question on the link you mentioned – Poojan Oct 09 '13 at 14:34
  • I wanted to point to some reference on how to exchange data between kernel and user space. - Stupid question: Does the kmalloc succeed? Is the address returned actually the same as the one passed to the callback? – JimmyB Oct 09 '13 at 15:02
  • My problem here is to make sure that memory allocated to pointer to timer_list is freed correctly. Yes, kmalloc is working fine and even the callback function is called, so kmalloc is definitely working. And yes, both the addresses are same – Poojan Oct 09 '13 at 15:14
  • As you are "getting a segmentation fault when I try to print" I think you will want to get that fixed first. – JimmyB Oct 09 '13 at 15:23
  • I believe I am getting that because when the callback function is called, the timer_list structure is freed automatically. If that is the case, my problem no longer exists – Poojan Oct 09 '13 at 15:25
  • `timer_list` is not freed automatically, you freed it with `kfree()` in your callback. So you are removoving the `timer_list` while your timer is running. I think that is the problem with your segmentation fault – Federico Oct 10 '13 at 07:47

1 Answers1

1

In some way you have to take track of all your timers. You can use, for example, a list (see list.h) of your pending timers. Then, you can loop on your list to check if any timer already expired and release its memory (and remove from the list). You can do this before allocate a new timer.

timer_list is not freed automatically because you can re-program it with mod_timer()

Federico
  • 3,782
  • 32
  • 46
  • That helps a lot! In that case I don't know why I am getting a segmentation fault when I try to free `timer_list` using kfree() – Poojan Oct 10 '13 at 14:30
  • It depends where you use `kfree()`. In your example you are invalidating the `timer_list` memory while in use. Probably it is not `kfree()` that fails, but something that use the `timer_list` memory after you did `kfree()` – Federico Oct 10 '13 at 14:33