Initialization of the Task Force column (init_work parameter problem)

Source: Internet
Author: User

When writing a small example of a work queue, you encounter

Error:macro "Init_work" passed 3 arguments, but takes just 2

Starting with the 2.6.20 kernel, init_work macros have changed,

It turns out to be three parameters, and then it's changed to two parameters.

From http://blog.csdn.net/fudan_abc/archive/2007/08/20/1751565.aspx

So let's take a closer look at Init_work and init_delayed_work. In fact, the former is a special case of the latter, they are involved in the legendary work queue. Both macros are defined in Include/linux/workqueue.h:

#define Init_work (_work, _func)/

do {/

Bayi (_work)->data = (atomic_long_t) work_data_init (); /

Init_list_head (& (_work)->entry); /

Prepare_work ((_work), (_func)); /

The while (0)

85

#define Init_delayed_work (_work, _func)/

do {/

Init_work (& (_work)->work, (_func)); /

Init_timer (& (_work)->timer); /

The while (0)

Workaround:

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

success.

Another workaround:container_of(but never tried)

http://www.linuxsir.org/bbs/thread310620.html

=>

http://rt2x00.serialmonkey.com/phpbb/viewtopic.php?f=8&t=2951&start=0&st=0&sk=t&sd=a& sid=0681e465914045dedf06f35334b99131

==>

(about Work_struct and init_work)

http://lwn.net/Articles/213149/

Okay.

(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 ()

Needs changing into a delayed_work struct.

Note this cancel_delayed_work () is often called where it's ll be ineffective
-I people misunderstand what it does.

(2) A delayed_work struct must is initialised with:

__delayed_work_initializer
Declare_delayed_work
Init_delayed_work

Rather than:

__work_initializer
Declare_work
Init_work

Those only apply to Work_struct (non-delayable work).

(3) The Initialisation functions no longer take a data argument, and this
should be deleted.

(4) Anywhere One of the following is called on a delayed_work struct:

Queue_work ()
QUEUE_WORK_ON ()
Schedule_work ()
SCHEDULE_WORK_ON ()

It must be converted to the equivalent one of:

Queue_delayed_work ()
QUEUE_DELAYED_WORK_ON ()
Schedule_delayed_work ()
SCHEDULE_DELAYED_WORK_ON ()

And given a 0 timeout argument as an additional argument. This just
Queues the work item and doesn ' t set the timer.

(5) Anywhere The work item ' s pending flag is examined directly with:

Test_bit (0, &work->pending)

This should is replaced with the appropriate one of:

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)
{
...
}

This is applies to both Work_struct and delayed_work handlers.

(a) If the Arbitary datum previously passed to the Initialiser is NULL,
Then the work argument should just be ignored.

(b) If the Datum is the address of the structure containing the
Work_struct, then something like the following should is used:

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 is placed at the beginning of the containing
Structure this would eliminate the subtraction instruction
Container_of () might otherwise require.

(c) If the Datum is the address of the structure containing the
Delayed_work, then something like the following should is used:

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! There ' s a extra ". Work" in the container_of () because the
Work_struct pointed to is embedded within the delayed_work.

(d) If The Datum is isn't a pointer to the container and but the container is
Guaranteed to exist whilst the work handler runs, then the Datum can
be stored in a extra variable in the container.

The handler would then is 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 "the other as its datum." The
Typical case is struct net_device and the private data. In the case
Just adding a back pointer of the private data to the Net_device
struct seems to work.

(e) If the auxiliary datum is totally unrelated and can ' t being stored in
Extra variable because the container might go away, then the
Work_struct or delayed_work should is initialised with one of the
instead

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" the pending flag is isn't
Cleared before the work function is called.

The datum is then stored in a extra variable in the container:

struct Foo {
struct WORK_STRUCT worker;
void *worker_data;
...
};

And a work item is initialised with something as 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, can have multiple auxiliary data if
Desire. ' re not limited to a single word.

(7) If The work function was being called directly, then rather than passing
In the auxiliary datum, you are have to pass at the address of the Work_struct
instead. So for a work_struct, your ' d change:

void Call_work (struct foo *foo)
{
...
-Foo_work_func (foo);
+ Foo_work_func (&foo->worker);
...
}

And for a delayed_work, your ' d do:

void Call_work (struct foo *foo)
{
...
-Foo_work_func (foo);
+ Foo_work_func (&foo->worker.work);
...
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.