/* * osal_thread.c * * osal driver * * Copyright (c) 2020-2021 Huawei Device Co., Ltd. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * 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. * */ #include "osal_thread.h" #include #include #include #include #include #include #include #include #include "hdf_log.h" #include "osal_mem.h" #include "securec.h" #define HDF_LOG_TAG osal_thread #define OSAL_INVALID_CPU_ID UINT_MAX struct thread_wrapper { OsalThreadEntry thread_entry; void *entry_para; struct task_struct *task; uint32_t cpu_id; }; enum { OSAL_PRIORITY_MIDDLE = 50, OSAL_PRIORITY_HIGH = 90, OSAL_PRIORITY_HIGHEST = 99, }; static int osal_thread_entry(void *para) { int ret = -1; struct thread_wrapper *wrapper = (struct thread_wrapper *)para; if (wrapper == NULL || wrapper->thread_entry == NULL) { HDF_LOGE("%s invalid param", __func__); } else { ret = wrapper->thread_entry(wrapper->entry_para); } do_exit(ret); return ret; } int32_t OsalThreadCreate(struct OsalThread *thread, OsalThreadEntry thread_entry, void *entry_para) { struct thread_wrapper *wrapper = NULL; if (thread == NULL || thread_entry == NULL) { HDF_LOGE("%s invalid param", __func__); return HDF_ERR_INVALID_PARAM; } thread->realThread = NULL; wrapper = (struct thread_wrapper *)OsalMemCalloc(sizeof(*wrapper)); if (wrapper == NULL) { HDF_LOGE("%s malloc fail", __func__); return HDF_ERR_MALLOC_FAIL; } wrapper->entry_para = entry_para; wrapper->thread_entry = thread_entry; wrapper->cpu_id = OSAL_INVALID_CPU_ID; thread->realThread = wrapper; return HDF_SUCCESS; } EXPORT_SYMBOL(OsalThreadCreate); int32_t OsalThreadBind(struct OsalThread *thread, unsigned int cpu_id) { struct thread_wrapper *wrapper = NULL; if (thread == NULL || thread->realThread == NULL) { HDF_LOGE("%s invalid parameter %d\n", __func__, __LINE__); return HDF_ERR_INVALID_PARAM; } wrapper = (struct thread_wrapper *)thread->realThread; wrapper->cpu_id = cpu_id; return HDF_SUCCESS; } EXPORT_SYMBOL(OsalThreadBind); int32_t OsalThreadStart(struct OsalThread *thread, const struct OsalThreadParam *param) { int32_t ret; struct sched_param sched_para; int32_t policy = SCHED_FIFO; struct task_struct *task = NULL; struct thread_wrapper *wrapper = NULL; if (thread == NULL || thread->realThread == NULL || param == NULL || param->name == NULL) { HDF_LOGE("%s invalid parameter\n", __func__); return HDF_ERR_INVALID_PARAM; } (void)memset_s(&sched_para, sizeof(sched_para), 0, sizeof(sched_para)); if (param->priority == OSAL_THREAD_PRI_HIGHEST) sched_para.sched_priority = OSAL_PRIORITY_HIGHEST; else if (param->priority == OSAL_THREAD_PRI_HIGH) sched_para.sched_priority = OSAL_PRIORITY_HIGH; else if (param->priority == OSAL_THREAD_PRI_DEFAULT) sched_para.sched_priority = OSAL_PRIORITY_MIDDLE; else policy = SCHED_NORMAL; wrapper = (struct thread_wrapper *)thread->realThread; task = kthread_create(osal_thread_entry, wrapper, param->name); if (IS_ERR(task)) { ret = PTR_ERR(task); HDF_LOGE("%s kthread_create fail %d", __func__, ret); return HDF_FAILURE; } if (wrapper->cpu_id != OSAL_INVALID_CPU_ID) { kthread_bind(task, wrapper->cpu_id); } wake_up_process(task); if (policy == SCHED_FIFO) { if (sched_setscheduler(task, policy, &sched_para)) { HDF_LOGE("%s sched_setscheduler fail", __func__); kthread_stop(task); return HDF_FAILURE; } } wrapper->task = task; return HDF_SUCCESS; } EXPORT_SYMBOL(OsalThreadStart); int32_t OsalThreadSuspend(struct OsalThread *thread) { return HDF_ERR_NOT_SUPPORT; } EXPORT_SYMBOL(OsalThreadSuspend); int32_t OsalThreadDestroy(struct OsalThread *thread) { if (thread == NULL || thread->realThread == NULL) { HDF_LOGE("%s invalid parameter\n", __func__); return HDF_ERR_INVALID_PARAM; } OsalMemFree(thread->realThread); thread->realThread = NULL; return HDF_SUCCESS; } EXPORT_SYMBOL(OsalThreadDestroy); int32_t OsalThreadResume(struct OsalThread *thread) { return HDF_ERR_NOT_SUPPORT; } EXPORT_SYMBOL(OsalThreadResume);