2 * Copyright (C) 2018 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include <urcu/list.h>
22 #include <common/macros.h>
23 #include <common/error.h>
24 #include <common/defaults.h>
26 static struct thread_list
{
27 struct cds_list_head head
;
30 .head
= CDS_LIST_HEAD_INIT(thread_list
.head
),
31 .lock
= PTHREAD_MUTEX_INITIALIZER
,
36 struct cds_list_head node
;
39 /* Main thread function */
40 lttng_thread_entry_point entry
;
42 * Thread-specific shutdown method. Allows threads to implement their
43 * own shutdown mechanism as some of them use a structured message
44 * passed through a command queue and some rely on a dedicated "quit"
47 lttng_thread_shutdown_cb shutdown
;
48 lttng_thread_cleanup_cb cleanup
;
49 /* Thread implementation-specific data. */
54 void lttng_thread_destroy(struct lttng_thread
*thread
)
56 if (thread
->cleanup
) {
57 thread
->cleanup(thread
->data
);
63 void lttng_thread_release(struct urcu_ref
*ref
)
65 lttng_thread_destroy(container_of(ref
, struct lttng_thread
, ref
));
69 void *launch_thread(void *data
)
72 struct lttng_thread
*thread
= (struct lttng_thread
*) data
;
74 DBG("Launching \"%s\" thread", thread
->name
);
75 ret
= thread
->entry(thread
->data
);
76 DBG("Thread \"%s\" has returned", thread
->name
);
80 struct lttng_thread
*lttng_thread_create(const char *name
,
81 lttng_thread_entry_point entry
,
82 lttng_thread_shutdown_cb shutdown
,
83 lttng_thread_cleanup_cb cleanup
,
87 struct lttng_thread
*thread
;
89 thread
= zmalloc(sizeof(*thread
));
94 urcu_ref_init(&thread
->ref
);
95 CDS_INIT_LIST_HEAD(&thread
->node
);
97 * Thread names are assumed to be statically allocated strings.
98 * It is unnecessary to copy this attribute.
101 thread
->entry
= entry
;
102 thread
->shutdown
= shutdown
;
103 thread
->cleanup
= cleanup
;
104 thread
->data
= thread_data
;
106 pthread_mutex_lock(&thread_list
.lock
);
108 * Add the thread at the head of the list to shutdown threads in the
109 * opposite order of their creation. A reference is taken for the
110 * thread list which will be released on shutdown of the thread.
112 cds_list_add(&thread
->node
, &thread_list
.head
);
113 (void) lttng_thread_get(thread
);
115 ret
= pthread_create(&thread
->thread
, default_pthread_attr(),
116 launch_thread
, thread
);
118 PERROR("Failed to create \"%s\" thread", thread
->name
);
119 goto error_pthread_create
;
122 pthread_mutex_unlock(&thread_list
.lock
);
125 error_pthread_create
:
126 cds_list_del(&thread
->node
);
127 /* Release list reference. */
128 lttng_thread_put(thread
);
129 pthread_mutex_unlock(&thread_list
.lock
);
130 /* Release initial reference. */
131 lttng_thread_put(thread
);
136 bool lttng_thread_get(struct lttng_thread
*thread
)
138 return urcu_ref_get_unless_zero(&thread
->ref
);
141 void lttng_thread_put(struct lttng_thread
*thread
)
143 assert(thread
->ref
.refcount
);
144 urcu_ref_put(&thread
->ref
, lttng_thread_release
);
147 const char *lttng_thread_get_name(const struct lttng_thread
*thread
)
153 bool _lttng_thread_shutdown(struct lttng_thread
*thread
)
159 DBG("Shutting down \"%s\" thread", thread
->name
);
160 if (thread
->shutdown
) {
161 result
= thread
->shutdown(thread
->data
);
168 ret
= pthread_join(thread
->thread
, &status
);
170 PERROR("Failed to join \"%s\" thread", thread
->name
);
174 /* Release the list's reference to the thread. */
175 cds_list_del(&thread
->node
);
176 lttng_thread_put(thread
);
181 bool lttng_thread_shutdown(struct lttng_thread
*thread
)
185 pthread_mutex_lock(&thread_list
.lock
);
186 result
= _lttng_thread_shutdown(thread
);
187 pthread_mutex_unlock(&thread_list
.lock
);
191 void lttng_thread_list_shutdown_orphans(void)
193 struct lttng_thread
*thread
, *tmp
;
195 pthread_mutex_lock(&thread_list
.lock
);
196 cds_list_for_each_entry_safe(thread
, tmp
, &thread_list
.head
, node
) {
198 const long ref
= uatomic_read(&thread
->ref
.refcount
);
202 * Other external references to the thread exist, skip.
207 result
= _lttng_thread_shutdown(thread
);
209 ERR("Failed to shutdown thread \"%s\"", thread
->name
);
212 pthread_mutex_unlock(&thread_list
.lock
);