blob: 2206023f65121c42d4318852547d94a2e14f5da1 [file] [log] [blame]
/*
* 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__ */