在编写工作队列的小例子时,遇到
error: macro "INIT_WORK" passed 3 arguments, but takes just 2
从2.6.20的内核开始,INIT_WORK宏做了改变,
原来是三个参数,后来改成了两个参数
from
于是就让我们来仔细看看INIT_WORK和INIT_DELAYED_WORK.其实前者是后者的一个特例,它们涉及到的就是传说中的工作队列.这两个宏都定义于include/linux/workqueue.h中:
解决方法:
http://ubuntuforums.org/showthread.php?t=441180
Change the following lines:
static void ppsc_tq_int (void *data)
change to
static void ppsc_tq_int (struct work_struct *data)
INIT_WORK (&pha->wq, ppsc_tq_int, pha);
change to
INIT_WORK (&pha->wq, ppsc_tq_int);
成功!
另一个解决方法:container_of(不过没试过)
http://www.linuxsir.org/bbs/thread310620.html
=>
==>
http://lwn.net/Articles/213149/
(1) Any work_struct struct that has one of the following called upon it:
queue_delayed_work()
queue_delayed_work_on()
schedule_delayed_work()
schedule_delayed_work_on()
cancel_rearming_delayed_work()
cancel_rearming_delayed_workqueue()
cancel_delayed_work()
(2) A delayed_work struct must be initialised with:
__DELAYED_WORK_INITIALIZER
DECLARE_DELAYED_WORK
INIT_DELAYED_WORK
__WORK_INITIALIZER
DECLARE_WORK
INIT_WORK
(3) The initialisation functions no longer take a data argument, and this
(4) Anywhere one of the following is called on a delayed_work struct:
queue_work()
queue_work_on()
schedule_work()
schedule_work_on()
queue_delayed_work()
queue_delayed_work_on()
schedule_delayed_work()
schedule_delayed_work_on()
(5) Anywhere the work item's pending flag is examined directly with:
test_bit(0, &work->pending)
work_pending(work)
delayed_work_pending(work)
(6) The work function _must_ be changed to conform to the following prototype:
void foo_work_func(struct work_struct *work)
{
...
}
struct foo {
struct work_struct worker;
...
};
void foo_work_func(struct work_struct *work)
{
struct foo *foo = container_of(work, struct foo, worker);
...
}
If the work_struct can be placed at the beginning of the containing
structure this will eliminate the subtraction instruction
container_of() might otherwise require.
struct foo {
struct delayed_work worker;
...
};
void foo_work_func(struct work_struct *work)
{
struct foo *foo = container_of(work, struct foo, worker.work);
...
}
NOTE!
work_struct pointed to is embedded within the delayed_work.
The handler would then be formed as for (b) or (c), and the extra
variable accessed after the container_of() line.
Quite often there's a linked pair of structures, with a work_struct in
one being initialised with the address of the other as its datum.
typical case is struct net_device and the private data.
just adding a back pointer from the private data to the net_device
struct seems to work.
DECLARE_WORK_NAR
DECLARE_DELAYED_WORK_NAR
INIT_WORK_NAR
INIT_DELAYED_WORK_NAR
__WORK_INITIALIZER_NAR
__DELAYED_WORK_INITIALIZER_NAR
These take the same arguments as the normal initialisers, but set a
flag in the work_struct to indicate that the pending flag is not to be
cleared before the work function is called.
The datum is then stored in an extra variable in the container:
struct foo {
struct work_struct worker;
void *worker_data;
...
};
And a work item is initialised with something like this:
void thing(struct foo *foo)
{
...
INIT_WORK_NAR(&foo->worker, foo_work_func);
foo->worker_data = silly_data;
...
}
And then the work function releases the work item itself when it has
extracted the auxiliary data:
void foo_work_func(struct work_struct *work)
{
struct foo *foo = container_of(work, struct foo, worker);
void *silly_data = foo->worker_data;
work_release(work);
...
}
As an added bonus, you can have multiple auxiliary data if you so
desire.
(7) If the work function was being called directly, then rather than passing
void call_work(struct foo *foo)
{
...
- foo_work_func(foo);
+ foo_work_func(&foo->worker);
...
}
void call_work(struct foo *foo)
{
...
- foo_work_func(foo);
+ foo_work_func(&foo->worker.work);
...
}