<commit_before>/*
 * Copyright (c) 2018 ARM Limited. All rights reserved.
 * SPDX-License-Identifier: Apache-2.0
 * Licensed under the Apache License, Version 2.0 (the License); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "ns_types.h"
#include "fhss_api.h"
#include "fhss_config.h"
#include "mbed.h"
#include "mbed_trace.h"
#include "platform/arm_hal_interrupt.h"
#include <Timer.h>

#define TRACE_GROUP "fhdr"
#define NUMBER_OF_SIMULTANEOUS_TIMEOUTS  2

static Timer timer;
static bool timer_initialized = false;
static const fhss_api_t *fhss_active_handle = NULL;
#if !MBED_CONF_NANOSTACK_HAL_CRITICAL_SECTION_USABLE_FROM_INTERRUPT
static EventQueue *equeue;
#endif

struct fhss_timeout_s
{
    void (*fhss_timer_callback)(const fhss_api_t *fhss_api, uint16_t);
    uint32_t start_time;
    uint32_t stop_time;
    bool active;
    Timeout timeout;
};

fhss_timeout_s fhss_timeout[NUMBER_OF_SIMULTANEOUS_TIMEOUTS];

static uint32_t read_current_time(void)
{
    return timer.read_us();
}

static fhss_timeout_s *find_timeout(void (*callback)(const fhss_api_t *api, uint16_t))
{
    for (int i = 0; i < NUMBER_OF_SIMULTANEOUS_TIMEOUTS; i++) {
        if (fhss_timeout[i].fhss_timer_callback == callback) {
            return &fhss_timeout[i];
        }
    }
    return NULL;
}

static fhss_timeout_s *allocate_timeout(void)
{
    for (int i = 0; i < NUMBER_OF_SIMULTANEOUS_TIMEOUTS; i++) {
        if (fhss_timeout[i].fhss_timer_callback == NULL) {
            memset(&fhss_timeout[i], sizeof(fhss_timeout_s), 0);
            return &fhss_timeout[i];
        }
    }
    return NULL;
}

static void fhss_timeout_handler(void)
{
    for (int i = 0; i < NUMBER_OF_SIMULTANEOUS_TIMEOUTS; i++) {
        if (fhss_timeout[i].active && ((fhss_timeout[i].stop_time - fhss_timeout[i].start_time) <= (read_current_time() - fhss_timeout[i].start_time))) {
            fhss_timeout[i].active = false;
            fhss_timeout[i].fhss_timer_callback(fhss_active_handle, read_current_time() - fhss_timeout[i].stop_time);
        }
    }
}

static void timer_callback(void)
{
#if MBED_CONF_NANOSTACK_HAL_CRITICAL_SECTION_USABLE_FROM_INTERRUPT
    fhss_timeout_handler();
#else
    equeue->call(fhss_timeout_handler);
#endif
}

static int platform_fhss_timer_start(uint32_t slots, void (*callback)(const fhss_api_t *api, uint16_t), const fhss_api_t *callback_param)
{
    int ret_val = -1;
    platform_enter_critical();
    if (timer_initialized == false) {
#if !MBED_CONF_NANOSTACK_HAL_CRITICAL_SECTION_USABLE_FROM_INTERRUPT
        equeue = mbed_highprio_event_queue();
        MBED_ASSERT(equeue != NULL);
#endif
        timer.start();
        timer_initialized = true;
    }
    fhss_timeout_s *fhss_tim = find_timeout(callback);
    if (!fhss_tim) {
        fhss_tim = allocate_timeout();
    }
    fhss_tim->fhss_timer_callback = callback;
    fhss_tim->start_time = read_current_time();
    fhss_tim->stop_time = fhss_tim->start_time + slots;
    fhss_tim->active = true;
    fhss_tim->timeout.attach_us(timer_callback, slots);
    fhss_active_handle = callback_param;
    ret_val = 0;
    platform_exit_critical();
    return ret_val;
}

static int platform_fhss_timer_stop(void (*callback)(const fhss_api_t *api, uint16_t), const fhss_api_t *api)
{
    (void)api;
    platform_enter_critical();
    fhss_timeout_s *fhss_tim = find_timeout(callback);
    if (!fhss_tim) {
        platform_exit_critical();
        return -1;
    }
    fhss_tim->timeout.detach();
    fhss_tim->active = false;
    platform_exit_critical();
    return 0;
}

static uint32_t platform_fhss_get_remaining_slots(void (*callback)(const fhss_api_t *api, uint16_t), const fhss_api_t *api)
{
    (void)api;
    platform_enter_critical();
    fhss_timeout_s *fhss_tim = find_timeout(callback);
    if (!fhss_tim) {
        platform_exit_critical();
        return 0;
    }
    platform_exit_critical();
    return fhss_tim->stop_time - read_current_time();
}

static uint32_t platform_fhss_timestamp_read(const fhss_api_t *api)
{
    (void)api;
    return read_current_time();
}

fhss_timer_t fhss_functions = {
    .fhss_timer_start = platform_fhss_timer_start,
    .fhss_timer_stop = platform_fhss_timer_stop,
    .fhss_get_remaining_slots = platform_fhss_get_remaining_slots,
    .fhss_get_timestamp = platform_fhss_timestamp_read,
    .fhss_resolution_divider = 1
};
<commit_msg>FHSS timer: Calculation in critical state<commit_after>/*
 * Copyright (c) 2018 ARM Limited. All rights reserved.
 * SPDX-License-Identifier: Apache-2.0
 * Licensed under the Apache License, Version 2.0 (the License); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "ns_types.h"
#include "fhss_api.h"
#include "fhss_config.h"
#include "mbed.h"
#include "mbed_trace.h"
#include "platform/arm_hal_interrupt.h"
#include <Timer.h>

#define TRACE_GROUP "fhdr"
#define NUMBER_OF_SIMULTANEOUS_TIMEOUTS  2

static Timer timer;
static bool timer_initialized = false;
static const fhss_api_t *fhss_active_handle = NULL;
#if !MBED_CONF_NANOSTACK_HAL_CRITICAL_SECTION_USABLE_FROM_INTERRUPT
static EventQueue *equeue;
#endif

struct fhss_timeout_s
{
    void (*fhss_timer_callback)(const fhss_api_t *fhss_api, uint16_t);
    uint32_t start_time;
    uint32_t stop_time;
    bool active;
    Timeout timeout;
};

fhss_timeout_s fhss_timeout[NUMBER_OF_SIMULTANEOUS_TIMEOUTS];

static uint32_t read_current_time(void)
{
    return timer.read_us();
}

static fhss_timeout_s *find_timeout(void (*callback)(const fhss_api_t *api, uint16_t))
{
    for (int i = 0; i < NUMBER_OF_SIMULTANEOUS_TIMEOUTS; i++) {
        if (fhss_timeout[i].fhss_timer_callback == callback) {
            return &fhss_timeout[i];
        }
    }
    return NULL;
}

static fhss_timeout_s *allocate_timeout(void)
{
    for (int i = 0; i < NUMBER_OF_SIMULTANEOUS_TIMEOUTS; i++) {
        if (fhss_timeout[i].fhss_timer_callback == NULL) {
            memset(&fhss_timeout[i], sizeof(fhss_timeout_s), 0);
            return &fhss_timeout[i];
        }
    }
    return NULL;
}

static void fhss_timeout_handler(void)
{
    for (int i = 0; i < NUMBER_OF_SIMULTANEOUS_TIMEOUTS; i++) {
        if (fhss_timeout[i].active && ((fhss_timeout[i].stop_time - fhss_timeout[i].start_time) <= (read_current_time() - fhss_timeout[i].start_time))) {
            fhss_timeout[i].active = false;
            fhss_timeout[i].fhss_timer_callback(fhss_active_handle, read_current_time() - fhss_timeout[i].stop_time);
        }
    }
}

static void timer_callback(void)
{
#if MBED_CONF_NANOSTACK_HAL_CRITICAL_SECTION_USABLE_FROM_INTERRUPT
    fhss_timeout_handler();
#else
    equeue->call(fhss_timeout_handler);
#endif
}

static int platform_fhss_timer_start(uint32_t slots, void (*callback)(const fhss_api_t *api, uint16_t), const fhss_api_t *callback_param)
{
    int ret_val = -1;
    platform_enter_critical();
    if (timer_initialized == false) {
#if !MBED_CONF_NANOSTACK_HAL_CRITICAL_SECTION_USABLE_FROM_INTERRUPT
        equeue = mbed_highprio_event_queue();
        MBED_ASSERT(equeue != NULL);
#endif
        timer.start();
        timer_initialized = true;
    }
    fhss_timeout_s *fhss_tim = find_timeout(callback);
    if (!fhss_tim) {
        fhss_tim = allocate_timeout();
    }
    fhss_tim->fhss_timer_callback = callback;
    fhss_tim->start_time = read_current_time();
    fhss_tim->stop_time = fhss_tim->start_time + slots;
    fhss_tim->active = true;
    fhss_tim->timeout.attach_us(timer_callback, slots);
    fhss_active_handle = callback_param;
    ret_val = 0;
    platform_exit_critical();
    return ret_val;
}

static int platform_fhss_timer_stop(void (*callback)(const fhss_api_t *api, uint16_t), const fhss_api_t *api)
{
    (void)api;
    platform_enter_critical();
    fhss_timeout_s *fhss_tim = find_timeout(callback);
    if (!fhss_tim) {
        platform_exit_critical();
        return -1;
    }
    fhss_tim->timeout.detach();
    fhss_tim->active = false;
    platform_exit_critical();
    return 0;
}

static uint32_t platform_fhss_get_remaining_slots(void (*callback)(const fhss_api_t *api, uint16_t), const fhss_api_t *api)
{
    (void)api;
    platform_enter_critical();
    fhss_timeout_s *fhss_tim = find_timeout(callback);
    if (!fhss_tim) {
        platform_exit_critical();
        return 0;
    }
    uint32_t remaining_slots = fhss_tim->stop_time - read_current_time();
    platform_exit_critical();
    return remaining_slots;
}

static uint32_t platform_fhss_timestamp_read(const fhss_api_t *api)
{
    (void)api;
    return read_current_time();
}

fhss_timer_t fhss_functions = {
    .fhss_timer_start = platform_fhss_timer_start,
    .fhss_timer_stop = platform_fhss_timer_stop,
    .fhss_get_remaining_slots = platform_fhss_get_remaining_slots,
    .fhss_get_timestamp = platform_fhss_timestamp_read,
    .fhss_resolution_divider = 1
};

{'fraction_non_alphanumeric': 0.10028919644701507, 'fraction_numerical': 0.0090890311919025, 'mean_word_length': 4.161513859275053, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2371697', 'n_tokens_mistral': 3674, 'n_tokens_neox': 3460, 'n_words': 696}