X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fbin%2Flttng-sessiond%2Fthread.c;h=a4e3cb86e125f7b3e365a80a27a82e2f610e2323;hb=HEAD;hp=7e16b69ed9ca5ddb113875b87cb6fa7be64c48e0;hpb=b878f05a6e62779ddf2364d5bb51821cb6d6d572;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/thread.c b/src/bin/lttng-sessiond/thread.c deleted file mode 100644 index 7e16b69ed..000000000 --- a/src/bin/lttng-sessiond/thread.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (C) 2018 - Jérémie Galarneau - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License, version 2 only, as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "thread.h" -#include -#include -#include -#include -#include -#include - -static struct thread_list { - struct cds_list_head head; - pthread_mutex_t lock; -} thread_list = { - .head = CDS_LIST_HEAD_INIT(thread_list.head), - .lock = PTHREAD_MUTEX_INITIALIZER, -}; - -struct lttng_thread { - struct urcu_ref ref; - struct cds_list_head node; - pthread_t thread; - const char *name; - /* Main thread function */ - lttng_thread_entry_point entry; - /* - * Thread-specific shutdown method. Allows threads to implement their - * own shutdown mechanism as some of them use a structured message - * passed through a command queue and some rely on a dedicated "quit" - * pipe. - */ - lttng_thread_shutdown_cb shutdown; - lttng_thread_cleanup_cb cleanup; - /* Thread implementation-specific data. */ - void *data; -}; - -static -void lttng_thread_destroy(struct lttng_thread *thread) -{ - if (thread->cleanup) { - thread->cleanup(thread->data); - } - free(thread); -} - -static -void lttng_thread_release(struct urcu_ref *ref) -{ - lttng_thread_destroy(container_of(ref, struct lttng_thread, ref)); -} - -static -void *launch_thread(void *data) -{ - void *ret; - struct lttng_thread *thread = (struct lttng_thread *) data; - - DBG("Launching \"%s\" thread", thread->name); - ret = thread->entry(thread->data); - DBG("Thread \"%s\" has returned", thread->name); - return ret; -} - -struct lttng_thread *lttng_thread_create(const char *name, - lttng_thread_entry_point entry, - lttng_thread_shutdown_cb shutdown, - lttng_thread_cleanup_cb cleanup, - void *thread_data) -{ - int ret; - struct lttng_thread *thread; - - thread = zmalloc(sizeof(*thread)); - if (!thread) { - goto error; - } - - urcu_ref_init(&thread->ref); - CDS_INIT_LIST_HEAD(&thread->node); - /* - * Thread names are assumed to be statically allocated strings. - * It is unnecessary to copy this attribute. - */ - thread->name = name; - thread->entry = entry; - thread->shutdown = shutdown; - thread->cleanup = cleanup; - thread->data = thread_data; - - pthread_mutex_lock(&thread_list.lock); - /* - * Add the thread at the head of the list to shutdown threads in the - * opposite order of their creation. A reference is taken for the - * thread list which will be released on shutdown of the thread. - */ - cds_list_add(&thread->node, &thread_list.head); - (void) lttng_thread_get(thread); - - ret = pthread_create(&thread->thread, default_pthread_attr(), - launch_thread, thread); - if (ret) { - PERROR("Failed to create \"%s\" thread", thread->name); - goto error_pthread_create; - } - - pthread_mutex_unlock(&thread_list.lock); - return thread; - -error_pthread_create: - cds_list_del(&thread->node); - /* Release list reference. */ - lttng_thread_put(thread); - pthread_mutex_unlock(&thread_list.lock); -error: - /* Release initial reference. */ - lttng_thread_put(thread); - return NULL; -} - -bool lttng_thread_get(struct lttng_thread *thread) -{ - return urcu_ref_get_unless_zero(&thread->ref); -} - -void lttng_thread_put(struct lttng_thread *thread) -{ - assert(thread->ref.refcount); - urcu_ref_put(&thread->ref, lttng_thread_release); -} - -const char *lttng_thread_get_name(const struct lttng_thread *thread) -{ - return thread->name; -} - -static -bool _lttng_thread_shutdown(struct lttng_thread *thread) -{ - int ret; - void *status; - bool result = true; - - DBG("Shutting down \"%s\" thread", thread->name); - if (thread->shutdown) { - result = thread->shutdown(thread->data); - if (!result) { - result = false; - goto end; - } - } - - ret = pthread_join(thread->thread, &status); - if (ret) { - PERROR("Failed to join \"%s\" thread", thread->name); - result = false; - } - /* Release the list's reference to the thread. */ - cds_list_del(&thread->node); - lttng_thread_put(thread); -end: - return result; -} - -bool lttng_thread_shutdown(struct lttng_thread *thread) -{ - bool result; - - pthread_mutex_lock(&thread_list.lock); - result = _lttng_thread_shutdown(thread); - pthread_mutex_unlock(&thread_list.lock); - return result; -} - -void lttng_thread_list_shutdown_orphans(void) -{ - struct lttng_thread *thread, *tmp; - - pthread_mutex_lock(&thread_list.lock); - cds_list_for_each_entry_safe(thread, tmp, &thread_list.head, node) { - bool result; - const long ref = uatomic_read(&thread->ref.refcount); - - if (ref != 1) { - /* - * Other external references to the thread exist, skip. - */ - continue; - } - - result = _lttng_thread_shutdown(thread); - if (!result) { - ERR("Failed to shutdown thread \"%s\"", thread->name); - } - } - pthread_mutex_unlock(&thread_list.lock); -}