/*
 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
 */
/******************************************************************************
 * @file     csi_rhino.c
 * @brief    the adapter file for the rhino
 * @version  V1.0
 * @date     20. July 2016
 ******************************************************************************/
#include <csi_kernel.h>
#include <k_api.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys_clk.h>

extern int32_t drv_get_sys_freq(void);

#define AUTORUN  1
#define TMR_ONE_SHOT_DLY             10
#define TMR_PERIODIC_PERIOD          10
#define RHINO_OS_MS_PERIOD_TICK      (1000 / RHINO_CONFIG_TICKS_PER_SECOND)

k_status_t csi_kernel_init(void)
{
    kstat_t ret = krhino_init();

#ifdef CONFIG_KERNEL_PWR_MGMT
    extern void cpu_pwrmgmt_init(void);
    cpu_pwrmgmt_init();
#endif

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else {
        return -EPERM;
    }
}

k_status_t csi_kernel_start(void)
{
    kstat_t ret = krhino_start();

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else {
        return -EPERM;
    }
}

k_sched_stat_t csi_kernel_get_stat(void)
{
    kstat_t get = g_sys_stat;

    if (get == RHINO_STOPPED) {
        return KSCHED_ST_INACTIVE;
    } else if (get == RHINO_RUNNING) {
        return KSCHED_ST_RUNNING;
    }

    return KSCHED_ST_ERROR;
}

int32_t csi_kernel_sched_lock(void)
{
    return -EOPNOTSUPP;
}

int32_t csi_kernel_sched_unlock(void)
{
    return -EOPNOTSUPP;
}

int32_t csi_kernel_sched_restore_lock(int32_t lock)
{
    return -EOPNOTSUPP;
}

uint32_t csi_kernel_sched_suspend(void)
{
    if (g_sys_stat != RHINO_RUNNING) {
        return 0;
    }

    krhino_sched_disable();
    return 0;
}

void csi_kernel_sched_resume(uint32_t sleep_ticks)
{
    if (g_sys_stat != RHINO_RUNNING) {
        return;
    }

    krhino_sched_enable();
}

k_status_t csi_kernel_task_new(k_task_entry_t task, const char *name, void *arg,
                               k_priority_t prio, uint32_t time_quanta,
                               void *stack, uint32_t stack_size, k_task_handle_t *task_handle)
{
    if ((task_handle == NULL) || (stack_size % 4 != 0) || ((stack_size == 0) && (stack == NULL)) || prio <= KPRIO_IDLE || prio > KPRIO_REALTIME7) {
        return -EINVAL;
    }

    k_status_t rc = -1;
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)

    uint8_t prio_trans = RHINO_CONFIG_USER_PRI_MAX - prio;

    csi_kernel_sched_suspend();

    kstat_t ret;

    if (name) {
        ret = krhino_task_dyn_create((ktask_t **)task_handle, name, arg, prio_trans, time_quanta, stack_size / 4, task, AUTORUN);
    } else {
        ret = krhino_task_dyn_create((ktask_t **)task_handle, "user_task", arg, prio_trans, time_quanta, stack_size / 4, task, AUTORUN);
    }

    if (ret == RHINO_SUCCESS) {
        csi_kernel_sched_resume(0);
        return 0;
    } else {
        csi_kernel_sched_resume(0);
        return -EPERM;
    }

#endif
    return rc;

}

k_status_t csi_kernel_task_del(k_task_handle_t task_handle)
{
    if (task_handle == NULL) {
        return -EINVAL;
    }

    k_status_t rc = -1;
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)

    kstat_t ret = krhino_task_dyn_del(task_handle);

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else {
        return -EPERM;
    }

#endif
    return rc;
}

k_task_handle_t csi_kernel_task_get_cur(void)
{
    ktask_t *ret;
    ret = g_active_task[cpu_cur_get()];
    return (k_task_handle_t)ret;
}

k_task_stat_t csi_kernel_task_get_stat(k_task_handle_t task_handle)
{
    if (task_handle == NULL) {
        return KTASK_ST_ERROR;
    }

    if (csi_kernel_task_get_cur() == task_handle) {
        return KTASK_ST_RUNNING;
    }

    task_stat_t get;
    ktask_t *handle = (ktask_t *)task_handle;
    get = handle->task_state;

    switch (get) {
        case K_PEND:
        case K_SUSPENDED:
        case K_PEND_SUSPENDED:
        case K_SLEEP:
        case K_SLEEP_SUSPENDED:
            return KTASK_ST_BLOCKED;
            break;

        case K_DELETED:
            return KTASK_ST_TERMINATED;
            break;

        case K_RDY:
            return KTASK_ST_READY;
            break;

        default:
            return KTASK_ST_ERROR;
    }
}

k_status_t csi_kernel_task_set_prio(k_task_handle_t task_handle, k_priority_t priority)
{
    if (task_handle  == NULL || priority <= KPRIO_IDLE || priority > KPRIO_REALTIME7) {
        return -EINVAL;
    }

    uint8_t prio = RHINO_CONFIG_USER_PRI_MAX - priority;
    uint8_t old;
    kstat_t ret = krhino_task_pri_change(task_handle, prio, &old);

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else {
        return -EPERM;
    }
}

k_priority_t csi_kernel_task_get_prio(k_task_handle_t task_handle)
{
    if (task_handle == NULL) {
        return KPRIO_ERROR;
    }

    ktask_t *handle = (ktask_t *)task_handle;
    uint8_t ret = handle->prio;

    if (ret <= RHINO_CONFIG_USER_PRI_MAX) {
        ret = RHINO_CONFIG_USER_PRI_MAX - ret;
    } else {
        ret = RHINO_CONFIG_PRI_MAX - ret;
    }

    return ret;
}

const char *csi_kernel_task_get_name(k_task_handle_t task_handle)
{
    if (task_handle == NULL) {
        return NULL;
    }

    ktask_t *handle = (ktask_t *)task_handle;

    return handle->task_name;
}

k_status_t csi_kernel_task_suspend(k_task_handle_t task_handle)
{
    if (task_handle == NULL) {
        return -EINVAL;
    }

    kstat_t ret = krhino_task_suspend(task_handle);

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else {
        return -EPERM;
    }
}

k_status_t csi_kernel_task_resume(k_task_handle_t task_handle)
{
    if (task_handle == NULL) {
        return -EINVAL;
    }

    kstat_t ret = krhino_task_resume(task_handle);

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else {
        return -EPERM;
    }
}

k_status_t csi_kernel_task_terminate(k_task_handle_t task_handle)
{
    return csi_kernel_task_del(task_handle);
}

void csi_kernel_task_exit(void)
{
    csi_kernel_task_del(csi_kernel_task_get_cur());
}

k_status_t csi_kernel_task_yield(void)
{
    kstat_t ret = krhino_task_yield();

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else {
        return -EPERM;
    }
}

uint32_t csi_kernel_task_get_count(void)
{
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
    klist_t *taskhead;
    klist_t *taskend;
    klist_t *tmp;

    taskhead = &g_kobj_list.task_head;
    taskend  = taskhead;

    uint32_t ret = 0;

    for (tmp = taskhead->next; tmp != taskend; tmp = tmp->next) {
        ret ++;
    }

    return ret;
#else
    return 0;
#endif
}

uint32_t csi_kernel_task_get_stack_size(k_task_handle_t task_handle)
{
    if (task_handle == NULL) {
        return 0;
    }

    ktask_t *handle = (ktask_t *)task_handle;
    return 4 * handle->stack_size;
}

uint32_t csi_kernel_task_get_stack_space(k_task_handle_t task_handle)
{
    if (task_handle == NULL) {
        return 0;
    }

    size_t stack_free;
    kstat_t ret = krhino_task_stack_min_free(task_handle, &stack_free);

    if (ret == RHINO_SUCCESS) {
        return 4 * stack_free;
    } else {
        return 0;
    }
}

uint32_t csi_kernel_task_list(k_task_handle_t *task_array, uint32_t array_items)
{
    if (task_array == NULL || array_items == 0) {
        return 0;
    }

    uint32_t real_tsk_num = 0;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
    klist_t *taskhead;
    klist_t *taskend;
    klist_t *tmp;
    ktask_t  *task;

    k_task_handle_t *tk_tmp = task_array;
    taskhead = &g_kobj_list.task_head;
    taskend  = taskhead;

#ifdef CONFIG_BACKTRACE
    uint32_t task_free;
    size_t irq_flags;
#endif
#ifdef CONFIG_STACK_GUARD
    int      stack_flags;
#endif

    for (tmp = taskhead->next; tmp != taskend; tmp = tmp->next) {
        real_tsk_num ++;
        task  = krhino_list_entry(tmp, ktask_t, task_stats_item);
#ifdef CONFIG_BACKTRACE
        krhino_task_stack_min_free(task, &task_free);
        printf("\n%s:\n\t    state %d, pri %d, stack: total %d, free %d\n",
               task->task_name, task->task_state, task->prio, 4 * task->stack_size, 4 * task_free);
#endif
    }

    if (array_items < real_tsk_num) {
        real_tsk_num = array_items;
    }

    for (tmp = taskhead->next; tmp != taskend && real_tsk_num >= 1; tmp = tmp->next) {
        task  = krhino_list_entry(tmp, ktask_t, task_stats_item);
        *tk_tmp = task;
        tk_tmp ++;
    }

#ifdef CONFIG_BACKTRACE
    irq_flags = cpu_intrpt_save();

#ifdef CONFIG_STACK_GUARD
    extern int stack_guard_save(void);
    stack_flags = stack_guard_save();
#endif

    for (tmp = taskhead->next; tmp != taskend; tmp = tmp->next) {
        task  = krhino_list_entry(tmp, ktask_t, task_stats_item);
        krhino_task_stack_min_free(task, &task_free);

        printf("\n%s:\n", task->task_name);
        extern int csky_task_backtrace(void *stack, char *buf, int len);
        csky_task_backtrace(task->task_stack, NULL, 0);
    }

#ifdef CONFIG_STACK_GUARD
    extern void stack_guard_restore(int value);
    stack_guard_restore(stack_flags);
#endif

    cpu_intrpt_restore(irq_flags);

#endif /* CONFIG_BACKTRACE */
#endif /* RHINO_CONFIG_SYSTEM_STATS */

    return real_tsk_num;
}

k_status_t csi_kernel_intrpt_enter(void)
{
    kstat_t ret = krhino_intrpt_enter();

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else {
        return -EPERM;
    }

    return 0;
}

k_status_t csi_kernel_intrpt_exit(void)
{
    krhino_intrpt_exit();
    return 0;
}


k_status_t csi_kernel_delay(uint32_t ticks)
{
    kstat_t ret = krhino_task_sleep(ticks);

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else {
        return -EPERM;
    }
}

k_status_t csi_kernel_delay_until(uint64_t ticks)
{
    return -EOPNOTSUPP;
}

uint64_t csi_kernel_tick2ms(uint32_t ticks)
{
    return ((uint64_t)ticks * RHINO_OS_MS_PERIOD_TICK);
}

uint64_t csi_kernel_ms2tick(uint32_t ms)
{
    if (ms < RHINO_OS_MS_PERIOD_TICK) {
        return 0;
    }

    return (((uint64_t)ms) / RHINO_OS_MS_PERIOD_TICK);
}

k_status_t csi_kernel_delay_ms(uint32_t ms)
{
    uint32_t ms_get = ms;

    if ((ms < RHINO_OS_MS_PERIOD_TICK) && (ms != 0)) {
        ms_get = RHINO_OS_MS_PERIOD_TICK;
    }

    uint64_t ticks = csi_kernel_ms2tick(ms_get);
    kstat_t ret = krhino_task_sleep(ticks);

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else {
        return -EPERM;
    }
}

uint64_t csi_kernel_get_ticks(void)
{
    return (uint64_t)krhino_sys_tick_get();
}

uint64_t csi_kernel_suspend_tick(void)
{
//    return next_task_wake_tick_get();
    return 0;
}

void csi_kernel_update_tick(uint32_t ms)
{
    extern uint64_t g_sys_tick_count;
    uint32_t ticks = ms * RHINO_CONFIG_TICKS_PER_SECOND / 1000;

    CPSR_ALLOC();

    RHINO_CPU_INTRPT_DISABLE();
    g_sys_tick_count += ticks;

    RHINO_CPU_INTRPT_ENABLE();
}

uint32_t csi_kernel_get_tick_freq(void)
{
    return RHINO_CONFIG_TICKS_PER_SECOND;
}

uint32_t csi_kernel_get_systimer_freq(void)
{
    return soc_get_cur_cpu_freq();
}

typedef struct tmr_arg {
    void       *arg;
    k_timer_cb_t   func;
} tmr_arg_t;

static void tmr_adapt_cb(void *timer, void *arg)
{
    ktimer_t  *get = (ktimer_t *)timer;
    tmr_arg_t *arg_above = (tmr_arg_t *)(get->timer_cb_arg);

    if (arg_above->func) {
        arg_above->func(arg_above->arg);
    }

    return;
}

k_timer_handle_t csi_kernel_timer_new(k_timer_cb_t func, k_timer_type_t type, void *arg)
{
    if (type < 0 || type > 1 || func == NULL) {
        return NULL;
    }

    tick_t first = TMR_ONE_SHOT_DLY;
    tick_t round;

    if (type == KTIMER_TYPE_ONCE) {
        round = 0;
    } else {
        round = TMR_PERIODIC_PERIOD;
    }

    tmr_arg_t *get_arg = (tmr_arg_t *)malloc(sizeof(tmr_arg_t));

    if (get_arg == NULL) {
        return NULL;
    }

    ktimer_t       *tmr;
    get_arg->arg  = arg;
    get_arg->func = func;

#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
    kstat_t ret = krhino_timer_dyn_create((ktimer_t **)&tmr, "UserTmr", (timer_cb_t)tmr_adapt_cb, first, round, get_arg, 0);

    if (ret == RHINO_SUCCESS) {
        return tmr;
    } else {
        free((void *)get_arg);
        return NULL;
    }

#else
    return NULL;
#endif
}

k_status_t csi_kernel_timer_del(k_timer_handle_t timer_handle)
{
    if (timer_handle == NULL) {
        return -EINVAL;
    }

    k_status_t rc = -1;
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)

    kstat_t ret = krhino_timer_dyn_del((ktimer_t *)timer_handle);

    if (ret == RHINO_SUCCESS) {
        free(((ktimer_t *)timer_handle)->timer_cb_arg);
        return 0;
    } else {
        return -EPERM;
    }

#endif
    return rc;
}

k_status_t csi_kernel_timer_start(k_timer_handle_t timer_handle, uint32_t ticks)
{
    if (timer_handle == NULL || ticks == 0) {
        return -EINVAL;
    }

    tick_t round;
    ktimer_t *handle = (ktimer_t *)timer_handle;

    round = handle->round_ticks;

    tick_t tr;
    tick_t tf = ticks;

    if (round != 0) {
        tr = ticks;
    } else {
        tr = 0;
    }

    kstat_t ret1 = krhino_timer_change(handle, tf, tr);

    if (ret1 == RHINO_SUCCESS) {
        kstat_t ret2 = krhino_timer_start(handle);

        if (ret2 == RHINO_SUCCESS) {
            return 0;
        } else {
            return -EPERM;
        }
    } else {
        return -EPERM;
    }
}

k_status_t csi_kernel_timer_stop(k_timer_handle_t timer_handle)
{
    if (timer_handle == NULL) {
        return -EINVAL;
    }

    ktimer_t *handle = (ktimer_t *)timer_handle;

    kstat_t ret = krhino_timer_stop(handle);

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else {
        return -EPERM;
    }
}

k_timer_stat_t csi_kernel_timer_get_stat(k_timer_handle_t timer_handle)
{
    if (timer_handle == NULL) {
        return KTIMER_ST_INACTIVE;
    }

    ktimer_t *handle = (ktimer_t *)(timer_handle);
    k_timer_state_t get = handle->timer_state;

    if (get == TIMER_DEACTIVE) {
        return KTIMER_ST_INACTIVE;
    } else {
        return KTIMER_ST_ACTIVE;
    }
}

k_event_handle_t csi_kernel_event_new(void)
{
#if (RHINO_CONFIG_EVENT_FLAG > 0)
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
    kevent_t *event_handle;
    kstat_t ret = krhino_event_dyn_create((kevent_t **)&event_handle, "UserEvent", 0);

    if (ret == RHINO_SUCCESS) {
        return event_handle;
    } else {
        return NULL;
    }

#else
return NULL:
#endif

#else
    return NULL;
#endif

}

k_status_t csi_kernel_event_del(k_event_handle_t ev_handle)
{
#if (RHINO_CONFIG_EVENT_FLAG > 0)

    if (ev_handle == NULL) {
        return -EINVAL;
    }

#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
    kstat_t ret = krhino_event_dyn_del(ev_handle);

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else {
        return -EPERM;
    }

#else
    return -EPERM;
#endif

#else
    return -EOPNOTSUPP;
#endif
}

k_status_t csi_kernel_event_set(k_event_handle_t ev_handle, uint32_t flags, uint32_t *ret_flags)
{
#if (RHINO_CONFIG_EVENT_FLAG > 0)

    if (ev_handle == NULL || ret_flags == NULL) {
        return -EINVAL;
    }

    kstat_t ret = krhino_event_set(ev_handle, flags, RHINO_OR);

    if (ret == RHINO_SUCCESS) {
        kevent_t *handle = (kevent_t *)ev_handle;
        *ret_flags = handle->flags;
        return 0;
    } else {
        return -EPERM;
    }

#else
    return -EOPNOTSUPP;
#endif
}

k_status_t csi_kernel_event_clear(k_event_handle_t ev_handle, uint32_t flags, uint32_t *ret_flags)
{
    return -EOPNOTSUPP;
}

k_status_t csi_kernel_event_get(k_event_handle_t ev_handle, uint32_t *ret_flags)
{
#if (RHINO_CONFIG_EVENT_FLAG > 0)

    if (ev_handle == NULL || ret_flags == NULL) {
        return -EINVAL;
    }

    kevent_t *handle = (kevent_t *)ev_handle;
    *ret_flags = handle->flags;
    return 0;
#else
    return -EOPNOTSUPP;
#endif
}

k_status_t csi_kernel_event_wait(k_event_handle_t ev_handle, uint32_t flags,
                                 k_event_opt_t options, uint8_t clr_on_exit,
                                 uint32_t *actl_flags, int32_t timeout)
{
#if (RHINO_CONFIG_EVENT_FLAG > 0)

    if (ev_handle == NULL || actl_flags == NULL
        || ((clr_on_exit != 0) && (clr_on_exit != 1))) {
        return -EINVAL;
    }

    if (options == KEVENT_OPT_CLR_ANY || options == KEVENT_OPT_CLR_ALL) {
        return -EOPNOTSUPP;
    }

    uint8_t opt = 0;

    if (options == KEVENT_OPT_SET_ANY) {
        if (clr_on_exit == 1) {
            opt = RHINO_OR_CLEAR;
        } else {
            opt = RHINO_OR;
        }
    } else if (options == KEVENT_OPT_SET_ALL) {
        if (clr_on_exit == 1) {
            opt = RHINO_AND_CLEAR;
        } else {
            opt = RHINO_AND;
        }
    }

    tick_t t;

    if (timeout < 0) {
        t = RHINO_WAIT_FOREVER;
    } else {
        t = timeout;
    }

    kstat_t ret = krhino_event_get(ev_handle, flags, opt, actl_flags, t);

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else if (ret == RHINO_BLK_TIMEOUT) {
        return -ETIMEDOUT;
    } else {
        return -EPERM;
    }

#else
    return -EOPNOTSUPP;
#endif
}

k_mutex_handle_t csi_kernel_mutex_new(void)
{
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
    kmutex_t *mutex_handle;
    kstat_t ret = krhino_mutex_dyn_create((kmutex_t **)&mutex_handle, "UserMutex");

    if (ret == RHINO_SUCCESS) {
        return mutex_handle;
    } else {
        return NULL;
    }

#else
    return NULL;
#endif
}

k_status_t csi_kernel_mutex_del(k_mutex_handle_t mutex_handle)
{
    if (mutex_handle == NULL) {
        return -EINVAL;
    }

#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
    kstat_t ret = krhino_mutex_dyn_del(mutex_handle);

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else {
        return -EPERM;
    }

#else
    return -EPERM;
#endif
}

k_status_t csi_kernel_mutex_lock(k_mutex_handle_t mutex_handle, int32_t timeout)
{
    if (mutex_handle == NULL) {
        return -EINVAL;
    }

    tick_t t;

    if (timeout < 0) {
        t = RHINO_WAIT_FOREVER;
    } else {
        t = timeout;
    }

    kstat_t ret = krhino_mutex_lock(mutex_handle, t);

    if (ret == RHINO_SUCCESS || ret == RHINO_MUTEX_OWNER_NESTED) {
        return 0;
    } else if (ret == RHINO_BLK_TIMEOUT) {
        return -ETIMEDOUT;
    } else {
        return -EPERM;
    }
}

k_status_t csi_kernel_mutex_unlock(k_mutex_handle_t mutex_handle)
{
    if (mutex_handle == NULL) {
        return -EINVAL;
    }

    kstat_t ret = krhino_mutex_unlock(mutex_handle);

    if (ret == RHINO_SUCCESS || ret == RHINO_MUTEX_OWNER_NESTED) {
        return 0;
    } else {
        return -EPERM;
    }
}

k_task_handle_t csi_kernel_mutex_get_owner(k_mutex_handle_t mutex_handle)
{
    if (mutex_handle == NULL) {
        return NULL;
    }

    kmutex_t *handle = (kmutex_t *)mutex_handle;
    return  handle->mutex_task;
}

k_sem_handle_t csi_kernel_sem_new(int32_t max_count, int32_t initial_count)
{
    if (max_count <= 0 || initial_count < 0) {
        return NULL;
    }

    if (max_count < initial_count) {
        return NULL;
    }

#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
    ksem_t *sem_handle;
    kstat_t ret = krhino_sem_dyn_create((ksem_t **)&sem_handle, "UserSem", initial_count);

    if (ret == RHINO_SUCCESS) {
        return sem_handle;
    } else {
        return NULL;
    }

#else
    return NULL;
#endif
}

k_status_t csi_kernel_sem_del(k_sem_handle_t sem_handle)
{
    if (sem_handle == NULL) {
        return -EINVAL;
    }

#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
    kstat_t ret = krhino_sem_dyn_del(sem_handle);

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else {
        return -EPERM;
    }

#else
    return -EPERM;
#endif
}

k_status_t csi_kernel_sem_wait(k_sem_handle_t sem_handle, int32_t timeout)
{
    if (sem_handle == NULL) {
        return -EINVAL;
    }

    tick_t t;

    if (timeout < 0) {
        t = RHINO_WAIT_FOREVER;
    } else {
        t = timeout;
    }

    kstat_t ret = krhino_sem_take(sem_handle, t);

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else  if (ret == RHINO_BLK_TIMEOUT) {
        return -ETIMEDOUT;
    } else {
        return -EPERM;
    }
}

k_status_t csi_kernel_sem_post(k_sem_handle_t sem_handle)
{
    if (sem_handle == NULL) {
        return -EINVAL;
    }

    kstat_t ret = krhino_sem_give(sem_handle);

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else {
        return -EPERM;
    }
}

int32_t csi_kernel_sem_get_count(k_sem_handle_t sem_handle)
{
    if (sem_handle == NULL) {
        return -EINVAL;
    }

    sem_count_t cnt;
    kstat_t ret = krhino_sem_count_get(sem_handle, &cnt);

    if (ret == RHINO_SUCCESS) {
        return (int32_t)cnt;
    } else {
        return -EPERM;
    }
}

k_mpool_handle_t csi_kernel_mpool_new(void *p_addr, int32_t block_count, int32_t block_size)
{
    if (p_addr == NULL || block_count < 0 || block_size <= 0 || (block_size % 4 != 0)) {
        return NULL;
    }

#if (RHINO_CONFIG_MM_BLK > 0)
    mblk_pool_t *handle = (mblk_pool_t *)malloc(sizeof(mblk_pool_t));

    if (handle == NULL) {
        return NULL;
    }

    kstat_t ret = krhino_mblk_pool_init(handle, "UserMp", p_addr, block_size, block_count * block_size);

    if (ret == RHINO_SUCCESS) {
        return handle;
    } else {
        return NULL;
    }

#else
    return NULL;
#endif
}

k_status_t csi_kernel_mpool_del(k_mpool_handle_t mp_handle)
{
    if (mp_handle == NULL) {
        return -EINVAL;
    }

    memset(mp_handle, 0, sizeof(mblk_pool_t));
    free(mp_handle);
    return 0;
}

void *csi_kernel_mpool_alloc(k_mpool_handle_t mp_handle, int32_t timeout)
{
    if (mp_handle == NULL) {
        return NULL;
    }

#if (RHINO_CONFIG_MM_BLK > 0)
    uint32_t g_csi_rhino_blk = 0;
    kstat_t ret = krhino_mblk_alloc(mp_handle, (void **)&g_csi_rhino_blk);

    if (ret == RHINO_SUCCESS) {
        return (void *)g_csi_rhino_blk;
    } else {
        return NULL;
    }

#else
    return NULL;
#endif
}

k_status_t csi_kernel_mpool_free(k_mpool_handle_t mp_handle, void *block)
{
    if (mp_handle == NULL || block == NULL) {
        return -EINVAL;
    }

#if (RHINO_CONFIG_MM_BLK > 0)
    kstat_t ret = krhino_mblk_free(mp_handle, block);

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else {
        return -EPERM;
    }

#else
    return -EPERM;
#endif
}

int32_t csi_kernel_mpool_get_count(k_mpool_handle_t mp_handle)
{
    if (mp_handle == NULL) {
        return 0;
    }

    mblk_pool_t *handle = (mblk_pool_t *)mp_handle;
    int32_t used = handle->blk_whole - handle->blk_avail;
    return used;
}

uint32_t csi_kernel_mpool_get_capacity(k_mpool_handle_t mp_handle)
{
    if (mp_handle == NULL) {
        return 0;
    }

    mblk_pool_t *handle = (mblk_pool_t *)mp_handle;
    return handle->blk_whole;
}

uint32_t csi_kernel_mpool_get_block_size(k_mpool_handle_t mp_handle)
{
    if (mp_handle == NULL) {
        return 0;
    }

    mblk_pool_t *handle = (mblk_pool_t *)mp_handle;
    return handle->blk_size;
}

typedef struct mq_adapter {
    kbuf_queue_t    *buf_q;
    int32_t         msg_size;
    int32_t         msg_count;
} mq_adapter_t;
k_msgq_handle_t csi_kernel_msgq_new(int32_t msg_count, int32_t msg_size)
{
    if (msg_count <= 0 || msg_size <= 0) {
        return NULL;
    }

#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
    mq_adapter_t *handle = (mq_adapter_t *)malloc(sizeof(mq_adapter_t));

    if (handle == NULL) {
        return NULL;
    }

    kstat_t ret  = krhino_buf_queue_dyn_create(&(handle->buf_q), "UserMsgQ", msg_size * (msg_count + 1), msg_size);

    if (ret == RHINO_SUCCESS) {
        handle->msg_count = msg_count;
        handle->msg_size = msg_size;
        return (k_msgq_handle_t)handle;
    } else {
        free(handle);
        return NULL;
    }

#else
    return NULL;
#endif
}

k_status_t csi_kernel_msgq_del(k_msgq_handle_t mq_handle)
{
    if (!mq_handle) {
        return -EINVAL;
    }

#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
    mq_adapter_t *handle = (mq_adapter_t *)mq_handle;
    kstat_t ret  = krhino_buf_queue_dyn_del(handle->buf_q);

    if (ret == RHINO_SUCCESS) {
        free(mq_handle);
        return 0;
    } else {
        return -EPERM;
    }

#else
    return -EPERM;
#endif
}

k_status_t csi_kernel_msgq_put(k_msgq_handle_t mq_handle, const void *msg_ptr, uint8_t front_or_back, int32_t timeout)
{
    k_status_t retval = -EPERM;

    if ((!mq_handle) || (msg_ptr == NULL) || ((front_or_back != 0) && (front_or_back != 1))) {
        return -EINVAL;
    }

    mq_adapter_t *handle = (mq_adapter_t *)mq_handle;

    if (front_or_back == 0) {
        kstat_t ret = krhino_buf_queue_send(handle->buf_q, (void *)msg_ptr, handle->msg_size);

        if (ret == RHINO_SUCCESS) {
            retval = 0 ;
        } else {
            retval = -EPERM;
        }
    } else if (front_or_back == 1) {
        kstat_t ret = krhino_buf_queue_send(handle->buf_q, (void *)msg_ptr, handle->msg_size);

        if (ret == RHINO_SUCCESS) {
            retval = 0;
        } else {
            retval = -EPERM;
        }
    }

    return retval;
}


k_status_t csi_kernel_msgq_get(k_msgq_handle_t mq_handle, void *msg_ptr, int32_t timeout)
{
    if (mq_handle == NULL || msg_ptr == NULL) {
        return -EINVAL;
    }

    tick_t t;

    if (timeout < 0) {
        t = RHINO_WAIT_FOREVER;
    } else {
        t = timeout;
    }

    mq_adapter_t *handle = (mq_adapter_t *)mq_handle;
    size_t size;
    kstat_t ret = krhino_buf_queue_recv(handle->buf_q, t, msg_ptr, &size);

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else if (ret == RHINO_BLK_TIMEOUT) {
        return -ETIMEDOUT;
    } else {
        return -EPERM;
    }
}

int32_t csi_kernel_msgq_get_count(k_msgq_handle_t mq_handle)
{
    if (mq_handle == NULL) {
        return -EINVAL;
    }

    mq_adapter_t *handle = (mq_adapter_t *)mq_handle;
    kbuf_queue_info_t info;
    kstat_t ret = krhino_buf_queue_info_get(handle->buf_q, &info);

    if (ret == RHINO_SUCCESS) {
        int32_t cnt = info.cur_num;
        return cnt;
    } else {
        return -EPERM;
    }
}

uint32_t csi_kernel_msgq_get_capacity(k_msgq_handle_t mq_handle)
{
    if (mq_handle == NULL) {
        return 0;
    }

    mq_adapter_t *handle = (mq_adapter_t *)mq_handle;
    return handle->msg_count;
}

uint32_t csi_kernel_msgq_get_msg_size(k_msgq_handle_t mq_handle)
{
    if (mq_handle == NULL) {
        return 0;
    }

    mq_adapter_t *handle = (mq_adapter_t *)mq_handle;
    return handle->buf_q->max_msg_size;
}

k_status_t csi_kernel_msgq_flush(k_msgq_handle_t mq_handle)
{
    if (mq_handle == NULL) {
        return -EINVAL;
    }

    mq_adapter_t *handle = (mq_adapter_t *)mq_handle;
    kstat_t ret = krhino_buf_queue_flush(handle->buf_q);

    if (ret == RHINO_SUCCESS) {
        return 0;
    } else {
        return -EPERM;
    }
}

void *csi_kernel_malloc(int32_t size, void *caller)
{
    void *ret;

    if (size < 1) {
        return NULL;
    }

    csi_kernel_sched_suspend();
    ret = krhino_mm_alloc(size, caller);
    csi_kernel_sched_resume(0);
    return ret;
}

void csi_kernel_free(void *ptr, void *caller)
{
    csi_kernel_sched_suspend();
    krhino_mm_free(ptr);
    csi_kernel_sched_resume(0);
}

void *csi_kernel_realloc(void *ptr, int32_t size, void *caller)
{
    void *new_ptr;

    new_ptr = krhino_mm_realloc(ptr, size, caller);

    return new_ptr;
}

k_status_t csi_kernel_get_mminfo(int32_t *total, int32_t *used, int32_t *free, int32_t *peak)
{
    *total = g_kmm_head->used_size + g_kmm_head->free_size;
    *used = g_kmm_head->used_size;
    *free = g_kmm_head->free_size;
    *peak = g_kmm_head->maxused_size;

    return 0;
}

k_status_t csi_kernel_mm_dump(void)
{
#if (RHINO_CONFIG_MM_DEBUG > 0u)
    dumpsys_mm_info_func(NULL, 0);
#endif

    return 0;
}
