From 042647efc85ae503bfa93ca35583a7afe20157df Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sat, 27 Oct 2012 15:21:36 +0200 Subject: [PATCH] --- yaml --- r: 349828 b: refs/heads/master c: e0bbe2d80c415bd4063d894ec2ccb336788af814 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/kernel/irq_work.c | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/[refs] b/[refs] index 8f4043b982dd..edd1050f4d57 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: c8446b75be6f85b3d40066922876cb7adc948afb +refs/heads/master: e0bbe2d80c415bd4063d894ec2ccb336788af814 diff --git a/trunk/kernel/irq_work.c b/trunk/kernel/irq_work.c index 57be1a6cd8da..64eddd59ed83 100644 --- a/trunk/kernel/irq_work.c +++ b/trunk/kernel/irq_work.c @@ -34,15 +34,21 @@ static DEFINE_PER_CPU(struct llist_head, irq_work_list); */ static bool irq_work_claim(struct irq_work *work) { - unsigned long flags, nflags; + unsigned long flags, oflags, nflags; + /* + * Start with our best wish as a premise but only trust any + * flag value after cmpxchg() result. + */ + flags = work->flags & ~IRQ_WORK_PENDING; for (;;) { - flags = work->flags; - if (flags & IRQ_WORK_PENDING) - return false; nflags = flags | IRQ_WORK_FLAGS; - if (cmpxchg(&work->flags, flags, nflags) == flags) + oflags = cmpxchg(&work->flags, flags, nflags); + if (oflags == flags) break; + if (oflags & IRQ_WORK_PENDING) + return false; + flags = oflags; cpu_relax(); }