6039 lines · 165.7 KB · C
RawDownload
{	struct worker *worker = current_wq_worker(); 	return worker && worker->rescue_wq;} /** * workqueue_congested - test whether a workqueue is congested * @cpu: CPU in question * @wq: target workqueue * * Test whether @wq's cpu workqueue for @cpu is congested.  There is * no synchronization around this function and the test result is * unreliable and only useful as advisory hints or for debugging. * * If @cpu is WORK_CPU_UNBOUND, the test is performed on the local CPU. * Note that both per-cpu and unbound workqueues may be associated with * multiple pool_workqueues which have separate congested states.  A * workqueue being congested on one CPU doesn't mean the workqueue is also * contested on other CPUs / NUMA nodes. * * Return: * %true if congested, %false otherwise. */bool workqueue_congested(int cpu, struct workqueue_struct *wq){	struct pool_workqueue *pwq;	bool ret; 	rcu_read_lock();	preempt_disable(); 	if (cpu == WORK_CPU_UNBOUND)		cpu = smp_processor_id(); 	if (!(wq->flags & WQ_UNBOUND))		pwq = per_cpu_ptr(wq->cpu_pwqs, cpu);	else		pwq = unbound_pwq_by_node(wq, cpu_to_node(cpu)); 	ret = !list_empty(&pwq->delayed_works);	preempt_enable();	rcu_read_unlock(); 	return ret;}EXPORT_SYMBOL_GPL(workqueue_congested); /** * work_busy - test whether a work is currently pending or running * @work: the work to be tested * * Test whether @work is currently pending or running.  There is no * synchronization around this function and the test result is * unreliable and only useful as advisory hints or for debugging. * * Return: * OR'd bitmask of WORK_BUSY_* bits. */unsigned int work_busy(struct work_struct *work){	struct worker_pool *pool;	unsigned long flags;	unsigned int ret = 0; 	if (work_pending(work))		ret |= WORK_BUSY_PENDING; 	rcu_read_lock();	pool = get_work_pool(work);	if (pool) {		raw_spin_lock_irqsave(&pool->lock, flags);		if (find_worker_executing_work(pool, work))			ret |= WORK_BUSY_RUNNING;		raw_spin_unlock_irqrestore(&pool->lock, flags);	}	rcu_read_unlock(); 	return ret;}EXPORT_SYMBOL_GPL(work_busy); /** * set_worker_desc - set description for the current work item * @fmt: printf-style format string * @...: arguments for the format string * * This function can be called by a running work function to describe what * the work item is about.  If the worker task gets dumped, this * information will be printed out together to help debugging.  The * description can be at most WORKER_DESC_LEN including the trailing '\0'. */void set_worker_desc(const char *fmt, ...){	struct worker *worker = current_wq_worker();	va_list args; 	if (worker) {		va_start(args, fmt);		vsnprintf(worker->desc, sizeof(worker->desc), fmt, args);		va_end(args);	}}EXPORT_SYMBOL_GPL(set_worker_desc); /** * print_worker_info - print out worker information and description * @log_lvl: the log level to use when printing * @task: target task * * If @task is a worker and currently executing a work item, print out the * name of the workqueue being serviced and worker description set with * set_worker_desc() by the currently executing work item. * * This function can be safely called on any task as long as the * task_struct itself is accessible.  While safe, this function isn't * synchronized and may print out mixups or garbages of limited length. */void print_worker_info(const char *log_lvl, struct task_struct *task){	work_func_t *fn = NULL;	char name[WQ_NAME_LEN] = { };	char desc[WORKER_DESC_LEN] = { };	struct pool_workqueue *pwq = NULL;	struct workqueue_struct *wq = NULL;	struct worker *worker; 	if (!(task->flags & PF_WQ_WORKER))		return; 	/*	 * This function is called without any synchronization and @task	 * could be in any state.  Be careful with dereferences.	 */	worker = kthread_probe_data(task); 	/*	 * Carefully copy the associated workqueue's workfn, name and desc.	 * Keep the original last '\0' in case the original is garbage.	 */	copy_from_kernel_nofault(&fn, &worker->current_func, sizeof(fn));	copy_from_kernel_nofault(&pwq, &worker->current_pwq, sizeof(pwq));	copy_from_kernel_nofault(&wq, &pwq->wq, sizeof(wq));	copy_from_kernel_nofault(name, wq->name, sizeof(name) - 1);	copy_from_kernel_nofault(desc, worker->desc, sizeof(desc) - 1); 	if (fn || name[0] || desc[0]) {		printk("%sWorkqueue: %s %ps", log_lvl, name, fn);		if (strcmp(name, desc))			pr_cont(" (%s)", desc);		pr_cont("\n");	}} static void pr_cont_pool_info(struct worker_pool *pool){	pr_cont(" cpus=%*pbl", nr_cpumask_bits, pool->attrs->cpumask);	if (pool->node != NUMA_NO_NODE)		pr_cont(" node=%d", pool->node);	pr_cont(" flags=0x%x nice=%d", pool->flags, pool->attrs->nice);} static void pr_cont_work(bool comma, struct work_struct *work){	if (work->func == wq_barrier_func) {		struct wq_barrier *barr; 		barr = container_of(work, struct wq_barrier, work); 		pr_cont("%s BAR(%d)", comma ? "," : "",			task_pid_nr(barr->task));	} else {		pr_cont("%s %ps", comma ? "," : "", work->func);	}} static void show_pwq(struct pool_workqueue *pwq){	struct worker_pool *pool = pwq->pool;	struct work_struct *work;	struct worker *worker;	bool has_in_flight = false, has_pending = false;	int bkt; 	pr_info("  pwq %d:", pool->id);	pr_cont_pool_info(pool); 	pr_cont(" active=%d/%d refcnt=%d%s\n",		pwq->nr_active, pwq->max_active, pwq->refcnt,		!list_empty(&pwq->mayday_node) ? " MAYDAY" : ""); 	hash_for_each(pool->busy_hash, bkt, worker, hentry) {		if (worker->current_pwq == pwq) {			has_in_flight = true;			break;		}	}	if (has_in_flight) {		bool comma = false; 		pr_info("    in-flight:");		hash_for_each(pool->busy_hash, bkt, worker, hentry) {			if (worker->current_pwq != pwq)				continue; 			pr_cont("%s %d%s:%ps", comma ? "," : "",				task_pid_nr(worker->task),				worker->rescue_wq ? "(RESCUER)" : "",				worker->current_func);			list_for_each_entry(work, &worker->scheduled, entry)				pr_cont_work(false, work);			comma = true;		}		pr_cont("\n");	} 	list_for_each_entry(work, &pool->worklist, entry) {		if (get_work_pwq(work) == pwq) {			has_pending = true;			break;		}	}	if (has_pending) {		bool comma = false; 		pr_info("    pending:");		list_for_each_entry(work, &pool->worklist, entry) {			if (get_work_pwq(work) != pwq)				continue; 			pr_cont_work(comma, work);			comma = !(*work_data_bits(work) & WORK_STRUCT_LINKED);		}		pr_cont("\n");	} 	if (!list_empty(&pwq->delayed_works)) {		bool comma = false; 		pr_info("    delayed:");		list_for_each_entry(work, &pwq->delayed_works, entry) {			pr_cont_work(comma, work);			comma = !(*work_data_bits(work) & WORK_STRUCT_LINKED);		}		pr_cont("\n");	}} /** * show_workqueue_state - dump workqueue state * * Called from a sysrq handler or try_to_freeze_tasks() and prints out * all busy workqueues and pools. */void show_workqueue_state(void){	struct workqueue_struct *wq;	struct worker_pool *pool;	unsigned long flags;	int pi; 	rcu_read_lock(); 	pr_info("Showing busy workqueues and worker pools:\n"); 	list_for_each_entry_rcu(wq, &workqueues, list) {		struct pool_workqueue *pwq;		bool idle = true; 		for_each_pwq(pwq, wq) {			if (pwq->nr_active || !list_empty(&pwq->delayed_works)) {				idle = false;				break;			}		}		if (idle)			continue; 		pr_info("workqueue %s: flags=0x%x\n", wq->name, wq->flags); 		for_each_pwq(pwq, wq) {			raw_spin_lock_irqsave(&pwq->pool->lock, flags);			if (pwq->nr_active || !list_empty(&pwq->delayed_works))				show_pwq(pwq);			raw_spin_unlock_irqrestore(&pwq->pool->lock, flags);			/*			 * We could be printing a lot from atomic context, e.g.			 * sysrq-t -> show_workqueue_state(). Avoid triggering			 * hard lockup.			 */			touch_nmi_watchdog();		}	} 	for_each_pool(pool, pi) {		struct worker *worker;		bool first = true; 		raw_spin_lock_irqsave(&pool->lock, flags);		if (pool->nr_workers == pool->nr_idle)			goto next_pool; 		pr_info("pool %d:", pool->id);		pr_cont_pool_info(pool);		pr_cont(" hung=%us workers=%d",			jiffies_to_msecs(jiffies - pool->watchdog_ts) / 1000,			pool->nr_workers);		if (pool->manager)			pr_cont(" manager: %d",				task_pid_nr(pool->manager->task));		list_for_each_entry(worker, &pool->idle_list, entry) {			pr_cont(" %s%d", first ? "idle: " : "",				task_pid_nr(worker->task));			first = false;		}		pr_cont("\n");	next_pool:		raw_spin_unlock_irqrestore(&pool->lock, flags);		/*		 * We could be printing a lot from atomic context, e.g.		 * sysrq-t -> show_workqueue_state(). Avoid triggering		 * hard lockup.		 */		touch_nmi_watchdog();	} 	rcu_read_unlock();} /* used to show worker information through /proc/PID/{comm,stat,status} */void wq_worker_comm(char *buf, size_t size, struct task_struct *task){	int off; 	/* always show the actual comm */	off = strscpy(buf, task->comm, size);	if (off < 0)		return; 	/* stabilize PF_WQ_WORKER and worker pool association */	mutex_lock(&wq_pool_attach_mutex); 	if (task->flags & PF_WQ_WORKER) {		struct worker *worker = kthread_data(task);		struct worker_pool *pool = worker->pool; 		if (pool) {			raw_spin_lock_irq(&pool->lock);			/*			 * ->desc tracks information (wq name or			 * set_worker_desc()) for the latest execution.  If			 * current, prepend '+', otherwise '-'.			 */			if (worker->desc[0] != '\0') {				if (worker->current_work)					scnprintf(buf + off, size - off, "+%s",						  worker->desc);				else					scnprintf(buf + off, size - off, "-%s",						  worker->desc);			}			raw_spin_unlock_irq(&pool->lock);		}	} 	mutex_unlock(&wq_pool_attach_mutex);} #ifdef CONFIG_SMP /* * CPU hotplug. * * There are two challenges in supporting CPU hotplug.  Firstly, there * are a lot of assumptions on strong associations among work, pwq and * pool which make migrating pending and scheduled works very * difficult to implement without impacting hot paths.  Secondly, * worker pools serve mix of short, long and very long running works making * blocked draining impractical. * * This is solved by allowing the pools to be disassociated from the CPU * running as an unbound one and allowing it to be reattached later if the * cpu comes back online. */ static void unbind_workers(int cpu){	struct worker_pool *pool;	struct worker *worker; 	for_each_cpu_worker_pool(pool, cpu) {		mutex_lock(&wq_pool_attach_mutex);		raw_spin_lock_irq(&pool->lock); 		/*		 * We've blocked all attach/detach operations. Make all workers		 * unbound and set DISASSOCIATED.  Before this, all workers		 * except for the ones which are still executing works from		 * before the last CPU down must be on the cpu.  After		 * this, they may become diasporas.		 */		for_each_pool_worker(worker, pool)			worker->flags |= WORKER_UNBOUND; 		pool->flags |= POOL_DISASSOCIATED; 		raw_spin_unlock_irq(&pool->lock);		mutex_unlock(&wq_pool_attach_mutex); 		/*		 * Call schedule() so that we cross rq->lock and thus can		 * guarantee sched callbacks see the %WORKER_UNBOUND flag.		 * This is necessary as scheduler callbacks may be invoked		 * from other cpus.		 */		schedule(); 		/*		 * Sched callbacks are disabled now.  Zap nr_running.		 * After this, nr_running stays zero and need_more_worker()		 * and keep_working() are always true as long as the		 * worklist is not empty.  This pool now behaves as an		 * unbound (in terms of concurrency management) pool which		 * are served by workers tied to the pool.		 */		atomic_set(&pool->nr_running, 0); 		/*		 * With concurrency management just turned off, a busy		 * worker blocking could lead to lengthy stalls.  Kick off		 * unbound chain execution of currently pending work items.		 */		raw_spin_lock_irq(&pool->lock);		wake_up_worker(pool);		raw_spin_unlock_irq(&pool->lock);	}} /** * rebind_workers - rebind all workers of a pool to the associated CPU * @pool: pool of interest * * @pool->cpu is coming online.  Rebind all workers to the CPU. */static void rebind_workers(struct worker_pool *pool){	struct worker *worker; 	lockdep_assert_held(&wq_pool_attach_mutex); 	/*	 * Restore CPU affinity of all workers.  As all idle workers should	 * be on the run-queue of the associated CPU before any local	 * wake-ups for concurrency management happen, restore CPU affinity	 * of all workers first and then clear UNBOUND.  As we're called	 * from CPU_ONLINE, the following shouldn't fail.	 */	for_each_pool_worker(worker, pool)		WARN_ON_ONCE(set_cpus_allowed_ptr(worker->task,						  pool->attrs->cpumask) < 0); 	raw_spin_lock_irq(&pool->lock); 	pool->flags &= ~POOL_DISASSOCIATED; 	for_each_pool_worker(worker, pool) {		unsigned int worker_flags = worker->flags; 		/*		 * A bound idle worker should actually be on the runqueue		 * of the associated CPU for local wake-ups targeting it to		 * work.  Kick all idle workers so that they migrate to the		 * associated CPU.  Doing this in the same loop as		 * replacing UNBOUND with REBOUND is safe as no worker will		 * be bound before @pool->lock is released.		 */		if (worker_flags & WORKER_IDLE)			wake_up_process(worker->task); 		/*		 * We want to clear UNBOUND but can't directly call		 * worker_clr_flags() or adjust nr_running.  Atomically		 * replace UNBOUND with another NOT_RUNNING flag REBOUND.		 * @worker will clear REBOUND using worker_clr_flags() when		 * it initiates the next execution cycle thus restoring		 * concurrency management.  Note that when or whether		 * @worker clears REBOUND doesn't affect correctness.		 *		 * WRITE_ONCE() is necessary because @worker->flags may be		 * tested without holding any lock in		 * wq_worker_running().  Without it, NOT_RUNNING test may		 * fail incorrectly leading to premature concurrency		 * management operations.		 */		WARN_ON_ONCE(!(worker_flags & WORKER_UNBOUND));		worker_flags |= WORKER_REBOUND;		worker_flags &= ~WORKER_UNBOUND;		WRITE_ONCE(worker->flags, worker_flags);	} 

Lines 4501–5000 of 6039. Previous lines