.. | .. |
---|
61 | 61 | * interrupt handler after suspending interrupts. For system |
---|
62 | 62 | * wakeup devices users need to implement wakeup detection in |
---|
63 | 63 | * their interrupt handlers. |
---|
| 64 | + * IRQF_NO_SOFTIRQ_CALL - Do not process softirqs in the irq thread context (RT) |
---|
64 | 65 | */ |
---|
65 | 66 | #define IRQF_SHARED 0x00000080 |
---|
66 | 67 | #define IRQF_PROBE_SHARED 0x00000100 |
---|
.. | .. |
---|
74 | 75 | #define IRQF_NO_THREAD 0x00010000 |
---|
75 | 76 | #define IRQF_EARLY_RESUME 0x00020000 |
---|
76 | 77 | #define IRQF_COND_SUSPEND 0x00040000 |
---|
| 78 | +#define IRQF_NO_SOFTIRQ_CALL 0x00080000 |
---|
77 | 79 | |
---|
78 | 80 | #define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND | IRQF_NO_THREAD) |
---|
79 | 81 | |
---|
.. | .. |
---|
427 | 429 | bool state); |
---|
428 | 430 | |
---|
429 | 431 | #ifdef CONFIG_IRQ_FORCED_THREADING |
---|
| 432 | +# ifdef CONFIG_PREEMPT_RT_BASE |
---|
| 433 | +# define force_irqthreads (true) |
---|
| 434 | +# else |
---|
430 | 435 | extern bool force_irqthreads; |
---|
| 436 | +# endif |
---|
431 | 437 | #else |
---|
432 | 438 | #define force_irqthreads (0) |
---|
433 | 439 | #endif |
---|
.. | .. |
---|
493 | 499 | void (*action)(struct softirq_action *); |
---|
494 | 500 | }; |
---|
495 | 501 | |
---|
| 502 | +#ifndef CONFIG_PREEMPT_RT_FULL |
---|
496 | 503 | asmlinkage void do_softirq(void); |
---|
497 | 504 | asmlinkage void __do_softirq(void); |
---|
498 | | - |
---|
| 505 | +static inline void thread_do_softirq(void) { do_softirq(); } |
---|
499 | 506 | #ifdef __ARCH_HAS_DO_SOFTIRQ |
---|
500 | 507 | void do_softirq_own_stack(void); |
---|
501 | 508 | #else |
---|
.. | .. |
---|
504 | 511 | __do_softirq(); |
---|
505 | 512 | } |
---|
506 | 513 | #endif |
---|
| 514 | +#else |
---|
| 515 | +extern void thread_do_softirq(void); |
---|
| 516 | +#endif |
---|
507 | 517 | |
---|
508 | 518 | extern void open_softirq(int nr, void (*action)(struct softirq_action *)); |
---|
509 | 519 | extern void softirq_init(void); |
---|
510 | 520 | extern void __raise_softirq_irqoff(unsigned int nr); |
---|
| 521 | +#ifdef CONFIG_PREEMPT_RT_FULL |
---|
| 522 | +extern void __raise_softirq_irqoff_ksoft(unsigned int nr); |
---|
| 523 | +#else |
---|
| 524 | +static inline void __raise_softirq_irqoff_ksoft(unsigned int nr) |
---|
| 525 | +{ |
---|
| 526 | + __raise_softirq_irqoff(nr); |
---|
| 527 | +} |
---|
| 528 | +#endif |
---|
511 | 529 | |
---|
512 | 530 | extern void raise_softirq_irqoff(unsigned int nr); |
---|
513 | 531 | extern void raise_softirq(unsigned int nr); |
---|
| 532 | +extern void softirq_check_pending_idle(void); |
---|
514 | 533 | |
---|
515 | 534 | DECLARE_PER_CPU(struct task_struct *, ksoftirqd); |
---|
516 | 535 | |
---|
.. | .. |
---|
532 | 551 | to be executed on some cpu at least once after this. |
---|
533 | 552 | * If the tasklet is already scheduled, but its execution is still not |
---|
534 | 553 | started, it will be executed only once. |
---|
535 | | - * If this tasklet is already running on another CPU (or schedule is called |
---|
536 | | - from tasklet itself), it is rescheduled for later. |
---|
| 554 | + * If this tasklet is already running on another CPU, it is rescheduled |
---|
| 555 | + for later. |
---|
| 556 | + * Schedule must not be called from the tasklet itself (a lockup occurs) |
---|
537 | 557 | * Tasklet is strictly serialized wrt itself, but not |
---|
538 | 558 | wrt another tasklets. If client needs some intertask synchronization, |
---|
539 | 559 | he makes it with spinlocks. |
---|
.. | .. |
---|
558 | 578 | enum |
---|
559 | 579 | { |
---|
560 | 580 | TASKLET_STATE_SCHED, /* Tasklet is scheduled for execution */ |
---|
561 | | - TASKLET_STATE_RUN /* Tasklet is running (SMP only) */ |
---|
| 581 | + TASKLET_STATE_RUN, /* Tasklet is running (SMP only) */ |
---|
| 582 | + TASKLET_STATE_PENDING, /* Tasklet is pending */ |
---|
| 583 | + TASKLET_STATE_CHAINED /* Tasklet is chained */ |
---|
562 | 584 | }; |
---|
563 | 585 | |
---|
564 | | -#ifdef CONFIG_SMP |
---|
| 586 | +#define TASKLET_STATEF_SCHED (1 << TASKLET_STATE_SCHED) |
---|
| 587 | +#define TASKLET_STATEF_RUN (1 << TASKLET_STATE_RUN) |
---|
| 588 | +#define TASKLET_STATEF_PENDING (1 << TASKLET_STATE_PENDING) |
---|
| 589 | +#define TASKLET_STATEF_CHAINED (1 << TASKLET_STATE_CHAINED) |
---|
| 590 | +#define TASKLET_STATEF_RC (TASKLET_STATEF_RUN | TASKLET_STATEF_CHAINED) |
---|
| 591 | + |
---|
| 592 | +#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT_FULL) |
---|
565 | 593 | static inline int tasklet_trylock(struct tasklet_struct *t) |
---|
566 | 594 | { |
---|
567 | 595 | return !test_and_set_bit(TASKLET_STATE_RUN, &(t)->state); |
---|
| 596 | +} |
---|
| 597 | + |
---|
| 598 | +static inline int tasklet_tryunlock(struct tasklet_struct *t) |
---|
| 599 | +{ |
---|
| 600 | + return cmpxchg(&t->state, TASKLET_STATEF_RUN, 0) == TASKLET_STATEF_RUN; |
---|
568 | 601 | } |
---|
569 | 602 | |
---|
570 | 603 | static inline void tasklet_unlock(struct tasklet_struct *t) |
---|
.. | .. |
---|
573 | 606 | clear_bit(TASKLET_STATE_RUN, &(t)->state); |
---|
574 | 607 | } |
---|
575 | 608 | |
---|
576 | | -static inline void tasklet_unlock_wait(struct tasklet_struct *t) |
---|
577 | | -{ |
---|
578 | | - while (test_bit(TASKLET_STATE_RUN, &(t)->state)) { barrier(); } |
---|
579 | | -} |
---|
| 609 | +extern void tasklet_unlock_wait(struct tasklet_struct *t); |
---|
| 610 | + |
---|
580 | 611 | #else |
---|
581 | 612 | #define tasklet_trylock(t) 1 |
---|
| 613 | +#define tasklet_tryunlock(t) 1 |
---|
582 | 614 | #define tasklet_unlock_wait(t) do { } while (0) |
---|
583 | 615 | #define tasklet_unlock(t) do { } while (0) |
---|
584 | 616 | #endif |
---|
.. | .. |
---|
612 | 644 | smp_mb(); |
---|
613 | 645 | } |
---|
614 | 646 | |
---|
615 | | -static inline void tasklet_enable(struct tasklet_struct *t) |
---|
616 | | -{ |
---|
617 | | - smp_mb__before_atomic(); |
---|
618 | | - atomic_dec(&t->count); |
---|
619 | | -} |
---|
620 | | - |
---|
| 647 | +extern void tasklet_enable(struct tasklet_struct *t); |
---|
621 | 648 | extern void tasklet_kill(struct tasklet_struct *t); |
---|
622 | 649 | extern void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu); |
---|
623 | 650 | extern void tasklet_init(struct tasklet_struct *t, |
---|
624 | 651 | void (*func)(unsigned long), unsigned long data); |
---|
625 | 652 | |
---|
| 653 | +#ifdef CONFIG_PREEMPT_RT_FULL |
---|
| 654 | +extern void softirq_early_init(void); |
---|
| 655 | +#else |
---|
| 656 | +static inline void softirq_early_init(void) { } |
---|
| 657 | +#endif |
---|
| 658 | + |
---|
626 | 659 | struct tasklet_hrtimer { |
---|
627 | 660 | struct hrtimer timer; |
---|
628 | 661 | struct tasklet_struct tasklet; |
---|