Setup_timer and its uses

So, today lets talk about setup_timer function as that is what I have been up to the past couple of weeks along with some other functions. Yes, I know I should have write about it 2 weeks ago but I was kind of busy with some other stuff along with my internship. 😦 That’s why didn’t find time to dedicate a proper blog to my work. Anyways, I am going to write 2 blogs about the work I did till now. In this blog I will write about setup_timer function and some interesting things I encountered while working with it.

Basically definition of setup_timer function unfolds to __setup_timer which goes like this:


#define __setup_timer(_timer, _fn, _data, _flags)
do {
__init_timer((_timer), (_flags));
(_timer)->function = (_fn);
(_timer)->data = (_data);
} while (0)

So, thing is we can use setup_timer instead of structure field assignments to initialize a timer. But its not always necessary that call to init_ and the initialization of the function & data fields occur in the order shown in the definition. It may possible that code can be something like this:

init_timer(&mp->mib_counters_timer);
mp->mib_counters_timer.data = (unsigned long)mp;
mp->mib_counters_timer.function = mib_counters_timer_wrapper;
[From file : drivers/net/ethernet/marvell/mv643xx_eth.c]

Actually for using setup_timer we can consider following cases:
1. init_timer first, function & data initialization after
a)function first then data
b)data first then function
2. function and data before, init_timer after
a)function first then data
b)data first then function
3. init_timer first then function (no data)
4. function first then data (no data)

Here, is a Coccinelle semantic patch:

@match_immediate_function_data_after_init_timer@
expression e, func, da;
@@

-init_timer(&e);
+setup_timer(&e, func, da);

(
-e.function = func;
-e.data = da;
|
-e.data = da;
-e.function = func;
)

@match_function_and_data_after_init_timer@
expression e1, e2, e3, e4, e5, a, b;
@@

-init_timer(&e1);
+setup_timer(&e1, a, b);

… when != a = e2
when != b = e3
(
-e1.function = a;
… when != b = e4
-e1.data = b;
|
-e1.data = b;
… when != a = e5
-e1.function = a;
)

@r1 exists@
identifier f;
position p;
@@

f(…) { … when any
init_timer@p(…)
… when any
}

@r2 exists@
identifier g != r1.f;
struct timer_list t;
expression e8;
@@

g(…) { … when any
t.data = e8
… when any
}

@script:python depends on r2@
p << r1.p;
@@

print “Data field initialized in another function. Dangerous to use setup_timer %s:%s” % (p[0].file,p[0].line)
cocci.include_match(False)

@r3@
expression e6, e7, c;
position r1.p;
@@

-init_timer@p(&e6);
+setup_timer(&e6, c, 0UL);
… when != c = e7
-e6.function = c;

There are 2 points about this semantic patch which I think I should write here:

  • Generally … matches with the code when there is something in between matching parts. But that doesn’t mean it do not match those code when there is nothing in between. Reason here we need this extra rule at the beginning is,  to increase the performance and speed. As when there are loops, semantic patch will take much more time than it is expected. Even with the timeout = 120 seconds, it was skipping some files. And adding one extra rule at the beginning was trivial and nicest solution of this problem. Although we are trying to look at things if we can do something else. I will update this blog if found something better. For now this works pretty fine.
  • For case 3 and 4, I observed some interesting patterns in code. We have some cases where init_ and function initialization are initialized in one function. And data is initialized in another function. In such cases it could be risky to use setup_timer. So, I just end up with one rule which matches this kind of code and gives warning. And then if no data field is found in entire file then it goes for writing data value = 0UL.

One more thing is, this is not whole semantic patch. As one can see, this is just part of it. It’s not covering all cases. But point here is this part covers most of  the cases[at least in a linux kernel] and other rules are pretty straight forward. There are two other functions, setup_timer_on_stack and setup_deferrable_timer_on_stack which can go with this semantic patch. I worked on setup_timer_on_stack and it is quite similar. So, not going to write much more about it.

By the way, I sent few patches on this and I am happy that those patches are accepted. I am going to send more. But yes still there are few points which I need to consider before adding this semantic patch in to the kernel. I think for now this is enough for this blog. I will update the blog with the complete semantic patch whenever this patch will be added in a kernel. 🙂

Advertisements