diff --git a/components/iar_tls/los_iar_tls.c b/components/iar_tls/los_iar_tls.c new file mode 100644 index 00000000..03db7ebd --- /dev/null +++ b/components/iar_tls/los_iar_tls.c @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "los_iar_tls.h" +#include +#include "los_task.h" +#include "los_mux.h" +#include "los_memory.h" + +/* IAR version is less than 8. */ +#if (__VER__ < 8000000) +void __DLIB_TLS_MEMORY *__iar_dlib_perthread_access(void _DLIB_TLS_MEMORY *symbp) +{ + if (!LOS_TaskIsRuning()) { + CHAR _DLIB_TLS_MEMORY *tlsAreaPtr = (char _DLIB_TLS_MEMORY *)__segment_begin("__DLIB_PERTHREAD"); + tlsAreaPtr += __IAR_DLIB_PERTHREAD_SYMBOL_OFFSET(symbp); + return (void __DLIB_TLS_MEMORY *)tlsAreaPtr; + } else { + UINT32 taskID = LOS_CurTaskIDGet(); + LosTaskCB *task = OS_TCB_FROM_TID(taskID); + if (task->iarTlsArea == NULL) { + task->iarTlsArea = __iar_dlib_perthread_allocate(); + } + return (void __DLIB_TLS_MEMORY *)task->iarTlsArea; + } +} + +#else /* IAR version 8 or above. */ +#pragma section="__iar_tls$$DATA" +void *__aeabi_read_tp(void) +{ + if (!LOS_TaskIsRunning()) { + return __section_begin("__iar_tls$$DATA"); + } else { + UINT32 taskID = LOS_CurTaskIDGet(); + LosTaskCB *task = OS_TCB_FROM_TID(taskID); + if (task->iarTlsArea == NULL) { + task->iarTlsArea = IarPerThreadTlsAreaAllocate(); + } + return task->iarTlsArea; + } +} + +void *IarPerThreadTlsAreaAllocate(void) +{ + UINT32 tlsAreaSize = __iar_tls_size(); + VOID *tlsAreaPtr = LOS_MemAlloc(m_aucSysMem0, tlsAreaSize); + if (tlsAreaPtr == NULL) { + return NULL; + } + + __iar_tls_init(tlsAreaPtr); + return tlsAreaPtr; +} + +void IarPerThreadTlsAreaDeallocate(void *tlsArea) +{ + __call_thread_dtors(); + LOS_MemFree(m_aucSysMem0, tlsArea); +} +#endif + +#ifndef _MAX_LOCK +#define _MAX_LOCK 4 +#endif + +#ifndef _MAX_FLOCK +#define _MAX_FLOCK FOPEN_MAX +#endif + +struct IarMutexInfo { + UINT32 muxID; + BOOL usedFlag; +}; + +STATIC struct IarMutexInfo g_iarSysMutex[_MAX_LOCK] = {0}; +STATIC struct IarMutexInfo g_iarFileMutex[_MAX_FLOCK] = {0}; + +STATIC __iar_Rmtx IarMtxCreate(struct IarMutexInfo *mutexArray, UINT32 size) +{ + UINT32 i; + + for (i = 0; i < size; i++) { + if (mutexArray[i].usedFlag == FALSE) { + UINT32 ret = LOS_MuxCreate(&mutexArray[i].muxID); + if (ret == LOS_OK) { + mutexArray[i].usedFlag = TRUE; + return (__iar_Rmtx)&mutexArray[i]; + } else { + break; + } + } + } + + return NULL; +} + +void __iar_system_Mtxinit(__iar_Rmtx *m) +{ + if (m == NULL) { + return; + } + + *m = IarMtxCreate(g_iarSysMutex, _MAX_LOCK); +} + +void __iar_system_Mtxdst(__iar_Rmtx *m) +{ + if (m == NULL) { + return; + } + struct IarMutexInfo *muxInfo = (struct IarMutexInfo *)*m; + + (void)LOS_MuxDelete(muxInfo->muxID); + muxInfo->usedFlag = FALSE; + *m = (__iar_Rmtx)NULL; +} + +void __iar_system_Mtxlock(__iar_Rmtx *m) +{ + if (m == NULL) { + return; + } + struct IarMutexInfo *muxInfo = (struct IarMutexInfo *)*m; + + if (LOS_TaskIsRunning()) { + (void)LOS_MuxPend(muxInfo->muxID, LOS_WAIT_FOREVER); + } +} + +void __iar_system_Mtxunlock(__iar_Rmtx *m) +{ + if (m == NULL) { + return; + } + struct IarMutexInfo *muxInfo = (struct IarMutexInfo *)*m; + + if (LOS_TaskIsRunning()) { + (void)LOS_MuxPost(muxInfo->muxID); + } +} + +void __iar_file_Mtxinit(__iar_Rmtx *m) +{ + if (m == NULL) { + return; + } + + *m = IarMtxCreate(g_iarFileMutex, _MAX_FLOCK); +} + +void __iar_file_Mtxdst(__iar_Rmtx *m) +{ + if (m == NULL) { + return; + } + struct IarMutexInfo *muxInfo = (struct IarMutexInfo *)*m; + + (void)LOS_MuxDelete(muxInfo->muxID); + muxInfo->usedFlag = FALSE; + *m = (__iar_Rmtx)NULL; +} + +void __iar_file_Mtxlock(__iar_Rmtx *m) +{ + if (m == NULL) { + return; + } + struct IarMutexInfo *muxInfo = (struct IarMutexInfo *)*m; + + if (LOS_TaskIsRunning()) { + (void)LOS_MuxPend(muxInfo->muxID, LOS_WAIT_FOREVER); + } +} + +void __iar_file_Mtxunlock(__iar_Rmtx *m) +{ + if (m == NULL) { + return; + } + struct IarMutexInfo *muxInfo = (struct IarMutexInfo *)*m; + + if (LOS_TaskIsRunning()) { + (void)LOS_MuxPost(muxInfo->muxID); + } +} \ No newline at end of file diff --git a/components/iar_tls/los_iar_tls.h b/components/iar_tls/los_iar_tls.h new file mode 100644 index 00000000..07d287d6 --- /dev/null +++ b/components/iar_tls/los_iar_tls.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "los_compiler.h" + +/* Using task extended field to realize IAR TLS function in target_config.h include this header file. */ +#define LOSCFG_TASK_STRUCT_EXTENSION VOID *iarTlsArea; + +#if (__VER__ < 8000000) +#include + +#define LOSCFG_TASK_CREATE_EXTENSION_HOOK(taskCB) + +#define LOSCFG_TASK_DELETE_EXTENSION_HOOK(taskCB) do { \ + if (taskCB->iarTlsArea != NULL) { \ + __iar_dlib_perthread_deallocate(taskCB->iarTlsArea); \ + taskCB->iarTlsArea = NULL; \ + } \ +} while (0); +#else +#include + +void *IarPerThreadTlsAreaAllocate(void); +void IarPerThreadTlsAreaDeallocate(void *tlsArea); + +#define LOSCFG_TASK_CREATE_EXTENSION_HOOK(taskCB) + +#define LOSCFG_TASK_DELETE_EXTENSION_HOOK(taskCB) do { \ + if (taskCB->iarTlsArea != NULL) { \ + IarPerThreadTlsAreaDeallocate(taskCB->iarTlsArea); \ + taskCB->iarTlsArea = NULL; \ + } \ +} while (0); +#endif + +/* In the main initialization phase, the macro should be called. */ +#define IAR_INIT_LOCKS() __iar_Initlocks() diff --git a/kernel/include/los_config.h b/kernel/include/los_config.h index c5e248f6..54e5402e 100644 --- a/kernel/include/los_config.h +++ b/kernel/include/los_config.h @@ -635,6 +635,20 @@ extern UINT8 *m_aucSysMem0; #define LOSCFG_ARCH_HWI_VECTOR_ALIGN 0x100 #endif +/** + * @ingroup los_config + * Task extension field additional functions, such as IAR TLS. + */ +#ifndef LOSCFG_TASK_STRUCT_EXTENSION +#define LOSCFG_TASK_STRUCT_EXTENSION +#endif +#ifndef LOSCFG_TASK_CREATE_EXTENSION_HOOK +#define LOSCFG_TASK_CREATE_EXTENSION_HOOK(taskCB) +#endif +#ifndef LOSCFG_TASK_DELETE_EXTENSION_HOOK +#define LOSCFG_TASK_DELETE_EXTENSION_HOOK(taskCB) +#endif + #ifdef __cplusplus #if __cplusplus } diff --git a/kernel/include/los_task.h b/kernel/include/los_task.h index bc531960..f1cf6c5e 100644 --- a/kernel/include/los_task.h +++ b/kernel/include/los_task.h @@ -1480,6 +1480,7 @@ typedef struct { UINT32 eventMode; /**< Event mode */ VOID *msg; /**< Memory allocated to queues */ INT32 errorNo; + LOSCFG_TASK_STRUCT_EXTENSION /**< Task extension field */ } LosTaskCB; typedef struct { diff --git a/kernel/src/los_task.c b/kernel/src/los_task.c index d5a5b925..8632df9f 100644 --- a/kernel/src/los_task.c +++ b/kernel/src/los_task.c @@ -749,6 +749,9 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreateOnly(UINT32 *taskID, TSK_INIT_PARAM_S if (retVal != LOS_OK) { return retVal; } + + LOSCFG_TASK_CREATE_EXTENSION_HOOK(taskCB); + #if (LOSCFG_BASE_CORE_CPUP == 1) intSave = LOS_IntLock(); g_cpup[taskCB->taskID].cpupID = taskCB->taskID; @@ -1084,6 +1087,9 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskID) // Ignore the return code when matching CSEC rule 6.6(4). (VOID)memset_s((VOID *)&g_cpup[taskCB->taskID], sizeof(OsCpupCB), 0, sizeof(OsCpupCB)); #endif + + LOSCFG_TASK_DELETE_EXTENSION_HOOK(taskCB); + if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) { if (!(taskCB->taskStatus & OS_TASK_STATUS_EXIT)) { taskCB->taskStatus = OS_TASK_STATUS_UNUSED;