2 * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
12 #include <common/macros.hpp>
13 #include <common/error.hpp>
14 #include <common/defaults.hpp>
18 struct cds_list_head head
;
21 .head
= CDS_LIST_HEAD_INIT(thread_list
.head
),
22 .lock
= PTHREAD_MUTEX_INITIALIZER
,
28 struct cds_list_head node
;
31 /* Main thread function */
32 lttng_thread_entry_point entry
;
34 * Thread-specific shutdown method. Allows threads to implement their
35 * own shutdown mechanism as some of them use a structured message
36 * passed through a command queue and some rely on a dedicated "quit"
39 lttng_thread_shutdown_cb shutdown
;
40 lttng_thread_cleanup_cb cleanup
;
41 /* Thread implementation-specific data. */
46 void lttng_thread_destroy(struct lttng_thread
*thread
)
48 if (thread
->cleanup
) {
49 thread
->cleanup(thread
->data
);
55 void lttng_thread_release(struct urcu_ref
*ref
)
57 lttng_thread_destroy(lttng::utils::container_of(ref
, <tng_thread::ref
));
61 void *launch_thread(void *data
)
64 struct lttng_thread
*thread
= (struct lttng_thread
*) data
;
66 logger_set_thread_name(thread
->name
, true);
67 DBG("Entering thread entry point");
68 ret
= thread
->entry(thread
->data
);
69 DBG("Thread entry point has returned");
73 struct lttng_thread
*lttng_thread_create(const char *name
,
74 lttng_thread_entry_point entry
,
75 lttng_thread_shutdown_cb shutdown
,
76 lttng_thread_cleanup_cb cleanup
,
80 struct lttng_thread
*thread
;
82 thread
= zmalloc
<lttng_thread
>();
87 urcu_ref_init(&thread
->ref
);
88 CDS_INIT_LIST_HEAD(&thread
->node
);
90 * Thread names are assumed to be statically allocated strings.
91 * It is unnecessary to copy this attribute.
94 thread
->entry
= entry
;
95 thread
->shutdown
= shutdown
;
96 thread
->cleanup
= cleanup
;
97 thread
->data
= thread_data
;
99 pthread_mutex_lock(&thread_list
.lock
);
101 * Add the thread at the head of the list to shutdown threads in the
102 * opposite order of their creation. A reference is taken for the
103 * thread list which will be released on shutdown of the thread.
105 cds_list_add(&thread
->node
, &thread_list
.head
);
106 (void) lttng_thread_get(thread
);
108 ret
= pthread_create(&thread
->thread
, default_pthread_attr(),
109 launch_thread
, thread
);
111 PERROR("Failed to create \"%s\" thread", thread
->name
);
112 goto error_pthread_create
;
115 pthread_mutex_unlock(&thread_list
.lock
);
118 error_pthread_create
:
119 cds_list_del(&thread
->node
);
120 /* Release list reference. */
121 lttng_thread_put(thread
);
122 pthread_mutex_unlock(&thread_list
.lock
);
123 /* Release initial reference. */
124 lttng_thread_put(thread
);
129 bool lttng_thread_get(struct lttng_thread
*thread
)
131 return urcu_ref_get_unless_zero(&thread
->ref
);
134 void lttng_thread_put(struct lttng_thread
*thread
)
139 LTTNG_ASSERT(thread
->ref
.refcount
);
140 urcu_ref_put(&thread
->ref
, lttng_thread_release
);
143 const char *lttng_thread_get_name(const struct lttng_thread
*thread
)
149 bool _lttng_thread_shutdown(struct lttng_thread
*thread
)
155 DBG("Shutting down \"%s\" thread", thread
->name
);
156 if (thread
->shutdown
) {
157 result
= thread
->shutdown(thread
->data
);
164 ret
= pthread_join(thread
->thread
, &status
);
166 PERROR("Failed to join \"%s\" thread", thread
->name
);
170 DBG("Joined thread \"%s\"", thread
->name
);
175 bool lttng_thread_shutdown(struct lttng_thread
*thread
)
177 const bool result
= _lttng_thread_shutdown(thread
);
180 /* Release the list's reference to the thread. */
181 pthread_mutex_lock(&thread_list
.lock
);
182 cds_list_del(&thread
->node
);
183 lttng_thread_put(thread
);
184 pthread_mutex_unlock(&thread_list
.lock
);
189 void lttng_thread_list_shutdown_orphans(void)
191 struct lttng_thread
*thread
, *tmp
;
193 pthread_mutex_lock(&thread_list
.lock
);
194 cds_list_for_each_entry_safe(thread
, tmp
, &thread_list
.head
, node
) {
196 const long ref
= uatomic_read(&thread
->ref
.refcount
);
200 * Other external references to the thread exist, skip.
205 result
= _lttng_thread_shutdown(thread
);
207 ERR("Failed to shutdown thread \"%s\"", thread
->name
);
210 pthread_mutex_unlock(&thread_list
.lock
);