]> Git Repo - linux.git/blob - drivers/md/dm-vdo/thread-utils.c
Merge tag 'kbuild-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy...
[linux.git] / drivers / md / dm-vdo / thread-utils.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright 2023 Red Hat
4  */
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
18 static struct hlist_head thread_list;
19 static struct mutex thread_mutex;
20
21 struct 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
29 void vdo_initialize_threads_mutex(void)
30 {
31         mutex_init(&thread_mutex);
32 }
33
34 static 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
50 int 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 module
72          * threads to have names like "uds:callbackW" and the main test runner thread to be named
73          * "zub:runtest".
74          *
75          * Otherwise if the current thread has a name containing a colon character, prefix the name
76          * 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 associated
78          * 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
99 void 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 }
This page took 0.048592 seconds and 4 git commands to generate.