2 * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
10 #include <common/defaults.hpp>
11 #include <common/error.hpp>
12 #include <common/macros.hpp>
15 #include <urcu/list.h>
20 struct cds_list_head head
;
23 .head
= CDS_LIST_HEAD_INIT(thread_list
.head
),
24 .lock
= PTHREAD_MUTEX_INITIALIZER
,
30 struct cds_list_head node
;
33 /* Main thread function */
34 lttng_thread_entry_point entry
;
36 * Thread-specific shutdown method. Allows threads to implement their
37 * own shutdown mechanism as some of them use a structured message
38 * passed through a command queue and some rely on a dedicated "quit"
41 lttng_thread_shutdown_cb shutdown
;
42 lttng_thread_cleanup_cb cleanup
;
43 /* Thread implementation-specific data. */
47 static void lttng_thread_destroy(struct lttng_thread
*thread
)
49 if (thread
->cleanup
) {
50 thread
->cleanup(thread
->data
);
55 static void lttng_thread_release(struct urcu_ref
*ref
)
57 lttng_thread_destroy(lttng::utils::container_of(ref
, <tng_thread::ref
));
60 static void *launch_thread(void *data
)
63 struct lttng_thread
*thread
= (struct lttng_thread
*) data
;
65 logger_set_thread_name(thread
->name
, true);
66 DBG("Entering thread entry point");
67 ret
= thread
->entry(thread
->data
);
68 DBG("Thread entry point has returned");
72 struct lttng_thread
*lttng_thread_create(const char *name
,
73 lttng_thread_entry_point entry
,
74 lttng_thread_shutdown_cb shutdown
,
75 lttng_thread_cleanup_cb cleanup
,
79 struct lttng_thread
*thread
;
81 thread
= zmalloc
<lttng_thread
>();
86 urcu_ref_init(&thread
->ref
);
87 CDS_INIT_LIST_HEAD(&thread
->node
);
89 * Thread names are assumed to be statically allocated strings.
90 * It is unnecessary to copy this attribute.
93 thread
->entry
= entry
;
94 thread
->shutdown
= shutdown
;
95 thread
->cleanup
= cleanup
;
96 thread
->data
= thread_data
;
98 pthread_mutex_lock(&thread_list
.lock
);
100 * Add the thread at the head of the list to shutdown threads in the
101 * opposite order of their creation. A reference is taken for the
102 * thread list which will be released on shutdown of the thread.
104 cds_list_add(&thread
->node
, &thread_list
.head
);
105 (void) lttng_thread_get(thread
);
107 ret
= pthread_create(&thread
->thread
, default_pthread_attr(), 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
)
146 static bool _lttng_thread_shutdown(struct lttng_thread
*thread
)
152 DBG("Shutting down \"%s\" thread", thread
->name
);
153 if (thread
->shutdown
) {
154 result
= thread
->shutdown(thread
->data
);
161 ret
= pthread_join(thread
->thread
, &status
);
163 PERROR("Failed to join \"%s\" thread", thread
->name
);
167 DBG("Joined thread \"%s\"", thread
->name
);
172 bool lttng_thread_shutdown(struct lttng_thread
*thread
)
174 const bool result
= _lttng_thread_shutdown(thread
);
177 /* Release the list's reference to the thread. */
178 pthread_mutex_lock(&thread_list
.lock
);
179 cds_list_del(&thread
->node
);
180 lttng_thread_put(thread
);
181 pthread_mutex_unlock(&thread_list
.lock
);
186 void lttng_thread_list_shutdown_orphans()
188 struct lttng_thread
*thread
, *tmp
;
190 pthread_mutex_lock(&thread_list
.lock
);
191 cds_list_for_each_entry_safe (thread
, tmp
, &thread_list
.head
, node
) {
193 const long ref
= uatomic_read(&thread
->ref
.refcount
);
197 * Other external references to the thread exist, skip.
202 result
= _lttng_thread_shutdown(thread
);
204 ERR("Failed to shutdown thread \"%s\"", thread
->name
);
207 pthread_mutex_unlock(&thread_list
.lock
);