diff --git a/qdf/inc/qdf_threads.h b/qdf/inc/qdf_threads.h index f91ebda322..82c0fcccfb 100644 --- a/qdf/inc/qdf_threads.h +++ b/qdf/inc/qdf_threads.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -28,6 +28,7 @@ #include "i_qdf_threads.h" typedef __qdf_thread_t qdf_thread_t; +typedef QDF_STATUS (*qdf_thread_func)(void *context); /* Function declarations and documenation */ @@ -56,6 +57,38 @@ void qdf_set_user_nice(qdf_thread_t *thread, long nice); qdf_thread_t *qdf_create_thread(int (*thread_handler)(void *data), void *data, const char thread_name[]); +/** + * qdf_thread_run() - run the given function in a new thread + * + * You must call qdf_thread_join() to avoid a reasource leak! + * + * For more flexibility, use qdf_create_thread() instead. + * + * Return: a new qdf_thread pointer + */ +qdf_thread_t *qdf_thread_run(qdf_thread_func callback, void *context); + +/** + * qdf_thread_join() - signal and wait for a thread to stop + * + * This sets a flag that the given thread can check to see if it should exit. + * The thread can check to see if this flag has been set by calling + * qdf_thread_should_stop(). + * + * Return: QDF_STATUS - the return value from the thread function + */ +QDF_STATUS qdf_thread_join(qdf_thread_t *thread); + +/** + * qdf_thread_should_stop() - true if the current thread was signalled to stop + * + * If qdf_thread_join() has been called on the current thread, this API returns + * true. Otherwise, this returns false. + * + * Return: true if the current thread should stop + */ +bool qdf_thread_should_stop(void); + /** * qdf_wake_up_process() - wake up given thread * @thread: pointer to thread which needs to be woken up diff --git a/qdf/linux/src/qdf_threads.c b/qdf/linux/src/qdf_threads.c index d1e8ddef06..ad4540cf0f 100644 --- a/qdf/linux/src/qdf_threads.c +++ b/qdf/linux/src/qdf_threads.c @@ -40,6 +40,8 @@ /* Function declarations and documenation */ +typedef int (*qdf_thread_os_func)(void *data); + /** * qdf_sleep() - sleep * @ms_interval : Number of milliseconds to suspend the current thread. @@ -117,6 +119,43 @@ qdf_thread_t *qdf_create_thread(int (*thread_handler)(void *data), void *data, } qdf_export_symbol(qdf_create_thread); +static uint16_t qdf_thread_id; + +qdf_thread_t *qdf_thread_run(qdf_thread_func callback, void *context) +{ + struct task_struct *thread; + + thread = kthread_create((qdf_thread_os_func)callback, context, + "qdf %u", qdf_thread_id++); + if (IS_ERR(thread)) + return NULL; + + get_task_struct(thread); + wake_up_process(thread); + + return thread; +} +qdf_export_symbol(qdf_thread_run); + +QDF_STATUS qdf_thread_join(qdf_thread_t *thread) +{ + QDF_STATUS status; + + QDF_BUG(thread); + + status = (QDF_STATUS)kthread_stop(thread); + put_task_struct(thread); + + return status; +} +qdf_export_symbol(qdf_thread_join); + +bool qdf_thread_should_stop(void) +{ + return kthread_should_stop(); +} +qdf_export_symbol(qdf_thread_should_stop); + int qdf_wake_up_process(qdf_thread_t *thread) { return wake_up_process(thread);