| /* |
| * FreeRTOS Kernel V10.2.1 |
| * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a copy of |
| * this software and associated documentation files (the "Software"), to deal in |
| * the Software without restriction, including without limitation the rights to |
| * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of |
| * the Software, and to permit persons to whom the Software is furnished to do so, |
| * subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included in all |
| * copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
| * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
| * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
| * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| * |
| * http://www.FreeRTOS.org |
| * http://aws.amazon.com/freertos |
| * |
| */ |
| |
| #if defined(__MW__) |
| |
| #include <stdint.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "FreeRTOS.h" |
| |
| #include "queue.h" |
| #include "semphr.h" |
| #include "task.h" |
| |
| #include "arc/arc_exception.h" |
| #include "embARC_toolchain.h" |
| #include "embARC_debug.h" |
| |
| #ifdef ENABLE_FREERTOS_TLS_DEBUG |
| #define TLS_DEBUG(fmt, ...) EMBARC_PRINTF(fmt, ##__VA_ARGS__) |
| #else |
| #define TLS_DEBUG(fmt, ...) |
| #endif |
| |
| /* |
| * Runtime routines to execute constructors and |
| * destructors for task local storage. |
| */ |
| extern void __mw_run_tls_dtor(); |
| extern void __mw_run_tls_ctor(); |
| |
| /* |
| * Linker generated symbols to mark .tls section addresses |
| * first byte .. last byte |
| */ |
| extern char _ftls[], _etls[]; |
| #pragma weak _ftls |
| #pragma weak _etls |
| |
| void executable_requires_tls_section(void) |
| { |
| #if _ARC |
| for (;;) { |
| _flag(1); |
| _nop(); |
| _nop(); |
| _nop(); |
| _nop(); |
| _nop(); |
| } |
| #endif |
| } |
| #pragma off_inline(executable_requires_tls_section); |
| #pragma alias(executable_requires_tls_section, "executable_requires_.tls_section"); |
| |
| static void* init_task_tls(void) |
| { |
| uint32_t len = (uint32_t)(_etls - _ftls); |
| void *tls = NULL; |
| |
| #if FREERTOS_HEAP_SEL == 3 |
| #warning "FreeRTOS TLS support is not compatible with heap 3 solution(FREERTOS_HEAP_SEL=3)!" |
| #warning "You can change FREERTOS_HEAP_SEL in freertos.mk to select other heap solution." |
| #else |
| tls = pvPortMalloc(len); |
| #endif |
| if (tls) { |
| TLS_DEBUG("Malloc task tls:%dbytes\r\n", len); |
| memcpy(tls, _ftls, len); |
| __mw_run_tls_ctor(); // Run constructors |
| } |
| return tls; |
| } |
| |
| static void free_task_tls(void *pxTCB) |
| { |
| TaskHandle_t task2free = (TaskHandle_t)pxTCB; |
| |
| if (task2free != NULL) { |
| void *tls = pvTaskGetThreadLocalStoragePointer(task2free, 0); |
| if (tls) { |
| TLS_DEBUG("Free task tls\r\n"); |
| __mw_run_tls_dtor(); |
| vPortFree(tls); |
| vTaskSetThreadLocalStoragePointer(task2free, 0, NULL); |
| } |
| } |
| } |
| |
| void task_end_hook(void *pxTCB) |
| { |
| free_task_tls(pxTCB); |
| } |
| |
| static void* get_isr_tls(void) |
| { |
| // In an ISR |
| static int first = 1; |
| if (_Rarely(first)) { |
| first = 0; |
| __mw_run_tls_ctor(); // Run constructors |
| } |
| return (void *)_ftls; |
| } |
| #pragma off_inline(get_isr_tls) |
| |
| static void* get_task_tls(void) |
| { |
| TaskHandle_t cur_task; |
| |
| cur_task = xTaskGetCurrentTaskHandle(); |
| if (cur_task == NULL) return get_isr_tls(); |
| void *tls = pvTaskGetThreadLocalStoragePointer(cur_task, 0); |
| if (tls == NULL) { |
| tls = init_task_tls(); |
| if (tls) { |
| vTaskSetThreadLocalStoragePointer(cur_task, 0, tls); |
| } else { |
| tls = get_isr_tls(); |
| } |
| } |
| return tls; |
| } |
| #pragma off_inline(get_task_tls) |
| |
| #if _ARC /* for ARC XCALLs need to preserve flags */ |
| extern void * _Preserve_flags _mwget_tls(void); |
| #endif |
| |
| /* |
| * Back end gens calls to find local data for this task |
| */ |
| void* _mwget_tls(void) |
| { |
| if (_ftls == (char *)0) { |
| executable_requires_tls_section(); |
| } |
| if (exc_sense()) { /* In ISR */ |
| return get_isr_tls(); |
| } else { /* In Task */ |
| return get_task_tls(); |
| } |
| } |
| |
| |
| // simple interface of thread safe |
| typedef xSemaphoreHandle _lock_t; |
| #if configUSE_RECURSIVE_MUTEXES != 1 |
| #error "configUSE_RECURSIVE_MUTEXES in FreeRTOSConfig.h need to 1" |
| #endif |
| |
| void _mwmutex_create(_lock_t *mutex_ptr) |
| { |
| *mutex_ptr = xSemaphoreCreateRecursiveMutex(); |
| } |
| |
| void _mwmutex_delete(_lock_t *mutex_ptr) |
| { |
| if ((*mutex_ptr) != NULL) { |
| vSemaphoreDelete(*mutex_ptr); |
| } |
| } |
| |
| void _mwmutex_lock(_lock_t mutex) |
| { |
| if ((mutex) != NULL) { |
| while (xSemaphoreTakeRecursive(mutex, portMAX_DELAY) != pdTRUE); |
| } |
| } |
| |
| void _mwmutex_unlock(_lock_t mutex) |
| { |
| if ((mutex) != NULL) { |
| xSemaphoreGiveRecursive(mutex); |
| } |
| } |
| |
| #else |
| |
| #endif /* __MW__ */ |