Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources

This commit is contained in:
2026-07-06 11:30:13 +08:00
commit e76462eeb7
3451 changed files with 1415300 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_API_H
#define K_API_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <k_config.h>
#include <k_default_config.h>
#include <k_types.h>
#include <k_err.h>
#include <k_critical.h>
#include <k_sys.h>
#include <k_bitmap.h>
#include <k_list.h>
#include <k_obj.h>
#include <k_sched.h>
#include <k_task.h>
#include <k_ringbuf.h>
#include <k_queue.h>
#include <k_buf_queue.h>
#include <k_sem.h>
#include <k_task_sem.h>
#include <k_mutex.h>
#include <k_timer.h>
#include <k_time.h>
#include <k_event.h>
#include <k_stats.h>
#include <k_mm_debug.h>
#include <k_mm_blk.h>
#include <k_mm_region.h>
#include <k_mm.h>
#include <k_workqueue.h>
#include <k_internal.h>
#include <k_trace.h>
#include <k_soc.h>
#include <k_hook.h>
#include <port.h>
#include <k_endian.h>
#include <k_fifo.h>
#ifndef __at_section
#define __at_section(sec) __attribute__((section(sec)))
#endif
#ifndef __bobj
#define __bobj
#endif
#ifndef __init
#define __init
#endif
extern void assert_internal(const char *__function, unsigned int __line, const char *__assertion, void *lr);
#ifdef __cplusplus
}
#endif
#endif /* K_API_H */

View File

@@ -0,0 +1,108 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_BITMAP_H
#define K_BITMAP_H
#define BITMAP_UNIT_SIZE 32U
#define BITMAP_UNIT_MASK 0X0000001F
#define BITMAP_UNIT_BITS 5U
#define BITMAP_MASK(nr) (1UL << (BITMAP_UNIT_SIZE - 1U - ((nr) & BITMAP_UNIT_MASK)))
#define BITMAP_WORD(nr) ((nr) >> BITMAP_UNIT_BITS)
#define LITTLE_TO_BIG_ENDIAN(x) ((uint32_t)(((x) & 0x000000ffUL) << 24u) | \
(((x) & 0x0000ff00UL) << 8u) | \
(((x) & 0x00ff0000UL) >> 8u) | \
(((x) & 0xff000000UL) >> 24u))
/**
** This MACRO will declare a bitmap
** @param[in] name the name of the bitmap to declare
** @param[in] bits the bits of the bitmap
** @return no return
**/
#define BITMAP_DECLARE(name, bits) uint32_t name[((bits) + (BITMAP_UNIT_SIZE - 1U)) >> BITMAP_UNIT_BITS]
#if (RHINO_CONFIG_BITMAP_HW != 0)
extern int32_t cpu_bitmap_clz(uint32_t val);
#endif
/**
** This function will set a bit of the bitmap
** @param[in] bitmap pointer to the bitmap
** @param[in] nr position of the bitmap to set
** @return no return
**/
RHINO_INLINE void krhino_bitmap_set(uint32_t *bitmap, int32_t nr)
{
bitmap[BITMAP_WORD(nr)] |= BITMAP_MASK(nr);
}
/**
** This function will clear a bit of the bitmap
** @param[in] bitmap pointer to the bitmap
** @param[in] nr position of the bitmap to clear
** @return no return
**/
RHINO_INLINE void krhino_bitmap_clear(uint32_t *bitmap, int32_t nr)
{
bitmap[BITMAP_WORD(nr)] &= ~BITMAP_MASK(nr);
}
/**
** This function will find the first bit(1) of the bitmap
** @param[in] bitmap pointer to the bitmap
** @return the first bit position
**/
RHINO_INLINE int krhino_find_first_bit(uint32_t *bitmap)
{
int32_t nr = 0;
uint32_t tmp = 0;
while (*bitmap == 0UL) {
nr += BITMAP_UNIT_SIZE;
bitmap++;
}
tmp = *bitmap;
#if (RHINO_CONFIG_LITTLE_ENDIAN == 0)
tmp = LITTLE_TO_BIG_ENDIAN(tmp);
#endif
#if (RHINO_CONFIG_BITMAP_HW == 0)
if (!(tmp & 0XFFFF0000)) {
tmp <<= 16;
nr += 16;
}
if (!(tmp & 0XFF000000)) {
tmp <<= 8;
nr += 8;
}
if (!(tmp & 0XF0000000)) {
tmp <<= 4;
nr += 4;
}
if (!(tmp & 0XC0000000)) {
tmp <<= 2;
nr += 2;
}
if (!(tmp & 0X80000000)) {
nr += 1;
}
#else
nr += cpu_bitmap_clz(tmp);
#endif
return nr;
}
#endif /* K_BITMAP_H */

View File

@@ -0,0 +1,122 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_BUF_QUEUE_H
#define K_BUF_QUEUE_H
typedef struct {
blk_obj_t blk_obj;
blk_obj_t sblk_obj;
void *buf;
k_ringbuf_t ringbuf;
size_t max_msg_size;
size_t cur_num;
size_t peak_num;
size_t min_free_buf_size;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_t buf_queue_item;
#endif
uint8_t mm_alloc_flag;
} kbuf_queue_t;
typedef struct {
size_t buf_size;
size_t max_msg_size;
size_t cur_num;
size_t peak_num;
size_t free_buf_size;
size_t min_free_buf_size;
} kbuf_queue_info_t;
/**
* This function will create a buf-queue
* @param[in] queue pointer to the queue(the space is provided by user)
* @param[in] name name of the queue
* @param[in] buf pointer to the buf
* @param[in] size size of the buf
* @param[in] max_msg max size of one msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_create(kbuf_queue_t *queue, const name_t *name,
void *buf,
size_t size, size_t max_msg);
/**
* This function will create a fix buf-queue
* @param[in] queue pointer to the queue(the space is provided by user)
* @param[in] name name of the queue
* @param[in] buf pointer to the buf
* @param[in] msg_size size of the msg
* @param[in] msg_num number of msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_fix_buf_queue_create(kbuf_queue_t *queue, const name_t *name,
void *buf, size_t msg_size, size_t msg_num);
/**
* This function will delete a queue
* @param[in] queue pointer to the queue
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_del(kbuf_queue_t *queue);
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
/**
* This function will create a dyn-queue
* @param[out] queue pointer to the queue(The space is provided by kernel)
* @param[in] name pointer to the nam
* @param[in] size size of the buf
* @param[in] max_msg max size of one msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_dyn_create(kbuf_queue_t **queue, const name_t *name,
size_t size, size_t max_msg);
/**
* This function will delete a dyn-queue
* @param[in] queue pointer to the queue
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_dyn_del(kbuf_queue_t *queue);
#endif
/**
* This function will send a msg at the end of queue
* @param[in] queue pointer to the queue
* @param[in] msg pointer to msg to be send
* @param[in] size size of the msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_send(kbuf_queue_t *queue, void *msg, size_t size, tick_t ticks);
/**
* This function will receive msg form aqueue
* @param[in] queue pointer to the queue
* @param[in] ticks ticks to wait before receiving msg
* @param[out] msg pointer to the buf to save msg
* @param[out] size size of received msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_recv(kbuf_queue_t *queue, tick_t ticks, void *msg,
size_t *size);
/**
* This function will reset queue
* @param[in] queue pointer to the queue
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_flush(kbuf_queue_t *queue);
/**
* This function will get information of a queue
* @param[in] queue pointer to the queue
* @param[out] free free size of the queue buf
* @param[out] total total size of the queue buf
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_buf_queue_info_get(kbuf_queue_t *queue, kbuf_queue_info_t *info);
#endif /* K_BUF_QUEUE_H */

View File

@@ -0,0 +1,132 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_CRITICAL_H
#define K_CRITICAL_H
typedef struct {
#if (RHINO_CONFIG_CPU_NUM > 1)
uint32_t owner; /* cpu index of owner */
#endif
uint32_t cnt;
cpu_cpsr_t cpsr; /* the int key for this lock */
} kspinlock_t;
#if (RHINO_CONFIG_CPU_NUM > 1)
/* SMP spin lock */
#define krhino_spin_lock(lock) do { \
kspinlock_t *s = (kspinlock_t*)(lock); \
cpu_spin_lock((lock)); \
s->cnt++; \
} while (0) \
#define krhino_spin_unlock(lock) do { \
kspinlock_t *s = (kspinlock_t*)(lock); \
s->cnt--; \
if (s->cnt == 0u) { \
cpu_spin_unlock((lock)); \
} \
} while (0)
#define krhino_spin_lock_irq_save(lock) do { \
kspinlock_t *s = (kspinlock_t*)(lock); \
s->cpsr = cpu_intrpt_save(); \
cpu_spin_lock((lock)); \
s->cnt++; \
} while (0)
#define krhino_spin_unlock_irq_restore(lock) do { \
kspinlock_t *s = (kspinlock_t*)(lock); \
s->cnt--; \
if (s->cnt == 0u) { \
cpu_spin_unlock((lock)); \
cpu_intrpt_restore(s->cpsr); \
} \
} while (0)
#define krhino_spin_init(lock) do{ \
kspinlock_t *s = (kspinlock_t*)(lock); \
s->owner = (uint32_t)-1; \
s->cnt = 0u; \
} while(0)
#else
/* UP spin lock */
#define krhino_spin_lock(lock) krhino_sched_disable();
#define krhino_spin_unlock(lock) krhino_sched_enable();
#define krhino_spin_lock_irq_save(lock) do { \
kspinlock_t *s = (kspinlock_t*)(lock); \
s->cpsr = cpu_intrpt_save(); \
s->cnt++; \
} while (0)
#define krhino_spin_unlock_irq_restore(lock) do { \
kspinlock_t *s = (kspinlock_t*)(lock); \
s->cnt--; \
if (s->cnt == 0u) { \
cpu_intrpt_restore(s->cpsr); \
} \
} while (0)
#define krhino_spin_init(lock)
#endif
#if (RHINO_CONFIG_DISABLE_INTRPT_STATS > 0)
#define RHINO_CRITICAL_ENTER() \
do { \
RHINO_CPU_INTRPT_DISABLE(); \
intrpt_disable_measure_start(); \
} while (0)
#define RHINO_CRITICAL_EXIT() \
do { \
intrpt_disable_measure_stop(); \
RHINO_CPU_INTRPT_ENABLE(); \
} while (0)
#if (RHINO_CONFIG_CPU_NUM > 1)
#define RHINO_CRITICAL_EXIT_SCHED() \
do { \
intrpt_disable_measure_stop(); \
core_sched(); \
RHINO_CPU_INTRPT_ENABLE(); \
} while (0)
#else
#define RHINO_CRITICAL_EXIT_SCHED() \
do { \
intrpt_disable_measure_stop(); \
RHINO_CPU_INTRPT_ENABLE(); \
core_sched(); \
} while (0)
#endif
#else /* RHINO_CONFIG_DISABLE_INTRPT_STATS */
#define RHINO_CRITICAL_ENTER() \
do { \
RHINO_CPU_INTRPT_DISABLE(); \
} while (0)
#define RHINO_CRITICAL_EXIT() \
do { \
RHINO_CPU_INTRPT_ENABLE(); \
} while (0)
#if (RHINO_CONFIG_CPU_NUM > 1)
#define RHINO_CRITICAL_EXIT_SCHED() \
do { \
core_sched(); \
RHINO_CPU_INTRPT_ENABLE(); \
} while (0)
#else
#define RHINO_CRITICAL_EXIT_SCHED() \
do { \
RHINO_CPU_INTRPT_ENABLE(); \
core_sched(); \
} while (0)
#endif
#endif /* RHINO_CONFIG_DISABLE_INTRPT_STATS */
#endif /* K_CRITICAL_H */

View File

@@ -0,0 +1,314 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_DEFAULT_CONFIG_H
#define K_DEFAULT_CONFIG_H
#ifndef RHINO_CONFIG_CPU_PWR_MGMT
#define RHINO_CONFIG_CPU_PWR_MGMT 0
#endif
/* leave this option as default unless your compiler does not support 64 bit data such as uint64_t */
#ifndef RHINO_CONFIG_64_BIT_TYPE
#define RHINO_CONFIG_64_BIT_TYPE 1
#endif
/* chip level conf */
#ifndef RHINO_CONFIG_LITTLE_ENDIAN
#define RHINO_CONFIG_LITTLE_ENDIAN 1
#endif
#ifndef RHINO_CONFIG_CPU_STACK_DOWN
#define RHINO_CONFIG_CPU_STACK_DOWN 1
#endif
#ifndef RHINO_CONFIG_BITMAP_HW
#define RHINO_CONFIG_BITMAP_HW 0
#endif
/* kernel feature conf */
#ifndef RHINO_CONFIG_SEM
#define RHINO_CONFIG_SEM 0
#endif
#ifndef RHINO_CONFIG_QUEUE
#define RHINO_CONFIG_QUEUE 0
#endif
#ifndef RHINO_CONFIG_TASK_SEM
#define RHINO_CONFIG_TASK_SEM 0
#endif
#ifndef RHINO_CONFIG_WORKQUEUE
#define RHINO_CONFIG_WORKQUEUE 0
#endif
#ifndef RHINO_CONFIG_WORKQUEUE_STACK_SIZE
#define RHINO_CONFIG_WORKQUEUE_STACK_SIZE 512
#endif
#ifndef RHINO_CONFIG_WORKQUEUE_TASK_PRIO
#define RHINO_CONFIG_WORKQUEUE_TASK_PRIO 9
#endif
#ifndef RHINO_CONFIG_EVENT_FLAG
#define RHINO_CONFIG_EVENT_FLAG 0
#endif
#ifndef RHINO_CONFIG_TIMER
#define RHINO_CONFIG_TIMER 0
#endif
#ifndef RHINO_CONFIG_BUF_QUEUE
#define RHINO_CONFIG_BUF_QUEUE 0
#endif
#ifndef RHINO_CONFIG_MM_BLK
#define RHINO_CONFIG_MM_BLK 1
#endif
#ifndef RHINO_CONFIG_MM_TLF
#define RHINO_CONFIG_MM_TLF 1
#endif
#ifndef RHINO_CONFIG_MM_MAXMSIZEBIT
#define RHINO_CONFIG_MM_MAXMSIZEBIT 20
#endif
#ifndef RHINO_CONFIG_MM_TLF_BLK_SIZE
#define RHINO_CONFIG_MM_TLF_BLK_SIZE 8192
#endif
#ifndef RHINO_CONFIG_MM_DEBUG
#define RHINO_CONFIG_MM_DEBUG 0
#endif
#ifndef RHINO_CONFIG_GCC_RETADDR
#define RHINO_CONFIG_GCC_RETADDR 0
#endif
#ifndef RHINO_CONFIG_MM_LEAKCHECK
#define RHINO_CONFIG_MM_LEAKCHECK 0
#endif
#ifndef K_MM_STATISTIC
#define K_MM_STATISTIC 0
#endif
#ifndef RHINO_CONFIG_TASK_SEM
#define RHINO_CONFIG_TASK_SEM 0
#endif
/* kernel task conf */
#ifndef RHINO_CONFIG_TASK_PRI_CHG
#define RHINO_CONFIG_TASK_PRI_CHG 1
#endif
#ifndef RHINO_CONFIG_TASK_INFO
#define RHINO_CONFIG_TASK_INFO 0
#endif
#ifndef RHINO_CONFIG_TASK_INFO_NUM
#define RHINO_CONFIG_TASK_INFO_NUM 2
#endif
#ifndef RHINO_CONFIG_TASK_DEL
#define RHINO_CONFIG_TASK_DEL 0
#endif
#ifndef RHINO_CONFIG_TASK_STACK_CUR_CHECK
#define RHINO_CONFIG_TASK_STACK_CUR_CHECK 0
#endif
#ifndef RHINO_CONFIG_TASK_WAIT_ABORT
#define RHINO_CONFIG_TASK_WAIT_ABORT 0
#endif
#ifndef RHINO_CONFIG_SCHED_RR
#define RHINO_CONFIG_SCHED_RR 0
#endif
#ifndef RHINO_CONFIG_TIME_SLICE_DEFAULT
#define RHINO_CONFIG_TIME_SLICE_DEFAULT 50
#endif
#ifndef RHINO_CONFIG_PRI_MAX
#define RHINO_CONFIG_PRI_MAX 62
#endif
#ifndef RHINO_CONFIG_USER_PRI_MAX
#define RHINO_CONFIG_USER_PRI_MAX (RHINO_CONFIG_PRI_MAX - 2)
#endif
#ifndef RHINO_CONFIG_RINGBUF_VENDOR
#define RHINO_CONFIG_RINGBUF_VENDOR 0
#endif
/* kernel mm_region conf */
#ifndef RHINO_CONFIG_MM_REGION_MUTEX
#define RHINO_CONFIG_MM_REGION_MUTEX 1
#endif
/* kernel timer&tick conf */
#ifndef RHINO_CONFIG_HW_COUNT
#define RHINO_CONFIG_HW_COUNT 0
#endif
#ifndef RHINO_CONFIG_TICKS_PER_SECOND
#define RHINO_CONFIG_TICKS_PER_SECOND 100
#endif
#ifndef RHINO_CONFIG_TIMER_TASK_STACK_SIZE
#define RHINO_CONFIG_TIMER_TASK_STACK_SIZE 200
#endif
#ifndef RHINO_CONFIG_TIMER_RATE
#define RHINO_CONFIG_TIMER_RATE 1
#endif
#ifndef RHINO_CONFIG_TIMER_TASK_PRI
#define RHINO_CONFIG_TIMER_TASK_PRI 5
#endif
#ifndef RHINO_CONFIG_TIMER_MSG_NUM
#define RHINO_CONFIG_TIMER_MSG_NUM 20
#endif
/* kernel intrpt conf */
#ifndef RHINO_CONFIG_INTRPT_STACK_REMAIN_GET
#define RHINO_CONFIG_INTRPT_STACK_REMAIN_GET 0
#endif
#ifndef RHINO_CONFIG_INTRPT_MAX_NESTED_LEVEL
#define RHINO_CONFIG_INTRPT_MAX_NESTED_LEVEL 188u
#endif
#ifndef RHINO_CONFIG_INTRPT_GUARD
#define RHINO_CONFIG_INTRPT_GUARD 0
#endif
/* kernel stack ovf check */
#ifndef RHINO_CONFIG_INTRPT_STACK_OVF_CHECK
#define RHINO_CONFIG_INTRPT_STACK_OVF_CHECK 0
#endif
#ifndef RHINO_CONFIG_TASK_STACK_OVF_CHECK
#define RHINO_CONFIG_TASK_STACK_OVF_CHECK 0
#endif
/* kernel dyn alloc conf */
#ifndef RHINO_CONFIG_KOBJ_DYN_ALLOC
#define RHINO_CONFIG_KOBJ_DYN_ALLOC 0
#endif
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
#ifndef RHINO_CONFIG_K_DYN_QUEUE_MSG
#define RHINO_CONFIG_K_DYN_QUEUE_MSG 30
#endif
#ifndef RHINO_CONFIG_K_DYN_TASK_STACK
#define RHINO_CONFIG_K_DYN_TASK_STACK 256
#endif
#ifndef RHINO_CONFIG_K_DYN_MEM_TASK_PRI
#define RHINO_CONFIG_K_DYN_MEM_TASK_PRI RHINO_CONFIG_USER_PRI_MAX
#endif
#endif /* RHINO_CONFIG_KOBJ_DYN_ALLOC */
/* kernel idle conf */
#ifndef RHINO_CONFIG_IDLE_TASK_STACK_SIZE
#define RHINO_CONFIG_IDLE_TASK_STACK_SIZE 100
#endif
/* kernel hook conf */
#ifndef RHINO_CONFIG_USER_HOOK
#define RHINO_CONFIG_USER_HOOK 1
#endif
/* kernel stats conf */
#ifndef RHINO_CONFIG_SYSTEM_STATS
#define RHINO_CONFIG_SYSTEM_STATS 0
#endif
#ifndef RHINO_CONFIG_DISABLE_SCHED_STATS
#define RHINO_CONFIG_DISABLE_SCHED_STATS 0
#endif
#ifndef RHINO_CONFIG_DISABLE_INTRPT_STATS
#define RHINO_CONFIG_DISABLE_INTRPT_STATS 0
#endif
#ifndef RHINO_CONFIG_CPU_USAGE_STATS
#define RHINO_CONFIG_CPU_USAGE_STATS 0
#endif
#ifndef RHINO_CONFIG_CPU_USAGE_TASK_PRI
#define RHINO_CONFIG_CPU_USAGE_TASK_PRI (RHINO_CONFIG_PRI_MAX - 2)
#endif
#ifndef RHINO_CONFIG_TASK_SCHED_STATS
#define RHINO_CONFIG_TASK_SCHED_STATS 0
#endif
#ifndef RHINO_CONFIG_CPU_USAGE_TASK_STACK
#define RHINO_CONFIG_CPU_USAGE_TASK_STACK 256
#endif
/* kernel trace conf */
#ifndef RHINO_CONFIG_TRACE
#define RHINO_CONFIG_TRACE 0
#endif
#ifndef RHINO_CONFIG_CPU_NUM
#define RHINO_CONFIG_CPU_NUM 1
#endif
#ifdef RHINO_CONFIG_ISR_TASK
#ifndef RHINO_CONFIG_ISR_BUFF_SIZE
#define RHINO_CONFIG_ISR_BUFF_SIZE (16)
#endif
#ifndef RHINO_CONFIG_ISR_TASK_PRI
#define RHINO_CONFIG_ISR_TASK_PRI (1)
#endif
#ifndef RHINO_CONFIG_ISR_TASK_STACK_SIZE
#define RHINO_CONFIG_ISR_TASK_STACK_SIZE (1024)
#endif
#endif
#if ((RHINO_CONFIG_TIMER >= 1) && (RHINO_CONFIG_BUF_QUEUE == 0))
#error "RHINO_CONFIG_BUF_QUEUE should be 1 when RHINO_CONFIG_TIMER is enabled."
#endif
#if ((RHINO_CONFIG_MM_TLF >= 1) && (RHINO_CONFIG_MM_BLK == 0))
#error "RHINO_CONFIG_MM_BLK should be 1 when RHINO_CONFIG_MM_TLF is enabled."
#endif
#if ((RHINO_CONFIG_KOBJ_DYN_ALLOC >= 1) && (RHINO_CONFIG_MM_TLF == 0))
#error "RHINO_CONFIG_MM_TLF should be 1 when RHINO_CONFIG_KOBJ_DYN_ALLOC is enabled."
#endif
#if (RHINO_CONFIG_PRI_MAX >= 256)
#error "RHINO_CONFIG_PRI_MAX must be <= 255."
#endif
#if ((RHINO_CONFIG_SEM == 0) && (RHINO_CONFIG_TASK_SEM >= 1))
#error "you need enable RHINO_CONFIG_SEM as well."
#endif
#if ((RHINO_CONFIG_HW_COUNT == 0) && (RHINO_CONFIG_TASK_SCHED_STATS >= 1))
#error "you need enable RHINO_CONFIG_HW_COUNT as well."
#endif
#if ((RHINO_CONFIG_HW_COUNT == 0) && (RHINO_CONFIG_DISABLE_SCHED_STATS >= 1))
#error "you need enable RHINO_CONFIG_HW_COUNT as well."
#endif
#if ((RHINO_CONFIG_HW_COUNT == 0) && (RHINO_CONFIG_DISABLE_INTRPT_STATS >= 1))
#error "you need enable RHINO_CONFIG_HW_COUNT as well."
#endif
#endif /* K_DEFAULT_CONFIG_H */

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_ENDIAN_H
#define K_ENDIAN_H
#if (RHINO_CONFIG_LITTLE_ENDIAN != 1)
#define krhino_htons(x) x
#define krhino_htonl(x) x
#define krhino_ntohl(x) x
#define krhino_ntohs(x) x
#else
#ifndef krhino_htons
#define krhino_htons(x) ((uint16_t)(((x) & 0x00ffU) << 8)| \
(((x) & 0xff00U) >> 8))
#endif
#ifndef krhino_htonl
#define krhino_htonl(x) ((uint32_t)(((x) & 0x000000ffUL) << 24) | \
(((x) & 0x0000ff00UL) << 8) | \
(((x) & 0x00ff0000UL) >> 8) | \
(((x) & 0xff000000UL) >> 24))
#endif
#ifndef krhino_ntohs
#define krhino_ntohs(x) ((uint16_t)((x & 0x00ffU) << 8) | \
((x & 0xff00U) >> 8))
#endif
#ifndef krhino_ntohl
#define krhino_ntohl(x) ((uint32_t)(((x) & 0x000000ffUL) << 24) | \
(((x) & 0x0000ff00UL) << 8) | \
(((x) & 0x00ff0000UL) >> 8) | \
(((x) & 0xff000000UL) >> 24))
#endif
#endif /*RHINO_CONFIG_LITTLE_ENDIAN*/
#endif

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_ERR_H
#define K_ERR_H
typedef enum {
RHINO_SUCCESS = 0u,
RHINO_SYS_FATAL_ERR,
RHINO_SYS_SP_ERR,
RHINO_RUNNING,
RHINO_STOPPED,
RHINO_INV_PARAM,
RHINO_NULL_PTR,
RHINO_INV_ALIGN,
RHINO_KOBJ_TYPE_ERR,
RHINO_KOBJ_DEL_ERR,
RHINO_KOBJ_DOCKER_EXIST,
RHINO_KOBJ_BLK,
RHINO_KOBJ_SET_FULL,
RHINO_NOTIFY_FUNC_EXIST,
RHINO_MM_POOL_SIZE_ERR = 100u,
RHINO_MM_ALLOC_SIZE_ERR,
RHINO_MM_FREE_ADDR_ERR,
RHINO_MM_CORRUPT_ERR,
RHINO_DYN_MEM_PROC_ERR,
RHINO_NO_MEM,
RHINO_RINGBUF_FULL,
RHINO_RINGBUF_EMPTY,
RHINO_SCHED_DISABLE = 200u,
RHINO_SCHED_ALREADY_ENABLED,
RHINO_SCHED_LOCK_COUNT_OVF,
RHINO_INV_SCHED_WAY,
RHINO_TASK_INV_STACK_SIZE = 300u,
RHINO_TASK_NOT_SUSPENDED,
RHINO_TASK_DEL_NOT_ALLOWED,
RHINO_TASK_SUSPEND_NOT_ALLOWED,
RHINO_SUSPENDED_COUNT_OVF,
RHINO_BEYOND_MAX_PRI,
RHINO_PRI_CHG_NOT_ALLOWED,
RHINO_INV_TASK_STATE,
RHINO_IDLE_TASK_EXIST,
RHINO_NO_PEND_WAIT = 400u,
RHINO_BLK_ABORT,
RHINO_BLK_TIMEOUT,
RHINO_BLK_DEL,
RHINO_BLK_INV_STATE,
RHINO_BLK_POOL_SIZE_ERR,
RHINO_TIMER_STATE_INV = 500u,
RHINO_NO_THIS_EVENT_OPT = 600u,
RHINO_BUF_QUEUE_INV_SIZE = 700u,
RHINO_BUF_QUEUE_SIZE_ZERO,
RHINO_BUF_QUEUE_FULL,
RHINO_BUF_QUEUE_MSG_SIZE_OVERFLOW,
RHINO_QUEUE_FULL,
RHINO_QUEUE_NOT_FULL,
RHINO_SEM_OVF = 800u,
RHINO_SEM_TASK_WAITING,
RHINO_MUTEX_NOT_RELEASED_BY_OWNER = 900u,
RHINO_MUTEX_OWNER_NESTED,
RHINO_MUTEX_NESTED_OVF,
RHINO_INTRPT_NESTED_LEVEL_OVERFLOW = 1000u,
RHINO_INV_INTRPT_NESTED_LEVEL,
RHINO_NOT_CALLED_BY_INTRPT,
RHINO_TRY_AGAIN,
RHINO_WORKQUEUE_EXIST = 1100u,
RHINO_WORKQUEUE_NOT_EXIST,
RHINO_WORKQUEUE_WORK_EXIST,
RHINO_WORKQUEUE_BUSY,
RHINO_WORKQUEUE_WORK_RUNNING,
RHINO_TASK_STACK_OVF = 1200u,
RHINO_INTRPT_STACK_OVF,
RHINO_INTRPT_ISR_OVF,
} kstat_t;
typedef void (*krhino_err_proc_t)(kstat_t err);
extern krhino_err_proc_t g_err_proc;
#endif /* K_ERR_H */

View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_EVENT_H
#define K_EVENT_H
typedef struct {
blk_obj_t blk_obj;
uint32_t flags;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_t event_item;
#endif
uint8_t mm_alloc_flag;
} kevent_t;
#define RHINO_FLAGS_AND_MASK 0x2u
#define RHINO_FLAGS_CLEAR_MASK 0x1u
#define RHINO_AND 0x02u
#define RHINO_AND_CLEAR 0x03u
#define RHINO_OR 0x00u
#define RHINO_OR_CLEAR 0x01u
/**
* This function will create a event
* @param[in] event pointer to the event
* @param[in] name name of the event
* @param[in] flags flags to be init
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_event_create(kevent_t *event, const name_t *name, uint32_t flags);
/**
* This function will delete a event
* @param[in] event pointer to a event
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_event_del(kevent_t *event);
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
/**
* This function will create a dyn-event
* @param[out] event pointer to the event
* @param[in] name name of the semaphore
* @param[in] flags flags to be init
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_event_dyn_create(kevent_t **event, const name_t *name,
uint32_t flags);
/**
* This function will delete a dyn created event
* @param[in] event pointer to a event
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_event_dyn_del(kevent_t *event);
#endif
/**
* This function will get event
* @param[in] event pointer to the event
* @param[in] flags which is provided by users
* @param[in] opt could be RHINO_AND, RHINO_AND_CLEAR, RHINO_OR, RHINO_OR_CLEAR
* @param[out] actl_flags the actually flag where flags is satisfied
* @param[in] ticks ticks to wait
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_event_get(kevent_t *event, uint32_t flags, uint8_t opt,
uint32_t *actl_flags, tick_t ticks);
/**
* This function will set a event
* @param[in] event pointer to a event
* @param[in] flags which users want to be set
* @param[in] opt could be RHINO_AND, RHINO_OR
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_event_set(kevent_t *event, uint32_t flags, uint8_t opt);
#endif /* K_EVENT_H */

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef FIFO_H
#define FIFO_H
#ifdef __cplusplus
extern "C" {
#endif
struct k_fifo {
uint32_t in;
uint32_t out;
uint32_t mask;
void *data;
uint32_t free_bytes;
uint32_t size;
};
#define fifo_min(x, y) ((x) > (y)?(y):(x))
#define fifo_max(x, y) ((x) > (y)?(x):(y))
/**
* This function will init the fifo.
* @param[in] fifo pointer to fifo
* @param[in] buffer pointer to fifo buffer
* @param[in] size size of fifo buffer
* @return the operation status, 0 is OK, others is error
*/
int8_t fifo_init(struct k_fifo *fifo, void *buffer, uint32_t size);
/**
* This function will write buf to fifo.
* @param[in] fifo pointer to fifo
* @param[in] buf pointer to buffer write
* @param[in] size size of buffer
* @return the size has been written to the fifo
*/
uint32_t fifo_in(struct k_fifo *fifo, const void *buf, uint32_t len);
/**
* This function will read fifo data to buf
* @param[in] fifo pointer to fifo
* @param[in] buf pointer to buffer read
* @param[in] len len of buffer
* @return the size has read
*/
uint32_t fifo_out(struct k_fifo *fifo, void *buf, uint32_t len);
/**
* This function will read fifo data to bufbut data remain in fifo
* @param[in] fifo pointer to fifo
* @param[in] buf pointer to buffer read
* @param[in] len len of buffer
* @return the size has read
*/
uint32_t fifo_out_peek(struct k_fifo *fifo,
void *buf, uint32_t len);
/**
* This function will read fifo all data
* @param[in] fifo pointer to fifo
* @param[in] buf pointer to buffer read
* @return the size has read
*/
uint32_t fifo_out_all(struct k_fifo *fifo, void *buf);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_HOOK_H
#define K_HOOK_H
#if (RHINO_CONFIG_USER_HOOK > 0)
/**
* This function will provide init hook
*/
void krhino_init_hook(void);
/**
* This function will provide system start hook
*/
void krhino_start_hook(void);
/**
* This function will provide task create hook
* @param[in] task pointer to the task
*/
void krhino_task_create_hook(ktask_t *task);
/**
* This function will provide task delete hook
* @param[in] task pointer to the task
*/
void krhino_task_del_hook(ktask_t *task, res_free_t *arg);
/**
* This function will provide task abort hook
* @param[in] task pointer to the task
*/
void krhino_task_abort_hook(ktask_t *task);
/**
* This function will provide task switch hook
*/
void krhino_task_switch_hook(ktask_t *orgin, ktask_t *dest);
/**
* This function will provide system tick hook
*/
void krhino_tick_hook(void);
/**
* This function will provide idle hook
*/
void krhino_idle_hook(void);
/**
* This function will provide idle pre hook
*/
void krhino_idle_pre_hook(void);
/**
* This function will provide krhino_mm_alloc hook
*/
void krhino_mm_alloc_hook(void *mem, size_t size);
#endif
#endif /* K_HOOK_H */

View File

@@ -0,0 +1,193 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_INTERNAL_H
#define K_INTERNAL_H
extern kstat_t g_sys_stat;
extern uint8_t g_idle_task_spawned[RHINO_CONFIG_CPU_NUM];
extern runqueue_t g_ready_queue;
/* System lock */
extern uint8_t g_sched_lock[RHINO_CONFIG_CPU_NUM];
extern uint8_t g_intrpt_nested_level[RHINO_CONFIG_CPU_NUM];
/* highest pri ready task object */
extern ktask_t *g_preferred_ready_task[RHINO_CONFIG_CPU_NUM];
/* current active task */
extern ktask_t *g_active_task[RHINO_CONFIG_CPU_NUM];
/* idle attribute */
extern ktask_t g_idle_task[RHINO_CONFIG_CPU_NUM];
extern idle_count_t g_idle_count[RHINO_CONFIG_CPU_NUM];
extern cpu_stack_t g_idle_task_stack[RHINO_CONFIG_CPU_NUM][RHINO_CONFIG_IDLE_TASK_STACK_SIZE];
/* tick attribute */
extern tick_t g_tick_count;
extern klist_t g_tick_head;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
extern kobj_list_t g_kobj_list;
#endif
#if (RHINO_CONFIG_TIMER > 0)
extern klist_t g_timer_head;
extern sys_time_t g_timer_count;
extern ktask_t g_timer_task;
extern cpu_stack_t g_timer_task_stack[RHINO_CONFIG_TIMER_TASK_STACK_SIZE];
extern kbuf_queue_t g_timer_queue;
extern k_timer_queue_cb timer_queue_cb[RHINO_CONFIG_TIMER_MSG_NUM];
#endif
#if (RHINO_CONFIG_DISABLE_SCHED_STATS > 0)
extern hr_timer_t g_sched_disable_time_start;
extern hr_timer_t g_sched_disable_max_time;
extern hr_timer_t g_cur_sched_disable_max_time;
#endif
#if (RHINO_CONFIG_DISABLE_INTRPT_STATS > 0)
extern uint16_t g_intrpt_disable_times;
extern hr_timer_t g_intrpt_disable_time_start;
extern hr_timer_t g_intrpt_disable_max_time;
extern hr_timer_t g_cur_intrpt_disable_max_time;
#endif
#if (RHINO_CONFIG_HW_COUNT > 0)
extern hr_timer_t g_sys_measure_waste;
#endif
#if (RHINO_CONFIG_CPU_USAGE_STATS > 0)
extern ktask_t g_cpu_usage_task;
extern cpu_stack_t g_cpu_task_stack[RHINO_CONFIG_CPU_USAGE_TASK_STACK];
extern idle_count_t g_idle_count_max;
extern uint32_t g_cpu_usage;
#endif
#if (RHINO_CONFIG_TASK_SCHED_STATS > 0)
extern ctx_switch_t g_sys_ctx_switch_times;
#endif
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
extern ksem_t g_res_sem;
extern klist_t g_res_list;
extern ktask_t g_dyn_task;
extern cpu_stack_t g_dyn_task_stack[RHINO_CONFIG_K_DYN_TASK_STACK];
#endif
#if (RHINO_CONFIG_WORKQUEUE > 0)
extern klist_t g_workqueue_list_head;
extern kmutex_t g_workqueue_mutex;
extern kworkqueue_t g_workqueue_default;
extern cpu_stack_t g_workqueue_stack[RHINO_CONFIG_WORKQUEUE_STACK_SIZE];
#endif
#if (RHINO_CONFIG_MM_TLF > 0)
extern k_mm_head *g_kmm_head;
#endif
#ifdef RHINO_CONFIG_ISR_TASK
extern ktask_t g_isr_task;
extern ksem_t g_isr_sem;
extern uint32_t g_isr_buff[4+2*RHINO_CONFIG_ISR_BUFF_SIZE];
extern cpu_stack_t g_isr_task_stack[RHINO_CONFIG_ISR_TASK_STACK_SIZE];
#endif
extern kspinlock_t g_sys_lock;
extern uint8_t g_in_interrupt;
#define K_OBJ_STATIC_ALLOC 1u
#define K_OBJ_DYN_ALLOC 2u
#define NULL_PARA_CHK(para) \
do { \
if (para == NULL) { \
return RHINO_NULL_PTR; \
} \
} while (0)
#define INTRPT_NESTED_LEVEL_CHK()\
do { \
if (g_intrpt_nested_level[cpu_cur_get()] > 0u) { \
RHINO_CRITICAL_EXIT(); \
return RHINO_NOT_CALLED_BY_INTRPT; \
} \
} while (0)
#define RES_FREE_NUM 4
typedef struct {
uint8_t cnt;
void *res[RES_FREE_NUM];
klist_t res_list;
} res_free_t;
void preferred_cpu_ready_task_get(runqueue_t *rq, uint8_t cpu_num);
void core_sched(void);
void runqueue_init(runqueue_t *rq);
void ready_list_add(runqueue_t *rq, ktask_t *task);
void ready_list_add_head(runqueue_t *rq, ktask_t *task);
void ready_list_add_tail(runqueue_t *rq, ktask_t *task);
void ready_list_rm(runqueue_t *rq, ktask_t *task);
void ready_list_head_to_tail(runqueue_t *rq, ktask_t *task);
void time_slice_update(void);
void timer_task_sched(void);
void pend_list_reorder(ktask_t *task);
void pend_task_wakeup(ktask_t *task);
void pend_to_blk_obj(blk_obj_t *blk_obj, ktask_t *task, tick_t timeout, uint32_t psr);
void pend_task_rm(ktask_t *task);
kstat_t pend_state_end_proc(ktask_t *task);
void idle_task(void *p_arg);
void idle_count_set(idle_count_t value);
idle_count_t idle_count_get(void);
void tick_list_init(void);
void tick_task_start(void);
void tick_list_rm(ktask_t *task);
void tick_list_insert(ktask_t *task, tick_t time);
void tick_list_update(tick_i_t ticks);
uint8_t mutex_pri_limit(ktask_t *tcb, uint8_t pri);
void mutex_task_pri_reset(ktask_t *tcb);
uint8_t mutex_pri_look(ktask_t *tcb, kmutex_t *mutex_rel);
kstat_t task_pri_change(ktask_t *task, uint8_t new_pri);
void k_err_proc(kstat_t err);
void ktimer_init(void);
void kisr_init(void);
void intrpt_disable_measure_start(void);
void intrpt_disable_measure_stop(void);
void dyn_mem_proc_task_start(void);
void cpu_usage_stats_start(void);
void dym_mem_proc_hdl(void);
kstat_t ringbuf_init(k_ringbuf_t *p_ringbuf, void *buf, size_t len, size_t type,
size_t block_size);
kstat_t ringbuf_reset(k_ringbuf_t *p_ringbuf);
kstat_t ringbuf_push(k_ringbuf_t *p_ringbuf, void *data, size_t len);
kstat_t ringbuf_head_push(k_ringbuf_t *p_ringbuf, void *data, size_t len);
kstat_t ringbuf_pop(k_ringbuf_t *p_ringbuf, void *pdata, size_t *plen);
uint8_t ringbuf_is_full(k_ringbuf_t *p_ringbuf);
uint8_t ringbuf_is_empty(k_ringbuf_t *p_ringbuf);
void workqueue_init(void);
//void k_mm_init(void);
#if (RHINO_CONFIG_CPU_PWR_MGMT > 0)
void cpu_pwr_down(void);
void cpu_pwr_up(void);
#endif
#endif /* K_INTERNAL_H */

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_LIST_H
#define K_LIST_H
typedef struct klist_s {
struct klist_s *next;
struct klist_s *prev;
} klist_t;
#define krhino_list_entry(node, type, member) ((type *)((uint8_t *)(node) - (size_t)(&((type *)0)->member)))
RHINO_INLINE void klist_init(klist_t *list_head)
{
list_head->next = list_head;
list_head->prev = list_head;
}
RHINO_INLINE uint8_t is_klist_empty(klist_t *list)
{
return (list->next == list);
}
RHINO_INLINE void klist_insert(klist_t *head, klist_t *element)
{
element->prev = head->prev;
element->next = head;
head->prev->next = element;
head->prev = element;
}
RHINO_INLINE void klist_add(klist_t *head, klist_t *element)
{
element->prev = head;
element->next = head->next;
head->next->prev = element;
head->next = element;
}
RHINO_INLINE void klist_rm(klist_t *element)
{
element->prev->next = element->next;
element->next->prev = element->prev;
}
RHINO_INLINE void klist_rm_init(klist_t *element)
{
element->prev->next = element->next;
element->next->prev = element->prev;
element->next = element->prev = element;
}
#endif /* K_LIST_H */

View File

@@ -0,0 +1,153 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_MM_H
#define K_MM_H
#ifdef HAVE_VALGRIND_H
#include <valgrind.h>
#include <memcheck.h>
#define VGF(X) X
#elif defined(HAVE_VALGRIND_VALGRIND_H)
#include <valgrind/valgrind.h>
#include <valgrind/memcheck.h>
#define VGF(X) X
#else
#define VGF(X)
#endif
/*use two level bit map to find free memory block*/
#if (RHINO_CONFIG_MM_TLF > 0)
#define MAX_MM_BIT RHINO_CONFIG_MM_MAXMSIZEBIT
#define MAX_MM_SIZE (1<<MAX_MM_BIT)
#define FIX_BLK_BIT 5 /*32 bytes*/
#define DEF_FIX_BLK_SIZE (1<<FIX_BLK_BIT) /*32 bytes*/
#define MIN_FLT_BIT 7 /*<2^7 only need one level mapping */
#define MIN_FLT_SIZE (1<<MIN_FLT_BIT)
#define MAX_LOG2_SLT 5
#define SLT_SIZE (1<<MAX_LOG2_SLT)
#define FLT_SIZE (MAX_MM_BIT - MIN_FLT_BIT + 1)
#define MM_ALIGIN_SIZE (1<<(MIN_FLT_BIT - MAX_LOG2_SLT))
#define MM_ALIGN_MASK (sizeof(void*)-1)
#define MM_ALIGN_UP(a) (((a) + MM_ALIGN_MASK) & ~MM_ALIGN_MASK)
#define MM_ALIGN_DOWN(a) ((a) & ~MM_ALIGN_MASK)
#define RHINO_MM_BLKSIZE_MASK (0xFFFFFFFF - MM_ALIGN_MASK)
#define DEF_TOTAL_FIXEDBLK_SIZE 8192 /*by default, total 2k momory fo fix size block */
#define MIN_FREE_MEMORY_SIZE 1024 /*at least need 1k for user alloced*/
/*bit 0 and bit 1 mask*/
#define RHINO_MM_CURSTAT_MASK 0x1
#define RHINO_MM_PRESTAT_MASK 0x2
/*bit 0*/
#define RHINO_MM_FREE 1
#define RHINO_MM_ALLOCED 0
/*bit 1*/
#define RHINO_MM_PREVFREE 2
#define RHINO_MM_PREVALLOCED 0
#define NEXT_MM_BLK(_addr, _r) ((k_mm_list_t *) ((uint8_t *) (_addr) + (_r)))
#define MMLIST_HEAD_SIZE (sizeof(k_mm_list_t) - sizeof(free_ptr_t))
/*
-------------------------------------------------------------------
| k_mm_list_t |k_mm_region_info_t|k_mm_list_t|free space |k_mm_list_t|
-------------------------------------------------------------------
*/
#define MMREGION_USED_SIZE (MM_ALIGN_UP(sizeof(k_mm_region_info_t)) + 3 * MMLIST_HEAD_SIZE )
/*struct of memory list ,every memory block include this information*/
typedef struct free_ptr_struct {
struct k_mm_list_struct *prev;
struct k_mm_list_struct *next;
} free_ptr_t;
typedef struct k_mm_list_struct {
#if (RHINO_CONFIG_MM_DEBUG > 0)
size_t dye;
size_t owner;
#endif
struct k_mm_list_struct *prev;
size_t size;
/* bit 0 indicates whether the block is used and */
/* bit 1 allows to know whether the previous block is free */
union {
struct free_ptr_struct free_ptr;
uint8_t buffer[1];
} mbinfo;
} k_mm_list_t;
typedef struct k_mm_region_info_struct {
k_mm_list_t *end;
struct k_mm_region_info_struct *next;
} k_mm_region_info_t;
typedef struct {
#if (RHINO_CONFIG_MM_REGION_MUTEX == 1)
kmutex_t mm_mutex;
#endif
k_mm_region_info_t *regioninfo;
k_mm_list_t *fixedmblk;
#if (K_MM_STATISTIC > 0)
size_t used_size;
size_t maxused_size;
size_t free_size;
size_t mm_size_stats[MAX_MM_BIT];
#endif
uint32_t fl_bitmap;
uint32_t sl_bitmap[FLT_SIZE]; /* the second-level bitmap */
k_mm_list_t *mm_tbl[FLT_SIZE][SLT_SIZE];
} k_mm_head;
kstat_t krhino_init_mm_head(k_mm_head **ppmmhead, void *addr, size_t len );
kstat_t krhino_deinit_mm_head(k_mm_head *mmhead);
kstat_t krhino_add_mm_region(k_mm_head *mmhead, void *addr, size_t len);
void *k_mm_alloc(k_mm_head *mmhead, size_t size);
void k_mm_free(k_mm_head *mmhead, void *ptr);
void *k_mm_realloc(k_mm_head *mmhead, void *oldmem, size_t new_size);
#endif
/**
* This function is wrapper of mm allocation
* @param[in] size size of the mem to malloc
* @return the operation status, NULL is error, others is memory address
*/
void *krhino_mm_alloc(size_t size, void *caller);
/**
* This function is wrapper of mm free
* @param[in] ptr address point of the mem
*/
void krhino_mm_free(void *ptr);
/**
* This function is wrapper of mm rallocation
* @param[in] oldmem oldmem address
* @param[in] size size of the mem to malloc
* @return the operation status, NULL is error, others is realloced memory address
*/
void *krhino_mm_realloc(void *oldmem, size_t newsize, void *caller);
#endif /* K_MM_BESTFIT_H */

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_MM_BLK_H
#define K_MM_BLK_H
typedef struct {
kobj_type_t obj_type;
const name_t *pool_name;
size_t blk_size;
size_t blk_avail;
size_t blk_whole;
uint8_t *avail_list;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_t mblkpool_stats_item;
#endif
} mblk_pool_t;
/**
* This function will init a blk-pool
* @param[in] pool pointer to the pool
* @param[in] name name of the pool
* @param[in] pool_start start addr of the pool
* @param[in] blk_size size of the blk
* @param[in] pool_size size of the pool
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_mblk_pool_init(mblk_pool_t *pool, const name_t *name,
void *pool_start,
size_t blk_size, size_t pool_size);
/**
* This function will alloc a blk-pool
* @param[in] pool pointer to a pool
* @param[in] blk pointer to a blk
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_mblk_alloc(mblk_pool_t *pool, void **blk);
/**
* This function will free a blk-pool
* @param[in] pool pointer to the pool
* @param[in] blk pointer to the blk
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_mblk_free(mblk_pool_t *pool, void *blk);
#endif /* K_MM_BLK_H */

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef RHINO_MM_DEBUG_H
#define RHINO_MM_DEBUG_H
#if (RHINO_CONFIG_MM_DEBUG > 0)
#ifdef __cplusplus
extern "C" {
#endif
#define AOS_MM_SCAN_REGION_MAX 10
typedef struct {
void *start;
void *end;
} mm_scan_region_t;
#if (RHINO_CONFIG_GCC_RETADDR > 0u)
#include <k_mm.h>
#define AOS_UNSIGNED_INT_MSB (1u << (sizeof(unsigned int) * 8 - 1))
void krhino_owner_attach(k_mm_head *mmhead, void *addr, size_t allocator);
#endif
uint32_t krhino_mm_leak_region_init(void *start, void *end);
uint32_t dumpsys_mm_info_func(char *buf, uint32_t len);
uint32_t dump_mmleak(void);
#ifdef __cplusplus
}
#endif
#endif /* RHINO_CONFIG_MM_DEBUG */
#endif /* YSH_H */

View File

@@ -0,0 +1,14 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_MM_REGION_H
#define K_MM_REGION_H
typedef struct {
uint8_t *start;
size_t len;
} k_mm_region_t;
#endif /* K_MM_REGION_H */

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_MUTEX_H
#define K_MUTEX_H
typedef struct mutex_s {
blk_obj_t blk_obj;
ktask_t *mutex_task; /* mutex owner task */
struct mutex_s *mutex_list; /* task mutex list */
mutex_nested_t owner_nested;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_t mutex_item;
#endif
uint8_t mm_alloc_flag;
} kmutex_t;
/**
* This function will create a mutex
* @param[in] mutex pointer to the mutex(the space is provided by user)
* @param[in] name name of the mutex
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_mutex_create(kmutex_t *mutex, const name_t *name);
/**
* This function will delete a mutex
* @param[in] mutex pointer to the mutex
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_mutex_del(kmutex_t *mutex);
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
/**
* This function will create a dyn mutex
* @param[in] mutex pointer to the mutex(the space is provided by user)
* @param[in] name name of the mutex
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_mutex_dyn_create(kmutex_t **mutex, const name_t *name);
/**
* This function will delete a dyn mutex
* @param[in] mutex pointer to the mutex
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_mutex_dyn_del(kmutex_t *mutex);
#endif
/**
* This function will lock mutex
* @param[in] mutex pointer to the mutex
* @param[in] ticks ticks to be wait for before lock
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_mutex_lock(kmutex_t *mutex, tick_t ticks, uint32_t lr);
/**
* This function will unlock a mutex
* @param[in] mutex pointer to the mutex
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_mutex_unlock(kmutex_t *mutex);
#endif /* K_MUTEX_H */

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_OBJ_H
#define K_OBJ_H
typedef enum {
BLK_POLICY_PRI = 0u,
BLK_POLICY_FIFO
} blk_policy_t;
typedef enum {
BLK_FINISH = 0,
BLK_ABORT,
BLK_TIMEOUT,
BLK_DEL,
BLK_INVALID
} blk_state_t;
typedef enum {
RHINO_OBJ_TYPE_NONE = 0,
RHINO_SEM_OBJ_TYPE,
RHINO_MUTEX_OBJ_TYPE,
RHINO_QUEUE_OBJ_TYPE,
RHINO_BUF_QUEUE_OBJ_TYPE,
RHINO_TIMER_OBJ_TYPE,
RHINO_EVENT_OBJ_TYPE,
RHINO_MM_BLK_OBJ_TYPE,
RHINO_MM_OBJ_TYPE,
RHINO_BLKLIST_OBJ_TYPE,
} kobj_type_t;
typedef struct blk_obj {
klist_t blk_list;
const name_t *name;
uint8_t blk_policy; // blk_policy_t
uint8_t obj_type; // blk_state_t
} blk_obj_t;
typedef struct {
klist_t task_head;
klist_t mutex_head;
#if (RHINO_CONFIG_MM_BLK > 0)
klist_t mblkpool_head;
#endif
#if (RHINO_CONFIG_SEM > 0)
klist_t sem_head;
#endif
#if (RHINO_CONFIG_QUEUE > 0)
klist_t queue_head;
#endif
#if (RHINO_CONFIG_EVENT_FLAG > 0)
klist_t event_head;
#endif
#if (RHINO_CONFIG_BUF_QUEUE > 0)
klist_t buf_queue_head;
#endif
} kobj_list_t;
#endif /* K_OBJ_H */

View File

@@ -0,0 +1,118 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_QUEUE_H
#define K_QUEUE_H
#define WAKE_ONE_TASK 0u
#define WAKE_ALL_TASK 1u
typedef struct {
void **queue_start;
size_t size;
size_t cur_num;
size_t peak_num;
} msg_q_t;
typedef struct {
msg_q_t msg_q;
klist_t *pend_entry;
} msg_info_t;
typedef struct queue_s {
blk_obj_t blk_obj;
k_ringbuf_t ringbuf;
msg_q_t msg_q;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_t queue_item;
#endif
uint8_t mm_alloc_flag;
} kqueue_t;
/**
* This function will create a queue
* @param[in] queue pointer to the queue(the space is provided by user)
* @param[in] name name of the queue
* @param[in] start start address of the queue internal space
* @param[in] msg_num num of the msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_queue_create(kqueue_t *queue, const name_t *name, void **start,
size_t msg_num);
/**
* This function will delete a queue
* @param[in] queue pointer to the queue
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_queue_del(kqueue_t *queue);
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
/**
* This function will create a dyn queue
* @param[in] queue pointer to the queue
* @param[in] name name of the queue
* @param[in] msg_num num of the msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_queue_dyn_create(kqueue_t **queue, const name_t *name,
size_t msg_num);
/**
* This function will delete a dyn created queue
* @param[in] queue pointer to the queue
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_queue_dyn_del(kqueue_t *queue);
#endif
/**
* This function will send a msg to the back of a queue
* @param[in] queue pointer to the queue
* @param[in] msg msg to send
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_queue_back_send(kqueue_t *queue, void *msg);
/**
* This function will send a msg to a queue and wake all tasks
* @param[in] queue pointer to the queue
* @param[in] msg msg to send
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_queue_all_send(kqueue_t *queue, void *msg);
/**
* This function will receive msg from a queue
* @param[in] queue pointer to the queue
* @param[in] ticks ticks to wait before receive
* @param[out] msg buf to save msg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_queue_recv(kqueue_t *queue, tick_t ticks, void **msg);
/**
* This function will detect a queue full or not
* @param[in] queue pointer to the queue
* @return the operation status, RHINO_QUEUE_FULL/RHINO_QUEUE_NOT_FULL
*/
kstat_t krhino_queue_is_full(kqueue_t *queue);
/**
* This function will reset a queue
* @param[in] queue pointer to the queue
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_queue_flush(kqueue_t *queue);
/**
* This function will get information of a queue
* @param[in] queue pointer to the queue
* @param[out] info buf to save msg-info
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_queue_info_get(kqueue_t *queue, msg_info_t *info);
#endif /* K_QUEUE_H */

View File

@@ -0,0 +1,101 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_MM_RINGBUF_H
#define K_MM_RINGBUF_H
#define RINGBUF_TYPE_FIX 0
#define RINGBUF_TYPE_DYN 1
#define RINGBUF_LEN_MAX_SIZE 3
#define RINGBUF_LEN_MASK_ONEBIT 0x80 //1000 0000
#define RINGBUF_LEN_MASK_TWOBIT 0xC0 //1100 0000
#define RINGBUF_LEN_MASK_CLEAN_TWOBIT 0x3f //0011 1111
#define RINGBUF_LEN_VLE_2BYTES 0x80 //1000 0000
#define RINGBUF_LEN_VLE_3BYTES 0xC0 //1100 0000
#define RINGBUF_LEN_1BYTE_MAXVALUE 0x7f //0111 1111; 127
#define RINGBUF_LEN_2BYTES_MAXVALUE 0x3fff // 16383
#define RINGBUF_LEN_3BYTES_MAXVALUE 0x3fffff //4194303
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
typedef struct {
uint8_t *buf;
uint8_t *end;
uint8_t *head;
uint8_t *tail;
size_t freesize;
size_t type;
size_t blk_size;
} k_ringbuf_t;
#define COMPRESS_LEN(x) ((x) <= RINGBUF_LEN_1BYTE_MAXVALUE ? 1: (x) <= RINGBUF_LEN_2BYTES_MAXVALUE ? 2: \
(x) <= RINGBUF_LEN_3BYTES_MAXVALUE ? 3 : RHINO_INV_PARAM)
#if (RHINO_CONFIG_RINGBUF_VENDOR > 0)
/**
* This function will init the mm ring buffer.
* @param[in] p_ringbuf pointer to ring buffer
* @param[in] buf pointer to memory buffer
* @param[in] len length of memory buffer
* @param[in] type type of ring buffer, fix length or dynamic length
* @param[in] block_size block size of fix length ringbuf, if dynamic ringbuffer, ignore this parameter
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_ringbuf_init (k_ringbuf_t *p_ringbuf, void *buf, size_t len,
size_t type, size_t block_size);
/**
* This function will clean all data in mm ring buffer.
* @param[in] p_ringbuf pointer to ring buffer
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_ringbuf_reset(k_ringbuf_t *p_ringbuf);
/**
* This function will push the data to ring buffer end.
* @param[in] p_ringbuf pointer to ring buffer
* @param[in] data pointer to data
* @param[in] len length of data
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_ringbuf_push(k_ringbuf_t *p_ringbuf, void *data, size_t len);
/**
* This function will pop the data from ring buffer head.
* @param[in] p_ringbuf pointer to ring buffer
* @param[out] pdata pointer to data
* @param[out] plen length of data
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_ringbuf_pop(k_ringbuf_t *p_ringbuf, void *pdata, size_t *plen);
/**
* This function will check if the ring buffer is full.
* @param[in] p_ringbuf pointer to ring buffer
* @return the ringbuf status, true is full. else is not.
*/
uint8_t krhino_ringbuf_is_full(k_ringbuf_t *p_ringbuf);
/**
* This function will check if the ring buffer is empty.
* @param[in] p_ringbuf pointer to ring buffer
* @return the ringbuf status, true is empty. else is not.
*/
uint8_t krhino_ringbuf_is_empty(k_ringbuf_t *p_ringbuf);
#endif
#endif

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_SCHED_H
#define K_SCHED_H
#define KSCHED_FIFO 0u
#define KSCHED_RR 1u
#define SCHED_MAX_LOCK_COUNT 200u
#define NUM_WORDS ((RHINO_CONFIG_PRI_MAX + 31) / 32)
typedef struct {
klist_t *cur_list_item[RHINO_CONFIG_PRI_MAX];
uint32_t task_bit_map[NUM_WORDS];
uint8_t highest_pri;
} runqueue_t;
/**
* This function will disable schedule
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sched_disable(void);
/**
* This function will enable schedule
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sched_enable(void);
#endif /* K_SCHED_H */

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_SEM_H
#define K_SEM_H
#define WAKE_ONE_SEM 0u
#define WAKE_ALL_SEM 1u
typedef struct sem_s {
blk_obj_t blk_obj;
sem_count_t count;
sem_count_t peak_count;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_t sem_item;
#endif
uint8_t mm_alloc_flag;
} ksem_t;
/**
* This function will create a semaphore
* @param[in] sem pointer to the semaphore(the space is provided by user)
* @param[in] name name of the semaphore
* @param[in] count the init count of the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sem_create(ksem_t *sem, const name_t *name, sem_count_t count);
/**
* This function will delete a semaphore
* @param[in] sem pointer to the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sem_del(ksem_t *sem);
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
/**
* This function will create a dyn-semaphore
* @param[out] sem pointer to the semaphore(the space is provided by kernel)
* @param[in] name name of the semaphore
* @param[in] count the init count of the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sem_dyn_create(ksem_t **sem, const name_t *name,
sem_count_t count);
/**
* This function will delete a dyn-semaphore
* @param[in] sem pointer to the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sem_dyn_del(ksem_t *sem);
#endif
/**
* This function will give a semaphore
* @param[in] sem pointer to the semphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sem_give(ksem_t *sem);
/**
* This function will give a semaphore and wakeup all thee waiting task
* @param[in] sem pointer to the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sem_give_all(ksem_t *sem);
/**
* This function will take a semaphore
* @param[in] sem pointer to the semaphore
* @param[in] ticks ticks to wait before take
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sem_take(ksem_t *sem, tick_t ticks);
/**
* This function will set the count of a semaphore
* @param[in] sem pointer to the semaphore
* @param[in] sem_count count of the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sem_count_set(ksem_t *sem, sem_count_t count);
/**
* This function will get count of a semaphore
* @param[in] sem pointer to the semaphore
* @param[out] count count of the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sem_count_get(ksem_t *sem, sem_count_t *count);
#endif /* K_SEM_H */

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_SOC_H
#define K_SOC_H
#if (RHINO_CONFIG_HW_COUNT > 0)
void soc_hw_timer_init(void);
hr_timer_t soc_hr_hw_cnt_get(void);
lr_timer_t soc_lr_hw_cnt_get(void);
#define HR_COUNT_GET() soc_hr_hw_cnt_get()
#else /* RHINO_CONFIG_HW_COUNT */
#define HR_COUNT_GET() 0u
#endif /* RHINO_CONFIG_HW_COUNT */
#if (RHINO_CONFIG_TASK_SCHED_STATS > 0)
#define LR_COUNT_GET() soc_lr_hw_cnt_get()
#else /* RHINO_CONFIG_TASK_SCHED_STATS */
#define LR_COUNT_GET() 0u
#endif /* RHINO_CONFIG_TASK_SCHED_STATS */
#if (RHINO_CONFIG_INTRPT_GUARD > 0)
void soc_intrpt_guard(void);
#endif
#if (RHINO_CONFIG_INTRPT_STACK_REMAIN_GET > 0)
size_t soc_intrpt_stack_remain_get(void);
#endif
#if (RHINO_CONFIG_INTRPT_STACK_OVF_CHECK > 0)
void soc_intrpt_stack_ovf_check(void);
#endif
void soc_err_proc(kstat_t err);
size_t soc_get_cur_sp(void);
#endif /* K_SOC_H */

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_STATS_H
#define K_STATS_H
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
void kobj_list_init(void);
#endif
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
/**
* This function will check task stack overflow
*/
void krhino_stack_ovf_check(void);
#endif
#if (RHINO_CONFIG_TASK_SCHED_STATS > 0)
/**
* This function will reset task schedule stats
*/
void krhino_task_sched_stats_reset(void);
/**
* This function will get task statistic data
*/
void krhino_task_sched_stats_get(void);
#endif
#if (RHINO_CONFIG_HW_COUNT > 0)
void krhino_overhead_measure(void);
#endif
#if (RHINO_CONFIG_CPU_USAGE_STATS > 0)
uint32_t krhino_get_cpu_usage(void);
#endif
#endif /* K_STATS_H */

View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_SYS_H
#define K_SYS_H
#define RHINO_VERSION 10000
#define RHINO_IDLE_PRI (RHINO_CONFIG_PRI_MAX - 1)
#define RHINO_FALSE 0u
#define RHINO_TRUE 1u
#define RHINO_NO_WAIT 0u
#define MAX_TIMER_TICKS ((tick_t)-1 >> 1)
#if (RHINO_CONFIG_64_BIT_TYPE > 0)
#define RHINO_WAIT_FOREVER ((uint64_t)-1)
typedef uint64_t sys_time_t;
typedef int64_t sys_time_i_t;
typedef uint64_t idle_count_t;
typedef uint64_t tick_t;
typedef int64_t tick_i_t;
#else
#define RHINO_WAIT_FOREVER ((uint32_t)-1)
typedef uint32_t sys_time_t;
typedef int32_t sys_time_i_t;
typedef uint32_t idle_count_t;
typedef uint32_t tick_t;
typedef int32_t tick_i_t;
#endif
#if (RHINO_CONFIG_INTRPT_STACK_OVF_CHECK > 0)
#if (RHINO_CONFIG_CPU_STACK_DOWN > 0)
extern cpu_stack_t *g_intrpt_stack_bottom;
#else
extern cpu_stack_t *g_intrpt_stack_top;
#endif
#endif /* RHINO_CONFIG_INTRPT_STACK_OVF_CHECK */
/**
* This function will init AliOS
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_init(void);
/**
* This function will start AliOS
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_start(void);
/**
* This function will enter interrupt
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_intrpt_enter(void);
/**
* This function will exit interrupt
*/
void krhino_intrpt_exit(void);
/**
* This function will check intrpt-stack overflow
*/
void krhino_intrpt_stack_ovf_check(void);
/**
* This function will get the whole ram space used by kernel
* @return the whole ram space used by kernel
*/
size_t krhino_global_space_get(void);
/**
* This function will get kernel version
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
uint32_t krhino_version_get(void);
void krhino_check_fatal_call(const char *func);
#endif /* K_SYS_H */

View File

@@ -0,0 +1,312 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_TASK_H
#define K_TASK_H
typedef enum {
K_SEED,
K_RDY,
K_PEND,
K_SUSPENDED,
K_PEND_SUSPENDED,
K_SLEEP,
K_SLEEP_SUSPENDED,
K_DELETED,
} task_stat_t;
typedef struct {
void *task_stack;
#if (RHINO_CONFIG_TASK_INFO > 0)
/* for user data extension do not move the position! */
void *user_info[RHINO_CONFIG_TASK_INFO_NUM];
#endif
cpu_stack_t *task_stack_base;
uint32_t stack_size;
klist_t task_list;
#if (RHINO_CONFIG_TASK_SUSPEND > 0)
suspend_nested_t suspend_count;
#endif
struct mutex_s *mutex_list;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_t task_stats_item;
#endif
klist_t tick_list;
tick_t tick_match;
tick_t tick_remain;
klist_t *tick_head;
void *msg;
#if (RHINO_CONFIG_BUF_QUEUE > 0)
size_t bq_msg_size;
#endif
const name_t *task_name;
task_stat_t task_state;
blk_state_t blk_state;
/* Task block on mutex, queue, semphore, event */
blk_obj_t *blk_obj;
#if (RHINO_CONFIG_TASK_SEM > 0)
struct sem_s *task_sem_obj;
#endif
#if (RHINO_CONFIG_TASK_SCHED_STATS > 0)
size_t task_free_stack_size;
ctx_switch_t task_ctx_switch_times;
sys_time_t task_time_total_run;
sys_time_t task_time_total_run_prev;
lr_timer_t task_exec_time;
lr_timer_t task_time_start;
#endif
#if (RHINO_CONFIG_DISABLE_INTRPT_STATS > 0)
hr_timer_t task_intrpt_disable_time_max;
#endif
#if (RHINO_CONFIG_DISABLE_SCHED_STATS > 0)
hr_timer_t task_sched_disable_time_max;
#endif
#if (RHINO_CONFIG_SCHED_RR > 0)
/* for task time slice*/
uint32_t time_slice;
uint32_t time_total;
#endif
#if (RHINO_CONFIG_EVENT_FLAG > 0)
uint32_t pend_flags;
void *pend_info;
uint8_t pend_option;
#endif
#if (RHINO_CONFIG_SCHED_RR > 0)
uint8_t sched_policy;
#endif
uint8_t cpu_num;
#if (RHINO_CONFIG_CPU_NUM > 1)
uint8_t cpu_binded;
uint8_t cur_exc;
#endif
/* current prio */
uint8_t prio;
/* base prio */
uint8_t b_prio;
uint8_t mm_alloc_flag:2, lprun:1, rev: 5;
void *arg;
uint32_t runtime;
int32_t task_errno;
} ktask_t;
typedef void (*task_entry_t)(void *arg);
/**
* This function will initialize a task
* @param[in] task the task to be created
* @param[in] name the name of task, which shall be unique
* @param[in] arg the parameter of task enter function
* @param[in] pri the prio of task
* @param[in] ticks the time slice if there are same prio task
* @param[in] stack_buf the start address of task stack
* @param[in] stack the size of thread stack
* @param[in] entry the entry function of task
* @param[in] autorun the autorunning flag of task
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_create(ktask_t *task, const name_t *name, void *arg,
uint8_t prio, tick_t ticks, cpu_stack_t *stack_buf,
size_t stack_size, task_entry_t entry, uint8_t autorun);
#if (RHINO_CONFIG_CPU_NUM > 1)
kstat_t krhino_task_cpu_create(ktask_t *task, const name_t *name, void *arg,
uint8_t prio, tick_t ticks, cpu_stack_t *stack_buf,
size_t stack_size, task_entry_t entry, uint8_t cpu_num,
uint8_t autorun);
kstat_t krhino_task_cpu_bind(ktask_t *task, uint8_t cpu_num);
kstat_t krhino_task_cpu_unbind(ktask_t *task);
#endif
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
/**
* This function will initialize a task
* @param[in] task the task to be created
* @param[in] name the name of task, which shall be unique
* @param[in] arg the parameter of task enter function
* @param[in] pri the prio of task
* @param[in] ticks the time slice if there are same prio task
* @param[in] stack the size of thread stack
* @param[in] entry the entry function of task
* @param[in] autorun the autorunning flag of task
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_dyn_create(ktask_t **task, const name_t *name, void *arg,
uint8_t pri,
tick_t ticks, void *stack, size_t stack_size,
task_entry_t entry, uint8_t autorun);
#if (RHINO_CONFIG_CPU_NUM > 1)
kstat_t krhino_task_cpu_dyn_create(ktask_t **task, const name_t *name, void *arg,
uint8_t pri, tick_t ticks, size_t stack,
task_entry_t entry, uint8_t cpu_num, uint8_t autorun);
#endif
#endif
#if (RHINO_CONFIG_TASK_DEL > 0)
/**
* This function will delete a task
* @param[in] task the task to be deleted.
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_del(ktask_t *task);
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
/**
* This function will delete a dyn-task
* @param[in] task the task to be deleted.
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_dyn_del(ktask_t *task);
#endif
#endif
/**
* This function will cause a task to sleep for some ticks
* @param[in] ticks the ticks to sleep
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_sleep(tick_t dly);
/**
* This function will yield a task
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_yield(void);
/**
* This function will get the current task for this cpu
* @return the current task
*/
ktask_t *krhino_cur_task_get(void);
#if (RHINO_CONFIG_TASK_SUSPEND > 0)
/**
* This function will suspend a task
* @param[in] task the task to be suspended
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_suspend(ktask_t *task);
/**
* This function will resume a task
* @param[in] task the task to be resumed
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_resume(ktask_t *task);
#endif
/**
* This function will get min free stack size in the total runtime
* @param[in] task the task where get free stack size.
* @param[in] free the free task stack size to be filled with.
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_stack_min_free(ktask_t *task, size_t *free);
/**
* This function will get current free stack size
* @param[in] task the task where get free stack size.
* @param[in] free the free task stack size to be filled with.
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_stack_cur_free(ktask_t *task, size_t *free);
/**
* This function will change the prio of task
* @param[in] task the task to be changed prio
* @param[in] pri the prio to be changed.
* @param[out] old_pri the old task prio to be filled with
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_pri_change(ktask_t *task, uint8_t pri, uint8_t *old_pri);
#if (RHINO_CONFIG_TASK_WAIT_ABORT > 0)
/**
* This function will abort a task and wakup the task
* @param[in] task the task to be aborted
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_wait_abort(ktask_t *task);
#endif
#if (RHINO_CONFIG_SCHED_RR > 0)
/**
* This function will set task timeslice
* @param[in] task the task to be set timeslice
* @param[in] slice the task time slice
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_time_slice_set(ktask_t *task, size_t slice);
/**
* This function will set task sched policy
* @param[in] task the task to be set timeslice
* @param[in] policy the policy to be set, pllicy option can be either KSCHED_FIFO or KSCHED_RR
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sched_policy_set(ktask_t *task, uint8_t policy);
/**
* This function will get task sched policy
* @param[in] task the task to be get timeslice
* @param[out] policy the policy to be get
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_sched_policy_get(ktask_t *task, uint8_t *policy);
#endif
#if (RHINO_CONFIG_TASK_INFO > 0)
/**
* This function will set task private infomation
* @param[in] task the task to be set private infomation
* @param[out] info the private information
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_info_set(ktask_t *task, size_t idx, void *info);
/**
* This function will get task private infomation
* @param[in] task the task to be get private infomation
* @param[out] info to save private infomation
* @return the task private information
*/
kstat_t krhino_task_info_get(ktask_t *task, size_t idx, void **info);
#endif
/**
* This function will be set in cpu_task_stack_init,set LR reg with
* this funtion pointer
*/
void krhino_task_deathbed(void);
void krhino_task_set_lprun(ktask_t *task, uint8_t run);
void krhino_lpower_mode(uint8_t enable);
#endif /* K_TASK_H */

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_TASK_SEM_H
#define K_TASK_SEM_H
/**
* This function will create a task-semaphore
* @param[in] task pointer to the task
* @param[in] sem pointer to the semaphore
* @param[in] name name of the task-semaphore
* @param[in] count count of the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_sem_create(ktask_t *task, ksem_t *sem, const name_t *name,
size_t count);
/**
* This function will delete a task-semaphore
* @param[in] task pointer to the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_sem_del(ktask_t *task);
/**
* This function will give up a task-semaphore
* @param[in] task pointer to the task
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_sem_give(ktask_t *task);
/**
* This function will take a task-semaphore
* @param[in] ticks ticks to wait before take the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_sem_take(tick_t ticks);
/**
* This function will set the count of a task-semaphore
* @param[in] task pointer to the task
* @param[in] count count of the semaphre to set
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_sem_count_set(ktask_t *task, sem_count_t count);
/**
* This function will get task-semaphore count
* @param[in] task pointer to the semphore
* @param[out] count count of the semaphore
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_task_sem_count_get(ktask_t *task, sem_count_t *count);
#endif /* K_TASK_SEM_H */

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_TIME_H
#define K_TIME_H
/**
* This function will handle systick routine
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
void krhino_tick_proc(void);
/**
* This function will get time of the system in ms
* @return system time
*/
sys_time_t krhino_sys_time_get(void);
/**
* This function will get ticks of the system
* @return the system ticks
*/
sys_time_t krhino_sys_tick_get(void);
/**
* This function will convert ms to ticks
* @param[in] ms ms which will be converted to ticks
* @return the ticks of the ms
*/
tick_t krhino_ms_to_ticks(sys_time_t ms);
/**
* This function will convert ticks to ms
* @param[in] ticks ticks which will be converted to ms
* @return the ms of the ticks
*/
sys_time_t krhino_ticks_to_ms(tick_t ticks);
#endif /* K_TIME_H */

View File

@@ -0,0 +1,137 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_TIMER_H
#define K_TIMER_H
enum {
TIMER_CMD_CB = 0u,
TIMER_CMD_START,
TIMER_CMD_STOP,
TIMER_CMD_CHG,
TIMER_ARG_CHG,
TIMER_ARG_CHG_AUTO,
TIMER_CMD_DEL,
TIMER_CMD_DYN_DEL
};
typedef void (*timer_cb_t)(void *timer, void *arg);
typedef struct {
klist_t timer_list;
klist_t *to_head;
const name_t *name;
timer_cb_t cb;
void *timer_cb_arg;
sys_time_t match;
sys_time_t remain;
sys_time_t init_count;
sys_time_t round_ticks;
void *priv;
kobj_type_t obj_type;
uint8_t timer_state;
uint8_t mm_alloc_flag;
} ktimer_t;
typedef struct {
ktimer_t *timer;
uint8_t cb_num;
sys_time_t first;
union {
sys_time_t round;
void *arg;
} u;
} k_timer_queue_cb;
typedef enum {
TIMER_DEACTIVE = 0u,
TIMER_ACTIVE
} k_timer_state_t;
/**
* This function will create a timer
* @param[in] timer pointer to the timer(the space is provided by user)
* @param[in] name name of the timer
* @param[in] cb callbak of the timer
* @param[in] first ticks of the first timer triger
* @param[in] round ticks of the normal timer triger
* @param[in] arg the argument of the callback
* @param[in] auto_run auto run or not when the timer is created
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_timer_create(ktimer_t *timer, const name_t *name, timer_cb_t cb,
sys_time_t first, sys_time_t round, void *arg, uint8_t auto_run);
/**
* This function will delete a timer
* @param[in] timer pointer to a timer
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_timer_del(ktimer_t *timer);
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
/**
* This function will create a dyn-timer
* @param[in] timer pointer to the timer
* @param[in] name name of the timer
* @param[in] cb callbak of the timer
* @param[in] first ticks of the first timer triger
* @param[in] round ticks of the normal timer triger
* @param[in] arg the argument of the callback
* @param[in] auto_run auto run or not when the timer is created
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_timer_dyn_create(ktimer_t **timer, const name_t *name,
timer_cb_t cb,
sys_time_t first, sys_time_t round, void *arg, uint8_t auto_run);
/**
* This function will delete a dyn-timer
* @param[in] timer pointer to a timer
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_timer_dyn_del(ktimer_t *timer);
#endif
/**
* This function will start a timer
* @param[in] timer pointer to the timer
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_timer_start(ktimer_t *timer);
/**
* This function will stop a timer
* @param[in] timer pointer to the timer
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_timer_stop(ktimer_t *timer);
/**
* This function will change attributes of a timer
* @param[in] timer pointer to the timer
* @param[in] first ticks of the first timer triger
* @param[in] round ticks of the normal timer triger
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_timer_change(ktimer_t *timer, sys_time_t first, sys_time_t round);
/**
* This function will change attributes of a timer without stop and start
* @param[in] timer pointer to the timer
* @param[in] first ticks of the first timer triger
* @param[in] round ticks of the normal timer triger
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_timer_arg_change_auto(ktimer_t *timer, void *arg);
/**
* This function will change callback arg attributes of a timer
* @param[in] timer pointer to the timer
* @param[in] arg timer callback arg
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_timer_arg_change(ktimer_t *timer, void *arg);
#endif /* K_TIMER_H */

View File

@@ -0,0 +1,207 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_TRACE_H
#define K_TRACE_H
#if (RHINO_CONFIG_TRACE > 0)
/* task trace function */
void _trace_init(void);
void _trace_task_switch(ktask_t *from, ktask_t *to);
void _trace_intrpt_task_switch(ktask_t *from, ktask_t *to);
void _trace_task_create(ktask_t *task);
void _trace_task_sleep(ktask_t *task, tick_t ticks);
void _trace_task_pri_change(ktask_t *task, ktask_t *task_pri_chg, uint8_t pri);
void _trace_task_suspend(ktask_t *task, ktask_t *task_suspended);
void _trace_task_resume(ktask_t *task, ktask_t *task_resumed);
void _trace_task_del(ktask_t *task, ktask_t *task_del);
void _trace_task_abort(ktask_t *task, ktask_t *task_abort);
/* semaphore trace function */
void _trace_sem_create(ktask_t *task, ksem_t *sem);
void _trace_sem_overflow(ktask_t *task, ksem_t *sem);
void _trace_sem_del(ktask_t *task, ksem_t *sem);
void _trace_sem_get_success(ktask_t *task, ksem_t *sem);
void _trace_sem_get_blk(ktask_t *task, ksem_t *sem, tick_t wait_option);
void _trace_sem_task_wake(ktask_t *task, ktask_t *task_waked_up, ksem_t *sem,
uint8_t opt_wake_all);
void _trace_sem_cnt_increase(ktask_t *task, ksem_t *sem);
/* mutex trace function */
void _trace_mutex_create(ktask_t *task, kmutex_t *mutex, const name_t *name);
void _trace_mutex_release(ktask_t *task, ktask_t *task_release,
uint8_t new_pri);
void _trace_mutex_get(ktask_t *task, kmutex_t *mutex, tick_t wait_option);
void _trace_task_pri_inv(ktask_t *task, ktask_t *mtxtsk);
void _trace_mutex_get_blk(ktask_t *task, kmutex_t *mutex, tick_t wait_option);
void _trace_mutex_release_success(ktask_t *task, kmutex_t *mutex);
void _trace_mutex_task_wake(ktask_t *task, ktask_t *task_waked_up,
kmutex_t *mutex);
void _trace_mutex_del(ktask_t *task, kmutex_t *mutex);
/* event trace function */
void _trace_event_create(ktask_t *task, kevent_t *event, const name_t *name,
uint32_t flags_init);
void _trace_event_get(ktask_t *task, kevent_t *event);
void _trace_event_get_blk(ktask_t *task, kevent_t *event, tick_t wait_option);
void _trace_event_task_wake(ktask_t *task, ktask_t *task_waked_up,
kevent_t *event);
void _trace_event_del(ktask_t *task, kevent_t *event);
/* buf_queue trace function */
void _trace_buf_queue_create(ktask_t *task, kbuf_queue_t *buf_queue);
void _trace_buf_max(ktask_t *task, kbuf_queue_t *buf_queue, void *p_void,
size_t msg_size);
void _trace_buf_post(ktask_t *task, kbuf_queue_t *buf_queue, void *p_void,
size_t msg_size);
void _trace_buf_queue_task_wake(ktask_t *task, ktask_t *task_waked_up,
kbuf_queue_t *buf_queue);
void _trace_buf_queue_get_blk(ktask_t *task, kbuf_queue_t *buf_queue,
tick_t wait_option);
/* timer trace function */
void _trace_timer_create(ktask_t *task, ktimer_t *timer);
void _trace_timer_del(ktask_t *task, ktimer_t *timer);
/* mblk trace function */
void _trace_mblk_pool_create(ktask_t *task, mblk_pool_t *pool);
/* mm trace function */
//void _trace_mm_pool_create(ktask_t *task, mm_pool_t *pool);
/* work queue trace */
void _trace_work_init(ktask_t *task, kwork_t *work);
void _trace_workqueue_create(ktask_t *task, kworkqueue_t *workqueue);
void _trace_workqueue_del(ktask_t *task, kworkqueue_t *workqueue);
/* task trace */
#define TRACE_INIT() _trace_init()
#define TRACE_TASK_SWITCH(from, to) _trace_task_switch(from, to)
#define TRACE_TASK_CREATE(task) _trace_task_create(task)
#define TRACE_TASK_SLEEP(task, ticks) _trace_task_sleep(task, ticks)
#define TRACE_INTRPT_TASK_SWITCH(from, to) _trace_intrpt_task_switch(from, to)
#define TRACE_TASK_PRI_CHANGE(task, task_pri_chg, pri) _trace_task_pri_change(task, task_pri_chg, pri)
#define TRACE_TASK_SUSPEND(task, task_suspended) _trace_task_suspend(task, task_suspended)
#define TRACE_TASK_RESUME(task, task_resumed) _trace_task_resume(task, task_resumed)
#define TRACE_TASK_DEL(task, task_del) _trace_task_del(task, task_del)
#define TRACE_TASK_WAIT_ABORT(task, task_abort) _trace_task_abort(task, task_abort)
/* semaphore trace */
#define TRACE_SEM_CREATE(task, sem) _trace_sem_create(task, sem)
#define TRACE_SEM_OVERFLOW(task, sem) _trace_sem_overflow(task, sem)
#define TRACE_SEM_CNT_INCREASE(task, sem) _trace_sem_cnt_increase(task, sem)
#define TRACE_SEM_GET_SUCCESS(task, sem) _trace_sem_get_success(task, sem)
#define TRACE_SEM_GET_BLK(task, sem, wait_option) _trace_sem_get_blk(task, sem, wait_option)
#define TRACE_SEM_TASK_WAKE(task, task_waked_up, sem, opt_wake_all) _trace_sem_task_wake(task, task_waked_up, sem, opt_wake_all)
#define TRACE_SEM_DEL(task, sem) _trace_sem_del(task, sem);
/* mutex trace */
#define TRACE_MUTEX_CREATE(task, mutex, name) _trace_mutex_create(task, mutex, name)
#define TRACE_MUTEX_RELEASE(task, task_release, new_pri) _trace_mutex_release(task, task_release, new_pri)
#define TRACE_MUTEX_GET(task, mutex, wait_option) _trace_mutex_get(task, mutex, wait_option)
#define TRACE_TASK_PRI_INV(task, mtxtsk) _trace_task_pri_inv(task, mtxtsk)
#define TRACE_MUTEX_GET_BLK(task, mutex, wait_option) _trace_mutex_get_blk(task, mutex, wait_option)
#define TRACE_MUTEX_RELEASE_SUCCESS(task, mutex) _trace_mutex_release_success(task, mutex)
#define TRACE_MUTEX_TASK_WAKE(task, task_waked_up, mutex) _trace_mutex_task_wake(task, task_waked_up, mutex)
#define TRACE_MUTEX_DEL(task, mutex) _trace_mutex_del(task, mutex)
/* event trace */
#define TRACE_EVENT_CREATE(task, event, name, flags_init) _trace_event_create(task, event, name, flags_init)
#define TRACE_EVENT_GET(task, event) _trace_event_get(task, event)
#define TRACE_EVENT_GET_BLK(task, event, wait_option) _trace_event_get_blk(task, event, wait_option)
#define TRACE_EVENT_TASK_WAKE(task, task_waked_up, event) _trace_event_task_wake(task, task_waked_up, event)
#define TRACE_EVENT_DEL(task, event) _trace_event_del(task, event)
/* buf_queue trace */
#define TRACE_BUF_QUEUE_CREATE(task, buf_queue) _trace_buf_queue_create(task, buf_queue)
#define TRACE_BUF_QUEUE_MAX(task, buf_queue, msg, msg_size) _trace_buf_max(task, buf_queue, msg, msg_size)
#define TRACE_BUF_QUEUE_POST(task, buf_queue, msg, msg_size) _trace_buf_post(task, buf_queue, msg, msg_size)
#define TRACE_BUF_QUEUE_TASK_WAKE(task, task_waked_up, queue) _trace_buf_queue_task_wake(task, task_waked_up, queue)
#define TRACE_BUF_QUEUE_GET_BLK(task, buf_queue, wait_option) _trace_buf_queue_get_blk(task, buf_queue, wait_option)
/* timer trace */
#define TRACE_TIMER_CREATE(task, timer) _trace_timer_create(task, timer)
#define TRACE_TIMER_DEL(task, timer) _trace_timer_del(task, timer)
/* mblk trace */
#define TRACE_MBLK_POOL_CREATE(task, pool) _trace_mblk_pool_create(task, pool)
/* mm trace */
#define TRACE_MM_POOL_CREATE(task, pool) _trace_mm_pool_create(task, pool)
/* mm region */
#define TRACE_MM_REGION_CREATE(task, regions) _trace_mm_region_create(task, regions)
/* work queue trace */
#define TRACE_WORK_INIT(task, work) _trace_work_init(task, work)
#define TRACE_WORKQUEUE_CREATE(task, workqueue) _trace_workqueue_create(task, workqueue)
#define TRACE_WORKQUEUE_DEL(task, workqueue) _trace_workqueue_del(task, workqueue)
#else
/* task trace */
#define TRACE_INIT()
#define TRACE_TASK_SWITCH(from, to)
#define TRACE_TASK_CREATE(task)
#define TRACE_TASK_SLEEP(task, ticks)
#define TRACE_INTRPT_TASK_SWITCH(from, to)
#define TRACE_TASK_PRI_CHANGE(task, task_pri_chg, pri)
#define TRACE_TASK_SUSPEND(task, task_suspended)
#define TRACE_TASK_RESUME(task, task_resumed)
#define TRACE_TASK_DEL(task, task_del)
#define TRACE_TASK_WAIT_ABORT(task, task_abort)
/* semaphore trace */
#define TRACE_SEM_CREATE(task, sem)
#define TRACE_SEM_OVERFLOW(task, sem)
#define TRACE_SEM_CNT_INCREASE(task, sem)
#define TRACE_SEM_GET_SUCCESS(task, sem)
#define TRACE_SEM_GET_BLK(task, sem, wait_option)
#define TRACE_SEM_TASK_WAKE(task, task_waked_up, sem, opt_wake_all)
#define TRACE_SEM_DEL(task, sem)
/* mutex trace */
#define TRACE_MUTEX_CREATE(task, mutex, name)
#define TRACE_MUTEX_RELEASE(task, task_release, new_pri)
#define TRACE_MUTEX_GET(task, mutex, wait_option)
#define TRACE_TASK_PRI_INV(task, mtxtsk)
#define TRACE_MUTEX_GET_BLK(task, mutex, wait_option)
#define TRACE_MUTEX_RELEASE_SUCCESS(task, mutex)
#define TRACE_MUTEX_TASK_WAKE(task, task_waked_up, mutex)
#define TRACE_MUTEX_DEL(task, mutex)
/* event trace */
#define TRACE_EVENT_CREATE(task, event, name, flags_init)
#define TRACE_EVENT_GET(task, event)
#define TRACE_EVENT_GET_BLK(task, event, wait_option)
#define TRACE_EVENT_TASK_WAKE(task, task_waked_up, event)
#define TRACE_EVENT_DEL(task, event)
/* buf_queue trace */
#define TRACE_BUF_QUEUE_CREATE(task, buf_queue)
#define TRACE_BUF_QUEUE_MAX(task, buf_queue, msg, msg_size)
#define TRACE_BUF_QUEUE_POST(task, buf_queue, msg, msg_size)
#define TRACE_BUF_QUEUE_TASK_WAKE(task, task_waked_up, queue)
#define TRACE_BUF_QUEUE_GET_BLK(task, buf_queue, wait_option)
/* timer trace */
#define TRACE_TIMER_CREATE(task, timer)
#define TRACE_TIMER_DEL(task, timer)
/* MBLK trace */
#define TRACE_MBLK_POOL_CREATE(task, pool)
/* MM trace */
#define TRACE_MM_POOL_CREATE(task, pool)
/* MM region trace*/
#define TRACE_MM_REGION_CREATE(task, regions)
/* work queue trace */
#define TRACE_WORK_INIT(task, work)
#define TRACE_WORKQUEUE_CREATE(task, workqueue)
#define TRACE_WORKQUEUE_DEL(task, workqueue)
#endif
#endif

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef K_WORKQUEUE_H
#define K_WORKQUEUE_H
#if (RHINO_CONFIG_WORKQUEUE > 0)
#define WORKQUEUE_WORK_MAX 32
typedef void (*work_handle_t)(void *arg);
typedef struct {
klist_t work_node;
work_handle_t handle;
void *arg;
tick_t dly;
ktimer_t *timer;
void *wq;
uint8_t work_exit;
} kwork_t;
typedef struct {
klist_t workqueue_node;
klist_t work_list;
kwork_t *work_current; /* current work */
const name_t *name;
ktask_t worker;
ksem_t sem;
} kworkqueue_t;
/**
* This function will creat a workqueue
* @param[in] workqueue the workqueue to be created
* @param[in] name the name of workqueue/worker, which should be unique
* @param[in] pri the priority of the worker
* @param[in] stack_buf the stack of the worker(task)
* @param[in] stack_size the size of the worker-stack
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_workqueue_create(kworkqueue_t *workqueue, const name_t *name,
uint8_t pri, cpu_stack_t *stack_buf, size_t stack_size);
/**
* This function will delete a workqueue
* @param[in] workqueue the workqueue to be deleted
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_workqueue_del(kworkqueue_t *workqueue);
/**
* This function will initialize a work
* @param[in] work the work to be initialized
* @param[in] handle the call back function to run
* @param[in] arg the paraments of the function
* @param[in] dly the ticks to delay before run
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_work_init(kwork_t *work, work_handle_t handle, void *arg,
tick_t dly);
/**
* This function will run a work on a workqueue
* @param[in] workqueue the workqueue to run work
* @param[in] work the work to run
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_work_run(kworkqueue_t *workqueue, kwork_t *work);
/**
* This function will run a work on the default workqueue
* @param[in] work the work to run
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_work_sched(kwork_t *work);
/**
* This function will cancel a work
* @param[in] work the work to cancel
* @return the operation status, RHINO_SUCCESS is OK, others is error
*/
kstat_t krhino_work_cancel(kwork_t *work);
#endif
#endif /* K_WORKQUEUE_H */

View File

@@ -0,0 +1,439 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#if (RHINO_CONFIG_BUF_QUEUE > 0)
static kstat_t buf_queue_create(kbuf_queue_t *queue, const name_t *name,
void *buf, size_t size, size_t max_msg, uint8_t mm_alloc_flag, size_t type)
{
CPSR_ALLOC();
NULL_PARA_CHK(queue);
NULL_PARA_CHK(buf);
NULL_PARA_CHK(name);
if (max_msg == 0u) {
return RHINO_INV_PARAM;
}
if (size == 0u) {
return RHINO_BUF_QUEUE_SIZE_ZERO;
}
/* init the queue blocked list */
klist_init(&queue->blk_obj.blk_list);
klist_init(&queue->sblk_obj.blk_list);
queue->buf = buf;
queue->cur_num = 0u;
queue->peak_num = 0u;
queue->max_msg_size = max_msg;
queue->blk_obj.name = name;
queue->blk_obj.blk_policy = BLK_POLICY_PRI;
queue->sblk_obj.name = name;
queue->sblk_obj.blk_policy = BLK_POLICY_PRI;
queue->mm_alloc_flag = mm_alloc_flag;
RHINO_CRITICAL_ENTER();
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_insert(&(g_kobj_list.buf_queue_head), &queue->buf_queue_item);
#endif
RHINO_CRITICAL_EXIT();
queue->blk_obj.obj_type = RHINO_BUF_QUEUE_OBJ_TYPE;
queue->sblk_obj.obj_type = RHINO_BUF_QUEUE_OBJ_TYPE;
ringbuf_init(&(queue->ringbuf), buf, size, type, max_msg);
queue->min_free_buf_size = queue->ringbuf.freesize;
TRACE_BUF_QUEUE_CREATE(krhino_cur_task_get(), queue);
return RHINO_SUCCESS;
}
kstat_t krhino_buf_queue_create(kbuf_queue_t *queue, const name_t *name,
void *buf, size_t size, size_t max_msg)
{
return buf_queue_create(queue, name, buf, size, max_msg, K_OBJ_STATIC_ALLOC, RINGBUF_TYPE_DYN);
}
kstat_t krhino_fix_buf_queue_create(kbuf_queue_t *queue, const name_t *name,
void *buf, size_t msg_size, size_t msg_num)
{
return buf_queue_create(queue, name, buf, msg_size * msg_num, msg_size, K_OBJ_STATIC_ALLOC, RINGBUF_TYPE_FIX);
}
kstat_t krhino_buf_queue_del(kbuf_queue_t *queue)
{
CPSR_ALLOC();
klist_t *head;
NULL_PARA_CHK(queue);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (queue->blk_obj.obj_type != RHINO_BUF_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (queue->mm_alloc_flag != K_OBJ_STATIC_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
head = &queue->blk_obj.blk_list;
queue->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
/* all task blocked on this queue is waken up */
while (!is_klist_empty(head)) {
pend_task_rm(krhino_list_entry(head->next, ktask_t, task_list));
}
head = &queue->sblk_obj.blk_list;
queue->sblk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
/* all task blocked on this queue is waken up */
while (!is_klist_empty(head)) {
pend_task_rm(krhino_list_entry(head->next, ktask_t, task_list));
}
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&queue->buf_queue_item);
#endif
ringbuf_reset(&queue->ringbuf);
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
kstat_t krhino_buf_queue_dyn_create(kbuf_queue_t **queue, const name_t *name,
size_t size, size_t max_msg)
{
kstat_t stat;
kbuf_queue_t *queue_obj;
NULL_PARA_CHK(queue);
if (size == 0u) {
return RHINO_BUF_QUEUE_SIZE_ZERO;
}
queue_obj = krhino_mm_alloc(sizeof(kbuf_queue_t), __builtin_return_address(0));
if (queue_obj == NULL) {
return RHINO_NO_MEM;
}
queue_obj->buf = krhino_mm_alloc(size, __builtin_return_address(0));
if (queue_obj->buf == NULL) {
krhino_mm_free(queue_obj);
return RHINO_NO_MEM;
}
stat = buf_queue_create(queue_obj, name, queue_obj->buf, size, max_msg,
K_OBJ_DYN_ALLOC, RINGBUF_TYPE_DYN);
if (stat != RHINO_SUCCESS) {
krhino_mm_free(queue_obj->buf);
krhino_mm_free(queue_obj);
return stat;
}
*queue = queue_obj;
return RHINO_SUCCESS;
}
kstat_t krhino_buf_queue_dyn_del(kbuf_queue_t *queue)
{
CPSR_ALLOC();
klist_t *head;
NULL_PARA_CHK(queue);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (queue->blk_obj.obj_type != RHINO_BUF_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (queue->mm_alloc_flag != K_OBJ_DYN_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
head = &queue->blk_obj.blk_list;
queue->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
while (!is_klist_empty(head)) {
pend_task_rm(krhino_list_entry(head->next, ktask_t, task_list));
}
head = &queue->sblk_obj.blk_list;
queue->sblk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
while (!is_klist_empty(head)) {
pend_task_rm(krhino_list_entry(head->next, ktask_t, task_list));
}
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&queue->buf_queue_item);
#endif
ringbuf_reset(&queue->ringbuf);
RHINO_CRITICAL_EXIT_SCHED();
krhino_mm_free(queue->buf);
krhino_mm_free(queue);
return RHINO_SUCCESS;
}
#endif
static kstat_t buf_queue_send(kbuf_queue_t *queue, void *msg, size_t msg_size, tick_t ticks)
{
CPSR_ALLOC();
klist_t *head;
ktask_t *task;
kstat_t err;
uint8_t cur_cpu_num;
/* this is only needed when system zero interrupt feature is enabled */
#if (RHINO_CONFIG_INTRPT_GUARD > 0)
soc_intrpt_guard();
#endif
__retry:
RHINO_CRITICAL_ENTER();
if (queue->blk_obj.obj_type != RHINO_BUF_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
cur_cpu_num = cpu_cur_get();
(void)cur_cpu_num;
if (msg_size > queue->max_msg_size) {
TRACE_BUF_QUEUE_MAX(g_active_task[cur_cpu_num], queue, msg, msg_size);
RHINO_CRITICAL_EXIT();
return RHINO_BUF_QUEUE_MSG_SIZE_OVERFLOW;
}
if (msg_size == 0) {
RHINO_CRITICAL_EXIT();
return RHINO_INV_PARAM;
}
head = &queue->blk_obj.blk_list;
/* buf queue is not full here, if there is no blocked receive task */
if (is_klist_empty(head)) {
err = ringbuf_push(&(queue->ringbuf), msg, msg_size);
if (err != RHINO_SUCCESS) {
if (err == RHINO_RINGBUF_FULL) {
if(ticks){
pend_to_blk_obj((blk_obj_t *)&queue->sblk_obj.blk_list, g_active_task[cur_cpu_num], ticks, psr);
RHINO_CRITICAL_EXIT_SCHED();
RHINO_CPU_INTRPT_DISABLE();
err = pend_state_end_proc(g_active_task[cur_cpu_num]);
RHINO_CPU_INTRPT_ENABLE();
if(err == RHINO_SUCCESS){
goto __retry;
}
RHINO_CRITICAL_ENTER();
}
err = RHINO_BUF_QUEUE_FULL;
}
RHINO_CRITICAL_EXIT();
return err;
}
queue->cur_num ++;
if (queue->peak_num < queue->cur_num) {
queue->peak_num = queue->cur_num;
}
if (queue->min_free_buf_size > queue->ringbuf.freesize) {
queue->min_free_buf_size = queue->ringbuf.freesize;
}
TRACE_BUF_QUEUE_POST(g_active_task[cur_cpu_num], queue, msg, msg_size);
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
task = krhino_list_entry(head->next, ktask_t, task_list);
memcpy(task->msg, msg, msg_size);
task->bq_msg_size = msg_size;
pend_task_wakeup(task);
TRACE_BUF_QUEUE_TASK_WAKE(g_active_task[cur_cpu_num], task, queue);
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
kstat_t krhino_buf_queue_send(kbuf_queue_t *queue, void *msg, size_t size, tick_t ticks)
{
NULL_PARA_CHK(queue);
NULL_PARA_CHK(msg);
return buf_queue_send(queue, msg, size, ticks);
}
kstat_t krhino_buf_queue_recv(kbuf_queue_t *queue, tick_t ticks, void *msg,
size_t *size)
{
CPSR_ALLOC();
klist_t *blk_list_head;
kstat_t ret;
uint8_t cur_cpu_num;
NULL_PARA_CHK(queue);
NULL_PARA_CHK(msg);
NULL_PARA_CHK(size);
krhino_check_fatal_call(__FUNCTION__);
RHINO_CRITICAL_ENTER();
cur_cpu_num = cpu_cur_get();
if ((g_intrpt_nested_level[cur_cpu_num] > 0u) && (ticks != RHINO_NO_WAIT)) {
RHINO_CRITICAL_EXIT();
return RHINO_NOT_CALLED_BY_INTRPT;
}
if (queue->blk_obj.obj_type != RHINO_BUF_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
blk_list_head = &queue->sblk_obj.blk_list;
if (!ringbuf_is_empty(&(queue->ringbuf))) {
ringbuf_pop(&(queue->ringbuf), msg, size);
queue->cur_num --;
while (!is_klist_empty(blk_list_head)) {
pend_task_wakeup(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
if (ticks == RHINO_NO_WAIT) {
*size = 0u;
RHINO_CRITICAL_EXIT();
return RHINO_NO_PEND_WAIT;
}
if (g_sched_lock[cur_cpu_num] > 0u) {
*size = 0u;
RHINO_CRITICAL_EXIT();
return RHINO_SCHED_DISABLE;
}
g_active_task[cur_cpu_num]->msg = msg;
pend_to_blk_obj((blk_obj_t *)queue, g_active_task[cur_cpu_num], ticks, psr);
TRACE_BUF_QUEUE_GET_BLK(g_active_task[cur_cpu_num], queue, ticks);
RHINO_CRITICAL_EXIT_SCHED();
RHINO_CPU_INTRPT_DISABLE();
cur_cpu_num = cpu_cur_get();
ret = pend_state_end_proc(g_active_task[cur_cpu_num]);
switch (ret) {
case RHINO_SUCCESS:
*size = g_active_task[cur_cpu_num]->bq_msg_size;
break;
default:
*size = 0u;
break;
}
RHINO_CPU_INTRPT_ENABLE();
return ret;
}
kstat_t krhino_buf_queue_flush(kbuf_queue_t *queue)
{
CPSR_ALLOC();
NULL_PARA_CHK(queue);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (queue->blk_obj.obj_type != RHINO_BUF_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
ringbuf_reset(&(queue->ringbuf));
queue->cur_num = 0u;
queue->peak_num = 0u;
queue->min_free_buf_size = queue->ringbuf.freesize;
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
kstat_t krhino_buf_queue_info_get(kbuf_queue_t *queue, kbuf_queue_info_t *info)
{
CPSR_ALLOC();
NULL_PARA_CHK(queue);
NULL_PARA_CHK(info);
RHINO_CRITICAL_ENTER();
if (queue->blk_obj.obj_type != RHINO_BUF_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
info->free_buf_size = queue->ringbuf.freesize;
info->min_free_buf_size = queue->min_free_buf_size;
info->buf_size = queue->ringbuf.end - queue->ringbuf.buf;
info->max_msg_size = queue->max_msg_size;
info->cur_num = queue->cur_num;
info->peak_num = queue->peak_num;
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
#endif

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
void dym_mem_proc_hdl(void)
{
CPSR_ALLOC();
res_free_t *res_free;
res_free_t tmp;
uint32_t i;
if (!is_klist_empty(&g_res_list)) {
RHINO_CRITICAL_ENTER();
res_free = krhino_list_entry(g_res_list.next, res_free_t, res_list);
klist_rm(&res_free->res_list);
RHINO_CRITICAL_EXIT();
memcpy(&tmp, res_free, sizeof(res_free_t));
for (i = 0; i < tmp.cnt; i++) {
krhino_mm_free(tmp.res[i]);
}
}
}
#if 0
void dyn_mem_proc_task(void *arg)
{
CPSR_ALLOC();
kstat_t ret;
res_free_t *res_free;
res_free_t tmp;
uint32_t i;
(void)arg;
while (1) {
ret = krhino_sem_take(&g_res_sem, RHINO_WAIT_FOREVER);
if (ret != RHINO_SUCCESS) {
k_err_proc(RHINO_DYN_MEM_PROC_ERR);
}
while (1) {
RHINO_CRITICAL_ENTER();
if (!is_klist_empty(&g_res_list)) {
res_free = krhino_list_entry(g_res_list.next, res_free_t, res_list);
klist_rm(&res_free->res_list);
RHINO_CRITICAL_EXIT();
memcpy(&tmp, res_free, sizeof(res_free_t));
for (i = 0; i < tmp.cnt; i++) {
krhino_mm_free(tmp.res[i]);
}
}
else {
RHINO_CRITICAL_EXIT();
break;
}
}
}
}
__init void dyn_mem_proc_task_start(void)
{
krhino_task_create(&g_dyn_task, "dyn_mem", 0, RHINO_CONFIG_K_DYN_MEM_TASK_PRI,
0, g_dyn_task_stack, RHINO_CONFIG_K_DYN_TASK_STACK,
dyn_mem_proc_task, 1);
}
#endif
#endif

View File

@@ -0,0 +1,17 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
void k_err_proc(kstat_t err)
{
#if 1
soc_err_proc(err);
#else
if (g_err_proc != NULL) {
g_err_proc(err);
}
#endif
}

View File

@@ -0,0 +1,339 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#if (RHINO_CONFIG_EVENT_FLAG > 0)
static kstat_t event_create(kevent_t *event, const name_t *name, uint32_t flags,
uint8_t mm_alloc_flag)
{
CPSR_ALLOC();
NULL_PARA_CHK(event);
NULL_PARA_CHK(name);
/* init the list */
klist_init(&event->blk_obj.blk_list);
event->blk_obj.blk_policy = BLK_POLICY_PRI;
event->blk_obj.name = name;
event->flags = flags;
event->mm_alloc_flag = mm_alloc_flag;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
RHINO_CRITICAL_ENTER();
klist_insert(&(g_kobj_list.event_head), &event->event_item);
RHINO_CRITICAL_EXIT();
#endif
TRACE_EVENT_CREATE(krhino_cur_task_get(), event, name, flags);
event->blk_obj.obj_type = RHINO_EVENT_OBJ_TYPE;
return RHINO_SUCCESS;
}
kstat_t krhino_event_create(kevent_t *event, const name_t *name, uint32_t flags)
{
return event_create(event, name, flags, K_OBJ_STATIC_ALLOC);
}
kstat_t krhino_event_del(kevent_t *event)
{
CPSR_ALLOC();
klist_t *blk_list_head;
NULL_PARA_CHK(event);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (event->blk_obj.obj_type != RHINO_EVENT_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (event->mm_alloc_flag != K_OBJ_STATIC_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
blk_list_head = &event->blk_obj.blk_list;
event->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
while (!is_klist_empty(blk_list_head)) {
pend_task_rm(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
event->flags = 0u;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&event->event_item);
#endif
TRACE_EVENT_DEL(g_active_task[cpu_cur_get()], event);
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
kstat_t krhino_event_dyn_create(kevent_t **event, const name_t *name,
uint32_t flags)
{
kstat_t stat;
kevent_t *event_obj;
if (event == NULL) {
return RHINO_NULL_PTR;
}
event_obj = krhino_mm_alloc(sizeof(kevent_t), __builtin_return_address(0));
if (event_obj == NULL) {
return RHINO_NO_MEM;
}
stat = event_create(event_obj, name, flags, K_OBJ_DYN_ALLOC);
if (stat != RHINO_SUCCESS) {
krhino_mm_free(event_obj);
return stat;
}
*event = event_obj;
return stat;
}
kstat_t krhino_event_dyn_del(kevent_t *event)
{
CPSR_ALLOC();
klist_t *blk_list_head;
NULL_PARA_CHK(event);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (event->blk_obj.obj_type != RHINO_EVENT_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (event->mm_alloc_flag != K_OBJ_DYN_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
blk_list_head = &event->blk_obj.blk_list;
event->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
while (!is_klist_empty(blk_list_head)) {
pend_task_rm(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
event->flags = 0u;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&event->event_item);
#endif
RHINO_CRITICAL_EXIT_SCHED();
krhino_mm_free(event);
return RHINO_SUCCESS;
}
#endif
kstat_t krhino_event_get(kevent_t *event, uint32_t flags, uint8_t opt,
uint32_t *actl_flags, tick_t ticks)
{
CPSR_ALLOC();
kstat_t stat;
uint8_t status;
uint8_t cur_cpu_num;
NULL_PARA_CHK(event);
NULL_PARA_CHK(actl_flags);
if ((opt != RHINO_AND) && (opt != RHINO_OR) && (opt != RHINO_AND_CLEAR) &&
(opt != RHINO_OR_CLEAR)) {
return RHINO_NO_THIS_EVENT_OPT;
}
krhino_check_fatal_call(__FUNCTION__);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (event->blk_obj.obj_type != RHINO_EVENT_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
cur_cpu_num = cpu_cur_get();
/* if option is AND MASK or OR MASK */
if (opt & RHINO_FLAGS_AND_MASK) {
if ((event->flags & flags) == flags) {
status = RHINO_TRUE;
} else {
status = RHINO_FALSE;
}
} else {
if ((event->flags & flags) > 0u) {
status = RHINO_TRUE;
} else {
status = RHINO_FALSE;
}
}
if (status == RHINO_TRUE) {
*actl_flags = event->flags;
if (opt & RHINO_FLAGS_CLEAR_MASK) {
event->flags &= ~flags;
}
TRACE_EVENT_GET(g_active_task[cur_cpu_num], event);
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
/* can't get event, and return immediately if wait_option is RHINO_NO_WAIT */
if (ticks == RHINO_NO_WAIT) {
RHINO_CRITICAL_EXIT();
return RHINO_NO_PEND_WAIT;
}
/* system is locked so task can not be blocked just return immediately */
if (g_sched_lock[cur_cpu_num] > 0u) {
RHINO_CRITICAL_EXIT();
return RHINO_SCHED_DISABLE;
}
/* remember the passed information */
g_active_task[cur_cpu_num]->pend_option = opt;
g_active_task[cur_cpu_num]->pend_flags = flags;
g_active_task[cur_cpu_num]->pend_info = actl_flags;
pend_to_blk_obj((blk_obj_t *)event, g_active_task[cur_cpu_num], ticks, psr);
TRACE_EVENT_GET_BLK(g_active_task[cur_cpu_num], event, ticks);
RHINO_CRITICAL_EXIT_SCHED();
RHINO_CPU_INTRPT_DISABLE();
/* so the task is waked up, need know which reason cause wake up */
stat = pend_state_end_proc(g_active_task[cpu_cur_get()]);
RHINO_CPU_INTRPT_ENABLE();
return stat;
}
static kstat_t event_set(kevent_t *event, uint32_t flags, uint8_t opt)
{
CPSR_ALLOC();
klist_t *iter;
klist_t *event_head;
klist_t *iter_temp;
ktask_t *task;
uint8_t status;
uint32_t cur_event_flags;
/* this is only needed when system zero interrupt feature is enabled */
#if (RHINO_CONFIG_INTRPT_GUARD > 0)
soc_intrpt_guard();
#endif
status = RHINO_FALSE;
RHINO_CRITICAL_ENTER();
if (event->blk_obj.obj_type != RHINO_EVENT_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
event_head = &event->blk_obj.blk_list;
/* if the set_option is AND_MASK, it just clears the flags and will return immediately */
if (opt & RHINO_FLAGS_AND_MASK) {
event->flags &= flags;
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
} else {
event->flags |= flags;
}
cur_event_flags = event->flags;
iter = event_head->next;
/* if list is not empty */
while (iter != event_head) {
task = krhino_list_entry(iter, ktask_t, task_list);
iter_temp = iter->next;
if (task->pend_option & RHINO_FLAGS_AND_MASK) {
if ((cur_event_flags & task->pend_flags) == task->pend_flags) {
status = RHINO_TRUE;
} else {
status = RHINO_FALSE;
}
} else {
if (cur_event_flags & task->pend_flags) {
status = RHINO_TRUE;
} else {
status = RHINO_FALSE;
}
}
if (status == RHINO_TRUE) {
(*(uint32_t *)(task->pend_info)) = cur_event_flags;
/* the task condition is met, just wake this task */
pend_task_wakeup(task);
TRACE_EVENT_TASK_WAKE(g_active_task[cpu_cur_get()], task, event);
/* does it need to clear the flags */
if (task->pend_option & RHINO_FLAGS_CLEAR_MASK) {
event->flags &= ~(task->pend_flags);
}
}
iter = iter_temp;
}
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
kstat_t krhino_event_set(kevent_t *event, uint32_t flags, uint8_t opt)
{
NULL_PARA_CHK(event);
if ((opt != RHINO_AND) && (opt != RHINO_OR)) {
return RHINO_NO_THIS_EVENT_OPT;
}
return event_set(event, flags, opt);
}
#endif /* RHINO_CONFIG_EVENT_FLAG */

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#if (RHINO_CONFIG_CPU_USAGE_STATS > 0)
void idle_count_set(idle_count_t value)
{
CPSR_ALLOC();
RHINO_CPU_INTRPT_DISABLE();
g_idle_count[cpu_cur_get()] = value;
RHINO_CPU_INTRPT_ENABLE();
}
idle_count_t idle_count_get(void)
{
CPSR_ALLOC();
idle_count_t idle_count;
RHINO_CPU_INTRPT_DISABLE();
idle_count = g_idle_count[cpu_cur_get()];
RHINO_CPU_INTRPT_ENABLE();
return idle_count;
}
#endif
void __attribute__((weak)) user_idle_hook(void)
{
}
void idle_task(void *arg)
{
CPSR_ALLOC();
/* avoid warning */
(void)arg;
#if (RHINO_CONFIG_USER_HOOK > 0)
krhino_idle_pre_hook();
#endif
while (RHINO_TRUE) {
RHINO_CPU_INTRPT_DISABLE();
g_idle_count[cpu_cur_get()]++;
RHINO_CPU_INTRPT_ENABLE();
user_idle_hook();
uint32_t in_disable_irq(void);
if (in_disable_irq()) {
void enable_irq(uint32_t flags);
enable_irq(0);
}
dym_mem_proc_hdl();
/* RHINO_CONFIG_CPU_PWR_MGMT */
#if (RHINO_CONFIG_CPU_PWR_MGMT > 0)
cpu_pwr_down();
#endif
}
}

View File

@@ -0,0 +1,108 @@
#include "sys_config.h"
#include "tx_platform.h"
#include <csi_kernel.h>
#include <k_api.h>
#include <csi_core.h>
#include <stdio.h>
#if RHINO_CONFIG_ISR_TASK
#define RB_NPOS(rb, pos, i) ({ \
uint32 __pos__ = (rb)->pos;\
((__pos__+(i)>=(rb)->qsize) ? (__pos__+(i)-(rb)->qsize) : (__pos__+(i))); \
})
/* rpos == wpos 表示 rbuffer 为空 */
#define RB_EMPTY(rb) ((rb)->wpos == (rb)->rpos)
/* wpos+1 == rpos 表示 rbuffer 已满 */
#define RB_FULL(rb) ({ \
uint32 _rpos_ = ((rb)->rpos);\
uint32 _wpos_ = ((rb)->wpos)+1;\
((_wpos_>=(rb)->qsize) ? (_wpos_-(rb)->qsize) : (_wpos_)) == (_rpos_);\
})
/* rbuffer 中未被读取的数据长度 */
#define RB_COUNT(rb) ({ \
uint32 _rpos_ = ((rb)->rpos);\
uint32 _wpos_ = ((rb)->wpos);\
((_rpos_<=_wpos_)? (_wpos_-_rpos_): ((rb)->qsize-_rpos_+_wpos_))\
})
/* rbuffer中剩余空间长度 */
#define RB_IDLE(rb) ({ \
uint32 _rpos_ = ((rb)->rpos);\
uint32 _wpos_ = ((rb)->wpos);\
((_wpos_<_rpos_)? (_rpos_-_wpos_-1): ((rb)->qsize-_wpos_+_rpos_-1))\
})
/*get a value from ringbuffer*/
#define RB_GET(rb, val) do{\
if(!RB_EMPTY(rb)){\
val = (rb)->rbq[(rb)->rpos];\
(rb)->rpos = RB_NPOS((rb), rpos, 1);\
}\
} while(0)
/*set a value into ringbuffer*/
#define RB_SET(rb, val) do{\
if(!RB_FULL(rb)){\
(rb)->rbq[(rb)->wpos] = val;\
(rb)->wpos = RB_NPOS((rb), wpos, 1);\
}else{ k_err_proc(RHINO_INTRPT_ISR_OVF); }\
} while (0)
typedef struct {
void (*hdl)(void *data);
void *data;
} k_isr_data;
struct k_isr_buff {
uint8_t rpos, wpos, qsize, busy;
k_isr_data *rbq;
};
static void ISR_task(void *pa)
{
kstat_t ret;
k_isr_data isr;
struct k_isr_buff *rb = (struct k_isr_buff *)g_isr_buff;
while (1) {
ret = krhino_sem_take(&g_isr_sem, 0xffffffff);
if (ret != RHINO_SUCCESS) {
k_err_proc(RHINO_SYS_FATAL_ERR);
}
isr.hdl = 0;
RB_GET(rb, isr);
if (isr.hdl) {
isr.hdl(isr.data);
}
}
}
__init void kisr_init(void)
{
struct k_isr_buff *rb = (struct k_isr_buff *)g_isr_buff;
rb->wpos = 0;
rb->rpos = 0;
rb->qsize = RHINO_CONFIG_ISR_BUFF_SIZE;
rb->rbq = (k_isr_data *)(rb + 1);
krhino_sem_create(&g_isr_sem, "isr_sem", 0);
krhino_task_create(&g_isr_task, "isr", NULL,
RHINO_CONFIG_ISR_TASK_PRI, 0u, g_isr_task_stack,
RHINO_CONFIG_ISR_TASK_STACK_SIZE, ISR_task, 1u);
}
void isr_run(void (*hdl)(void *data), void *data)
{
k_isr_data isr = { hdl, data };
struct k_isr_buff *rb = (struct k_isr_buff *)g_isr_buff;
uint32_t flag = __disable_irq();
RB_SET(rb, isr);
if (!flag) __enable_irq();
krhino_sem_give(&g_isr_sem);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,141 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#ifndef MPOOL_ALLOC
#if (RHINO_CONFIG_MM_BLK > 0)
kstat_t krhino_mblk_pool_init(mblk_pool_t *pool, const name_t *name,
void *pool_start,
size_t blk_size, size_t pool_size)
{
CPSR_ALLOC();
uint32_t blks; /* max blocks mem pool offers */
uint8_t *blk_cur; /* block pointer for traversing */
uint8_t *blk_next; /* next block pointe for traversing */
uint8_t *pool_end; /* mem pool end */
uint8_t addr_align_mask; /* address alignment */
NULL_PARA_CHK(pool);
NULL_PARA_CHK(name);
NULL_PARA_CHK(pool_start);
/* over one block at least */
if (pool_size < (blk_size << 1u)) {
return RHINO_BLK_POOL_SIZE_ERR;
}
/* check address & size alignment */
addr_align_mask = sizeof(void *) - 1u;
if (((size_t)pool_start & addr_align_mask) > 0u) {
return RHINO_INV_ALIGN;
}
if ((blk_size & addr_align_mask) > 0u) {
return RHINO_INV_ALIGN;
}
if ((pool_size & addr_align_mask) > 0u) {
return RHINO_INV_ALIGN;
}
pool_end = (uint8_t *)pool_start + pool_size;
blks = 0u;
blk_cur = (uint8_t *)pool_start;
blk_next = blk_cur + blk_size;
while (blk_next < pool_end) {
blks++;
/* use initial 4 byte point to next block */
*(uint8_t **)blk_cur = blk_next;
blk_cur = blk_next;
blk_next = blk_cur + blk_size;
}
if (blk_next == pool_end) {
blks++;
}
/* the last one */
*((uint8_t **)blk_cur) = NULL;
pool->pool_name = name;
pool->blk_whole = blks;
pool->blk_avail = blks;
pool->blk_size = blk_size;
pool->avail_list = (uint8_t *)pool_start;
pool->obj_type = RHINO_MM_BLK_OBJ_TYPE;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
RHINO_CRITICAL_ENTER();
klist_insert(&(g_kobj_list.mblkpool_head), &pool->mblkpool_stats_item);
RHINO_CRITICAL_EXIT();
#endif
TRACE_MBLK_POOL_CREATE(krhino_cur_task_get(), pool);
return RHINO_SUCCESS;
}
kstat_t krhino_mblk_alloc(mblk_pool_t *pool, void **blk)
{
CPSR_ALLOC();
kstat_t status;
uint8_t *avail_blk;
NULL_PARA_CHK(pool);
NULL_PARA_CHK(blk);
if (pool->obj_type != RHINO_MM_BLK_OBJ_TYPE) {
return RHINO_KOBJ_TYPE_ERR;
}
RHINO_CRITICAL_ENTER();
if (pool->blk_avail > 0u) {
avail_blk = pool->avail_list;
*((uint8_t **)blk) = avail_blk;
/* the first 4 byte is the pointer for next block */
pool->avail_list = *(uint8_t **)(avail_blk);
pool->blk_avail--;
status = RHINO_SUCCESS;
} else {
*((uint8_t **)blk) = NULL;
status = RHINO_NO_MEM;
}
RHINO_CRITICAL_EXIT();
return status;
}
kstat_t krhino_mblk_free(mblk_pool_t *pool, void *blk)
{
CPSR_ALLOC();
NULL_PARA_CHK(pool);
NULL_PARA_CHK(blk);
if (pool->obj_type != RHINO_MM_BLK_OBJ_TYPE) {
return RHINO_KOBJ_TYPE_ERR;
}
RHINO_CRITICAL_ENTER();
/* use the first 4 byte of the free block point to head of avail list */
*((uint8_t **)blk) = pool->avail_list;
pool->avail_list = blk;
pool->blk_avail++;
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
#endif /* RHINO_CONFIG_MM_BLK */
#endif

View File

@@ -0,0 +1,480 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <k_api.h>
#ifndef MPOOL_ALLOC
#if (RHINO_CONFIG_MM_TLF > 0)
#include "k_mm.h"
#endif
#include "k_mm_debug.h"
#ifdef CONFIG_AOS_CLI
#include "aos/types.h"
#include "aos/cli.h"
extern int csp_printf(const char *fmt, ...);
#define print aos_cli_printf
#else
#define print printf
#endif
#if (RHINO_CONFIG_MM_DEBUG > 0)
extern klist_t g_mm_region_list_head;
#if (RHINO_CONFIG_MM_LEAKCHECK > 0)
static mm_scan_region_t g_mm_scan_region[AOS_MM_SCAN_REGION_MAX];
static void **g_leak_match;
static uint32_t g_recheck_flag = 0;
static uint32_t check_malloc_region(void *adress);
uint32_t if_adress_is_valid(void *adress);
uint32_t dump_mmleak(void);
uint32_t krhino_mm_leak_region_init(void *start, void *end)
{
static uint32_t i = 0;
if (i >= AOS_MM_SCAN_REGION_MAX) {
return i;
}
if ((start == NULL) || (end == NULL)) {
return i;
}
g_mm_scan_region[i].start = start;
g_mm_scan_region[i].end = end;
i++;
return i;
}
static uint32_t check_task_stack(ktask_t *task, void **p)
{
uint32_t offset = 0;
kstat_t rst = RHINO_SUCCESS;
void *start, *cur, *end;
start = task->task_stack_base;
end = task->task_stack_base + task->stack_size;
rst = krhino_task_stack_cur_free(task, &offset);
if (rst == RHINO_SUCCESS) {
cur = task->task_stack_base + task->stack_size - offset;
} else {
k_err_proc(RHINO_SYS_SP_ERR);
return 0;
}
if ((size_t)p >= (size_t)cur &&
(size_t)p < (size_t)end) {
return 1;
} else if ((size_t)p >= (size_t)start && (size_t)p < (size_t)cur) {
return 0;
}
/*maybe lost*/
return 1;
}
static uint32_t check_if_in_stack(void **p)
{
klist_t *taskhead = &g_kobj_list.task_head;
klist_t *taskend = taskhead;
klist_t *tmp;
ktask_t *task;
for (tmp = taskhead->next; tmp != taskend; tmp = tmp->next) {
task = krhino_list_entry(tmp, ktask_t, task_stats_item);
if (1 == check_task_stack(task, p)) {
return 1;
}
}
return 0;
}
uint32_t scan_region(void *start, void *end, void *adress)
{
void **p = (void **)((uint32_t)start & ~(sizeof(size_t) - 1));
while ((void *)p < end) {
if (NULL != p && adress == *p) {
g_leak_match = p;
return 1;
}
p++;
}
return 0;
}
uint32_t check_mm_leak(uint8_t *adress)
{
uint32_t rst = 0;
uint32_t i;
for (i = 0; i < AOS_MM_SCAN_REGION_MAX; i++) {
if ((NULL == g_mm_scan_region[i].start) || (NULL == g_mm_scan_region[i].end)) {
continue;
}
if (1 == scan_region(g_mm_scan_region[i].start, g_mm_scan_region[i].end,
adress)) {
return 1;
}
}
rst = check_malloc_region(adress);
if (1 == rst) {
return 1;
}
return 0;
}
static uint32_t recheck(void *start, void *end)
{
void **p = (void **)((uint32_t)start & ~(sizeof(size_t) - 1));
g_recheck_flag = 1;
while ((void *)p <= end) {
if (NULL != p && 1 == if_adress_is_valid(*p)) {
if ( 1 == check_mm_leak(*p)) {
g_recheck_flag = 0;
return 1;
}
}
p++;
}
g_recheck_flag = 0;
return 0;
}
#if (RHINO_CONFIG_MM_TLF > 0)
uint32_t check_malloc_region(void *adress)
{
uint32_t rst = 0;
k_mm_region_info_t *reginfo, *nextreg;
k_mm_list_t *next, *cur;
NULL_PARA_CHK(g_kmm_head);
reginfo = g_kmm_head->regioninfo;
while (reginfo) {
VGF(VALGRIND_MAKE_MEM_DEFINED(reginfo, sizeof(k_mm_region_info_t)));
cur = (k_mm_list_t *) ((char *) reginfo - MMLIST_HEAD_SIZE);
/*jump first blk*/
cur = NEXT_MM_BLK(cur->mbinfo.buffer, cur->size & RHINO_MM_BLKSIZE_MASK);
while (cur) {
VGF(VALGRIND_MAKE_MEM_DEFINED(cur, MMLIST_HEAD_SIZE));
if ((cur->size & RHINO_MM_BLKSIZE_MASK)) {
next = NEXT_MM_BLK(cur->mbinfo.buffer, cur->size & RHINO_MM_BLKSIZE_MASK);
if (0 == g_recheck_flag && !(cur->size & RHINO_MM_FREE)) {
if ((uint8_t *)krhino_cur_task_get()->task_stack_base >= cur->mbinfo.buffer
&& (uint8_t *)krhino_cur_task_get()->task_stack_base < (uint8_t *)next) {
cur = next;
continue;
}
rst = scan_region(cur->mbinfo.buffer, (void *) next, adress);
if (1 == rst) {
VGF(VALGRIND_MAKE_MEM_NOACCESS(cur, MMLIST_HEAD_SIZE));
VGF(VALGRIND_MAKE_MEM_NOACCESS(reginfo, sizeof(k_mm_region_info_t)));
return check_if_in_stack(g_leak_match);
}
}
} else {
next = NULL;
}
if (1 == g_recheck_flag &&
(uint32_t)adress >= (uint32_t)cur->mbinfo.buffer &&
(uint32_t)adress < (uint32_t)next) {
VGF(VALGRIND_MAKE_MEM_NOACCESS(cur, MMLIST_HEAD_SIZE));
VGF(VALGRIND_MAKE_MEM_NOACCESS(reginfo, sizeof(k_mm_region_info_t)));
return 1;
}
VGF(VALGRIND_MAKE_MEM_NOACCESS(cur, MMLIST_HEAD_SIZE));
cur = next;
}
nextreg = reginfo->next;
VGF(VALGRIND_MAKE_MEM_NOACCESS(reginfo, sizeof(k_mm_region_info_t)));
reginfo = nextreg;
}
return 0;
}
uint32_t if_adress_is_valid(void *adress)
{
k_mm_region_info_t *reginfo, *nextreg;
k_mm_list_t *next, *cur;
reginfo = g_kmm_head->regioninfo;
while (reginfo) {
VGF(VALGRIND_MAKE_MEM_DEFINED(reginfo, sizeof(k_mm_region_info_t)));
cur = (k_mm_list_t *) ((char *) reginfo - MMLIST_HEAD_SIZE);
/*jump first blk*/
cur = NEXT_MM_BLK(cur->mbinfo.buffer, cur->size & RHINO_MM_BLKSIZE_MASK);
while (cur) {
VGF(VALGRIND_MAKE_MEM_DEFINED(cur, MMLIST_HEAD_SIZE));
if ((cur->size & RHINO_MM_BLKSIZE_MASK)) {
next = NEXT_MM_BLK(cur->mbinfo.buffer, cur->size & RHINO_MM_BLKSIZE_MASK);
if (!(cur->size & RHINO_MM_FREE) &&
(size_t)adress >= (size_t)cur->mbinfo.buffer && (size_t)adress < (size_t)next ) {
VGF(VALGRIND_MAKE_MEM_NOACCESS(cur, MMLIST_HEAD_SIZE));
VGF(VALGRIND_MAKE_MEM_NOACCESS(reginfo, sizeof(k_mm_region_info_t)));
return 1;
}
} else {
next = NULL;
}
VGF(VALGRIND_MAKE_MEM_NOACCESS(cur, MMLIST_HEAD_SIZE));
cur = next;
}
nextreg = reginfo->next;
VGF(VALGRIND_MAKE_MEM_NOACCESS(reginfo, sizeof(k_mm_region_info_t)));
reginfo = nextreg;
}
return 0;
}
uint32_t dump_mmleak()
{
k_mm_region_info_t *reginfo, *nextreg;
k_mm_list_t *next, *cur;
#if (RHINO_CONFIG_MM_REGION_MUTEX == 1)
krhino_mutex_lock(&g_kmm_head->mm_mutex, RHINO_WAIT_FOREVER);
#endif
reginfo = g_kmm_head->regioninfo;
while (reginfo) {
VGF(VALGRIND_MAKE_MEM_DEFINED(reginfo, sizeof(k_mm_region_info_t)));
cur = (k_mm_list_t *) ((char *) reginfo - MMLIST_HEAD_SIZE);
/*jump first blk*/
cur = NEXT_MM_BLK(cur->mbinfo.buffer, cur->size & RHINO_MM_BLKSIZE_MASK);
while (cur) {
VGF(VALGRIND_MAKE_MEM_DEFINED(cur, MMLIST_HEAD_SIZE));
if ((cur->size & RHINO_MM_BLKSIZE_MASK)) {
next = NEXT_MM_BLK(cur->mbinfo.buffer, cur->size & RHINO_MM_BLKSIZE_MASK);
if (!(cur->size & RHINO_MM_FREE) &&
0 == check_mm_leak(cur->mbinfo.buffer)
&& 0 == recheck((void *)cur->mbinfo.buffer , (void *)next)) {
print("adress:0x%0x owner:0x%0x len:%-5d type:%s\r\n",
(void *)cur->mbinfo.buffer, cur->owner,
cur->size & RHINO_MM_BLKSIZE_MASK, "leak");
}
} else {
next = NULL;
}
VGF(VALGRIND_MAKE_MEM_NOACCESS(cur, MMLIST_HEAD_SIZE));
cur = next;
}
nextreg = reginfo->next;
VGF(VALGRIND_MAKE_MEM_NOACCESS(reginfo, sizeof(k_mm_region_info_t)));
reginfo = nextreg;
}
#if (RHINO_CONFIG_MM_REGION_MUTEX == 1)
krhino_mutex_unlock(&g_kmm_head->mm_mutex);
#endif
return 0;
}
#endif
#endif
#if (RHINO_CONFIG_MM_TLF > 0)
void print_block(k_mm_list_t *b)
{
if (!b) {
return;
}
print("%p ", b);
if (b->size & RHINO_MM_FREE) {
#if (RHINO_CONFIG_MM_DEBUG > 0u)
if (b->dye != RHINO_MM_FREE_DYE) {
print("!");
} else {
print(" ");
}
#endif
print("free ");
} else {
#if (RHINO_CONFIG_MM_DEBUG > 0u)
if (b->dye != RHINO_MM_CORRUPT_DYE) {
print("!");
} else {
print(" ");
}
#endif
print("used ");
}
if ((b->size & RHINO_MM_BLKSIZE_MASK)) {
print(" %6lu ", (unsigned long) (b->size & RHINO_MM_BLKSIZE_MASK));
} else {
print(" sentinel ");
}
#if (RHINO_CONFIG_MM_DEBUG > 0u)
print(" %8x ", b->dye);
print(" 0x%-8x ", b->owner);
#endif
if (b->size & RHINO_MM_PREVFREE) {
print("pre-free [%8p];", b->prev);
} else {
print("pre-used;");
}
if (b->size & RHINO_MM_FREE) {
VGF(VALGRIND_MAKE_MEM_DEFINED(&b->mbinfo, sizeof(struct free_ptr_struct)));
print(" free[%8p,%8p] ", b->mbinfo.free_ptr.prev, b->mbinfo.free_ptr.next);
VGF(VALGRIND_MAKE_MEM_NOACCESS(&b->mbinfo, sizeof(struct free_ptr_struct)));
}
print("\r\n");
}
void dump_kmm_free_map(k_mm_head *mmhead)
{
k_mm_list_t *next, *tmp;
int i, j;
if (!mmhead) {
return;
}
print("address, stat size dye caller pre-stat point\r\n");
print("FL bitmap: 0x%x\r\n", (unsigned) mmhead->fl_bitmap);
for (i = 0; i < FLT_SIZE; i++) {
if (mmhead->sl_bitmap[i]) {
print("SL bitmap 0x%x\r\n", (unsigned) mmhead->sl_bitmap[i]);
}
for (j = 0; j < SLT_SIZE; j++) {
next = mmhead->mm_tbl[i][j];
if (next) {
print("-> [%d][%d]\r\n", i, j);
}
while (next) {
VGF(VALGRIND_MAKE_MEM_DEFINED(next, MMLIST_HEAD_SIZE));
print_block(next);
VGF(VALGRIND_MAKE_MEM_DEFINED(&next->mbinfo, sizeof(struct free_ptr_struct)));
tmp = next->mbinfo.free_ptr.next;
VGF(VALGRIND_MAKE_MEM_NOACCESS(&next->mbinfo, sizeof(struct free_ptr_struct)));
VGF(VALGRIND_MAKE_MEM_NOACCESS(next, MMLIST_HEAD_SIZE));
next = tmp;
}
}
}
}
void dump_kmm_map(k_mm_head *mmhead)
{
k_mm_region_info_t *reginfo, *nextreg;
k_mm_list_t *next, *cur;
if (!mmhead) {
return;
}
print("ALL BLOCKS\r\n");
print("address, stat size dye caller pre-stat point\r\n");
reginfo = mmhead->regioninfo;
while (reginfo) {
VGF(VALGRIND_MAKE_MEM_DEFINED(reginfo, sizeof(k_mm_region_info_t)));
cur = (k_mm_list_t *) ((char *) reginfo - MMLIST_HEAD_SIZE);
while (cur) {
VGF(VALGRIND_MAKE_MEM_DEFINED(cur, MMLIST_HEAD_SIZE));
print_block(cur);
if ((cur->size & RHINO_MM_BLKSIZE_MASK)) {
next = NEXT_MM_BLK(cur->mbinfo.buffer, cur->size & RHINO_MM_BLKSIZE_MASK);
} else {
next = NULL;
}
VGF(VALGRIND_MAKE_MEM_NOACCESS(cur, MMLIST_HEAD_SIZE));
cur = next;
}
nextreg = reginfo->next;
VGF(VALGRIND_MAKE_MEM_NOACCESS(reginfo, sizeof(k_mm_region_info_t)));
reginfo = nextreg;
}
}
void dump_kmm_statistic_info(k_mm_head *mmhead)
{
int i = 0;
if (!mmhead) {
return;
}
#if (K_MM_STATISTIC > 0)
print(" free | used | maxused\r\n");
print(" %10d | %10d | %10d\r\n", mmhead->free_size, mmhead->used_size,
mmhead->maxused_size);
print("\r\n");
print("-----------------alloc size statistic:-----------------\r\n");
for (i = 0; i < MAX_MM_BIT - 1; i++) {
if (i % 4 == 0 && i != 0) {
print("\r\n");
}
print("[2^%02d] bytes: %5d |", (i + 2), mmhead->mm_size_stats[i]);
}
print("\r\n");
#endif
}
uint32_t dumpsys_mm_info_func(char *buf, uint32_t len)
{
#if (RHINO_CONFIG_MM_REGION_MUTEX == 1)
krhino_mutex_lock(&g_kmm_head->mm_mutex, RHINO_WAIT_FOREVER);
#endif
VGF(VALGRIND_MAKE_MEM_DEFINED(g_kmm_head, sizeof(k_mm_head)));
print("\r\n");
print("------------------------------- all memory blocks --------------------------------- \r\n");
print("g_kmm_head = %8x\r\n", (unsigned int)g_kmm_head);
dump_kmm_map(g_kmm_head);
print("\r\n");
print("----------------------------- all free memory blocks ------------------------------- \r\n");
dump_kmm_free_map(g_kmm_head);
print("\r\n");
print("------------------------- memory allocation statistic ------------------------------ \r\n");
dump_kmm_statistic_info(g_kmm_head);
VGF(VALGRIND_MAKE_MEM_NOACCESS(g_kmm_head, sizeof(k_mm_head)));
#if (RHINO_CONFIG_MM_REGION_MUTEX == 1)
krhino_mutex_unlock(&g_kmm_head->mm_mutex);
#endif
return RHINO_SUCCESS;
}
#endif
#endif
#endif

View File

@@ -0,0 +1,456 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#include "csi_core.h"
kstat_t mutex_create(kmutex_t *mutex, const name_t *name, uint8_t mm_alloc_flag)
{
CPSR_ALLOC();
NULL_PARA_CHK(mutex);
NULL_PARA_CHK(name);
/* init the list */
klist_init(&mutex->blk_obj.blk_list);
mutex->blk_obj.blk_policy = BLK_POLICY_PRI;
mutex->blk_obj.name = name;
mutex->mutex_task = NULL;
mutex->mutex_list = NULL;
mutex->mm_alloc_flag = mm_alloc_flag;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
RHINO_CRITICAL_ENTER();
klist_insert(&(g_kobj_list.mutex_head), &mutex->mutex_item);
RHINO_CRITICAL_EXIT();
#endif
mutex->blk_obj.obj_type = RHINO_MUTEX_OBJ_TYPE;
TRACE_MUTEX_CREATE(krhino_cur_task_get(), mutex, name);
return RHINO_SUCCESS;
}
kstat_t krhino_mutex_create(kmutex_t *mutex, const name_t *name)
{
return mutex_create(mutex, name, K_OBJ_STATIC_ALLOC);
}
static void mutex_release(ktask_t *task, kmutex_t *mutex_rel)
{
uint8_t new_pri;
/* find suitable task prio */
new_pri = mutex_pri_look(task, mutex_rel);
if (new_pri != task->prio) {
/* change prio */
task_pri_change(task, new_pri);
TRACE_MUTEX_RELEASE(g_active_task[cpu_cur_get()], task, new_pri);
}
}
kstat_t krhino_mutex_del(kmutex_t *mutex)
{
CPSR_ALLOC();
klist_t *blk_list_head;
if (mutex == NULL) {
return RHINO_NULL_PTR;
}
NULL_PARA_CHK(mutex);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (mutex->blk_obj.obj_type != RHINO_MUTEX_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (mutex->mm_alloc_flag != K_OBJ_STATIC_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
blk_list_head = &mutex->blk_obj.blk_list;
mutex->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
if (mutex->mutex_task != NULL) {
mutex_release(mutex->mutex_task, mutex);
}
/* all task blocked on this mutex is waken up */
while (!is_klist_empty(blk_list_head)) {
pend_task_rm(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&mutex->mutex_item);
#endif
TRACE_MUTEX_DEL(g_active_task[cpu_cur_get()], mutex);
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
kstat_t krhino_mutex_dyn_create(kmutex_t **mutex, const name_t *name)
{
kstat_t stat;
kmutex_t *mutex_obj;
if (mutex == NULL) {
return RHINO_NULL_PTR;
}
NULL_PARA_CHK(mutex);
mutex_obj = krhino_mm_alloc(sizeof(kmutex_t), __builtin_return_address(0));
if (mutex_obj == NULL) {
return RHINO_NO_MEM;
}
stat = mutex_create(mutex_obj, name, K_OBJ_DYN_ALLOC);
if (stat != RHINO_SUCCESS) {
krhino_mm_free(mutex_obj);
return stat;
}
*mutex = mutex_obj;
return stat;
}
kstat_t krhino_mutex_dyn_del(kmutex_t *mutex)
{
CPSR_ALLOC();
klist_t *blk_list_head;
if (mutex == NULL) {
return RHINO_NULL_PTR;
}
NULL_PARA_CHK(mutex);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (mutex->blk_obj.obj_type != RHINO_MUTEX_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (mutex->mm_alloc_flag != K_OBJ_DYN_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
blk_list_head = &mutex->blk_obj.blk_list;
mutex->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
if (mutex->mutex_task != NULL) {
mutex_release(mutex->mutex_task, mutex);
}
/* all task blocked on this mutex is waken up */
while (!is_klist_empty(blk_list_head)) {
pend_task_rm(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&mutex->mutex_item);
#endif
TRACE_MUTEX_DEL(g_active_task[cpu_cur_get()], mutex);
RHINO_CRITICAL_EXIT_SCHED();
krhino_mm_free(mutex);
return RHINO_SUCCESS;
}
#endif
uint8_t mutex_pri_limit(ktask_t *task, uint8_t pri)
{
kmutex_t *mutex_tmp;
uint8_t high_pri;
ktask_t *first_blk_task;
klist_t *blk_list_head;
high_pri = pri;
for (mutex_tmp = task->mutex_list; mutex_tmp != NULL;
mutex_tmp = mutex_tmp->mutex_list) {
blk_list_head = &mutex_tmp->blk_obj.blk_list;
if (!is_klist_empty(blk_list_head)) {
first_blk_task = krhino_list_entry(blk_list_head->next, ktask_t, task_list);
pri = first_blk_task->prio;
}
/* can not set lower prio than the highest prio in all mutexes which hold lock */
if (pri < high_pri) {
high_pri = pri;
}
}
return high_pri;
}
uint8_t mutex_pri_look(ktask_t *task, kmutex_t *mutex_rel)
{
kmutex_t *mutex_tmp;
kmutex_t **prev;
uint8_t new_pri;
uint8_t pri;
ktask_t *first_blk_task;
klist_t *blk_list_head;
/* the base prio of task */
new_pri = task->b_prio;
/* the highest prio in mutex which is locked */
pri = new_pri;
prev = &task->mutex_list;
while ((mutex_tmp = *prev) != NULL) {
if (mutex_tmp == mutex_rel) {
/* delete itself from list and make task->mutex_list point to next */
*prev = mutex_tmp->mutex_list;
continue;
}
blk_list_head = &mutex_tmp->blk_obj.blk_list;
if (!is_klist_empty(blk_list_head)) {
first_blk_task = krhino_list_entry(blk_list_head->next, ktask_t, task_list);
pri = first_blk_task->prio;
}
if (new_pri > pri) {
new_pri = pri;
}
prev = &mutex_tmp->mutex_list;
}
return new_pri;
}
void mutex_task_pri_reset(ktask_t *task)
{
kmutex_t *mutex_tmp;
ktask_t *mutex_task;
if (task->blk_obj->obj_type == RHINO_MUTEX_OBJ_TYPE) {
mutex_tmp = (kmutex_t *)(task->blk_obj);
mutex_task = mutex_tmp->mutex_task;
/* the new highest prio task blocked on this mutex may decrease prio than before so reset the mutex task prio */
if (mutex_task->prio == task->prio) {
mutex_release(mutex_task, NULL);
}
}
}
#ifdef MUTEX_LOCKERR_MAX
extern uint32_t mutex_lockerr_list[MUTEX_LOCKERR_MAX];
extern uint32_t mutex_lockerr_cnt;
void krhino_mutex_lockerr(uint32_t lr)
{
int i = 0;
for(i=0; i<mutex_lockerr_cnt; i++){
if(mutex_lockerr_list[i] == lr){
return;
}
}
mutex_lockerr_list[mutex_lockerr_cnt++] = lr;
}
#endif
kstat_t krhino_mutex_lock(kmutex_t *mutex, tick_t ticks, uint32_t lr)
{
CPSR_ALLOC();
kstat_t ret;
ktask_t *mutex_task;
uint8_t cur_cpu_num;
NULL_PARA_CHK(mutex);
if (g_sys_stat == RHINO_STOPPED) {
return RHINO_SUCCESS;
}
krhino_check_fatal_call(__FUNCTION__);
RHINO_CRITICAL_ENTER();
#ifdef MUTEX_LOCKERR_MAX
if(mutex_lockerr_cnt < MUTEX_LOCKERR_MAX && (__in_disable_irq(psr) || __in_interrupt())){
krhino_mutex_lockerr(mutex, lr);
}
#endif
INTRPT_NESTED_LEVEL_CHK();
if (mutex->blk_obj.obj_type != RHINO_MUTEX_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
cur_cpu_num = cpu_cur_get();
/* if the same task get the same mutex again, it causes mutex owner nested */
if (g_active_task[cur_cpu_num] == mutex->mutex_task) {
if (mutex->owner_nested == (mutex_nested_t)-1) {
/* fatal error here, system must be stoped here */
k_err_proc(RHINO_MUTEX_NESTED_OVF);
RHINO_CRITICAL_EXIT();
return RHINO_MUTEX_NESTED_OVF;
} else {
mutex->owner_nested++;
}
RHINO_CRITICAL_EXIT();
return RHINO_MUTEX_OWNER_NESTED;
}
mutex_task = mutex->mutex_task;
if (mutex_task == NULL) {
/* get lock */
mutex->mutex_task = g_active_task[cur_cpu_num];
mutex->mutex_list = g_active_task[cur_cpu_num]->mutex_list;
g_active_task[cur_cpu_num]->mutex_list = mutex;
mutex->owner_nested = 1u;
TRACE_MUTEX_GET(g_active_task[cur_cpu_num], mutex, ticks);
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
/* can't get mutex, and return immediately if wait_option is RHINO_NO_WAIT */
if (ticks == RHINO_NO_WAIT) {
RHINO_CRITICAL_EXIT();
return RHINO_NO_PEND_WAIT;
}
/* system is locked so task can not be blocked just return immediately */
if (g_sched_lock[cur_cpu_num] > 0u) {
RHINO_CRITICAL_EXIT();
return RHINO_SCHED_DISABLE;
}
/* if current task is a higher prio task and block on the mutex
prio inverse condition happened, prio inherit method is used here */
if (g_active_task[cur_cpu_num]->prio < mutex_task->prio) {
task_pri_change(mutex_task, g_active_task[cur_cpu_num]->prio);
TRACE_TASK_PRI_INV(g_active_task[cur_cpu_num], mutex_task);
}
/* any way block the current task */
pend_to_blk_obj((blk_obj_t *)mutex, g_active_task[cur_cpu_num], ticks, psr);
TRACE_MUTEX_GET_BLK(g_active_task[cur_cpu_num], mutex, ticks);
RHINO_CRITICAL_EXIT_SCHED();
RHINO_CPU_INTRPT_DISABLE();
/* so the task is waked up, need know which reason cause wake up */
ret = pend_state_end_proc(g_active_task[cpu_cur_get()]);
RHINO_CPU_INTRPT_ENABLE();
return ret;
}
kstat_t krhino_mutex_unlock(kmutex_t *mutex)
{
CPSR_ALLOC();
klist_t *blk_list_head;
ktask_t *task;
uint8_t cur_cpu_num;
NULL_PARA_CHK(mutex);
if (g_sys_stat == RHINO_STOPPED) {
return RHINO_SUCCESS;
}
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (mutex->blk_obj.obj_type != RHINO_MUTEX_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
cur_cpu_num = cpu_cur_get();
/* mutex must be released by itself */
if (g_active_task[cur_cpu_num] != mutex->mutex_task) {
RHINO_CRITICAL_EXIT();
return RHINO_MUTEX_NOT_RELEASED_BY_OWNER;
}
mutex->owner_nested--;
if (mutex->owner_nested > 0u) {
RHINO_CRITICAL_EXIT();
return RHINO_MUTEX_OWNER_NESTED;
}
mutex_release(g_active_task[cur_cpu_num], mutex);
blk_list_head = &mutex->blk_obj.blk_list;
/* if no block task on this list just return */
if (is_klist_empty(blk_list_head)) {
/* No wait task */
mutex->mutex_task = NULL;
TRACE_MUTEX_RELEASE_SUCCESS(g_active_task[cur_cpu_num], mutex);
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
/* there must have task blocked on this mutex object */
task = krhino_list_entry(blk_list_head->next, ktask_t, task_list);
/* wake up the occupy task, which is the highst prio task on the list */
pend_task_wakeup(task);
TRACE_MUTEX_TASK_WAKE(g_active_task[cur_cpu_num], task, mutex);
/* change mutex get task */
mutex->mutex_task = task;
mutex->mutex_list = task->mutex_list;
task->mutex_list = mutex;
mutex->owner_nested = 1u;
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
__bobj uint64_t g_sys_tick_count;
__bobj uint32_t g_cpuloading;
__bobj uint32_t g_cpuloading_int;
__bobj volatile uint64_t g_sys_time_last;
__bobj kstat_t g_sys_stat;
__bobj uint8_t g_idle_task_spawned[RHINO_CONFIG_CPU_NUM];
__bobj runqueue_t g_ready_queue;
/* schedule lock counter */
__bobj uint8_t g_sched_lock[RHINO_CONFIG_CPU_NUM];
__bobj uint8_t g_intrpt_nested_level[RHINO_CONFIG_CPU_NUM];
/* highest pri task in ready queue */
__bobj ktask_t *g_preferred_ready_task[RHINO_CONFIG_CPU_NUM];
/* current active task */
__bobj ktask_t *g_active_task[RHINO_CONFIG_CPU_NUM];
/* idle task attribute */
__bobj ktask_t g_idle_task[RHINO_CONFIG_CPU_NUM];
__bobj idle_count_t g_idle_count[RHINO_CONFIG_CPU_NUM];
__bobj cpu_stack_t g_idle_task_stack[RHINO_CONFIG_CPU_NUM][RHINO_CONFIG_IDLE_TASK_STACK_SIZE];
/* tick attribute */
__bobj tick_t g_tick_count;
__bobj klist_t g_tick_head;
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
__bobj kobj_list_t g_kobj_list;
#endif
#if (RHINO_CONFIG_TIMER > 0)
__bobj klist_t g_timer_head;
__bobj sys_time_t g_timer_count;
__bobj ktask_t g_timer_task;
__bobj cpu_stack_t g_timer_task_stack[RHINO_CONFIG_TIMER_TASK_STACK_SIZE];
__bobj kbuf_queue_t g_timer_queue;
__bobj k_timer_queue_cb timer_queue_cb[RHINO_CONFIG_TIMER_MSG_NUM];
#endif
#if (RHINO_CONFIG_ISR_TASK > 0)
__bobj ktask_t g_isr_task;
__bobj ksem_t g_isr_sem;
__bobj uint32_t g_isr_buff[4+2*RHINO_CONFIG_ISR_BUFF_SIZE];
__bobj cpu_stack_t g_isr_task_stack[RHINO_CONFIG_ISR_TASK_STACK_SIZE];
#endif
#if (RHINO_CONFIG_DISABLE_SCHED_STATS > 0)
__bobj hr_timer_t g_sched_disable_time_start;
__bobj hr_timer_t g_sched_disable_max_time;
__bobj hr_timer_t g_cur_sched_disable_max_time;
#endif
#if (RHINO_CONFIG_DISABLE_INTRPT_STATS > 0)
__bobj uint16_t g_intrpt_disable_times;
__bobj hr_timer_t g_intrpt_disable_time_start;
__bobj hr_timer_t g_intrpt_disable_max_time;
__bobj hr_timer_t g_cur_intrpt_disable_max_time;
#endif
#if (RHINO_CONFIG_HW_COUNT > 0)
__bobj hr_timer_t g_sys_measure_waste;
#endif
#if (RHINO_CONFIG_CPU_USAGE_STATS > 0)
__bobj ktask_t g_cpu_usage_task;
__bobj cpu_stack_t g_cpu_task_stack[RHINO_CONFIG_CPU_USAGE_TASK_STACK];
__bobj idle_count_t g_idle_count_max;
__bobj uint32_t g_cpu_usage;
#endif
#if (RHINO_CONFIG_TASK_SCHED_STATS > 0)
__bobj ctx_switch_t g_sys_ctx_switch_times;
#endif
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
__bobj ksem_t g_res_sem;
__bobj klist_t g_res_list;
__bobj ktask_t g_dyn_task;
__bobj cpu_stack_t g_dyn_task_stack[RHINO_CONFIG_K_DYN_TASK_STACK];
#endif
#if (RHINO_CONFIG_WORKQUEUE > 0)
__bobj klist_t g_workqueue_list_head;
__bobj kmutex_t g_workqueue_mutex;
__bobj kworkqueue_t g_workqueue_default;
__bobj cpu_stack_t g_workqueue_stack[RHINO_CONFIG_WORKQUEUE_STACK_SIZE];
#endif
#if (RHINO_CONFIG_MM_TLF > 0)
//k_mm_head *g_kmm_head;
#endif
__bobj kspinlock_t g_sys_lock;
__bobj uint8_t g_in_interrupt;

View File

@@ -0,0 +1,140 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#include "csi_core.h"
RHINO_INLINE void pend_list_add(klist_t *head, ktask_t *task)
{
klist_t *tmp;
klist_t *list_start = head;
klist_t *list_end = head;
for (tmp = list_start->next; tmp != list_end; tmp = tmp->next) {
if (krhino_list_entry(tmp, ktask_t, task_list)->prio > task->prio) {
break;
}
}
klist_insert(tmp, &task->task_list);
}
void pend_task_wakeup(ktask_t *task)
{
/* wake up task depend on the different state of task */
switch (task->task_state) {
case K_PEND:
/* remove task on the block list because task is waken up */
klist_rm(&task->task_list);
/* add to the ready list again */
ready_list_add(&g_ready_queue, task);
task->task_state = K_RDY;
break;
case K_PEND_SUSPENDED:
/* remove task on the block list because task is waken up */
klist_rm(&task->task_list);
task->task_state = K_SUSPENDED;
break;
default:
k_err_proc(RHINO_SYS_FATAL_ERR);
break;
}
/* remove task on the tick list because task is waken up */
tick_list_rm(task);
task->blk_state = BLK_FINISH;
task->blk_obj = NULL;
}
void pend_to_blk_obj(blk_obj_t *blk_obj, ktask_t *task, tick_t timeout, uint32_t psr)
{
if(__in_disable_irq(psr) || __in_interrupt()){
assert_internal(__FUNCTION__, __LINE__, "SYS IRQ DISABLED",__builtin_return_address(0));
}
/* task need to remember which object is blocked on */
task->blk_obj = blk_obj;
if (timeout != RHINO_WAIT_FOREVER) {
tick_list_insert(task, timeout);
}
task->task_state = K_PEND;
/* remove from the ready list */
ready_list_rm(&g_ready_queue, task);
if (blk_obj->blk_policy == BLK_POLICY_FIFO) {
/* add to the end of blocked objet list */
klist_insert(&blk_obj->blk_list, &task->task_list);
} else {
/* add to the prio sorted block list */
pend_list_add(&blk_obj->blk_list, task);
}
}
void pend_task_rm(ktask_t *task)
{
switch (task->task_state) {
case K_PEND:
/* remove task on the block list because task is waken up */
klist_rm(&task->task_list);
/*add to the ready list again*/
ready_list_add(&g_ready_queue, task);
task->task_state = K_RDY;
break;
case K_PEND_SUSPENDED:
/* remove task on the block list because task is waken up */
klist_rm(&task->task_list);
task->task_state = K_SUSPENDED;
break;
default:
k_err_proc(RHINO_SYS_FATAL_ERR);
break;
}
/* remove task on the tick list because task is waken up */
tick_list_rm(task);
task->blk_state = BLK_DEL;
/* task is nothing blocked on so reset it to NULL */
task->blk_obj = NULL;
}
void pend_list_reorder(ktask_t *task)
{
if (task->blk_obj->blk_policy == BLK_POLICY_PRI) {
/* remove it first and add it again in prio sorted list */
klist_rm(&task->task_list);
pend_list_add(&task->blk_obj->blk_list, task);
}
}
kstat_t pend_state_end_proc(ktask_t *task)
{
kstat_t status;
switch (task->blk_state) {
case BLK_FINISH:
status = RHINO_SUCCESS;
break;
case BLK_ABORT:
status = RHINO_BLK_ABORT;
break;
case BLK_TIMEOUT:
status = RHINO_BLK_TIMEOUT;
break;
case BLK_DEL:
status = RHINO_BLK_DEL;
break;
default:
k_err_proc(RHINO_BLK_INV_STATE);
status = RHINO_BLK_INV_STATE;
break;
}
return status;
}

View File

@@ -0,0 +1,410 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#if (RHINO_CONFIG_QUEUE > 0)
RHINO_INLINE void task_msg_recv(ktask_t *task, void *msg)
{
task->msg = msg;
pend_task_wakeup(task);
}
static kstat_t queue_create(kqueue_t *queue, const name_t *name, void **start,
size_t msg_num, uint8_t mm_alloc_flag)
{
CPSR_ALLOC();
NULL_PARA_CHK(queue);
NULL_PARA_CHK(start);
NULL_PARA_CHK(name);
if (msg_num == 0u) {
return RHINO_INV_PARAM;
}
/* init the queue blocked list */
klist_init(&queue->blk_obj.blk_list);
queue->blk_obj.name = name;
queue->blk_obj.blk_policy = BLK_POLICY_PRI;
queue->msg_q.queue_start = start;
ringbuf_init(&queue->ringbuf, (void *)start, msg_num * sizeof(void *),
RINGBUF_TYPE_FIX, sizeof(void *));
queue->msg_q.size = msg_num;
queue->msg_q.cur_num = 0u;
queue->msg_q.peak_num = 0u;
queue->mm_alloc_flag = mm_alloc_flag;
RHINO_CRITICAL_ENTER();
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_insert(&(g_kobj_list.queue_head), &queue->queue_item);
#endif
RHINO_CRITICAL_EXIT();
queue->blk_obj.obj_type = RHINO_QUEUE_OBJ_TYPE;
return RHINO_SUCCESS;
}
kstat_t krhino_queue_create(kqueue_t *queue, const name_t *name, void **start,
size_t msg_num)
{
return queue_create(queue, name, start, msg_num, K_OBJ_STATIC_ALLOC);
}
kstat_t krhino_queue_del(kqueue_t *queue)
{
CPSR_ALLOC();
klist_t *blk_list_head;
NULL_PARA_CHK(queue);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (queue->mm_alloc_flag != K_OBJ_STATIC_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
blk_list_head = &queue->blk_obj.blk_list;
queue->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
/* all task blocked on this queue is waken up */
while (!is_klist_empty(blk_list_head)) {
pend_task_rm(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&queue->queue_item);
#endif
ringbuf_reset(&queue->ringbuf);
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
kstat_t krhino_queue_dyn_create(kqueue_t **queue, const name_t *name,
size_t msg_num)
{
kstat_t stat;
kqueue_t *queue_obj;
void *msg_start;
NULL_PARA_CHK(queue);
queue_obj = krhino_mm_alloc(sizeof(kqueue_t), __builtin_return_address(0));
if (queue_obj == NULL) {
return RHINO_NO_MEM;
}
msg_start = krhino_mm_alloc(msg_num * sizeof(void *), __builtin_return_address(0));
if (msg_start == NULL) {
krhino_mm_free(queue_obj);
return RHINO_NO_MEM;
}
stat = queue_create(queue_obj, name, (void **)msg_start, msg_num,
K_OBJ_DYN_ALLOC);
if (stat != RHINO_SUCCESS) {
krhino_mm_free(msg_start);
krhino_mm_free(queue_obj);
return stat;
}
*queue = queue_obj;
return stat;
}
kstat_t krhino_queue_dyn_del(kqueue_t *queue)
{
CPSR_ALLOC();
klist_t *blk_list_head;
NULL_PARA_CHK(queue);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (queue->mm_alloc_flag != K_OBJ_DYN_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
blk_list_head = &queue->blk_obj.blk_list;
queue->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
/* all task blocked on this queue is waken up */
while (!is_klist_empty(blk_list_head)) {
pend_task_rm(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&queue->queue_item);
#endif
ringbuf_reset(&queue->ringbuf);
RHINO_CRITICAL_EXIT_SCHED();
krhino_mm_free(queue->msg_q.queue_start);
krhino_mm_free(queue);
return RHINO_SUCCESS;
}
#endif
static kstat_t msg_send(kqueue_t *p_q, void *p_void, uint8_t opt_wake_all)
{
CPSR_ALLOC();
klist_t *blk_list_head;
NULL_PARA_CHK(p_q);
/* this is only needed when system zero interrupt feature is enabled */
#if (RHINO_CONFIG_INTRPT_GUARD > 0)
soc_intrpt_guard();
#endif
RHINO_CRITICAL_ENTER();
if (p_q->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (p_q->msg_q.cur_num >= p_q->msg_q.size) {
RHINO_CRITICAL_EXIT();
return RHINO_QUEUE_FULL;
}
blk_list_head = &p_q->blk_obj.blk_list;
/* queue is not full here, if there is no blocked receive task */
if (is_klist_empty(blk_list_head)) {
p_q->msg_q.cur_num++;
/* update peak_num for debug */
if (p_q->msg_q.cur_num > p_q->msg_q.peak_num) {
p_q->msg_q.peak_num = p_q->msg_q.cur_num;
}
ringbuf_push(&p_q->ringbuf, &p_void, sizeof(void *));
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
/* wake all the task blocked on this queue */
if (opt_wake_all) {
while (!is_klist_empty(blk_list_head)) {
task_msg_recv(krhino_list_entry(blk_list_head->next, ktask_t, task_list),
p_void);
}
} else {
task_msg_recv(krhino_list_entry(blk_list_head->next, ktask_t, task_list),
p_void);
}
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
kstat_t krhino_queue_back_send(kqueue_t *queue, void *msg)
{
return msg_send(queue, msg, WAKE_ONE_TASK);
}
kstat_t krhino_queue_all_send(kqueue_t *queue, void *msg)
{
return msg_send(queue, msg, WAKE_ALL_TASK);
}
kstat_t krhino_queue_recv(kqueue_t *queue, tick_t ticks, void **msg)
{
CPSR_ALLOC();
kstat_t ret;
uint8_t cur_cpu_num;
NULL_PARA_CHK(queue);
NULL_PARA_CHK(msg);
krhino_check_fatal_call(__FUNCTION__);
RHINO_CRITICAL_ENTER();
cur_cpu_num = cpu_cur_get();
if ((g_intrpt_nested_level[cur_cpu_num] > 0u) && (ticks != RHINO_NO_WAIT)) {
RHINO_CRITICAL_EXIT();
return RHINO_NOT_CALLED_BY_INTRPT;
}
if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
/* if queue has msgs, just receive it */
if (queue->msg_q.cur_num > 0u) {
ringbuf_pop(&queue->ringbuf, msg, NULL);
queue->msg_q.cur_num--;
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
if (ticks == RHINO_NO_WAIT) {
*msg = NULL;
RHINO_CRITICAL_EXIT();
return RHINO_NO_PEND_WAIT;
}
/* if system is locked, block operation is not allowed */
if (g_sched_lock[cur_cpu_num] > 0u) {
*msg = NULL;
RHINO_CRITICAL_EXIT();
return RHINO_SCHED_DISABLE;
}
pend_to_blk_obj((blk_obj_t *)queue, g_active_task[cur_cpu_num], ticks, psr);
RHINO_CRITICAL_EXIT_SCHED();
RHINO_CPU_INTRPT_DISABLE();
cur_cpu_num = cpu_cur_get();
ret = pend_state_end_proc(g_active_task[cur_cpu_num]);
switch (ret) {
case RHINO_SUCCESS:
*msg = g_active_task[cur_cpu_num]->msg;
break;
default:
*msg = NULL;
break;
}
RHINO_CPU_INTRPT_ENABLE();
return ret;
}
kstat_t krhino_queue_is_full(kqueue_t *queue)
{
CPSR_ALLOC();
kstat_t ret;
NULL_PARA_CHK(queue);
RHINO_CRITICAL_ENTER();
if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (queue->msg_q.cur_num >= queue->msg_q.size) {
ret = RHINO_QUEUE_FULL;
} else {
ret = RHINO_QUEUE_NOT_FULL;
}
RHINO_CRITICAL_EXIT();
return ret;
}
kstat_t krhino_queue_flush(kqueue_t *queue)
{
CPSR_ALLOC();
NULL_PARA_CHK(queue);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
queue->msg_q.cur_num = 0u;
ringbuf_reset(&queue->ringbuf);
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
kstat_t krhino_queue_info_get(kqueue_t *queue, msg_info_t *info)
{
CPSR_ALLOC();
klist_t *blk_list_head;
if (queue == NULL) {
return RHINO_NULL_PTR;
}
if (info == NULL) {
return RHINO_NULL_PTR;
}
NULL_PARA_CHK(queue);
NULL_PARA_CHK(info);
RHINO_CPU_INTRPT_DISABLE();
if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
RHINO_CPU_INTRPT_ENABLE();
return RHINO_KOBJ_TYPE_ERR;
}
blk_list_head = &queue->blk_obj.blk_list;
info->msg_q.peak_num = queue->msg_q.peak_num;
info->msg_q.cur_num = queue->msg_q.cur_num;
info->msg_q.queue_start = queue->msg_q.queue_start;
info->msg_q.size = queue->msg_q.size;
info->pend_entry = blk_list_head->next;
RHINO_CPU_INTRPT_ENABLE();
return RHINO_SUCCESS;
}
#endif

View File

@@ -0,0 +1,367 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
kstat_t ringbuf_init(k_ringbuf_t *p_ringbuf, void *buf, size_t len, size_t type,
size_t block_size)
{
p_ringbuf->type = type;
p_ringbuf->buf = buf;
p_ringbuf->end = (uint8_t *)buf + len;
p_ringbuf->blk_size = block_size;
ringbuf_reset(p_ringbuf);
return RHINO_SUCCESS;
}
static size_t ringbuf_headlen_compress(size_t head_len, uint8_t *cmp_buf)
{
size_t len_bytes = 0;
uint8_t *p_len = NULL;
uint32_t be_len = 0;
be_len = krhino_ntohl(head_len);
p_len = (uint8_t *)&be_len;
len_bytes = COMPRESS_LEN(head_len);
if (len_bytes == 1) {
cmp_buf[0] = RINGBUF_LEN_1BYTE_MAXVALUE & p_len[3];
} else if (len_bytes == 2) {
cmp_buf[0] = RINGBUF_LEN_VLE_2BYTES | p_len[2];
cmp_buf[1] = p_len[3];
} else if (len_bytes == 3) {
cmp_buf[0] = RINGBUF_LEN_VLE_3BYTES | p_len[1];
cmp_buf[1] = p_len[2];
cmp_buf[2] = p_len[3];
}
return len_bytes;
}
static size_t ringbuf_headlen_decompress(size_t buf_len, uint8_t *cmp_buf)
{
size_t data_len = 0;
uint32_t be_len = 0;
uint8_t *len_buf = (uint8_t *)&be_len;
memcpy(&len_buf[sizeof(uint32_t) - buf_len], cmp_buf, buf_len);
if (buf_len > 1) {
len_buf[sizeof(uint32_t) - buf_len] &= RINGBUF_LEN_MASK_CLEAN_TWOBIT;
}
data_len = krhino_ntohl(be_len);
return data_len;
}
kstat_t ringbuf_push(k_ringbuf_t *p_ringbuf, void *data, size_t len)
{
size_t len_bytes = 0;
size_t split_len = 0;
uint8_t c_len[RINGBUF_LEN_MAX_SIZE] = {0};
if (ringbuf_is_full(p_ringbuf)) {
return RHINO_RINGBUF_FULL;
}
if (p_ringbuf->type == RINGBUF_TYPE_FIX) {
if (p_ringbuf->tail == p_ringbuf->end) {
p_ringbuf->tail = p_ringbuf->buf;
}
memcpy(p_ringbuf->tail, data, p_ringbuf->blk_size);
p_ringbuf->tail += p_ringbuf->blk_size;
p_ringbuf->freesize -= p_ringbuf->blk_size;
} else {
len_bytes = ringbuf_headlen_compress(len, c_len);
if (len_bytes == 0 || len_bytes > RINGBUF_LEN_MAX_SIZE ) {
return RHINO_INV_PARAM;
}
/* for dynamic length ringbuf */
if (p_ringbuf->freesize < len_bytes + len ) {
return RHINO_RINGBUF_FULL;
}
if (p_ringbuf->tail == p_ringbuf->end) {
p_ringbuf->tail = p_ringbuf->buf;
}
/* copy length data to buffer */
if (p_ringbuf->tail >= p_ringbuf->head &&
(split_len = p_ringbuf->end - p_ringbuf->tail) < len_bytes && split_len > 0) {
memcpy(p_ringbuf->tail, &c_len[0], split_len);
len_bytes -= split_len;
p_ringbuf->tail = p_ringbuf->buf;
p_ringbuf->freesize -= split_len;
} else {
split_len = 0;
}
if (len_bytes > 0) {
memcpy(p_ringbuf->tail, &c_len[split_len], len_bytes);
p_ringbuf->freesize -= len_bytes;
p_ringbuf->tail += len_bytes;
}
/* copy data to ringbuf, if break by buffer end, split data and copy to buffer head*/
split_len = 0;
if (p_ringbuf->tail == p_ringbuf->end) {
p_ringbuf->tail = p_ringbuf->buf;
}
if (p_ringbuf->tail >= p_ringbuf->head &&
((split_len = p_ringbuf->end - p_ringbuf->tail) < len) &&
split_len > 0) {
memcpy(p_ringbuf->tail, data, split_len);
data = (uint8_t *)data + split_len;
len -= split_len;
p_ringbuf->tail = p_ringbuf->buf;
p_ringbuf->freesize -= split_len;
}
memcpy(p_ringbuf->tail, data, len);
p_ringbuf->tail += len;
p_ringbuf->freesize -= len;
}
return RHINO_SUCCESS;
}
kstat_t ringbuf_pop(k_ringbuf_t *p_ringbuf, void *pdata, size_t *plen)
{
size_t split_len = 0;
uint8_t *data = pdata;
size_t len = 0;
uint8_t c_len[RINGBUF_LEN_MAX_SIZE] = {0};
size_t len_bytes = 0;
if (ringbuf_is_empty(p_ringbuf)) {
return RHINO_RINGBUF_EMPTY;
}
if (p_ringbuf->type == RINGBUF_TYPE_FIX) {
if (p_ringbuf->head == p_ringbuf->end) {
p_ringbuf->head = p_ringbuf->buf;
}
memcpy(pdata, p_ringbuf->head, p_ringbuf->blk_size);
p_ringbuf->head += p_ringbuf->blk_size;
p_ringbuf->freesize += p_ringbuf->blk_size;
if (plen != NULL) {
*plen = p_ringbuf->blk_size;
}
return RHINO_SUCCESS;
} else {
if (p_ringbuf->head == p_ringbuf->end) {
p_ringbuf->head = p_ringbuf->buf;
}
/*decode length */
if ((*p_ringbuf->head & RINGBUF_LEN_MASK_ONEBIT) == 0 ) {
/*length use one byte*/
len_bytes = 1;
} else if ((*p_ringbuf->head & RINGBUF_LEN_MASK_TWOBIT) ==
RINGBUF_LEN_VLE_2BYTES) {
/*length use 2 bytes*/
len_bytes = 2;
} else if ((*p_ringbuf->head & RINGBUF_LEN_MASK_TWOBIT) ==
RINGBUF_LEN_VLE_3BYTES) {
/*length use 3 bytes*/
len_bytes = 3;
} else {
return RHINO_INV_PARAM;
}
if (((split_len = p_ringbuf->end - p_ringbuf->head) < len_bytes) &&
split_len > 0) {
memcpy(&c_len[0], p_ringbuf->head, split_len);
p_ringbuf->head = p_ringbuf->buf;
p_ringbuf->freesize += split_len;
} else {
split_len = 0;
}
if (len_bytes - split_len > 0) {
memcpy(&c_len[split_len], p_ringbuf->head, (len_bytes - split_len));
p_ringbuf->head += (len_bytes - split_len);
p_ringbuf->freesize += (len_bytes - split_len);
}
*plen = len = ringbuf_headlen_decompress(len_bytes, c_len);
if (p_ringbuf->head == p_ringbuf->end) {
p_ringbuf->head = p_ringbuf->buf;
}
if (p_ringbuf->head > p_ringbuf->tail &&
(split_len = p_ringbuf->end - p_ringbuf->head) < len) {
memcpy(pdata, p_ringbuf->head, split_len);
data = (uint8_t *)pdata + split_len;
len -= split_len;
p_ringbuf->head = p_ringbuf->buf;
p_ringbuf->freesize += split_len;
}
memcpy(data, p_ringbuf->head, len);
p_ringbuf->head += len;
p_ringbuf->freesize += len;
return RHINO_SUCCESS;
}
}
uint8_t ringbuf_is_full(k_ringbuf_t *p_ringbuf)
{
if (p_ringbuf->type == RINGBUF_TYPE_DYN && p_ringbuf->freesize < 2) {
return 1;
}
if (p_ringbuf->type == RINGBUF_TYPE_FIX &&
p_ringbuf->freesize < p_ringbuf->blk_size) {
return 1;
}
return false;
}
uint8_t ringbuf_is_empty(k_ringbuf_t *p_ringbuf)
{
if (p_ringbuf->freesize == (size_t)(p_ringbuf->end - p_ringbuf->buf)) {
return true;
}
return false;
}
/*external api*/
kstat_t ringbuf_reset(k_ringbuf_t *p_ringbuf)
{
p_ringbuf->head = p_ringbuf->buf;
p_ringbuf->tail = p_ringbuf->buf;
p_ringbuf->freesize = p_ringbuf->end - p_ringbuf->buf;
return RHINO_SUCCESS;
}
#if (RHINO_CONFIG_RINGBUF_VENDOR > 0)
kstat_t krhino_ringbuf_reset(k_ringbuf_t *p_ringbuf)
{
CPSR_ALLOC();
kstat_t err;
NULL_PARA_CHK(p_ringbuf);
RHINO_CRITICAL_ENTER();
err = ringbuf_reset(p_ringbuf);
RHINO_CRITICAL_EXIT();
return err;
}
kstat_t krhino_ringbuf_init(k_ringbuf_t *p_ringbuf, void *buf, size_t len,
size_t type, size_t block_size)
{
CPSR_ALLOC();
kstat_t err;
NULL_PARA_CHK(p_ringbuf);
NULL_PARA_CHK(buf);
if (len == 0 || (type != RINGBUF_TYPE_DYN && type != RINGBUF_TYPE_FIX)) {
return RHINO_INV_PARAM;
}
if (type == RINGBUF_TYPE_FIX) {
if (len == 0 || block_size == 0 || len % block_size) {
return RHINO_INV_PARAM;
}
}
RHINO_CRITICAL_ENTER();
err = ringbuf_init(p_ringbuf, buf, len, type, block_size);
RHINO_CRITICAL_EXIT();
return err;
}
kstat_t krhino_ringbuf_push(k_ringbuf_t *p_ringbuf, void *data, size_t len)
{
CPSR_ALLOC();
kstat_t err;
NULL_PARA_CHK(p_ringbuf);
NULL_PARA_CHK(data);
if (len <= 0 || len > RINGBUF_LEN_3BYTES_MAXVALUE ||
(p_ringbuf->type == RINGBUF_TYPE_FIX && len != p_ringbuf->blk_size) ) {
return RHINO_INV_PARAM;
}
RHINO_CRITICAL_ENTER();
err = ringbuf_push(p_ringbuf, data, len);
RHINO_CRITICAL_EXIT();
return err;
}
kstat_t krhino_ringbuf_pop(k_ringbuf_t *p_ringbuf, void *pdata, size_t *plen)
{
CPSR_ALLOC();
kstat_t err;
NULL_PARA_CHK(p_ringbuf);
NULL_PARA_CHK(pdata);
if (p_ringbuf->type == RINGBUF_TYPE_DYN && plen == NULL) {
return RHINO_INV_PARAM;
}
RHINO_CRITICAL_ENTER();
err = ringbuf_pop(p_ringbuf, pdata, plen);
RHINO_CRITICAL_EXIT();
return err;
}
uint8_t krhino_ringbuf_is_empty(k_ringbuf_t *p_ringbuf)
{
CPSR_ALLOC();
uint8_t empty;
NULL_PARA_CHK(p_ringbuf);
RHINO_CRITICAL_ENTER();
empty = ringbuf_is_empty(p_ringbuf);
RHINO_CRITICAL_EXIT();
return empty;
}
uint8_t krhino_ringbuf_is_full(k_ringbuf_t *p_ringbuf)
{
CPSR_ALLOC();
uint8_t full;
NULL_PARA_CHK(p_ringbuf);
RHINO_CRITICAL_ENTER();
full = ringbuf_is_full(p_ringbuf);
RHINO_CRITICAL_EXIT();
return full;
}
#endif

View File

@@ -0,0 +1,490 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#include <csi_core.h>
#if (RHINO_CONFIG_DISABLE_SCHED_STATS > 0)
static void sched_disable_measure_start(void)
{
/* start measure system lock time */
if (g_sched_lock[cpu_cur_get()] == 0u) {
g_sched_disable_time_start = HR_COUNT_GET();
}
}
static void sched_disable_measure_stop(void)
{
hr_timer_t diff;
/* stop measure system lock time, g_sched_lock is always zero here */
diff = HR_COUNT_GET() - g_sched_disable_time_start;
if (g_sched_disable_max_time < diff) {
g_sched_disable_max_time = diff;
}
if (g_cur_sched_disable_max_time < diff) {
g_cur_sched_disable_max_time = diff;
}
}
#endif
kstat_t krhino_sched_disable(void)
{
CPSR_ALLOC();
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (g_sched_lock[cpu_cur_get()] >= SCHED_MAX_LOCK_COUNT) {
RHINO_CRITICAL_EXIT();
return RHINO_SCHED_LOCK_COUNT_OVF;
}
#if (RHINO_CONFIG_DISABLE_SCHED_STATS > 0)
sched_disable_measure_start();
#endif
g_sched_lock[cpu_cur_get()]++;
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
kstat_t krhino_sched_enable(void)
{
CPSR_ALLOC();
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (g_sched_lock[cpu_cur_get()] == 0u) {
RHINO_CRITICAL_EXIT();
return RHINO_SCHED_ALREADY_ENABLED;
}
g_sched_lock[cpu_cur_get()]--;
if (g_sched_lock[cpu_cur_get()] > 0u) {
RHINO_CRITICAL_EXIT();
return RHINO_SCHED_DISABLE;
}
#if (RHINO_CONFIG_DISABLE_SCHED_STATS > 0)
sched_disable_measure_stop();
#endif
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
#if (RHINO_CONFIG_CPU_NUM > 1)
void core_sched(void)
{
uint8_t cur_cpu_num;
cur_cpu_num = cpu_cur_get();
if (g_intrpt_nested_level[cur_cpu_num] > 0u) {
return;
}
if (g_sched_lock[cur_cpu_num] > 0u) {
return;
}
preferred_cpu_ready_task_get(&g_ready_queue, cur_cpu_num);
/* if preferred task is currently task, then no need to do switch and just return */
if (g_preferred_ready_task[cur_cpu_num] == g_active_task[cur_cpu_num]) {
return;
}
TRACE_TASK_SWITCH(g_active_task[cur_cpu_num], g_preferred_ready_task[cur_cpu_num]);
#if (RHINO_CONFIG_USER_HOOK > 0)
krhino_task_switch_hook(g_active_task[cur_cpu_num], g_preferred_ready_task[cur_cpu_num]);
#endif
g_active_task[cur_cpu_num]->cur_exc = 0;
cpu_task_switch();
}
#else
void core_sched(void)
{
CPSR_ALLOC();
uint8_t cur_cpu_num;
RHINO_CPU_INTRPT_DISABLE();
cur_cpu_num = cpu_cur_get();
if (g_intrpt_nested_level[cur_cpu_num] > 0u) {
RHINO_CPU_INTRPT_ENABLE();
return;
}
if (g_sched_lock[cur_cpu_num] > 0u) {
RHINO_CPU_INTRPT_ENABLE();
return;
}
preferred_cpu_ready_task_get(&g_ready_queue, cur_cpu_num);
/* if preferred task is currently task, then no need to do switch and just return */
if (g_preferred_ready_task[cur_cpu_num] == g_active_task[cur_cpu_num]) {
RHINO_CPU_INTRPT_ENABLE();
return;
}
TRACE_TASK_SWITCH(g_active_task[cur_cpu_num], g_preferred_ready_task[cur_cpu_num]);
#if (RHINO_CONFIG_USER_HOOK > 0)
krhino_task_switch_hook(g_active_task[cur_cpu_num], g_preferred_ready_task[cur_cpu_num]);
#endif
cpu_task_switch();
RHINO_CPU_INTRPT_ENABLE();
}
#endif
__init void runqueue_init(runqueue_t *rq)
{
uint8_t prio;
rq->highest_pri = RHINO_CONFIG_PRI_MAX;
for (prio = 0; prio < RHINO_CONFIG_PRI_MAX; prio++) {
rq->cur_list_item[prio] = NULL;
}
}
RHINO_INLINE void ready_list_init(runqueue_t *rq, ktask_t *task)
{
rq->cur_list_item[task->prio] = &task->task_list;
klist_init(rq->cur_list_item[task->prio]);
krhino_bitmap_set(rq->task_bit_map, task->prio);
if ((task->prio) < (rq->highest_pri)) {
rq->highest_pri = task->prio;
}
}
RHINO_INLINE uint8_t is_ready_list_empty(uint8_t prio)
{
return (g_ready_queue.cur_list_item[prio] == NULL);
}
RHINO_INLINE void _ready_list_add_tail(runqueue_t *rq, ktask_t *task)
{
if (is_ready_list_empty(task->prio)) {
ready_list_init(rq, task);
return;
}
klist_insert(rq->cur_list_item[task->prio], &task->task_list);
}
RHINO_INLINE void _ready_list_add_head(runqueue_t *rq, ktask_t *task)
{
if (is_ready_list_empty(task->prio)) {
ready_list_init(rq, task);
return;
}
klist_insert(rq->cur_list_item[task->prio], &task->task_list);
rq->cur_list_item[task->prio] = &task->task_list;
}
#if (RHINO_CONFIG_CPU_NUM > 1)
static void task_sched_to_cpu(runqueue_t *rq, ktask_t *task, uint8_t cur_cpu_num)
{
uint8_t i;
uint8_t low_pri;
(void)rq;
if (g_sys_stat == RHINO_RUNNING) {
if (task->cpu_binded == 1) {
if (task->cpu_num != cur_cpu_num) {
if (task->prio <= g_active_task[task->cpu_num]->prio) {
cpu_signal(task->cpu_num);
}
}
} else {
/* find the lowest pri */
low_pri = g_active_task[0]->prio;
for (i = 0; i < RHINO_CONFIG_CPU_NUM - 1; i++) {
if (low_pri < g_active_task[i + 1]->prio) {
low_pri = g_active_task[i + 1]->prio;
}
}
/* which cpu run the lowest pri, just notify it */
for (i = 0; i < RHINO_CONFIG_CPU_NUM; i++) {
if (low_pri == g_active_task[i]->prio) {
if (i != cur_cpu_num) {
cpu_signal(i);
}
return;
}
}
}
}
}
void ready_list_add_head(runqueue_t *rq, ktask_t *task)
{
_ready_list_add_head(rq, task);
task_sched_to_cpu(rq, task, cpu_cur_get());
}
void ready_list_add_tail(runqueue_t *rq, ktask_t *task)
{
_ready_list_add_tail(rq, task);
task_sched_to_cpu(rq, task, cpu_cur_get());
}
#else
void ready_list_add_head(runqueue_t *rq, ktask_t *task)
{
_ready_list_add_head(rq, task);
}
void ready_list_add_tail(runqueue_t *rq, ktask_t *task)
{
_ready_list_add_tail(rq, task);
}
#endif
void ready_list_add(runqueue_t *rq, ktask_t *task)
{
/* if task prio is equal current task prio then add to the end */
if (task->prio == g_active_task[cpu_cur_get()]->prio) {
ready_list_add_tail(rq, task);
} else {
ready_list_add_head(rq, task);
}
}
void ready_list_rm(runqueue_t *rq, ktask_t *task)
{
int32_t i;
uint8_t pri = task->prio;
/* if the ready list is not only one, we do not need to update the highest prio */
if ((rq->cur_list_item[pri]) != (rq->cur_list_item[pri]->next)) {
if (rq->cur_list_item[pri] == &task->task_list) {
rq->cur_list_item[pri] = rq->cur_list_item[pri]->next;
}
klist_rm(&task->task_list);
return;
}
/* only one item,just set cur item ptr to NULL */
rq->cur_list_item[pri] = NULL;
krhino_bitmap_clear(rq->task_bit_map, pri);
/* if task prio not equal to the highest prio, then we do not need to update the highest prio */
/* this condition happens when a current high prio task to suspend a low priotity task */
if (pri != rq->highest_pri) {
return;
}
/* find the highest ready task */
i = krhino_find_first_bit(rq->task_bit_map);
/* update the next highest prio task */
if (i >= 0) {
rq->highest_pri = i;
} else {
k_err_proc(RHINO_SYS_FATAL_ERR);
}
}
void ready_list_head_to_tail(runqueue_t *rq, ktask_t *task)
{
rq->cur_list_item[task->prio] = rq->cur_list_item[task->prio]->next;
}
#if (RHINO_CONFIG_CPU_NUM > 1)
void preferred_cpu_ready_task_get(runqueue_t *rq, uint8_t cpu_num)
{
klist_t *iter;
ktask_t *task;
uint32_t task_bit_map[NUM_WORDS];
klist_t *node;
uint8_t flag;
uint8_t highest_pri = rq->highest_pri;
node = rq->cur_list_item[highest_pri];
iter = node;
memcpy(task_bit_map, rq->task_bit_map, NUM_WORDS * sizeof(uint32_t));
while (1) {
task = krhino_list_entry(iter, ktask_t, task_list);
if (g_active_task[cpu_num] == task) {
break;
}
flag = ((task->cur_exc == 0) && (task->cpu_binded == 0))
|| ((task->cur_exc == 0) && (task->cpu_binded == 1) && (task->cpu_num == cpu_num));
if (flag > 0) {
task->cpu_num = cpu_num;
task->cur_exc = 1;
g_preferred_ready_task[cpu_num] = task;
break;
}
if (iter->next == rq->cur_list_item[highest_pri]) {
task_bit_map[highest_pri >> 5] &= ~(1u << (31u - (highest_pri & 31u)));
highest_pri = krhino_find_first_bit(task_bit_map);
iter = rq->cur_list_item[highest_pri];
} else {
iter = iter->next;
}
}
}
#else
void preferred_cpu_ready_task_get(runqueue_t *rq, uint8_t cpu_num)
{
klist_t *node = rq->cur_list_item[rq->highest_pri];
/* get the highest prio task object */
g_preferred_ready_task[cpu_num] = krhino_list_entry(node, ktask_t, task_list);
}
#endif
#if (RHINO_CONFIG_SCHED_RR > 0)
#if (RHINO_CONFIG_CPU_NUM > 1)
static void _time_slice_update(ktask_t *task, uint8_t i)
{
klist_t *head;
head = g_ready_queue.cur_list_item[task->prio];
task->runtime++;
/* if ready list is empty then just return because nothing is to be caculated */
if (is_ready_list_empty(task->prio)) {
return;
}
if (task->sched_policy == KSCHED_FIFO) {
return;
}
/* there is only one task on this ready list, so do not need to caculate time slice */
/* idle task must satisfy this condition */
if (head->next == head) {
return;
}
if (task->time_slice > 0u) {
task->time_slice--;
}
/* if current active task has time_slice, just return */
if (task->time_slice > 0u) {
return;
}
/* move current active task to the end of ready list for the same prio */
ready_list_head_to_tail(&g_ready_queue, task);
/* restore the task time slice */
task->time_slice = task->time_total;
if (i != cpu_cur_get()) {
cpu_signal(i);
}
}
void time_slice_update(void)
{
CPSR_ALLOC();
uint8_t i;
RHINO_CRITICAL_ENTER();
for (i = 0; i < RHINO_CONFIG_CPU_NUM; i++) {
_time_slice_update(g_active_task[i], i);
}
RHINO_CRITICAL_EXIT();
}
#else
void time_slice_update(void)
{
CPSR_ALLOC();
ktask_t *task;
klist_t *head;
uint8_t task_pri;
RHINO_CRITICAL_ENTER();
task_pri = g_active_task[cpu_cur_get()]->prio;
head = g_ready_queue.cur_list_item[task_pri];
/* if ready list is empty then just return because nothing is to be caculated */
if (is_ready_list_empty(task_pri)) {
RHINO_CRITICAL_EXIT();
return;
}
/* Always look at the first task on the ready list */
task = krhino_list_entry(head, ktask_t, task_list);
task->runtime++;
if (task->sched_policy == KSCHED_FIFO) {
RHINO_CRITICAL_EXIT();
return;
}
/* there is only one task on this ready list, so do not need to caculate time slice */
/* idle task must satisfy this condition */
if (head->next == head) {
RHINO_CRITICAL_EXIT();
return;
}
if (task->time_slice > 0u) {
task->time_slice--;
}
/* if current active task has time_slice, just return */
if (task->time_slice > 0u) {
RHINO_CRITICAL_EXIT();
return;
}
/* move current active task to the end of ready list for the same prio */
ready_list_head_to_tail(&g_ready_queue, task);
/* restore the task time slice */
task->time_slice = task->time_total;
RHINO_CRITICAL_EXIT();
}
#endif
#endif

View File

@@ -0,0 +1,345 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#if (RHINO_CONFIG_SEM > 0)
static kstat_t sem_create(ksem_t *sem, const name_t *name, sem_count_t count,
uint8_t mm_alloc_flag)
{
CPSR_ALLOC();
NULL_PARA_CHK(sem);
NULL_PARA_CHK(name);
/* init the list */
klist_init(&sem->blk_obj.blk_list);
/* init resource */
sem->count = count;
sem->peak_count = count;
sem->blk_obj.name = name;
sem->blk_obj.blk_policy = BLK_POLICY_PRI;
sem->mm_alloc_flag = mm_alloc_flag;
RHINO_CRITICAL_ENTER();
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_insert(&(g_kobj_list.sem_head), &sem->sem_item);
#endif
RHINO_CRITICAL_EXIT();
sem->blk_obj.obj_type = RHINO_SEM_OBJ_TYPE;
TRACE_SEM_CREATE(krhino_cur_task_get(), sem);
return RHINO_SUCCESS;
}
kstat_t krhino_sem_create(ksem_t *sem, const name_t *name, sem_count_t count)
{
return sem_create(sem, name, count, K_OBJ_STATIC_ALLOC);
}
kstat_t krhino_sem_del(ksem_t *sem)
{
CPSR_ALLOC();
klist_t *blk_list_head;
NULL_PARA_CHK(sem);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (sem->blk_obj.obj_type != RHINO_SEM_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (sem->mm_alloc_flag != K_OBJ_STATIC_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
blk_list_head = &sem->blk_obj.blk_list;
sem->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
/* all task blocked on this queue is waken up */
while (!is_klist_empty(blk_list_head)) {
pend_task_rm(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&sem->sem_item);
#endif
TRACE_SEM_DEL(g_active_task[cpu_cur_get()], sem);
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
kstat_t krhino_sem_dyn_create(ksem_t **sem, const name_t *name,
sem_count_t count)
{
kstat_t stat;
ksem_t *sem_obj;
NULL_PARA_CHK(sem);
sem_obj = krhino_mm_alloc(sizeof(ksem_t), __builtin_return_address(0));
if (sem_obj == NULL) {
return RHINO_NO_MEM;
}
stat = sem_create(sem_obj, name, count, K_OBJ_DYN_ALLOC);
if (stat != RHINO_SUCCESS) {
krhino_mm_free(sem_obj);
return stat;
}
*sem = sem_obj;
return stat;
}
kstat_t krhino_sem_dyn_del(ksem_t *sem)
{
CPSR_ALLOC();
klist_t *blk_list_head;
NULL_PARA_CHK(sem);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (sem->blk_obj.obj_type != RHINO_SEM_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
if (sem->mm_alloc_flag != K_OBJ_DYN_ALLOC) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_DEL_ERR;
}
blk_list_head = &sem->blk_obj.blk_list;
sem->blk_obj.obj_type = RHINO_OBJ_TYPE_NONE;
/* all task blocked on this queue is waken up */
while (!is_klist_empty(blk_list_head)) {
pend_task_rm(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
klist_rm(&sem->sem_item);
#endif
TRACE_SEM_DEL(g_active_task[cpu_cur_get()], sem);
RHINO_CRITICAL_EXIT_SCHED();
krhino_mm_free(sem);
return RHINO_SUCCESS;
}
#endif
static kstat_t sem_give(ksem_t *sem, uint8_t opt_wake_all)
{
CPSR_ALLOC();
uint8_t cur_cpu_num;
klist_t *blk_list_head;
/* this is only needed when system zero interrupt feature is enabled */
#if (RHINO_CONFIG_INTRPT_GUARD > 0)
soc_intrpt_guard();
#endif
RHINO_CRITICAL_ENTER();
if (sem->blk_obj.obj_type != RHINO_SEM_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
cur_cpu_num = cpu_cur_get();
(void)cur_cpu_num;
blk_list_head = &sem->blk_obj.blk_list;
if (is_klist_empty(blk_list_head)) {
if (sem->count == (sem_count_t)-1) {
TRACE_SEM_OVERFLOW(g_active_task[cur_cpu_num], sem);
RHINO_CRITICAL_EXIT();
return RHINO_SEM_OVF;
}
/* increase resource */
sem->count++;
if (sem->count > sem->peak_count) {
sem->peak_count = sem->count;
}
TRACE_SEM_CNT_INCREASE(g_active_task[cur_cpu_num], sem);
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
/* wake all the task blocked on this semaphore */
if (opt_wake_all) {
while (!is_klist_empty(blk_list_head)) {
TRACE_SEM_TASK_WAKE(g_active_task[cur_cpu_num], krhino_list_entry(blk_list_head->next,
ktask_t, task_list),
sem, opt_wake_all);
pend_task_wakeup(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
} else {
TRACE_SEM_TASK_WAKE(g_active_task[cur_cpu_num], krhino_list_entry(blk_list_head->next,
ktask_t, task_list),
sem, opt_wake_all);
/* wake up the highest prio task block on the semaphore */
pend_task_wakeup(krhino_list_entry(blk_list_head->next, ktask_t, task_list));
}
RHINO_CRITICAL_EXIT_SCHED();
return RHINO_SUCCESS;
}
kstat_t krhino_sem_give(ksem_t *sem)
{
NULL_PARA_CHK(sem);
return sem_give(sem, WAKE_ONE_SEM);
}
kstat_t krhino_sem_give_all(ksem_t *sem)
{
NULL_PARA_CHK(sem);
return sem_give(sem, WAKE_ALL_SEM);
}
kstat_t krhino_sem_take(ksem_t *sem, tick_t ticks)
{
CPSR_ALLOC();
uint8_t cur_cpu_num;
kstat_t stat;
NULL_PARA_CHK(sem);
krhino_check_fatal_call(__FUNCTION__);
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (sem->blk_obj.obj_type != RHINO_SEM_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
cur_cpu_num = cpu_cur_get();
if (sem->count > 0u) {
sem->count--;
TRACE_SEM_GET_SUCCESS(g_active_task[cur_cpu_num], sem);
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
/* can't get semphore, and return immediately if wait_option is RHINO_NO_WAIT */
if (ticks == RHINO_NO_WAIT) {
RHINO_CRITICAL_EXIT();
return RHINO_NO_PEND_WAIT;
}
if (g_sched_lock[cur_cpu_num] > 0u) {
RHINO_CRITICAL_EXIT();
return RHINO_SCHED_DISABLE;
}
pend_to_blk_obj((blk_obj_t *)sem, g_active_task[cur_cpu_num], ticks, psr);
TRACE_SEM_GET_BLK(g_active_task[cur_cpu_num], sem, ticks);
RHINO_CRITICAL_EXIT_SCHED();
RHINO_CPU_INTRPT_DISABLE();
stat = pend_state_end_proc(g_active_task[cpu_cur_get()]);
RHINO_CPU_INTRPT_ENABLE();
return stat;
}
kstat_t krhino_sem_count_set(ksem_t *sem, sem_count_t sem_count)
{
CPSR_ALLOC();
klist_t *blk_list_head;
NULL_PARA_CHK(sem);
blk_list_head = &sem->blk_obj.blk_list;
RHINO_CRITICAL_ENTER();
INTRPT_NESTED_LEVEL_CHK();
if (sem->blk_obj.obj_type != RHINO_SEM_OBJ_TYPE) {
RHINO_CRITICAL_EXIT();
return RHINO_KOBJ_TYPE_ERR;
}
/* set new count */
if (sem->count > 0u) {
sem->count = sem_count;
} else {
if (is_klist_empty(blk_list_head)) {
sem->count = sem_count;
} else {
RHINO_CRITICAL_EXIT();
return RHINO_SEM_TASK_WAITING;
}
}
/* update sem peak count if need */
if (sem->count > sem->peak_count) {
sem->peak_count = sem->count;
}
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
kstat_t krhino_sem_count_get(ksem_t *sem, sem_count_t *count)
{
NULL_PARA_CHK(sem);
NULL_PARA_CHK(count);
*count = sem->count;
return RHINO_SUCCESS;
}
#endif /* RHINO_CONFIG_SEM */

View File

@@ -0,0 +1,231 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#include <csi_core.h>
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
__init void kobj_list_init(void)
{
klist_init(&(g_kobj_list.task_head));
klist_init(&(g_kobj_list.mutex_head));
#if (RHINO_CONFIG_MM_BLK > 0)
klist_init(&(g_kobj_list.mblkpool_head));
#endif
#if (RHINO_CONFIG_SEM > 0)
klist_init(&(g_kobj_list.sem_head));
#endif
#if (RHINO_CONFIG_QUEUE > 0)
klist_init(&(g_kobj_list.queue_head));
#endif
#if (RHINO_CONFIG_BUF_QUEUE > 0)
klist_init(&(g_kobj_list.buf_queue_head));
#endif
#if (RHINO_CONFIG_EVENT_FLAG > 0)
klist_init(&(g_kobj_list.event_head));
#endif
}
#endif
#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
#if (RHINO_CONFIG_CPU_STACK_DOWN > 0)
void krhino_stack_ovf_check(void)
{
cpu_stack_t *stack_start;
stack_start = g_active_task[cpu_cur_get()]->task_stack_base;
if (*stack_start != RHINO_TASK_STACK_OVF_MAGIC) {
k_err_proc(RHINO_TASK_STACK_OVF);
}
if ((cpu_stack_t *)(g_active_task[cpu_cur_get()]->task_stack) < stack_start) {
k_err_proc(RHINO_TASK_STACK_OVF);
}
}
#else
void krhino_stack_ovf_check(void)
{
cpu_stack_t *stack_start;
cpu_stack_t *stack_end;
stack_start = g_active_task[cpu_cur_get()]->task_stack_base;
stack_end = stack_start + g_active_task[cpu_cur_get()]->stack_size;
if (*(stack_end - 1) != RHINO_TASK_STACK_OVF_MAGIC) {
k_err_proc(RHINO_TASK_STACK_OVF);
}
if ((cpu_stack_t *)(g_active_task[cpu_cur_get()]->task_stack) > stack_end) {
k_err_proc(RHINO_TASK_STACK_OVF);
}
}
#endif
#endif
#if (RHINO_CONFIG_TASK_SCHED_STATS > 0)
void krhino_task_sched_stats_reset(void)
{
lr_timer_t cur_time;
#if (RHINO_CONFIG_DISABLE_INTRPT_STATS > 0)
g_cur_intrpt_disable_max_time = 0;
#endif
#if (RHINO_CONFIG_DISABLE_SCHED_STATS > 0)
g_cur_sched_disable_max_time = 0;
#endif
/* system first task starting time should be measured otherwise not correct */
cur_time = (lr_timer_t)LR_COUNT_GET();
g_preferred_ready_task->task_time_start = cur_time;
}
void krhino_task_sched_stats_get(void)
{
lr_timer_t cur_time;
lr_timer_t exec_time;
#if (RHINO_CONFIG_DISABLE_INTRPT_STATS > 0)
hr_timer_t intrpt_disable_time;
if (g_cur_intrpt_disable_max_time > g_sys_measure_waste) {
intrpt_disable_time = g_cur_intrpt_disable_max_time - g_sys_measure_waste;
} else {
intrpt_disable_time = 0;
}
if (g_active_task[cpu_cur_get()]->task_intrpt_disable_time_max < intrpt_disable_time) {
g_active_task[cpu_cur_get()]->task_intrpt_disable_time_max = intrpt_disable_time;
}
g_cur_intrpt_disable_max_time = 0;
#endif
#if (RHINO_CONFIG_DISABLE_SCHED_STATS > 0)
if (g_active_task[cpu_cur_get()]->task_sched_disable_time_max < g_cur_sched_disable_max_time) {
g_active_task[cpu_cur_get()]->task_sched_disable_time_max = g_cur_sched_disable_max_time;
}
g_cur_sched_disable_max_time = 0;
#endif
/* Keep track of new task and total system context switch times */
g_preferred_ready_task[cpu_cur_get()]->task_ctx_switch_times++;
g_sys_ctx_switch_times++;
cur_time = (lr_timer_t)LR_COUNT_GET();
exec_time = cur_time - g_active_task[cpu_cur_get()]->task_time_start;
g_active_task[cpu_cur_get()]->task_time_total_run += (sys_time_t)exec_time;
g_preferred_ready_task[cpu_cur_get()]->task_time_start = cur_time;
}
#endif /* RHINO_CONFIG_TASK_SCHED_STATS */
#if (RHINO_CONFIG_DISABLE_INTRPT_STATS > 0)
void intrpt_disable_measure_start(void)
{
g_intrpt_disable_times++;
/* start measure interrupt disable time */
if (g_intrpt_disable_times == 1u) {
g_intrpt_disable_time_start = HR_COUNT_GET();
}
}
void intrpt_disable_measure_stop(void)
{
hr_timer_t diff;
g_intrpt_disable_times--;
if (g_intrpt_disable_times == 0u) {
diff = HR_COUNT_GET() - g_intrpt_disable_time_start;
if (g_intrpt_disable_max_time < diff) {
g_intrpt_disable_max_time = diff;
}
if (g_cur_intrpt_disable_max_time < diff) {
g_cur_intrpt_disable_max_time = diff;
}
}
}
#endif
#if (RHINO_CONFIG_HW_COUNT > 0)
void krhino_overhead_measure(void)
{
hr_timer_t diff;
hr_timer_t m1;
hr_timer_t m2;
m1 = HR_COUNT_GET();
HR_COUNT_GET();
HR_COUNT_GET();
m2 = HR_COUNT_GET();
diff = m2 - m1;
/* measure time overhead */
g_sys_measure_waste = diff;
}
#endif
/*it should be called in cpu_stats task*/
#if (RHINO_CONFIG_CPU_USAGE_STATS > 0)
static void cpu_usage_task_entry(void *arg)
{
idle_count_t idle_count;
(void)arg;
while (1) {
idle_count_set(0u);
krhino_task_sleep(RHINO_CONFIG_TICKS_PER_SECOND / 2);
idle_count = idle_count_get();
if (idle_count > g_idle_count_max) {
g_idle_count_max = idle_count;
}
if (idle_count < g_idle_count_max) {
/* use 64bit for cpu_task_idle_count to avoid overflow quickly */
g_cpu_usage = 10000 - (uint32_t)((idle_count * 10000) / g_idle_count_max);
}
else {
g_cpu_usage = 10000;
}
}
}
__init void cpu_usage_stats_start(void)
{
/* create a statistic task to calculate cpu usage */
krhino_task_create(&g_cpu_usage_task, "cpu_stats", 0,
RHINO_CONFIG_CPU_USAGE_TASK_PRI,
0, g_cpu_task_stack, RHINO_CONFIG_CPU_USAGE_TASK_STACK, cpu_usage_task_entry,
1);
}
uint32_t krhino_get_cpu_usage(void)
{
return g_cpu_usage;
}
#endif /* RHINO_CONFIG_CPU_USAGE_STATS */

View File

@@ -0,0 +1,249 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#include <csi_core.h>
__init RHINO_INLINE void rhino_stack_check_init(void)
{
#if (RHINO_CONFIG_INTRPT_STACK_OVF_CHECK > 0)
#if (RHINO_CONFIG_CPU_STACK_DOWN > 0)
*g_intrpt_stack_bottom = RHINO_INTRPT_STACK_OVF_MAGIC;
#else
*g_intrpt_stack_top = RHINO_INTRPT_STACK_OVF_MAGIC;
#endif
#endif /* RHINO_CONFIG_INTRPT_STACK_OVF_CHECK */
#if (RHINO_CONFIG_STACK_OVF_CHECK_HW != 0)
cpu_intrpt_stack_protect();
#endif
}
__init kstat_t krhino_init(void)
{
g_sys_stat = RHINO_STOPPED;
krhino_spin_init(&g_sys_lock);
#if (RHINO_CONFIG_USER_HOOK > 0)
krhino_init_hook();
#endif
runqueue_init(&g_ready_queue);
tick_list_init();
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
kobj_list_init();
#endif
#if (RHINO_CONFIG_MM_TLF > 0)
//k_mm_init();
#endif
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
klist_init(&g_res_list);
krhino_sem_create(&g_res_sem, "res_sem", 0);
//dyn_mem_proc_task_start(); //idle task do it.
#endif
#if (RHINO_CONFIG_CPU_NUM > 1)
for (uint8_t i = 0; i < RHINO_CONFIG_CPU_NUM; i++) {
krhino_task_cpu_create(&g_idle_task[i], "idle_task", NULL, RHINO_IDLE_PRI, 0,
&g_idle_task_stack[i][0], RHINO_CONFIG_IDLE_TASK_STACK_SIZE,
idle_task, i, 1u);
}
#else
krhino_task_create(&g_idle_task[0], "idle_task", NULL, RHINO_IDLE_PRI, 0,
&g_idle_task_stack[0][0], RHINO_CONFIG_IDLE_TASK_STACK_SIZE,
idle_task, 1u);
#endif
#if (RHINO_CONFIG_WORKQUEUE > 0)
workqueue_init();
#endif
#if (RHINO_CONFIG_TIMER > 0)
ktimer_init();
#endif
#if (RHINO_CONFIG_CPU_USAGE_STATS > 0)
cpu_usage_stats_start();
#endif
#if (RHINO_CONFIG_ISR_TASK > 0)
kisr_init();
#endif
rhino_stack_check_init();
return RHINO_SUCCESS;
}
__init kstat_t krhino_start(void)
{
if (g_sys_stat == RHINO_STOPPED) {
#if (RHINO_CONFIG_CPU_NUM > 1)
for (uint8_t i = 0; i < RHINO_CONFIG_CPU_NUM; i++) {
preferred_cpu_ready_task_get(&g_ready_queue, i);
g_active_task[i] = g_preferred_ready_task[i];
g_active_task[i]->cur_exc = 1;
}
#else
preferred_cpu_ready_task_get(&g_ready_queue, 0);
g_active_task[0] = g_preferred_ready_task[0];
#endif
#if (RHINO_CONFIG_USER_HOOK > 0)
krhino_start_hook();
#endif
g_sys_stat = RHINO_RUNNING;
cpu_first_task_start();
/* should not be here */
return RHINO_SYS_FATAL_ERR;
}
return RHINO_RUNNING;
}
#if (RHINO_CONFIG_INTRPT_STACK_OVF_CHECK > 0)
#if (RHINO_CONFIG_CPU_STACK_DOWN > 0)
void krhino_intrpt_stack_ovf_check(void)
{
if (*g_intrpt_stack_bottom != RHINO_INTRPT_STACK_OVF_MAGIC) {
k_err_proc(RHINO_INTRPT_STACK_OVF);
}
}
#else
void krhino_intrpt_stack_ovf_check(void)
{
if (*g_intrpt_stack_top != RHINO_INTRPT_STACK_OVF_MAGIC) {
k_err_proc(RHINO_INTRPT_STACK_OVF);
}
}
#endif
#endif /* RHINO_CONFIG_INTRPT_STACK_OVF_CHECK */
kstat_t krhino_intrpt_enter(void)
{
CPSR_ALLOC();
#if (RHINO_CONFIG_INTRPT_STACK_OVF_CHECK > 0)
krhino_intrpt_stack_ovf_check();
#endif
RHINO_CPU_INTRPT_DISABLE();
/* RHINO_CONFIG_CPU_PWR_MGMT */
#if (RHINO_CONFIG_CPU_PWR_MGMT > 0)
cpu_pwr_up();
#endif
if (g_intrpt_nested_level[cpu_cur_get()] >= RHINO_CONFIG_INTRPT_MAX_NESTED_LEVEL) {
k_err_proc(RHINO_INTRPT_NESTED_LEVEL_OVERFLOW);
RHINO_CPU_INTRPT_ENABLE();
return RHINO_INTRPT_NESTED_LEVEL_OVERFLOW;
}
g_intrpt_nested_level[cpu_cur_get()]++;
RHINO_CPU_INTRPT_ENABLE();
return RHINO_SUCCESS;
}
void krhino_intrpt_exit(void)
{
CPSR_ALLOC();
uint8_t cur_cpu_num;
#if (RHINO_CONFIG_INTRPT_STACK_OVF_CHECK > 0)
krhino_intrpt_stack_ovf_check();
#endif
RHINO_CPU_INTRPT_DISABLE();
cur_cpu_num = cpu_cur_get();
if (g_intrpt_nested_level[cur_cpu_num] == 0u) {
RHINO_CPU_INTRPT_ENABLE();
k_err_proc(RHINO_INV_INTRPT_NESTED_LEVEL);
}
g_intrpt_nested_level[cur_cpu_num]--;
if (g_intrpt_nested_level[cur_cpu_num] > 0u) {
RHINO_CPU_INTRPT_ENABLE();
return;
}
if (g_sched_lock[cur_cpu_num] > 0u) {
RHINO_CPU_INTRPT_ENABLE();
return;
}
preferred_cpu_ready_task_get(&g_ready_queue, cur_cpu_num);
if (g_preferred_ready_task[cur_cpu_num] == g_active_task[cur_cpu_num]) {
RHINO_CPU_INTRPT_ENABLE();
return;
}
TRACE_INTRPT_TASK_SWITCH(g_active_task[cur_cpu_num], g_preferred_ready_task[cur_cpu_num]);
#if (RHINO_CONFIG_CPU_NUM > 1)
g_active_task[cur_cpu_num]->cur_exc = 0;
#endif
cpu_intrpt_switch();
RHINO_CPU_INTRPT_ENABLE();
}
size_t krhino_global_space_get(void)
{
size_t mem;
mem = sizeof(g_sys_stat) + sizeof(g_idle_task_spawned) + sizeof(g_ready_queue)
+ sizeof(g_sched_lock) + sizeof(g_intrpt_nested_level) + sizeof(g_preferred_ready_task)
+ sizeof(g_active_task) + sizeof(g_idle_task) + sizeof(g_idle_task_stack)
+ sizeof(g_tick_head) + sizeof(g_tick_count) + sizeof(g_idle_count);
#if (RHINO_CONFIG_TIMER > 0)
mem += sizeof(g_timer_head) + sizeof(g_timer_count)
+ sizeof(g_timer_task) + sizeof(g_timer_task_stack)
+ sizeof(g_timer_queue) + sizeof(timer_queue_cb);
#endif
#if (RHINO_CONFIG_SYSTEM_STATS > 0)
mem += sizeof(g_kobj_list);
#endif
mem += sizeof(g_sys_lock);
return mem;
}
uint32_t krhino_version_get(void)
{
return RHINO_VERSION;
}
void krhino_check_fatal_call(const char *func)
{
#ifdef SYSCHK_FATAL_CALL
uint8_t loop = 0;
uint32_t psr = __get_PSR();
if(__in_disable_irq(psr) || __in_interrupt()){
while(loop++ < 10){
printf("\0013**DANGEROUS** DO NOT CALL %s %s !\r\n", func, __in_disable_irq(psr)?"WHEN IRQ DISABLED":"IN INTERRUPT");
}
}
#endif
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#if (RHINO_CONFIG_TASK_SEM > 0)
kstat_t krhino_task_sem_create(ktask_t *task, ksem_t *sem, const name_t *name,
size_t count)
{
kstat_t ret;
if (task == NULL) {
return RHINO_NULL_PTR;
}
NULL_PARA_CHK(task);
ret = krhino_sem_create(sem, name, count);
if (ret == RHINO_SUCCESS) {
task->task_sem_obj = sem;
} else {
task->task_sem_obj = NULL;
}
return ret;
}
kstat_t krhino_task_sem_del(ktask_t *task)
{
NULL_PARA_CHK(task);
return krhino_sem_del(task->task_sem_obj);
}
kstat_t krhino_task_sem_give(ktask_t *task)
{
NULL_PARA_CHK(task);
return krhino_sem_give(task->task_sem_obj);
}
kstat_t krhino_task_sem_take(tick_t ticks)
{
return krhino_sem_take(krhino_cur_task_get()->task_sem_obj, ticks);
}
kstat_t krhino_task_sem_count_set(ktask_t *task, sem_count_t count)
{
NULL_PARA_CHK(task);
return krhino_sem_count_set(task->task_sem_obj, count);
}
kstat_t krhino_task_sem_count_get(ktask_t *task, sem_count_t *count)
{
NULL_PARA_CHK(task);
return krhino_sem_count_get(task->task_sem_obj, count);
}
#endif

View File

@@ -0,0 +1,129 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
__init void tick_list_init(void)
{
klist_init(&g_tick_head);
}
RHINO_INLINE void tick_list_pri_insert(klist_t *head, ktask_t *task)
{
tick_t val;
klist_t *q;
klist_t *list_start;
klist_t *list_end;
ktask_t *task_iter_temp;
list_start = list_end = head;
val = task->tick_remain;
for (q = list_start->next; q != list_end; q = q->next) {
task_iter_temp = krhino_list_entry(q, ktask_t, tick_list);
if ((task_iter_temp->tick_match - g_tick_count) > val) {
break;
}
}
klist_insert(q, &task->tick_list);
}
void tick_list_insert(ktask_t *task, tick_t time)
{
klist_t *tick_head_ptr;
if (time > 0u) {
task->tick_match = g_tick_count + time;
task->tick_remain = time;
tick_head_ptr = &g_tick_head;
tick_list_pri_insert(tick_head_ptr, task);
task->tick_head = tick_head_ptr;
}
}
void tick_list_rm(ktask_t *task)
{
klist_t *tick_head_ptr = task->tick_head;
if (tick_head_ptr != NULL) {
klist_rm(&task->tick_list);
task->tick_head = NULL;
}
}
void tick_list_update(tick_i_t ticks)
{
CPSR_ALLOC();
klist_t *tick_head_ptr;
ktask_t *p_tcb;
klist_t *iter;
klist_t *iter_temp;
tick_i_t delta;
RHINO_CRITICAL_ENTER();
g_tick_count += ticks;
tick_head_ptr = &g_tick_head;
iter = tick_head_ptr->next;
while (RHINO_TRUE) {
/* search all the time list if possible */
if (iter != tick_head_ptr) {
iter_temp = iter->next;
p_tcb = krhino_list_entry(iter, ktask_t, tick_list);
delta = (tick_i_t)p_tcb->tick_match - (tick_i_t)g_tick_count;
/* since time list is sorted by remain time, so just campare the absolute time */
if (delta <= 0) {
switch (p_tcb->task_state) {
case K_SLEEP:
p_tcb->blk_state = BLK_FINISH;
p_tcb->task_state = K_RDY;
tick_list_rm(p_tcb);
ready_list_add(&g_ready_queue, p_tcb);
break;
case K_PEND:
tick_list_rm(p_tcb);
/* remove task on the block list because task is timeout */
klist_rm(&p_tcb->task_list);
ready_list_add(&g_ready_queue, p_tcb);
p_tcb->blk_state = BLK_TIMEOUT;
p_tcb->task_state = K_RDY;
mutex_task_pri_reset(p_tcb);
p_tcb->blk_obj = NULL;
break;
case K_PEND_SUSPENDED:
tick_list_rm(p_tcb);
/* remove task on the block list because task is timeout */
klist_rm(&p_tcb->task_list);
p_tcb->blk_state = BLK_TIMEOUT;
p_tcb->task_state = K_SUSPENDED;
mutex_task_pri_reset(p_tcb);
p_tcb->blk_obj = NULL;
break;
case K_SLEEP_SUSPENDED:
p_tcb->task_state = K_SUSPENDED;
p_tcb->blk_state = BLK_FINISH;
tick_list_rm(p_tcb);
break;
default:
k_err_proc(RHINO_SYS_FATAL_ERR);
break;
}
iter = iter_temp;
} else {
break;
}
} else {
break;
}
}
RHINO_CRITICAL_EXIT();
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
void mcu_watchdog_feed(void);
void krhino_tick_proc(void)
{
#if (RHINO_CONFIG_INTRPT_GUARD > 0)
soc_intrpt_guard();
#endif
#if (RHINO_CONFIG_USER_HOOK > 0)
krhino_tick_hook();
#endif
tick_list_update(1);
#if (RHINO_CONFIG_SCHED_RR > 0)
time_slice_update();
#endif
// mcu_watchdog_feed();
}
sys_time_t krhino_sys_tick_get(void)
{
CPSR_ALLOC();
sys_time_t tick_tmp;
RHINO_CPU_INTRPT_DISABLE();
tick_tmp = g_tick_count;
RHINO_CPU_INTRPT_ENABLE();
return tick_tmp;
}
sys_time_t krhino_sys_time_get(void)
{
return (sys_time_t)(krhino_sys_tick_get() * 1000 /
RHINO_CONFIG_TICKS_PER_SECOND);
}
tick_t krhino_ms_to_ticks(sys_time_t ms)
{
uint16_t padding;
uint16_t surplus;
tick_t ticks;
surplus = ms % 1000;
ticks = (ms / 1000) * RHINO_CONFIG_TICKS_PER_SECOND;
padding = 1000 / RHINO_CONFIG_TICKS_PER_SECOND;
padding = (padding > 0) ? (padding - 1) : 0;
ticks += ((surplus + padding) * RHINO_CONFIG_TICKS_PER_SECOND) / 1000;
return ticks;
}
sys_time_t krhino_ticks_to_ms(tick_t ticks)
{
uint32_t padding;
uint32_t surplus;
sys_time_t time;
surplus = ticks % RHINO_CONFIG_TICKS_PER_SECOND;
time = (ticks / RHINO_CONFIG_TICKS_PER_SECOND) * 1000;
padding = RHINO_CONFIG_TICKS_PER_SECOND / 1000;
padding = (padding > 0) ? (padding - 1) : 0;
time += ((surplus + padding) * 1000) / RHINO_CONFIG_TICKS_PER_SECOND;
return time;
}

View File

@@ -0,0 +1,452 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#if (RHINO_CONFIG_TIMER > 0)
static void timer_list_pri_insert(klist_t *head, ktimer_t *timer)
{
sys_time_t val;
klist_t *q;
klist_t *start;
klist_t *end;
ktimer_t *task_iter_temp;
start = end = head;
val = timer->remain;
for (q = start->next; q != end; q = q->next) {
task_iter_temp = krhino_list_entry(q, ktimer_t, timer_list);
if ((task_iter_temp->match - g_timer_count) > val) {
break;
}
}
klist_insert(q, &timer->timer_list);
}
static void timer_list_rm(ktimer_t *timer)
{
klist_t *head;
head = timer->to_head;
if (head != NULL) {
klist_rm(&timer->timer_list);
timer->to_head = NULL;
}
}
static kstat_t timer_create(ktimer_t *timer, const name_t *name, timer_cb_t cb,
sys_time_t first, sys_time_t round, void *arg, uint8_t auto_run,
uint8_t mm_alloc_flag)
{
kstat_t err = RHINO_SUCCESS;
NULL_PARA_CHK(timer);
NULL_PARA_CHK(name);
NULL_PARA_CHK(cb);
if (first == 0u) {
return RHINO_INV_PARAM;
}
if (first >= MAX_TIMER_TICKS) {
return RHINO_INV_PARAM;
}
if (round >= MAX_TIMER_TICKS) {
return RHINO_INV_PARAM;
}
timer->name = name;
timer->cb = cb;
timer->init_count = first;
timer->round_ticks = round;
timer->remain = 0u;
timer->match = 0u;
timer->timer_state = TIMER_DEACTIVE;
timer->to_head = NULL;
timer->mm_alloc_flag = mm_alloc_flag;
timer->timer_cb_arg = arg;
klist_init(&timer->timer_list);
timer->obj_type = RHINO_TIMER_OBJ_TYPE;
if (auto_run > 0u) {
err = krhino_timer_start(timer);
}
TRACE_TIMER_CREATE(krhino_cur_task_get(), timer);
return err;
}
kstat_t krhino_timer_create(ktimer_t *timer, const name_t *name, timer_cb_t cb,
sys_time_t first, sys_time_t round, void *arg, uint8_t auto_run)
{
return timer_create(timer, name, cb, first, round, arg, auto_run,
K_OBJ_STATIC_ALLOC);
}
kstat_t krhino_timer_del(ktimer_t *timer)
{
k_timer_queue_cb cb;
kstat_t err;
NULL_PARA_CHK(timer);
cb.timer = timer;
cb.cb_num = TIMER_CMD_DEL;
err = krhino_buf_queue_send(&g_timer_queue, &cb, sizeof(k_timer_queue_cb), 0);
return err;
}
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
kstat_t krhino_timer_dyn_create(ktimer_t **timer, const name_t *name,
timer_cb_t cb,
sys_time_t first, sys_time_t round, void *arg, uint8_t auto_run)
{
kstat_t ret;
ktimer_t *timer_obj;
NULL_PARA_CHK(timer);
if (first >= MAX_TIMER_TICKS) {
return RHINO_INV_PARAM;
}
if (round >= MAX_TIMER_TICKS) {
return RHINO_INV_PARAM;
}
timer_obj = krhino_mm_alloc(sizeof(ktimer_t), __builtin_return_address(0));
if (timer_obj == NULL) {
return RHINO_NO_MEM;
}
ret = timer_create(timer_obj, name, cb, first, round, arg, auto_run,
K_OBJ_DYN_ALLOC);
if (ret != RHINO_SUCCESS) {
krhino_mm_free(timer_obj);
return ret;
}
*timer = timer_obj;
return ret;
}
kstat_t krhino_timer_dyn_del(ktimer_t *timer)
{
k_timer_queue_cb cb;
kstat_t err;
NULL_PARA_CHK(timer);
cb.timer = timer;
cb.cb_num = TIMER_CMD_DYN_DEL;
err = krhino_buf_queue_send(&g_timer_queue, &cb, sizeof(k_timer_queue_cb), 0);
return err;
}
#endif
kstat_t krhino_timer_start(ktimer_t *timer)
{
k_timer_queue_cb cb;
kstat_t err;
NULL_PARA_CHK(timer);
cb.timer = timer;
cb.cb_num = TIMER_CMD_START;
err = krhino_buf_queue_send(&g_timer_queue, &cb, sizeof(k_timer_queue_cb), 0);
return err;
}
kstat_t krhino_timer_stop(ktimer_t *timer)
{
k_timer_queue_cb cb;
kstat_t err;
NULL_PARA_CHK(timer);
cb.timer = timer;
cb.cb_num = TIMER_CMD_STOP;
err = krhino_buf_queue_send(&g_timer_queue, &cb, sizeof(k_timer_queue_cb), 0);
return err;
}
kstat_t krhino_timer_change(ktimer_t *timer, sys_time_t first, sys_time_t round)
{
k_timer_queue_cb cb;
kstat_t err;
NULL_PARA_CHK(timer);
if (first >= (tick_t)-1) {
return RHINO_INV_PARAM;
}
if (round >= (tick_t)-1) {
return RHINO_INV_PARAM;
}
cb.timer = timer;
cb.first = first;
cb.u.round = round;
cb.cb_num = TIMER_CMD_CHG;
err = krhino_buf_queue_send(&g_timer_queue, &cb, sizeof(k_timer_queue_cb), 0);
return err;
}
kstat_t krhino_timer_arg_change(ktimer_t *timer, void *arg)
{
k_timer_queue_cb cb;
kstat_t err;
NULL_PARA_CHK(timer);
cb.timer = timer;
cb.u.arg = arg;
cb.cb_num = TIMER_ARG_CHG;
err = krhino_buf_queue_send(&g_timer_queue, &cb, sizeof(k_timer_queue_cb), 0);
return err;
}
kstat_t krhino_timer_arg_change_auto(ktimer_t *timer, void *arg)
{
k_timer_queue_cb cb;
kstat_t err;
NULL_PARA_CHK(timer);
cb.timer = timer;
cb.u.arg = arg;
cb.cb_num = TIMER_ARG_CHG_AUTO;
err = krhino_buf_queue_send(&g_timer_queue, &cb, sizeof(k_timer_queue_cb), 0);
return err;
}
extern uint64_t os_mseconds(void);
extern void hgprintf(const char *fmt, ...);
static void timer_cb_proc(void)
{
klist_t *q;
klist_t *start;
klist_t *end;
ktimer_t *timer;
sys_time_i_t delta;
uint64_t tick;
start = end = &g_timer_head;
for (q = start->next; q != end; q = q->next) {
timer = krhino_list_entry(q, ktimer_t, timer_list);
delta = (sys_time_i_t)timer->match - (sys_time_i_t)g_timer_count;
if (delta <= 0) {
tick = os_mseconds();
timer->cb(timer, timer->timer_cb_arg);
if(os_mseconds() - tick > 5){
hgprintf("\0011timer:%p, callback:%p use time: %d ms!\r\n", timer, timer->cb, (uint32_t)(os_mseconds() - tick));
}
timer_list_rm(timer);
if (timer->round_ticks > 0u) {
timer->remain = timer->round_ticks;
timer->match = g_timer_count + timer->remain;
timer->to_head = &g_timer_head;
timer_list_pri_insert(&g_timer_head, timer);
} else {
timer->timer_state = TIMER_DEACTIVE;
}
}
else {
break;
}
}
}
static void cmd_proc(k_timer_queue_cb *cb, uint8_t cmd)
{
ktimer_t *timer;
timer = cb->timer;
switch (cmd) {
case TIMER_CMD_START:
if (timer->obj_type != RHINO_TIMER_OBJ_TYPE) {
break;
}
if (timer->timer_state == TIMER_ACTIVE) {
break;
}
timer->match = g_timer_count + timer->init_count;
/* sort by remain time */
timer->remain = timer->init_count;
/* used by timer delete */
timer->to_head = &g_timer_head;
timer_list_pri_insert(&g_timer_head, timer);
timer->timer_state = TIMER_ACTIVE;
break;
case TIMER_CMD_STOP:
if (timer->obj_type != RHINO_TIMER_OBJ_TYPE) {
break;
}
if (timer->timer_state == TIMER_DEACTIVE) {
break;
}
timer_list_rm(timer);
timer->timer_state = TIMER_DEACTIVE;
break;
case TIMER_CMD_CHG:
if (cb->first == 0u) {
break;
}
if (timer->obj_type != RHINO_TIMER_OBJ_TYPE) {
break;
}
if (timer->timer_state != TIMER_DEACTIVE) {
timer_list_rm(timer);
timer->timer_state = TIMER_DEACTIVE;
}
timer->init_count = cb->first;
timer->round_ticks = cb->u.round;
break;
case TIMER_ARG_CHG:
if (timer->obj_type != RHINO_TIMER_OBJ_TYPE) {
break;
}
if (timer->timer_state != TIMER_DEACTIVE) {
break;
}
timer->timer_cb_arg = cb->u.arg;
break;
case TIMER_CMD_DEL:
if (timer->obj_type != RHINO_TIMER_OBJ_TYPE) {
break;
}
if (timer->timer_state != TIMER_DEACTIVE) {
break;
}
if (timer->mm_alloc_flag != K_OBJ_STATIC_ALLOC) {
break;
}
timer->obj_type = RHINO_OBJ_TYPE_NONE;
TRACE_TIMER_DEL(krhino_cur_task_get(), timer);
break;
#if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
case TIMER_CMD_DYN_DEL:
if (timer->obj_type != RHINO_TIMER_OBJ_TYPE) {
break;
}
if (timer->timer_state != TIMER_DEACTIVE) {
break;
}
if (timer->mm_alloc_flag != K_OBJ_DYN_ALLOC) {
break;
}
timer->obj_type = RHINO_OBJ_TYPE_NONE;
TRACE_TIMER_DEL(krhino_cur_task_get(), timer);
krhino_mm_free(timer);
break;
#endif
default:
k_err_proc(RHINO_SYS_FATAL_ERR);
break;
}
}
static void timer_cmd_proc(k_timer_queue_cb *cb)
{
if (cb->cb_num == TIMER_ARG_CHG_AUTO) {
cmd_proc(cb, TIMER_CMD_STOP);
cmd_proc(cb, TIMER_ARG_CHG);
cmd_proc(cb, TIMER_CMD_START);
}
else {
cmd_proc(cb, cb->cb_num);
}
}
static void timer_task(void *pa)
{
ktimer_t *timer;
k_timer_queue_cb cb_msg;
kstat_t err;
sys_time_t tick_start;
sys_time_t tick_end;
sys_time_i_t delta;
size_t msg_size;
(void)pa;
while (RHINO_TRUE) {
err = krhino_buf_queue_recv(&g_timer_queue, RHINO_WAIT_FOREVER, &cb_msg, &msg_size);
tick_end = krhino_sys_tick_get();
if (err == RHINO_SUCCESS) {
g_timer_count = tick_end;
}
else {
k_err_proc(RHINO_SYS_FATAL_ERR);
}
timer_cmd_proc(&cb_msg);
while (!is_klist_empty(&g_timer_head)) {
timer = krhino_list_entry(g_timer_head.next, ktimer_t, timer_list);
tick_start = krhino_sys_tick_get();
delta = (sys_time_i_t)timer->match - (sys_time_i_t)tick_start;
if (delta > 0) {
err = krhino_buf_queue_recv(&g_timer_queue, (tick_t)delta, &cb_msg, &msg_size);
tick_end = krhino_sys_tick_get();
if (err == RHINO_BLK_TIMEOUT) {
g_timer_count = tick_end;
}
else if (err == RHINO_SUCCESS) {
g_timer_count = tick_end;
timer_cmd_proc(&cb_msg);
}
else {
k_err_proc(RHINO_SYS_FATAL_ERR);
}
}
else {
g_timer_count = tick_start;
}
timer_cb_proc();
}
}
}
__init void ktimer_init(void)
{
klist_init(&g_timer_head);
krhino_fix_buf_queue_create(&g_timer_queue, "timer_queue",
timer_queue_cb, sizeof(k_timer_queue_cb), RHINO_CONFIG_TIMER_MSG_NUM);
krhino_task_create(&g_timer_task, "timer_task", NULL,
RHINO_CONFIG_TIMER_TASK_PRI, 0u, g_timer_task_stack,
RHINO_CONFIG_TIMER_TASK_STACK_SIZE, timer_task, 1u);
}
#endif /* RHINO_CONFIG_TIMER */

View File

@@ -0,0 +1,327 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <k_api.h>
#if (RHINO_CONFIG_WORKQUEUE > 0)
static kstat_t workqueue_is_exist(kworkqueue_t *workqueue)
{
CPSR_ALLOC();
kworkqueue_t *pos;
RHINO_CRITICAL_ENTER();
for (pos = krhino_list_entry(g_workqueue_list_head.next, kworkqueue_t, workqueue_node);
&pos->workqueue_node != &g_workqueue_list_head;
pos = krhino_list_entry(pos->workqueue_node.next, kworkqueue_t, workqueue_node)) {
if (pos == workqueue) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_EXIST;
}
}
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_NOT_EXIST;
}
static void worker_task(void *arg)
{
CPSR_ALLOC();
kstat_t ret;
kwork_t *work = NULL;
kworkqueue_t *queue = (kworkqueue_t *)arg;
while (1) {
ret = krhino_sem_take(&(queue->sem), RHINO_WAIT_FOREVER);
if (ret != RHINO_SUCCESS) {
k_err_proc(ret);
}
RHINO_CRITICAL_ENTER();
/* have work to do. */
work = krhino_list_entry(queue->work_list.next, kwork_t, work_node);
klist_rm_init(&(work->work_node));
queue->work_current = work;
work->work_exit = 0;
RHINO_CRITICAL_EXIT();
/* do work */
work->handle(work->arg);
RHINO_CRITICAL_ENTER();
/* clean current work */
queue->work_current = NULL;
RHINO_CRITICAL_EXIT();
}
}
kstat_t krhino_workqueue_create(kworkqueue_t *workqueue, const name_t *name,
uint8_t pri, cpu_stack_t *stack_buf, size_t stack_size)
{
CPSR_ALLOC();
kstat_t ret;
NULL_PARA_CHK(workqueue);
NULL_PARA_CHK(name);
NULL_PARA_CHK(stack_buf);
if (pri >= RHINO_CONFIG_PRI_MAX) {
return RHINO_BEYOND_MAX_PRI;
}
if (stack_size == 0u) {
return RHINO_TASK_INV_STACK_SIZE;
}
ret = workqueue_is_exist(workqueue);
if (ret == RHINO_WORKQUEUE_EXIST) {
return RHINO_WORKQUEUE_EXIST;
}
klist_init(&(workqueue->workqueue_node));
klist_init(&(workqueue->work_list));
workqueue->work_current = NULL;
workqueue->name = name;
ret = krhino_sem_create(&(workqueue->sem), "WORKQUEUE-SEM", 0);
if (ret != RHINO_SUCCESS) {
return ret;
}
RHINO_CRITICAL_ENTER();
klist_insert(&g_workqueue_list_head, &(workqueue->workqueue_node));
RHINO_CRITICAL_EXIT();
ret = krhino_task_create(&(workqueue->worker), name, (void *)workqueue, pri,
0, stack_buf, stack_size, worker_task, 1);
if (ret != RHINO_SUCCESS) {
RHINO_CRITICAL_ENTER();
klist_rm_init(&(workqueue->workqueue_node));
RHINO_CRITICAL_EXIT();
krhino_sem_del(&(workqueue->sem));
return ret;
}
TRACE_WORKQUEUE_CREATE(krhino_cur_task_get(), workqueue);
return RHINO_SUCCESS;
}
kstat_t krhino_workqueue_del(kworkqueue_t *workqueue)
{
CPSR_ALLOC();
kstat_t ret;
NULL_PARA_CHK(workqueue);
ret = workqueue_is_exist(workqueue);
if (ret == RHINO_WORKQUEUE_NOT_EXIST) {
return RHINO_WORKQUEUE_NOT_EXIST;
}
RHINO_CRITICAL_ENTER();
if (!is_klist_empty(&(workqueue->work_list))) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_BUSY;
}
if (workqueue->work_current != NULL) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_BUSY;
}
RHINO_CRITICAL_EXIT();
ret = krhino_task_del(&(workqueue->worker));
if (ret != RHINO_SUCCESS) {
return ret;
}
ret = krhino_sem_del(&(workqueue->sem));
if (ret != RHINO_SUCCESS) {
return ret;
}
RHINO_CRITICAL_ENTER();
klist_rm_init(&(workqueue->workqueue_node));
TRACE_WORKQUEUE_DEL(g_active_task[cpu_cur_get()], workqueue);
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
static void work_timer_cb(void *timer, void *arg)
{
CPSR_ALLOC();
kstat_t ret;
kwork_t *work = ((ktimer_t *)timer)->priv;
kworkqueue_t *wq = (kworkqueue_t *)arg;
RHINO_CRITICAL_ENTER();
if (wq->work_current == work) {
RHINO_CRITICAL_EXIT();
return;
}
if (work->work_exit == 1) {
RHINO_CRITICAL_EXIT();
return;
}
/* NOTE: the work MUST be initialized firstly */
klist_rm_init(&(work->work_node));
klist_insert(&(wq->work_list), &(work->work_node));
work->wq = wq;
work->work_exit = 1;
RHINO_CRITICAL_EXIT();
ret = krhino_sem_give(&(wq->sem));
if (ret != RHINO_SUCCESS) {
return;
}
}
kstat_t krhino_work_init(kwork_t *work, work_handle_t handle, void *arg,
tick_t dly)
{
kstat_t ret;
if (work == NULL) {
return RHINO_NULL_PTR;
}
if (handle == NULL) {
return RHINO_NULL_PTR;
}
NULL_PARA_CHK(work);
NULL_PARA_CHK(handle);
memset(work, 0, sizeof(kwork_t));
klist_init(&(work->work_node));
work->handle = handle;
work->arg = arg;
work->dly = dly;
work->wq = NULL;
if (dly > 0) {
ret = krhino_timer_dyn_create((ktimer_t **)(&work->timer), "WORK-TIMER", work_timer_cb,
work->dly, 0, (void *)work, 0);
if (ret != RHINO_SUCCESS) {
return ret;
}
}
TRACE_WORK_INIT(krhino_cur_task_get(), work);
return RHINO_SUCCESS;
}
kstat_t krhino_work_run(kworkqueue_t *workqueue, kwork_t *work)
{
CPSR_ALLOC();
kstat_t ret;
NULL_PARA_CHK(workqueue);
NULL_PARA_CHK(work);
if (work->dly == 0) {
RHINO_CRITICAL_ENTER();
if (workqueue->work_current == work) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_WORK_RUNNING;
}
if (work->work_exit == 1) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_WORK_EXIST;
}
/* NOTE: the work MUST be initialized firstly */
klist_rm_init(&(work->work_node));
klist_insert(&(workqueue->work_list), &(work->work_node));
work->wq = workqueue;
work->work_exit = 1;
RHINO_CRITICAL_EXIT();
ret = krhino_sem_give(&(workqueue->sem));
if (ret != RHINO_SUCCESS) {
return ret;
}
} else {
RHINO_CRITICAL_ENTER();
work->timer->priv = work;
RHINO_CRITICAL_EXIT();
ret = krhino_timer_arg_change_auto(work->timer, (void *)workqueue);
if (ret != RHINO_SUCCESS) {
return ret;
}
}
return RHINO_SUCCESS;
}
kstat_t krhino_work_sched(kwork_t *work)
{
return krhino_work_run(&g_workqueue_default, work);
}
kstat_t krhino_work_cancel(kwork_t *work)
{
CPSR_ALLOC();
kworkqueue_t *wq;
NULL_PARA_CHK(work);
wq = (kworkqueue_t *)work->wq;
if (wq == NULL) {
if (work->dly > 0) {
krhino_timer_stop(work->timer);
}
return RHINO_SUCCESS;
}
RHINO_CRITICAL_ENTER();
if (wq->work_current == work) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_WORK_RUNNING;
}
if (work->work_exit == 1) {
RHINO_CRITICAL_EXIT();
return RHINO_WORKQUEUE_WORK_EXIST;
}
klist_rm_init(&(work->work_node));
work->wq = NULL;
RHINO_CRITICAL_EXIT();
return RHINO_SUCCESS;
}
void workqueue_init(void)
{
klist_init(&g_workqueue_list_head);
krhino_workqueue_create(&g_workqueue_default, "DEFAULT-WORKQUEUE",
RHINO_CONFIG_WORKQUEUE_TASK_PRIO, g_workqueue_stack,
RHINO_CONFIG_WORKQUEUE_STACK_SIZE);
}
#endif