History

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. ]

Frederic Weisbecker committed 7 years ago

Commit 153bedb1 parent 31f4f5b5 files · +19 −15Browse files

Unified · Split

5 files
  1. include/linux/irq_work.h +7 −3
  2. kernel/bpf/stackmap.c +1 −1
  3. kernel/irq_work.c +9 −9
  4. kernel/printk/printk.c +1 −1
  5. kernel/trace/bpf_trace.c +1 −1
include/linux/irq_work.h+7−3
@@ -22,7 +22,7 @@ · 21 unmodified lines
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 };
@@ -30,11 +30,15 @@ struct irq_work { · 1 unmodified line
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+1−1
@@ -289,7 +289,7 @@ static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs, · 288 unmodified lines
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+9−9
@@ -29,16 +29,16 @@ static DEFINE_PER_CPU(struct llist_head, lazy_list); · 28 unmodified lines
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) · 16 unmodified lines
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) · 75 unmodified lines
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) · 9 unmodified lines
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) · 25 unmodified lines
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+1−1
@@ -2961,7 +2961,7 @@ static void wake_up_klogd_work_func(struct irq_work *irq_work) · 2960 unmodified lines
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+1−1
@@ -660,7 +660,7 @@ BPF_CALL_1(bpf_send_signal, u32, sig) · 659 unmodified lines
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,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t