History

workqueue: implement several utility APIs

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().

Tejun Heo committed 16 years ago

Commit dcd989c1 parent d320c032 files · +117 −2Browse files

Showing the changes to kernel/workqueue.c (1 of 2 files). Show all

Unified · Split

kernel/workqueue.c+107−1
@@ -203,7 +203,7 @@ struct workqueue_struct { · 202 unmodified lines
203 cpumask_var_t mayday_mask; /* cpus requesting rescue */203 cpumask_var_t mayday_mask; /* cpus requesting rescue */
204 struct worker *rescuer; /* I: rescue worker */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 const char *name; /* I: workqueue name */207 const char *name; /* I: workqueue name */
208#ifdef CONFIG_LOCKDEP208#ifdef CONFIG_LOCKDEP
209 struct lockdep_map lockdep_map;209 struct lockdep_map lockdep_map;
@@ -2675,6 +2675,112 @@ void destroy_workqueue(struct workqueue_struct *wq) · 2465 unmodified lines
2675}2675}
2676EXPORT_SYMBOL_GPL(destroy_workqueue);2676EXPORT_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 */
2688void 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}
2712EXPORT_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 */
2726bool 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}
2732EXPORT_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 */
2741unsigned 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}
2747EXPORT_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 */
2762unsigned 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}
2782EXPORT_SYMBOL_GPL(work_busy);
2783
2678/*2784/*
2679 * CPU hotplug.2785 * CPU hotplug.
2680 *2786 *