2 * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
12 #include <common/macros.h>
13 #include <common/error.h>
14 #include <common/defaults.h>
16 static struct thread_list
{
17 struct cds_list_head head
;
20 .head
= CDS_LIST_HEAD_INIT(thread_list
.head
),
21 .lock
= PTHREAD_MUTEX_INITIALIZER
,
26 struct cds_list_head node
;
29 /* Main thread function */
30 lttng_thread_entry_point entry
;
32 * Thread-specific shutdown method. Allows threads to implement their
33 * own shutdown mechanism as some of them use a structured message
34 * passed through a command queue and some rely on a dedicated "quit"
37 lttng_thread_shutdown_cb shutdown
;
38 lttng_thread_cleanup_cb cleanup
;
39 /* Thread implementation-specific data. */
44 void lttng_thread_destroy(struct lttng_thread
*thread
)
46 if (thread
->cleanup
) {
47 thread
->cleanup(thread
->data
);
53 void lttng_thread_release(struct urcu_ref
*ref
)
55 lttng_thread_destroy(container_of(ref
, struct lttng_thread
, ref
));
59 void *launch_thread(void *data
)
62 struct lttng_thread
*thread
= (struct lttng_thread
*) data
;
64 logger_set_thread_name(thread
->name
, true);
65 DBG("Entering thread entry point");
66 ret
= thread
->entry(thread
->data
);
67 DBG("Thread entry point has returned");
71 struct lttng_thread
*lttng_thread_create(const char *name
,
72 lttng_thread_entry_point entry
,
73 lttng_thread_shutdown_cb shutdown
,
74 lttng_thread_cleanup_cb cleanup
,
78 struct lttng_thread
*thread
;
80 thread
= zmalloc(sizeof(*thread
));
85 urcu_ref_init(&thread
->ref
);
86 CDS_INIT_LIST_HEAD(&thread
->node
);
88 * Thread names are assumed to be statically allocated strings.
89 * It is unnecessary to copy this attribute.
92 thread
->entry
= entry
;
93 thread
->shutdown
= shutdown
;
94 thread
->cleanup
= cleanup
;
95 thread
->data
= thread_data
;
97 pthread_mutex_lock(&thread_list
.lock
);
99 * Add the thread at the head of the list to shutdown threads in the
100 * opposite order of their creation. A reference is taken for the
101 * thread list which will be released on shutdown of the thread.
103 cds_list_add(&thread
->node
, &thread_list
.head
);
104 (void) lttng_thread_get(thread
);
106 ret
= pthread_create(&thread
->thread
, default_pthread_attr(),
107 launch_thread
, thread
);
109 PERROR("Failed to create \"%s\" thread", thread
->name
);
110 goto error_pthread_create
;
113 pthread_mutex_unlock(&thread_list
.lock
);
116 error_pthread_create
:
117 cds_list_del(&thread
->node
);
118 /* Release list reference. */
119 lttng_thread_put(thread
);
120 pthread_mutex_unlock(&thread_list
.lock
);
121 /* Release initial reference. */
122 lttng_thread_put(thread
);
127 bool lttng_thread_get(struct lttng_thread
*thread
)
129 return urcu_ref_get_unless_zero(&thread
->ref
);
132 void lttng_thread_put(struct lttng_thread
*thread
)
137 LTTNG_ASSERT(thread
->ref
.refcount
);
138 urcu_ref_put(&thread
->ref
, lttng_thread_release
);
141 const char *lttng_thread_get_name(const struct lttng_thread
*thread
)
147 bool _lttng_thread_shutdown(struct lttng_thread
*thread
)
153 DBG("Shutting down \"%s\" thread", thread
->name
);
154 if (thread
->shutdown
) {
155 result
= thread
->shutdown(thread
->data
);
162 ret
= pthread_join(thread
->thread
, &status
);
164 PERROR("Failed to join \"%s\" thread", thread
->name
);
168 DBG("Joined thread \"%s\"", thread
->name
);
173 bool lttng_thread_shutdown(struct lttng_thread
*thread
)
175 const bool result
= _lttng_thread_shutdown(thread
);
178 /* Release the list's reference to the thread. */
179 pthread_mutex_lock(&thread_list
.lock
);
180 cds_list_del(&thread
->node
);
181 lttng_thread_put(thread
);
182 pthread_mutex_unlock(&thread_list
.lock
);
187 void lttng_thread_list_shutdown_orphans(void)
189 struct lttng_thread
*thread
, *tmp
;
191 pthread_mutex_lock(&thread_list
.lock
);
192 cds_list_for_each_entry_safe(thread
, tmp
, &thread_list
.head
, node
) {
194 const long ref
= uatomic_read(&thread
->ref
.refcount
);
198 * Other external references to the thread exist, skip.
203 result
= _lttng_thread_shutdown(thread
);
205 ERR("Failed to shutdown thread \"%s\"", thread
->name
);
208 pthread_mutex_unlock(&thread_list
.lock
);