Implement the following utility APIs. workqueue_set_max_active() : adjust max_active of a wq workqueue_congested() : test whether a wq is contested work_cpu() : determine the last / current cpu of a work work_busy() : query whether a work is busy * Anton Blanchard fixed missing ret initialization in work_busy().
Showing the changes to kernel/workqueue.c (1 of 2 files). Show all
Unified · Split
| @@ -203,7 +203,7 @@ struct workqueue_struct { · 202 unmodified lines | ||
| 203 | 203 | cpumask_var_t mayday_mask; /* cpus requesting rescue */ |
| 204 | 204 | struct worker *rescuer; /* I: rescue worker */ |
| 205 | 205 | |
| 206 | − int saved_max_active; /* I: saved cwq max_active */ | |
| 206 | + int saved_max_active; /* W: saved cwq max_active */ | |
| 207 | 207 | const char *name; /* I: workqueue name */ |
| 208 | 208 | #ifdef CONFIG_LOCKDEP |
| 209 | 209 | struct lockdep_map lockdep_map; |
| @@ -2675,6 +2675,112 @@ void destroy_workqueue(struct workqueue_struct *wq) · 2465 unmodified lines | ||
| 2675 | 2675 | } |
| 2676 | 2676 | EXPORT_SYMBOL_GPL(destroy_workqueue); |
| 2677 | 2677 | |
| 2678 | +/** | |
| 2679 | + * workqueue_set_max_active - adjust max_active of a workqueue | |
| 2680 | + * @wq: target workqueue | |
| 2681 | + * @max_active: new max_active value. | |
| 2682 | + * | |
| 2683 | + * Set max_active of @wq to @max_active. | |
| 2684 | + * | |
| 2685 | + * CONTEXT: | |
| 2686 | + * Don't call from IRQ context. | |
| 2687 | + */ | |
| 2688 | +void workqueue_set_max_active(struct workqueue_struct *wq, int max_active) | |
| 2689 | +{ | |
| 2690 | + unsigned int cpu; | |
| 2691 | + | |
| 2692 | + max_active = wq_clamp_max_active(max_active, wq->name); | |
| 2693 | + | |
| 2694 | + spin_lock(&workqueue_lock); | |
| 2695 | + | |
| 2696 | + wq->saved_max_active = max_active; | |
| 2697 | + | |
| 2698 | + for_each_possible_cpu(cpu) { | |
| 2699 | + struct global_cwq *gcwq = get_gcwq(cpu); | |
| 2700 | + | |
| 2701 | + spin_lock_irq(&gcwq->lock); | |
| 2702 | + | |
| 2703 | + if (!(wq->flags & WQ_FREEZEABLE) || | |
| 2704 | + !(gcwq->flags & GCWQ_FREEZING)) | |
| 2705 | + get_cwq(gcwq->cpu, wq)->max_active = max_active; | |
| 2706 | + | |
| 2707 | + spin_unlock_irq(&gcwq->lock); | |
| 2708 | + } | |
| 2709 | + | |
| 2710 | + spin_unlock(&workqueue_lock); | |
| 2711 | +} | |
| 2712 | +EXPORT_SYMBOL_GPL(workqueue_set_max_active); | |
| 2713 | + | |
| 2714 | +/** | |
| 2715 | + * workqueue_congested - test whether a workqueue is congested | |
| 2716 | + * @cpu: CPU in question | |
| 2717 | + * @wq: target workqueue | |
| 2718 | + * | |
| 2719 | + * Test whether @wq's cpu workqueue for @cpu is congested. There is | |
| 2720 | + * no synchronization around this function and the test result is | |
| 2721 | + * unreliable and only useful as advisory hints or for debugging. | |
| 2722 | + * | |
| 2723 | + * RETURNS: | |
| 2724 | + * %true if congested, %false otherwise. | |
| 2725 | + */ | |
| 2726 | +bool workqueue_congested(unsigned int cpu, struct workqueue_struct *wq) | |
| 2727 | +{ | |
| 2728 | + struct cpu_workqueue_struct *cwq = get_cwq(cpu, wq); | |
| 2729 | + | |
| 2730 | + return !list_empty(&cwq->delayed_works); | |
| 2731 | +} | |
| 2732 | +EXPORT_SYMBOL_GPL(workqueue_congested); | |
| 2733 | + | |
| 2734 | +/** | |
| 2735 | + * work_cpu - return the last known associated cpu for @work | |
| 2736 | + * @work: the work of interest | |
| 2737 | + * | |
| 2738 | + * RETURNS: | |
| 2739 | + * CPU number if @work was ever queued. NR_CPUS otherwise. | |
| 2740 | + */ | |
| 2741 | +unsigned int work_cpu(struct work_struct *work) | |
| 2742 | +{ | |
| 2743 | + struct global_cwq *gcwq = get_work_gcwq(work); | |
| 2744 | + | |
| 2745 | + return gcwq ? gcwq->cpu : NR_CPUS; | |
| 2746 | +} | |
| 2747 | +EXPORT_SYMBOL_GPL(work_cpu); | |
| 2748 | + | |
| 2749 | +/** | |
| 2750 | + * work_busy - test whether a work is currently pending or running | |
| 2751 | + * @work: the work to be tested | |
| 2752 | + * | |
| 2753 | + * Test whether @work is currently pending or running. There is no | |
| 2754 | + * synchronization around this function and the test result is | |
| 2755 | + * unreliable and only useful as advisory hints or for debugging. | |
| 2756 | + * Especially for reentrant wqs, the pending state might hide the | |
| 2757 | + * running state. | |
| 2758 | + * | |
| 2759 | + * RETURNS: | |
| 2760 | + * OR'd bitmask of WORK_BUSY_* bits. | |
| 2761 | + */ | |
| 2762 | +unsigned int work_busy(struct work_struct *work) | |
| 2763 | +{ | |
| 2764 | + struct global_cwq *gcwq = get_work_gcwq(work); | |
| 2765 | + unsigned long flags; | |
| 2766 | + unsigned int ret = 0; | |
| 2767 | + | |
| 2768 | + if (!gcwq) | |
| 2769 | + return false; | |
| 2770 | + | |
| 2771 | + spin_lock_irqsave(&gcwq->lock, flags); | |
| 2772 | + | |
| 2773 | + if (work_pending(work)) | |
| 2774 | + ret |= WORK_BUSY_PENDING; | |
| 2775 | + if (find_worker_executing_work(gcwq, work)) | |
| 2776 | + ret |= WORK_BUSY_RUNNING; | |
| 2777 | + | |
| 2778 | + spin_unlock_irqrestore(&gcwq->lock, flags); | |
| 2779 | + | |
| 2780 | + return ret; | |
| 2781 | +} | |
| 2782 | +EXPORT_SYMBOL_GPL(work_busy); | |
| 2783 | + | |
| 2678 | 2784 | /* |
| 2679 | 2785 | * CPU hotplug. |
| 2680 | 2786 | * |