brintos

brintos / linux-shallow public Read only

0
0
Text · 2.9 KiB · ec08478 Raw
109 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright 2023 Red Hat4 */5 6#include "thread-utils.h"7 8#include <asm/current.h>9#include <linux/delay.h>10#include <linux/kthread.h>11#include <linux/mutex.h>12#include <linux/types.h>13 14#include "errors.h"15#include "logger.h"16#include "memory-alloc.h"17 18static struct hlist_head thread_list;19static struct mutex thread_mutex;20 21struct thread {22	void (*thread_function)(void *thread_data);23	void *thread_data;24	struct hlist_node thread_links;25	struct task_struct *thread_task;26	struct completion thread_done;27};28 29void vdo_initialize_threads_mutex(void)30{31	mutex_init(&thread_mutex);32}33 34static int thread_starter(void *arg)35{36	struct registered_thread allocating_thread;37	struct thread *thread = arg;38 39	thread->thread_task = current;40	mutex_lock(&thread_mutex);41	hlist_add_head(&thread->thread_links, &thread_list);42	mutex_unlock(&thread_mutex);43	vdo_register_allocating_thread(&allocating_thread, NULL);44	thread->thread_function(thread->thread_data);45	vdo_unregister_allocating_thread();46	complete(&thread->thread_done);47	return 0;48}49 50int vdo_create_thread(void (*thread_function)(void *), void *thread_data,51		      const char *name, struct thread **new_thread)52{53	char *name_colon = strchr(name, ':');54	char *my_name_colon = strchr(current->comm, ':');55	struct task_struct *task;56	struct thread *thread;57	int result;58 59	result = vdo_allocate(1, struct thread, __func__, &thread);60	if (result != VDO_SUCCESS) {61		vdo_log_warning("Error allocating memory for %s", name);62		return result;63	}64 65	thread->thread_function = thread_function;66	thread->thread_data = thread_data;67	init_completion(&thread->thread_done);68	/*69	 * Start the thread, with an appropriate thread name.70	 *71	 * If the name supplied contains a colon character, use that name. This causes uds module72	 * threads to have names like "uds:callbackW" and the main test runner thread to be named73	 * "zub:runtest".74	 *75	 * Otherwise if the current thread has a name containing a colon character, prefix the name76	 * supplied with the name of the current thread up to (and including) the colon character.77	 * Thus when the "kvdo0:dedupeQ" thread opens an index session, all the threads associated78	 * with that index will have names like "kvdo0:foo".79	 *80	 * Otherwise just use the name supplied. This should be a rare occurrence.81	 */82	if ((name_colon == NULL) && (my_name_colon != NULL)) {83		task = kthread_run(thread_starter, thread, "%.*s:%s",84				   (int) (my_name_colon - current->comm), current->comm,85				   name);86	} else {87		task = kthread_run(thread_starter, thread, "%s", name);88	}89 90	if (IS_ERR(task)) {91		vdo_free(thread);92		return PTR_ERR(task);93	}94 95	*new_thread = thread;96	return VDO_SUCCESS;97}98 99void vdo_join_threads(struct thread *thread)100{101	while (wait_for_completion_interruptible(&thread->thread_done))102		fsleep(1000);103 104	mutex_lock(&thread_mutex);105	hlist_del(&thread->thread_links);106	mutex_unlock(&thread_mutex);107	vdo_free(thread);108}109