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
22#define IRQ_WORK_CLAIMED (IRQ_WORK_PENDING | IRQ_WORK_BUSY)22#define IRQ_WORK_CLAIMED (IRQ_WORK_PENDING | IRQ_WORK_BUSY)
23 23
24struct irq_work {24struct irq_work {
25 unsigned long flags;25 atomic_t flags;
26 struct llist_node llnode;26 struct llist_node llnode;
27 void (*func)(struct irq_work *);27 void (*func)(struct irq_work *);
28};28};
@@ -30,11 +30,15 @@ struct irq_work { · 1 unmodified line
30static inline30static inline
31void init_irq_work(struct irq_work *work, void (*func)(struct irq_work *))31void init_irq_work(struct irq_work *work, void (*func)(struct irq_work *))
32{32{
33 work->flags = 0;33 atomic_set(&work->flags, 0);
34 work->func = func;34 work->func = func;
35}35}
36 36
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
38 42
39bool irq_work_queue(struct irq_work *work);43bool irq_work_queue(struct irq_work *work);
40bool irq_work_queue_on(struct irq_work *work, int cpu);44bool 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
289 289
290 if (in_nmi()) {290 if (in_nmi()) {
291 work = this_cpu_ptr(&up_read_work);291 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)
293 /* cannot queue more up_read, fallback */293 /* cannot queue more up_read, fallback */
294 irq_work_busy = true;294 irq_work_busy = true;
295 }295 }
kernel/irq_work.c+9−9
@@ -29,16 +29,16 @@ static DEFINE_PER_CPU(struct llist_head, lazy_list); · 28 unmodified lines
29 */29 */
30static bool irq_work_claim(struct irq_work *work)30static bool irq_work_claim(struct irq_work *work)
31{31{
32 unsigned long flags, oflags, nflags;32 int flags, oflags, nflags;
33 33
34 /*34 /*
35 * Start with our best wish as a premise but only trust any35 * Start with our best wish as a premise but only trust any
36 * flag value after cmpxchg() result.36 * flag value after cmpxchg() result.
37 */37 */
38 flags = work->flags & ~IRQ_WORK_PENDING;38 flags = atomic_read(&work->flags) & ~IRQ_WORK_PENDING;
39 for (;;) {39 for (;;) {
40 nflags = flags | IRQ_WORK_CLAIMED;40 nflags = flags | IRQ_WORK_CLAIMED;
41 oflags = cmpxchg(&work->flags, flags, nflags);41 oflags = atomic_cmpxchg(&work->flags, flags, nflags);
42 if (oflags == flags)42 if (oflags == flags)
43 break;43 break;
44 if (oflags & IRQ_WORK_PENDING)44 if (oflags & IRQ_WORK_PENDING)
@@ -61,7 +61,7 @@ void __weak arch_irq_work_raise(void) · 16 unmodified lines
61static void __irq_work_queue_local(struct irq_work *work)61static void __irq_work_queue_local(struct irq_work *work)
62{62{
63 /* If the work is "lazy", handle it from next tick if any */63 /* 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) {
65 if (llist_add(&work->llnode, this_cpu_ptr(&lazy_list)) &&65 if (llist_add(&work->llnode, this_cpu_ptr(&lazy_list)) &&
66 tick_nohz_tick_stopped())66 tick_nohz_tick_stopped())
67 arch_irq_work_raise();67 arch_irq_work_raise();
@@ -143,7 +143,7 @@ static void irq_work_run_list(struct llist_head *list) · 75 unmodified lines
143{143{
144 struct irq_work *work, *tmp;144 struct irq_work *work, *tmp;
145 struct llist_node *llnode;145 struct llist_node *llnode;
146 unsigned long flags;146 int flags;
147 147
148 BUG_ON(!irqs_disabled());148 BUG_ON(!irqs_disabled());
149 149
@@ -159,15 +159,15 @@ static void irq_work_run_list(struct llist_head *list) · 9 unmodified lines
159 * to claim that work don't rely on us to handle their data159 * to claim that work don't rely on us to handle their data
160 * while we are in the middle of the func.160 * while we are in the middle of the func.
161 */161 */
162 flags = work->flags & ~IRQ_WORK_PENDING;162 flags = atomic_read(&work->flags) & ~IRQ_WORK_PENDING;
163 xchg(&work->flags, flags);163 atomic_xchg(&work->flags, flags);
164 164
165 work->func(work);165 work->func(work);
166 /*166 /*
167 * Clear the BUSY bit and return to the free state if167 * Clear the BUSY bit and return to the free state if
168 * no-one else claimed it meanwhile.168 * no-one else claimed it meanwhile.
169 */169 */
170 (void)cmpxchg(&work->flags, flags, flags & ~IRQ_WORK_BUSY);170 (void)atomic_cmpxchg(&work->flags, flags, flags & ~IRQ_WORK_BUSY);
171 }171 }
172}172}
173 173
@@ -199,7 +199,7 @@ void irq_work_sync(struct irq_work *work) · 25 unmodified lines
199{199{
200 lockdep_assert_irqs_enabled();200 lockdep_assert_irqs_enabled();
201 201
202 while (work->flags & IRQ_WORK_BUSY)202 while (atomic_read(&work->flags) & IRQ_WORK_BUSY)
203 cpu_relax();203 cpu_relax();
204}204}
205EXPORT_SYMBOL_GPL(irq_work_sync);205EXPORT_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
2961 2961
2962static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = {2962static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = {
2963 .func = wake_up_klogd_work_func,2963 .func = wake_up_klogd_work_func,
2964 .flags = IRQ_WORK_LAZY,2964 .flags = ATOMIC_INIT(IRQ_WORK_LAZY),
2965};2965};
2966 2966
2967void wake_up_klogd(void)2967void 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
660 return -EINVAL;660 return -EINVAL;
661 661
662 work = this_cpu_ptr(&send_signal_work);662 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)
664 return -EBUSY;664 return -EBUSY;
665 665
666 /* Add the current task, which is the target of sending signal,666 /* 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