Christian Brauner (Amutable)exec_state: relocate dumpable information6b1c66c5 months agoHistory
1738 lines · 47.6 KB · C
RawDownload
	wake_up_process(kthreadd_task);	/*	 * Wait for completion in killable state, for I might be chosen by	 * the OOM killer while kthreadd is trying to allocate memory for	 * new kernel thread.	 */	if (unlikely(wait_for_completion_killable(&done))) {		/*		 * If I was killed by a fatal signal before kthreadd (or new		 * kernel thread) calls complete(), leave the cleanup of this		 * structure to that thread.		 */		if (xchg(&create->done, NULL))			return ERR_PTR(-EINTR);		/*		 * kthreadd (or new kernel thread) will call complete()		 * shortly.		 */		wait_for_completion(&done);	}	task = create->result;free_create:	kfree(create);	return task;} /** * kthread_create_on_node - create a kthread. * @threadfn: the function to run until signal_pending(current). * @data: data ptr for @threadfn. * @node: task and thread structures for the thread are allocated on this node * @namefmt: printf-style name for the thread. * * Description: This helper function creates and names a kernel * thread.  The thread will be stopped: use wake_up_process() to start * it.  See also kthread_run().  The new thread has SCHED_NORMAL policy and * is affine to all CPUs. * * If thread is going to be bound on a particular cpu, give its node * in @node, to get NUMA affinity for kthread stack, or else give NUMA_NO_NODE. * When woken, the thread will run @threadfn() with @data as its * argument. @threadfn() can either return directly if it is a * standalone thread for which no one will call kthread_stop(), or * return when 'kthread_should_stop()' is true (which means * kthread_stop() has been called).  The return value should be zero * or a negative error number; it will be passed to kthread_stop(). * * Returns a task_struct or ERR_PTR(-ENOMEM) or ERR_PTR(-EINTR). */struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),					   void *data, int node,					   const char namefmt[],					   ...){	struct task_struct *task;	va_list args; 	va_start(args, namefmt);	task = __kthread_create_on_node(threadfn, data, node, namefmt, args);	va_end(args); 	return task;}EXPORT_SYMBOL(kthread_create_on_node); static void __kthread_bind_mask(struct task_struct *p, const struct cpumask *mask, unsigned int state){	if (!wait_task_inactive(p, state)) {		WARN_ON(1);		return;	} 	scoped_guard (raw_spinlock_irqsave, &p->pi_lock)		set_cpus_allowed_force(p, mask); 	/* It's safe because the task is inactive. */	p->flags |= PF_NO_SETAFFINITY;} static void __kthread_bind(struct task_struct *p, unsigned int cpu, unsigned int state){	__kthread_bind_mask(p, cpumask_of(cpu), state);} void kthread_bind_mask(struct task_struct *p, const struct cpumask *mask){	struct kthread *kthread = to_kthread(p);	__kthread_bind_mask(p, mask, TASK_UNINTERRUPTIBLE);	WARN_ON_ONCE(kthread->started);} /** * kthread_bind - bind a just-created kthread to a cpu. * @p: thread created by kthread_create(). * @cpu: cpu (might not be online, must be possible) for @k to run on. * * Description: This function is equivalent to set_cpus_allowed(), * except that @cpu doesn't need to be online, and the thread must be * stopped (i.e., just returned from kthread_create()). */void kthread_bind(struct task_struct *p, unsigned int cpu){	struct kthread *kthread = to_kthread(p);	__kthread_bind(p, cpu, TASK_UNINTERRUPTIBLE);	WARN_ON_ONCE(kthread->started);}EXPORT_SYMBOL(kthread_bind); /** * kthread_create_on_cpu - Create a cpu bound kthread * @threadfn: the function to run until signal_pending(current). * @data: data ptr for @threadfn. * @cpu: The cpu on which the thread should be bound, * @namefmt: printf-style name for the thread. Format is restricted *	     to "name.*%u". Code fills in cpu number. * * Description: This helper function creates and names a kernel thread */struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data),					  void *data, unsigned int cpu,					  const char *namefmt){	struct task_struct *p; 	p = kthread_create_on_node(threadfn, data, cpu_to_node(cpu), namefmt,				   cpu);	if (IS_ERR(p))		return p;	kthread_bind(p, cpu);	/* CPU hotplug need to bind once again when unparking the thread. */	to_kthread(p)->cpu = cpu;	return p;}EXPORT_SYMBOL(kthread_create_on_cpu); void kthread_set_per_cpu(struct task_struct *k, int cpu){	struct kthread *kthread = to_kthread(k);	if (!kthread)		return; 	WARN_ON_ONCE(!(k->flags & PF_NO_SETAFFINITY)); 	if (cpu < 0) {		clear_bit(KTHREAD_IS_PER_CPU, &kthread->flags);		return;	} 	kthread->cpu = cpu;	set_bit(KTHREAD_IS_PER_CPU, &kthread->flags);} bool kthread_is_per_cpu(struct task_struct *p){	struct kthread *kthread = tsk_is_kthread(p);	if (!kthread)		return false; 	return test_bit(KTHREAD_IS_PER_CPU, &kthread->flags);} /** * kthread_unpark - unpark a thread created by kthread_create(). * @k:		thread created by kthread_create(). * * Sets kthread_should_park() for @k to return false, wakes it, and * waits for it to return. If the thread is marked percpu then its * bound to the cpu again. */void kthread_unpark(struct task_struct *k){	struct kthread *kthread = to_kthread(k); 	if (!test_bit(KTHREAD_SHOULD_PARK, &kthread->flags))		return;	/*	 * Newly created kthread was parked when the CPU was offline.	 * The binding was lost and we need to set it again.	 */	if (test_bit(KTHREAD_IS_PER_CPU, &kthread->flags))		__kthread_bind(k, kthread->cpu, TASK_PARKED); 	clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags);	/*	 * __kthread_parkme() will either see !SHOULD_PARK or get the wakeup.	 */	wake_up_state(k, TASK_PARKED);}EXPORT_SYMBOL_GPL(kthread_unpark); /** * kthread_park - park a thread created by kthread_create(). * @k: thread created by kthread_create(). * * Sets kthread_should_park() for @k to return true, wakes it, and * waits for it to return. This can also be called after kthread_create() * instead of calling wake_up_process(): the thread will park without * calling threadfn(). * * Returns 0 if the thread is parked, -ENOSYS if the thread exited. * If called by the kthread itself just the park bit is set. */int kthread_park(struct task_struct *k){	struct kthread *kthread = to_kthread(k); 	if (WARN_ON(k->flags & PF_EXITING))		return -ENOSYS; 	if (WARN_ON_ONCE(test_bit(KTHREAD_SHOULD_PARK, &kthread->flags)))		return -EBUSY; 	set_bit(KTHREAD_SHOULD_PARK, &kthread->flags);	if (k != current) {		wake_up_process(k);		/*		 * Wait for __kthread_parkme() to complete(), this means we		 * _will_ have TASK_PARKED and are about to call schedule().		 */		wait_for_completion(&kthread->parked);		/*		 * Now wait for that schedule() to complete and the task to		 * get scheduled out.		 */		WARN_ON_ONCE(!wait_task_inactive(k, TASK_PARKED));	} 	return 0;}EXPORT_SYMBOL_GPL(kthread_park); /** * kthread_stop - stop a thread created by kthread_create(). * @k: thread created by kthread_create(). * * Sets kthread_should_stop() for @k to return true, wakes it, and * waits for it to exit. This can also be called after kthread_create() * instead of calling wake_up_process(): the thread will exit without * calling threadfn(). * * If threadfn() may call kthread_exit() itself, the caller must ensure * task_struct can't go away. * * Returns the result of threadfn(), or %-EINTR if wake_up_process() * was never called. */int kthread_stop(struct task_struct *k){	struct kthread *kthread;	int ret; 	trace_sched_kthread_stop(k); 	get_task_struct(k);	kthread = to_kthread(k);	set_bit(KTHREAD_SHOULD_STOP, &kthread->flags);	kthread_unpark(k);	set_tsk_thread_flag(k, TIF_NOTIFY_SIGNAL);	wake_up_process(k);	wait_for_completion(&kthread->exited);	ret = kthread->result;	put_task_struct(k); 	trace_sched_kthread_stop_ret(ret);	return ret;}EXPORT_SYMBOL(kthread_stop); /** * kthread_stop_put - stop a thread and put its task struct * @k: thread created by kthread_create(). * * Stops a thread created by kthread_create() and put its task_struct. * Only use when holding an extra task struct reference obtained by * calling get_task_struct(). */int kthread_stop_put(struct task_struct *k){	int ret; 	ret = kthread_stop(k);	put_task_struct(k);	return ret;}EXPORT_SYMBOL(kthread_stop_put); int kthreadd(void *unused){	static const char comm[TASK_COMM_LEN] = "kthreadd";	struct task_struct *tsk = current; 	/* Setup a clean context for our children to inherit. */	set_task_comm(tsk, comm);	ignore_signals(tsk);	set_mems_allowed(node_states[N_MEMORY]); 	current->flags |= PF_NOFREEZE;	cgroup_init_kthreadd(); 	kthread_affine_node(); 	for (;;) {		set_current_state(TASK_INTERRUPTIBLE);		if (list_empty(&kthread_create_list))			schedule();		__set_current_state(TASK_RUNNING); 		spin_lock(&kthread_create_lock);		while (!list_empty(&kthread_create_list)) {			struct kthread_create_info *create; 			create = list_entry(kthread_create_list.next,					    struct kthread_create_info, list);			list_del_init(&create->list);			spin_unlock(&kthread_create_lock); 			create_kthread(create); 			spin_lock(&kthread_create_lock);		}		spin_unlock(&kthread_create_lock);	} 	return 0;} /** * kthread_affine_preferred - Define a kthread's preferred affinity * @p: thread created by kthread_create(). * @mask: preferred mask of CPUs (might not be online, must be possible) for @p *        to run on. * * Similar to kthread_bind_mask() except that the affinity is not a requirement * but rather a preference that can be constrained by CPU isolation or CPU hotplug. * Must be called before the first wakeup of the kthread. * * Returns 0 if the affinity has been applied. */int kthread_affine_preferred(struct task_struct *p, const struct cpumask *mask){	struct kthread *kthread = to_kthread(p);	cpumask_var_t affinity;	int ret = 0; 	if (!wait_task_inactive(p, TASK_UNINTERRUPTIBLE) || kthread->started) {		WARN_ON(1);		return -EINVAL;	} 	WARN_ON_ONCE(kthread->preferred_affinity); 	if (!zalloc_cpumask_var(&affinity, GFP_KERNEL))		return -ENOMEM; 	kthread->preferred_affinity = kzalloc(sizeof(struct cpumask), GFP_KERNEL);	if (!kthread->preferred_affinity) {		ret = -ENOMEM;		goto out;	} 	mutex_lock(&kthread_affinity_lock);	cpumask_copy(kthread->preferred_affinity, mask);	WARN_ON_ONCE(!list_empty(&kthread->affinity_node));	list_add_tail(&kthread->affinity_node, &kthread_affinity_list);	kthread_fetch_affinity(kthread, affinity); 	scoped_guard (raw_spinlock_irqsave, &p->pi_lock)		set_cpus_allowed_force(p, affinity); 	mutex_unlock(&kthread_affinity_lock);out:	free_cpumask_var(affinity); 	return ret;}EXPORT_SYMBOL_GPL(kthread_affine_preferred); static int kthreads_update_affinity(bool force){	cpumask_var_t affinity;	struct kthread *k;	int ret; 	guard(mutex)(&kthread_affinity_lock); 	if (list_empty(&kthread_affinity_list))		return 0; 	if (!zalloc_cpumask_var(&affinity, GFP_KERNEL))		return -ENOMEM; 	ret = 0; 	list_for_each_entry(k, &kthread_affinity_list, affinity_node) {		if (WARN_ON_ONCE((k->task->flags & PF_NO_SETAFFINITY) ||				 kthread_is_per_cpu(k->task))) {			ret = -EINVAL;			continue;		} 		/*		 * Unbound kthreads without preferred affinity are already affine		 * to housekeeping, whether those CPUs are online or not. So no need		 * to handle newly online CPUs for them. However housekeeping changes		 * have to be applied.		 *		 * But kthreads with a preferred affinity or node are different:		 * if none of their preferred CPUs are online and part of		 * housekeeping at the same time, they must be affine to housekeeping.		 * But as soon as one of their preferred CPU becomes online, they must		 * be affine to them.		 */		if (force || k->preferred_affinity || k->node != NUMA_NO_NODE) {			kthread_fetch_affinity(k, affinity);			set_cpus_allowed_ptr(k->task, affinity);		}	} 	free_cpumask_var(affinity); 	return ret;} /** * kthreads_update_housekeeping - Update kthreads affinity on cpuset change * * When cpuset changes a partition type to/from "isolated" or updates related * cpumasks, propagate the housekeeping cpumask change to preferred kthreads * affinity. * * Returns 0 if successful, -ENOMEM if temporary mask couldn't * be allocated or -EINVAL in case of internal error. */int kthreads_update_housekeeping(void){	return kthreads_update_affinity(true);} /* * Re-affine kthreads according to their preferences * and the newly online CPU. The CPU down part is handled * by select_fallback_rq() which default re-affines to * housekeepers from other nodes in case the preferred * affinity doesn't apply anymore. */static int kthreads_online_cpu(unsigned int cpu){	return kthreads_update_affinity(false);} static int kthreads_init(void){	return cpuhp_setup_state(CPUHP_AP_KTHREADS_ONLINE, "kthreads:online",				kthreads_online_cpu, NULL);}early_initcall(kthreads_init); void __kthread_init_worker(struct kthread_worker *worker,				const char *name,				struct lock_class_key *key){	memset(worker, 0, sizeof(struct kthread_worker));	raw_spin_lock_init(&worker->lock);	lockdep_set_class_and_name(&worker->lock, key, name);	INIT_LIST_HEAD(&worker->work_list);	INIT_LIST_HEAD(&worker->delayed_work_list);}EXPORT_SYMBOL_GPL(__kthread_init_worker); /** * kthread_worker_fn - kthread function to process kthread_worker * @worker_ptr: pointer to initialized kthread_worker * * This function implements the main cycle of kthread worker. It processes * work_list until it is stopped with kthread_stop(). It sleeps when the queue * is empty. * * The works are not allowed to keep any locks, disable preemption or interrupts * when they finish. There is defined a safe point for freezing when one work * finishes and before a new one is started. * * Also the works must not be handled by more than one worker at the same time, * see also kthread_queue_work(). */int kthread_worker_fn(void *worker_ptr){	struct kthread_worker *worker = worker_ptr;	struct kthread_work *work; 	/*	 * FIXME: Update the check and remove the assignment when all kthread	 * worker users are created using kthread_create_worker*() functions.	 */	WARN_ON(worker->task && worker->task != current);	worker->task = current; 	if (worker->flags & KTW_FREEZABLE)		set_freezable(); repeat:

Lines 501–1000 of 1738. Previous lines

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t