Skip to content

Commit 153bedb

Browse files
Frederic WeisbeckerIngo Molnar
authored andcommitted
irq_work: Convert flags to atomic_t
We need to convert flags to atomic_t in order to later fix an ordering issue on atomic_cmpxchg() failure. This will allow us to use atomic_fetch_or(). Also clarify the nature of those flags. [ mingo: Converted two more usage site the original patch missed. ] Signed-off-by: Frederic Weisbecker <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Paul E . McKenney <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent 31f4f5b commit 153bedb

File tree

5 files changed

+19
-15
lines changed

5 files changed

+19
-15
lines changed

include/linux/irq_work.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,23 @@
2222
#define IRQ_WORK_CLAIMED (IRQ_WORK_PENDING | IRQ_WORK_BUSY)
2323

2424
struct irq_work {
25-
unsigned long flags;
25+
atomic_t flags;
2626
struct llist_node llnode;
2727
void (*func)(struct irq_work *);
2828
};
2929

3030
static inline
3131
void init_irq_work(struct irq_work *work, void (*func)(struct irq_work *))
3232
{
33-
work->flags = 0;
33+
atomic_set(&work->flags, 0);
3434
work->func = func;
3535
}
3636

37-
#define DEFINE_IRQ_WORK(name, _f) struct irq_work name = { .func = (_f), }
37+
#define DEFINE_IRQ_WORK(name, _f) struct irq_work name = { \
38+
.flags = ATOMIC_INIT(0), \
39+
.func = (_f) \
40+
}
41+
3842

3943
bool irq_work_queue(struct irq_work *work);
4044
bool irq_work_queue_on(struct irq_work *work, int cpu);

kernel/bpf/stackmap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
289289

290290
if (in_nmi()) {
291291
work = this_cpu_ptr(&up_read_work);
292-
if (work->irq_work.flags & IRQ_WORK_BUSY)
292+
if (atomic_read(&work->irq_work.flags) & IRQ_WORK_BUSY)
293293
/* cannot queue more up_read, fallback */
294294
irq_work_busy = true;
295295
}

kernel/irq_work.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,16 @@ static DEFINE_PER_CPU(struct llist_head, lazy_list);
2929
*/
3030
static bool irq_work_claim(struct irq_work *work)
3131
{
32-
unsigned long flags, oflags, nflags;
32+
int flags, oflags, nflags;
3333

3434
/*
3535
* Start with our best wish as a premise but only trust any
3636
* flag value after cmpxchg() result.
3737
*/
38-
flags = work->flags & ~IRQ_WORK_PENDING;
38+
flags = atomic_read(&work->flags) & ~IRQ_WORK_PENDING;
3939
for (;;) {
4040
nflags = flags | IRQ_WORK_CLAIMED;
41-
oflags = cmpxchg(&work->flags, flags, nflags);
41+
oflags = atomic_cmpxchg(&work->flags, flags, nflags);
4242
if (oflags == flags)
4343
break;
4444
if (oflags & IRQ_WORK_PENDING)
@@ -61,7 +61,7 @@ void __weak arch_irq_work_raise(void)
6161
static void __irq_work_queue_local(struct irq_work *work)
6262
{
6363
/* If the work is "lazy", handle it from next tick if any */
64-
if (work->flags & IRQ_WORK_LAZY) {
64+
if (atomic_read(&work->flags) & IRQ_WORK_LAZY) {
6565
if (llist_add(&work->llnode, this_cpu_ptr(&lazy_list)) &&
6666
tick_nohz_tick_stopped())
6767
arch_irq_work_raise();
@@ -143,7 +143,7 @@ static void irq_work_run_list(struct llist_head *list)
143143
{
144144
struct irq_work *work, *tmp;
145145
struct llist_node *llnode;
146-
unsigned long flags;
146+
int flags;
147147

148148
BUG_ON(!irqs_disabled());
149149

@@ -159,15 +159,15 @@ static void irq_work_run_list(struct llist_head *list)
159159
* to claim that work don't rely on us to handle their data
160160
* while we are in the middle of the func.
161161
*/
162-
flags = work->flags & ~IRQ_WORK_PENDING;
163-
xchg(&work->flags, flags);
162+
flags = atomic_read(&work->flags) & ~IRQ_WORK_PENDING;
163+
atomic_xchg(&work->flags, flags);
164164

165165
work->func(work);
166166
/*
167167
* Clear the BUSY bit and return to the free state if
168168
* no-one else claimed it meanwhile.
169169
*/
170-
(void)cmpxchg(&work->flags, flags, flags & ~IRQ_WORK_BUSY);
170+
(void)atomic_cmpxchg(&work->flags, flags, flags & ~IRQ_WORK_BUSY);
171171
}
172172
}
173173

@@ -199,7 +199,7 @@ void irq_work_sync(struct irq_work *work)
199199
{
200200
lockdep_assert_irqs_enabled();
201201

202-
while (work->flags & IRQ_WORK_BUSY)
202+
while (atomic_read(&work->flags) & IRQ_WORK_BUSY)
203203
cpu_relax();
204204
}
205205
EXPORT_SYMBOL_GPL(irq_work_sync);

kernel/printk/printk.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2961,7 +2961,7 @@ static void wake_up_klogd_work_func(struct irq_work *irq_work)
29612961

29622962
static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = {
29632963
.func = wake_up_klogd_work_func,
2964-
.flags = IRQ_WORK_LAZY,
2964+
.flags = ATOMIC_INIT(IRQ_WORK_LAZY),
29652965
};
29662966

29672967
void wake_up_klogd(void)

kernel/trace/bpf_trace.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@ BPF_CALL_1(bpf_send_signal, u32, sig)
660660
return -EINVAL;
661661

662662
work = this_cpu_ptr(&send_signal_work);
663-
if (work->irq_work.flags & IRQ_WORK_BUSY)
663+
if (atomic_read(&work->irq_work.flags) & IRQ_WORK_BUSY)
664664
return -EBUSY;
665665

666666
/* Add the current task, which is the target of sending signal,

0 commit comments

Comments
 (0)