/* * 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 * * 1 tab == 4 spaces! */ #if defined(__MW__) #include #include #include #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__ */