1701 lines · 42.9 KB · C
RawDownload
/* * linux/kernel/workqueue.c * * Generic mechanism for defining kernel helper threads for running * arbitrary tasks in process context. * * Started by Ingo Molnar, Copyright (C) 2002 * * Derived from the taskqueue/keventd code by: * *   David Woodhouse <dwmw2@infradead.org> *   Andrew Morton *   Kai Petzke <wpp@marie.physik.tu-berlin.de> *   Theodore Ts'o <tytso@mit.edu> * * Made to use alloc_percpu by Christoph Lameter. */ #include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/signal.h>#include <linux/completion.h>#include <linux/workqueue.h>#include <linux/slab.h>#include <linux/cpu.h>#include <linux/notifier.h>#include <linux/kthread.h>#include <linux/hardirq.h>#include <linux/mempolicy.h>#include <linux/freezer.h>#include <linux/kallsyms.h>#include <linux/debug_locks.h>#include <linux/lockdep.h>#include <linux/idr.h> /* * Structure fields follow one of the following exclusion rules. * * I: Set during initialization and read-only afterwards. * * L: cwq->lock protected.  Access with cwq->lock held. * * F: wq->flush_mutex protected. * * W: workqueue_lock protected. */ struct cpu_workqueue_struct; struct worker {	struct work_struct	*current_work;	/* L: work being processed */	struct list_head	scheduled;	/* L: scheduled works */	struct task_struct	*task;		/* I: worker task */	struct cpu_workqueue_struct *cwq;	/* I: the associated cwq */	int			id;		/* I: worker id */}; /* * The per-CPU workqueue (if single thread, we always use the first * possible cpu).  The lower WORK_STRUCT_FLAG_BITS of * work_struct->data are used for flags and thus cwqs need to be * aligned at two's power of the number of flag bits. */struct cpu_workqueue_struct { 	spinlock_t lock; 	struct list_head worklist;	wait_queue_head_t more_work;	unsigned int		cpu;	struct worker		*worker; 	struct workqueue_struct *wq;		/* I: the owning workqueue */	int			work_color;	/* L: current color */	int			flush_color;	/* L: flushing color */	int			nr_in_flight[WORK_NR_COLORS];						/* L: nr of in_flight works */}; /* * Structure used to wait for workqueue flush. */struct wq_flusher {	struct list_head	list;		/* F: list of flushers */	int			flush_color;	/* F: flush color waiting for */	struct completion	done;		/* flush completion */}; /* * The externally visible workqueue abstraction is an array of * per-CPU workqueues: */struct workqueue_struct {	unsigned int		flags;		/* I: WQ_* flags */	struct cpu_workqueue_struct *cpu_wq;	/* I: cwq's */	struct list_head	list;		/* W: list of all workqueues */ 	struct mutex		flush_mutex;	/* protects wq flushing */	int			work_color;	/* F: current work color */	int			flush_color;	/* F: current flush color */	atomic_t		nr_cwqs_to_flush; /* flush in progress */	struct wq_flusher	*first_flusher;	/* F: first flusher */	struct list_head	flusher_queue;	/* F: flush waiters */	struct list_head	flusher_overflow; /* F: flush overflow list */ 	const char		*name;		/* I: workqueue name */#ifdef CONFIG_LOCKDEP	struct lockdep_map	lockdep_map;#endif}; #ifdef CONFIG_DEBUG_OBJECTS_WORK static struct debug_obj_descr work_debug_descr; /* * fixup_init is called when: * - an active object is initialized */static int work_fixup_init(void *addr, enum debug_obj_state state){	struct work_struct *work = addr; 	switch (state) {	case ODEBUG_STATE_ACTIVE:		cancel_work_sync(work);		debug_object_init(work, &work_debug_descr);		return 1;	default:		return 0;	}} /* * fixup_activate is called when: * - an active object is activated * - an unknown object is activated (might be a statically initialized object) */static int work_fixup_activate(void *addr, enum debug_obj_state state){	struct work_struct *work = addr; 	switch (state) { 	case ODEBUG_STATE_NOTAVAILABLE:		/*		 * This is not really a fixup. The work struct was		 * statically initialized. We just make sure that it		 * is tracked in the object tracker.		 */		if (test_bit(WORK_STRUCT_STATIC_BIT, work_data_bits(work))) {			debug_object_init(work, &work_debug_descr);			debug_object_activate(work, &work_debug_descr);			return 0;		}		WARN_ON_ONCE(1);		return 0; 	case ODEBUG_STATE_ACTIVE:		WARN_ON(1); 	default:		return 0;	}} /* * fixup_free is called when: * - an active object is freed */static int work_fixup_free(void *addr, enum debug_obj_state state){	struct work_struct *work = addr; 	switch (state) {	case ODEBUG_STATE_ACTIVE:		cancel_work_sync(work);		debug_object_free(work, &work_debug_descr);		return 1;	default:		return 0;	}} static struct debug_obj_descr work_debug_descr = {	.name		= "work_struct",	.fixup_init	= work_fixup_init,	.fixup_activate	= work_fixup_activate,	.fixup_free	= work_fixup_free,}; static inline void debug_work_activate(struct work_struct *work){	debug_object_activate(work, &work_debug_descr);} static inline void debug_work_deactivate(struct work_struct *work){	debug_object_deactivate(work, &work_debug_descr);} void __init_work(struct work_struct *work, int onstack){	if (onstack)		debug_object_init_on_stack(work, &work_debug_descr);	else		debug_object_init(work, &work_debug_descr);}EXPORT_SYMBOL_GPL(__init_work); void destroy_work_on_stack(struct work_struct *work){	debug_object_free(work, &work_debug_descr);}EXPORT_SYMBOL_GPL(destroy_work_on_stack); #elsestatic inline void debug_work_activate(struct work_struct *work) { }static inline void debug_work_deactivate(struct work_struct *work) { }#endif /* Serializes the accesses to the list of workqueues. */static DEFINE_SPINLOCK(workqueue_lock);static LIST_HEAD(workqueues);static DEFINE_PER_CPU(struct ida, worker_ida); static int worker_thread(void *__worker); static int singlethread_cpu __read_mostly; static struct cpu_workqueue_struct *get_cwq(unsigned int cpu,					    struct workqueue_struct *wq){	return per_cpu_ptr(wq->cpu_wq, cpu);} static struct cpu_workqueue_struct *target_cwq(unsigned int cpu,					       struct workqueue_struct *wq){	if (unlikely(wq->flags & WQ_SINGLE_THREAD))		cpu = singlethread_cpu;	return get_cwq(cpu, wq);} static unsigned int work_color_to_flags(int color){	return color << WORK_STRUCT_COLOR_SHIFT;} static int get_work_color(struct work_struct *work){	return (*work_data_bits(work) >> WORK_STRUCT_COLOR_SHIFT) &		((1 << WORK_STRUCT_COLOR_BITS) - 1);} static int work_next_color(int color){	return (color + 1) % WORK_NR_COLORS;} /* * Set the workqueue on which a work item is to be run * - Must *only* be called if the pending flag is set */static inline void set_wq_data(struct work_struct *work,			       struct cpu_workqueue_struct *cwq,			       unsigned long extra_flags){	BUG_ON(!work_pending(work)); 	atomic_long_set(&work->data, (unsigned long)cwq | work_static(work) |			WORK_STRUCT_PENDING | extra_flags);} /* * Clear WORK_STRUCT_PENDING and the workqueue on which it was queued. */static inline void clear_wq_data(struct work_struct *work){	atomic_long_set(&work->data, work_static(work));} static inline struct cpu_workqueue_struct *get_wq_data(struct work_struct *work){	return (void *)(atomic_long_read(&work->data) &			WORK_STRUCT_WQ_DATA_MASK);} /** * insert_work - insert a work into cwq * @cwq: cwq @work belongs to * @work: work to insert * @head: insertion point * @extra_flags: extra WORK_STRUCT_* flags to set * * Insert @work into @cwq after @head. * * CONTEXT: * spin_lock_irq(cwq->lock). */static void insert_work(struct cpu_workqueue_struct *cwq,			struct work_struct *work, struct list_head *head,			unsigned int extra_flags){	/* we own @work, set data and link */	set_wq_data(work, cwq, extra_flags); 	/*	 * Ensure that we get the right work->data if we see the	 * result of list_add() below, see try_to_grab_pending().	 */	smp_wmb(); 	list_add_tail(&work->entry, head);	wake_up(&cwq->more_work);} static void __queue_work(unsigned int cpu, struct workqueue_struct *wq,			 struct work_struct *work){	struct cpu_workqueue_struct *cwq = target_cwq(cpu, wq);	unsigned long flags; 	debug_work_activate(work);	spin_lock_irqsave(&cwq->lock, flags);	BUG_ON(!list_empty(&work->entry));	cwq->nr_in_flight[cwq->work_color]++;	insert_work(cwq, work, &cwq->worklist,		    work_color_to_flags(cwq->work_color));	spin_unlock_irqrestore(&cwq->lock, flags);} /** * queue_work - queue work on a workqueue * @wq: workqueue to use * @work: work to queue * * Returns 0 if @work was already on a queue, non-zero otherwise. * * We queue the work to the CPU on which it was submitted, but if the CPU dies * it can be processed by another CPU. */int queue_work(struct workqueue_struct *wq, struct work_struct *work){	int ret; 	ret = queue_work_on(get_cpu(), wq, work);	put_cpu(); 	return ret;}EXPORT_SYMBOL_GPL(queue_work); /** * queue_work_on - queue work on specific cpu * @cpu: CPU number to execute work on * @wq: workqueue to use * @work: work to queue * * Returns 0 if @work was already on a queue, non-zero otherwise. * * We queue the work to a specific CPU, the caller must ensure it * can't go away. */intqueue_work_on(int cpu, struct workqueue_struct *wq, struct work_struct *work){	int ret = 0; 	if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work))) {		__queue_work(cpu, wq, work);		ret = 1;	}	return ret;}EXPORT_SYMBOL_GPL(queue_work_on); static void delayed_work_timer_fn(unsigned long __data){	struct delayed_work *dwork = (struct delayed_work *)__data;	struct cpu_workqueue_struct *cwq = get_wq_data(&dwork->work); 	__queue_work(smp_processor_id(), cwq->wq, &dwork->work);} /** * queue_delayed_work - queue work on a workqueue after delay * @wq: workqueue to use * @dwork: delayable work to queue * @delay: number of jiffies to wait before queueing * * Returns 0 if @work was already on a queue, non-zero otherwise. */int queue_delayed_work(struct workqueue_struct *wq,			struct delayed_work *dwork, unsigned long delay){	if (delay == 0)		return queue_work(wq, &dwork->work); 	return queue_delayed_work_on(-1, wq, dwork, delay);}EXPORT_SYMBOL_GPL(queue_delayed_work); /** * queue_delayed_work_on - queue work on specific CPU after delay * @cpu: CPU number to execute work on * @wq: workqueue to use * @dwork: work to queue * @delay: number of jiffies to wait before queueing * * Returns 0 if @work was already on a queue, non-zero otherwise. */int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,			struct delayed_work *dwork, unsigned long delay){	int ret = 0;	struct timer_list *timer = &dwork->timer;	struct work_struct *work = &dwork->work; 	if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work))) {		BUG_ON(timer_pending(timer));		BUG_ON(!list_empty(&work->entry)); 		timer_stats_timer_set_start_info(&dwork->timer); 		/* This stores cwq for the moment, for the timer_fn */		set_wq_data(work, target_cwq(raw_smp_processor_id(), wq), 0);		timer->expires = jiffies + delay;		timer->data = (unsigned long)dwork;		timer->function = delayed_work_timer_fn; 		if (unlikely(cpu >= 0))			add_timer_on(timer, cpu);		else			add_timer(timer);		ret = 1;	}	return ret;}EXPORT_SYMBOL_GPL(queue_delayed_work_on); static struct worker *alloc_worker(void){	struct worker *worker; 	worker = kzalloc(sizeof(*worker), GFP_KERNEL);	if (worker)		INIT_LIST_HEAD(&worker->scheduled);	return worker;} /** * create_worker - create a new workqueue worker * @cwq: cwq the new worker will belong to * @bind: whether to set affinity to @cpu or not * * Create a new worker which is bound to @cwq.  The returned worker * can be started by calling start_worker() or destroyed using * destroy_worker(). * * CONTEXT: * Might sleep.  Does GFP_KERNEL allocations. * * RETURNS: * Pointer to the newly created worker. */static struct worker *create_worker(struct cpu_workqueue_struct *cwq, bool bind){	int id = -1;	struct worker *worker = NULL; 	spin_lock(&workqueue_lock);	while (ida_get_new(&per_cpu(worker_ida, cwq->cpu), &id)) {		spin_unlock(&workqueue_lock);		if (!ida_pre_get(&per_cpu(worker_ida, cwq->cpu), GFP_KERNEL))			goto fail;		spin_lock(&workqueue_lock);	}	spin_unlock(&workqueue_lock); 	worker = alloc_worker();	if (!worker)		goto fail; 	worker->cwq = cwq;	worker->id = id; 	worker->task = kthread_create(worker_thread, worker, "kworker/%u:%d",				      cwq->cpu, id);	if (IS_ERR(worker->task))		goto fail; 	if (bind)		kthread_bind(worker->task, cwq->cpu); 	return worker;fail:	if (id >= 0) {

Lines 1–500 of 1701.