1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright 2023 Red Hat
6 #include "thread-utils.h"
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>
16 #include "memory-alloc.h"
18 static struct hlist_head thread_list
;
19 static struct mutex thread_mutex
;
22 void (*thread_function
)(void *thread_data
);
24 struct hlist_node thread_links
;
25 struct task_struct
*thread_task
;
26 struct completion thread_done
;
29 void vdo_initialize_threads_mutex(void)
31 mutex_init(&thread_mutex
);
34 static int thread_starter(void *arg
)
36 struct registered_thread allocating_thread
;
37 struct thread
*thread
= arg
;
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
);
50 int vdo_create_thread(void (*thread_function
)(void *), void *thread_data
,
51 const char *name
, struct thread
**new_thread
)
53 char *name_colon
= strchr(name
, ':');
54 char *my_name_colon
= strchr(current
->comm
, ':');
55 struct task_struct
*task
;
56 struct thread
*thread
;
59 result
= vdo_allocate(1, struct thread
, __func__
, &thread
);
60 if (result
!= VDO_SUCCESS
) {
61 vdo_log_warning("Error allocating memory for %s", name
);
65 thread
->thread_function
= thread_function
;
66 thread
->thread_data
= thread_data
;
67 init_completion(&thread
->thread_done
);
69 * Start the thread, with an appropriate thread name.
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
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".
80 * Otherwise just use the name supplied. This should be a rare occurrence.
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
,
87 task
= kthread_run(thread_starter
, thread
, "%s", name
);
99 void vdo_join_threads(struct thread
*thread
)
101 while (wait_for_completion_interruptible(&thread
->thread_done
))
104 mutex_lock(&thread_mutex
);
105 hlist_del(&thread
->thread_links
);
106 mutex_unlock(&thread_mutex
);