/*
 * Copyright 2017, Data61
 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
 * ABN 41 687 119 230.
 *
 * This software may be distributed and modified according to the terms of
 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
 * See "LICENSE_BSD2.txt" for details.
 *
 * @TAG(DATA61_BSD)
 */

#pragma once
/**
 *
 * Builder functions for thread configs
 *
 */

#include <autoconf.h>
#include <sel4utils/gen_config.h>
#include <sel4/types.h>
#include <simple/simple.h>
#include <sel4utils/api.h>

/* Threads and processes use this struct as both need scheduling config parameters */
typedef struct sched_params {
    /* seL4 priority for the thread to be scheduled with. */
    uint8_t priority;
    /* seL4 maximum controlled priority for the thread. */
    uint8_t mcp;
    /* TCB to derive MCP from when setting priority/mcp (in future API) */
    seL4_CPtr auth;
    /* true if sel4utils should create an sc */
    bool create_sc;
    /* sel4 sched control cap for creating sc */
    seL4_CPtr sched_ctrl;
    /* scheduling parameters */
    uint64_t period;
    uint64_t budget;
    seL4_Word extra_refills;
    seL4_Word badge;
    /* otherwise use this provided sc */
    seL4_CPtr sched_context;
    /* affinity for this tcb. Must set sched_ctrl if CONFIG_RT */
    seL4_Word core;
} sched_params_t;

typedef struct sel4utils_thread_config {
    /* fault_endpoint endpoint to set as the threads fault endpoint. Can be seL4_CapNull. */
    seL4_CPtr fault_endpoint;
    /* root of the cspace to start the thread in */
    seL4_CNode cspace;
    /* data for cspace access */
    seL4_Word cspace_root_data;
    /* use a custom stack size? */
    bool custom_stack_size;
    /* custom stack size in 4k pages for this thread */
    seL4_Word stack_size;
    /* true if this thread should have no ipc buffer */
    bool no_ipc_buffer;
    /* scheduling parameters */
    sched_params_t sched_params;
    /* true if sel4utils should create a reply */
    bool create_reply;
    /* otherwise provide one */
    seL4_CPtr reply;
} sel4utils_thread_config_t;

static inline sched_params_t sched_params_periodic(sched_params_t params, simple_t *simple, seL4_Word core,
                                                   uint64_t period_us,
                                                   uint64_t budget_us, seL4_Word extra_refills, seL4_Word badge)
{
    if (!config_set(CONFIG_KERNEL_MCS)) {
        ZF_LOGW("Setting sched params on non-RT kernel will have no effect");
    }
    params.sched_ctrl = simple_get_sched_ctrl(simple, core);
    params.period = period_us;
    params.budget = budget_us;
    params.extra_refills = extra_refills;
    params.badge = badge;
    params.create_sc = true;
    return params;
}

static inline sched_params_t sched_params_round_robin(sched_params_t params, simple_t *simple, seL4_Word core,
                                                      uint64_t timeslice_us)
{
    return sched_params_periodic(params, simple, core, timeslice_us, timeslice_us, 0, 0);
}

static inline sched_params_t sched_params_core(sched_params_t params, seL4_Word core)
{
    if (!config_set(CONFIG_KERNEL_MCS)) {
        ZF_LOGW("Setting core on RT kernel will have no effect - sched ctrl required");
    }
    params.core = core;
    return params;
}

static inline sel4utils_thread_config_t thread_config_create_reply(sel4utils_thread_config_t config)
{
    config.create_reply = true;
    return config;
}

static inline sel4utils_thread_config_t thread_config_reply(sel4utils_thread_config_t config, seL4_CPtr reply)
{
    config.create_reply = false;
    config.reply = reply;
    return config;
}

static inline sel4utils_thread_config_t thread_config_sched_context(sel4utils_thread_config_t config,
                                                                    seL4_CPtr sched_context)
{
    config.sched_params.create_sc = false;
    config.sched_params.sched_context = sched_context;
    return config;
}

static inline sel4utils_thread_config_t thread_config_cspace(sel4utils_thread_config_t config, seL4_CPtr cspace_root,
                                                             seL4_Word cspace_root_data)
{
    config.cspace = cspace_root;
    config.cspace_root_data = cspace_root_data;
    return config;
}

static inline sel4utils_thread_config_t thread_config_auth(sel4utils_thread_config_t config, seL4_CPtr tcb)
{
    config.sched_params.auth = tcb;
    return config;
}

static inline sel4utils_thread_config_t thread_config_new(simple_t *simple)
{
    sel4utils_thread_config_t config = {0};
    seL4_Word data = api_make_guard_skip_word(seL4_WordBits - simple_get_cnode_size_bits(simple));
    config = thread_config_auth(config, simple_get_tcb(simple));
    return thread_config_cspace(config, simple_get_cnode(simple), data);
}

static inline sel4utils_thread_config_t thread_config_priority(sel4utils_thread_config_t config, uint8_t priority)
{
    config.sched_params.priority = priority;
    return config;
}

static inline sel4utils_thread_config_t thread_config_mcp(sel4utils_thread_config_t config, uint8_t mcp)
{
    config.sched_params.mcp = mcp;
    return config;
}

static inline sel4utils_thread_config_t thread_config_stack_size(sel4utils_thread_config_t config, seL4_Word size)
{
    config.stack_size = size;
    config.custom_stack_size = true;
    return config;
}

static inline sel4utils_thread_config_t thread_config_no_ipc_buffer(sel4utils_thread_config_t config)
{
    config.no_ipc_buffer = true;
    return config;
}

static inline sel4utils_thread_config_t thread_config_fault_endpoint(sel4utils_thread_config_t config,
                                                                     seL4_CPtr fault_ep)
{
    config.fault_endpoint = fault_ep;
    return config;
}

static inline sel4utils_thread_config_t thread_config_default(simple_t *simple, seL4_CPtr cnode, seL4_Word data,
                                                              seL4_CPtr fault_ep, uint8_t prio)
{
    sel4utils_thread_config_t config = thread_config_new(simple);
    config = thread_config_cspace(config, cnode, data);
    config = thread_config_fault_endpoint(config, fault_ep);
    config = thread_config_priority(config, prio);
    if (config_set(CONFIG_KERNEL_MCS)) {
        uint64_t timeslice = CONFIG_BOOT_THREAD_TIME_SLICE;
        config.sched_params = sched_params_round_robin(config.sched_params, simple, 0, timeslice * US_IN_MS);
    }
    config = thread_config_create_reply(config);
    return config;
}
