#ifndef _SR_CT_H_
#define _SR_CT_H_

#include "sr_list.h"
#include "lc.h"

extern int g_ctReturn;

#define _OS_ERR_STACK_OF   -1  


//协程结构体
typedef struct ct
{
    lc_t     lc;         //记录代码行号
    uint32_t tick;       //用于记录起始系统tick
    uint32_t time_ms;    //延时时间，单位ms
    uint32_t wait;       //阻塞状态
	uint16_t stackSize;  //协程栈大小
}SR_CT_T;


//协程返回状态

#if   0
#define SR_CT_WAITING 0
#define SR_CT_YIELDED 1
#define SR_CT_EXITED  2
#define SR_CT_ENDED   3

#else
//LW_RETURN_TEST
#define SR_CT_WAITING ((int)0x7FFFFFFF)
#define SR_CT_YIELDED ((int)0x7FFFFFFE)
#define SR_CT_EXITED  ((int)0x7FFFFFFD)
#define SR_CT_ENDED   ((int)0x7FFFFFFC)

#endif


#define SR_CT_INSTANCE(name) static struct ct name={0}


//协程上下文初始化
#if  0
#define SR_CT_INIT(ct)          \
    do                          \
    {                           \
        LC_INIT((ct)->lc);      \
        LC_INIT((ct)->tick);    \
        LC_INIT((ct)->time_ms); \
        LC_INIT((ct)->wait);    \
		LC_INIT((ct)->stackSize);\
    } while (0)
#else
#define SR_CT_INIT(ct)          \
    do                          \
    {                           \
        LC_INIT((ct)->lc);      \
        LC_INIT((ct)->tick);    \
        LC_INIT((ct)->time_ms); \
        LC_INIT((ct)->wait);    \
		(ct)->stackSize = sizeof(SR_CT_T);\
    } while (0)

#endif

//协程环境起始位置声明
#define SR_CT_BEGIN()     \
{                           \
		char SR_CT_YIELD_FLAG = 1; (void)SR_CT_YIELD_FLAG;\
		LC_RESUME((ct)->lc)



//协程环境结束位置声明
#if   0
#define SR_CT_END(ct)   \
    LC_END((ct)->lc);    \
    SR_CT_YIELD_FLAG = 0;  \
    SR_CT_INIT(ct);     \
    return SR_CT_ENDED; \
    }

#else
//LW_RETURN_TEST
#define SR_CT_END()   \
    LC_END((ct)->lc);    \
    SR_CT_YIELD_FLAG = 0;  \
    return SR_CT_ENDED; \
    }


#endif

		
 
//协程重启
#define SR_CT_RESTART()     \
    do                        \
    {                         \
        SR_CT_INIT(ct);       \
        return SR_CT_WAITING; \
    } while (0)

	
//协程退出
#define SR_CT_EXIT()       \
    do                       \
    {                        \
        SR_CT_INIT(ct);      \
        return SR_CT_EXITED; \
    } while (0)



		
//当前协程让出CPU权限
#define SR_CT_YIELD()            \
    do                             \
    {                              \
        SR_CT_YIELD_FLAG = 0;      \
        LC_SET((ct)->lc);           \
        if (SR_CT_YIELD_FLAG == 0) \
        {                          \
            return SR_CT_YIELDED;  \
        }                          \
    } while (0)


//当前协程让出CPU权限，直到条件满足
#define SR_CT_YIELD_UNTIL(cond)          \
    do                                       \
    {                                        \
        SR_CT_YIELD_FLAG = 0;                \
        LC_SET((ct)->lc);                     \
        if ((SR_CT_YIELD_FLAG == 0) || !(cond)) \
        {                                       \
            return SR_CT_YIELDED;               \
        }                                       \
    } while (0)
		

//阻塞等待，直到条件为真
#define SR_CT_WAIT_UNTIL(ct, condition) \
    do                                  \
    {                                   \
        LC_SET((ct)->lc);                \
        if (!(condition))               \
        {                               \
            return SR_CT_WAITING;       \
        }                               \
    } while (0)

//阻塞等待，直到条件为真或者超时
#define SR_CT_WAIT_TIMEOUT(ct, condition, timeout)                          \
    do                                                                      \
    {                                                                       \
        if ((ct)->wait == 0)                                                \
        {                                                                   \
            (ct)->tick    = SR_OsGetTick();                                 \
            (ct)->time_ms = SR_TICKS_TO_MS(timeout);                        \
            (ct)->wait    = 1;                                              \
        }                                                                   \
        LC_SET((ct)->lc);                                                   \
        g_ctReturn=(condition);                                             \
        if (!((g_ctReturn) || (SR_OsGetTick() - (ct)->tick) >= (ct)->time_ms)) \
        {                                                                   \
            return SR_CT_WAITING;                                           \
        }                                                                   \
        (ct)->wait = 0;                                                     \
	if (!(g_ctReturn))   g_ctReturn = SR_TIMEOUT;                       \
    } while (0)

//判断是否超时
#define SR_CT_IS_TIMEOUT()  (g_ctReturn == SR_TIMEOUT)

//获取内部全局返回值		
#define SR_CT_GET_RET()    (g_ctReturn)

//设置内部全局返回值
#define SR_CT_SET_RET(ret) (g_ctReturn=ret) 
		
		
//当条件为真时，一直阻塞
#define SR_CT_WAIT_WHILE(ct, cond) SR_CT_WAIT_UNTIL((ct), !(cond))

		
//协程休眠延时
#define SR_CT_DELAY_MS(ms) SR_CT_WAIT_TIMEOUT(ct, 0, ms)
		
	
//
#if   0
#define SR_CT_CHILD_RET(ret,func)     \
    do                        \
    {                         \
        if((g_curThread->sp +(ct)->stackSize + sizeof(SR_CT_T))>=(g_curThread->stack+g_curThread->stackSize)) _OsErrHdl(_OS_ERR_STACK_OF);\
        SR_CT_INIT(((SR_CT_T *)(g_curThread->sp+(ct)->stackSize))); \
        ((SR_CT_T *)(g_curThread->sp+(ct)->stackSize))->stackSize = sizeof(SR_CT_T);\
        LC_SET((ct)->lc);                \
        g_curThread->sp += (ct)->stackSize;  \
        if ((func < SR_CT_EXITED))           \
        {                               \
            return SR_CT_WAITING;       \
        }      \
        g_curThread->sp -= (ct)->stackSize; \
        ret = g_ctReturn; \
    } while (0)
#else
//调用子协程。适用于调用一些函数指针的情况，用形参ret接收返回值
#define SR_CT_CHILD_RET(ret,func)     \
    do                        \
    {                         \
        if((g_curThread->sp +(ct)->stackSize + sizeof(SR_CT_T))>=(g_curThread->stack+g_curThread->stackSize)) _OsErrHdl(_OS_ERR_STACK_OF);\
        SR_CT_INIT(((SR_CT_T *)(g_curThread->sp+(ct)->stackSize))); \
        ((SR_CT_T *)(g_curThread->sp+(ct)->stackSize))->stackSize = sizeof(SR_CT_T);\
        LC_SET((ct)->lc);                \
        g_curThread->sp += (ct)->stackSize;  \
        if (((ret=func) > SR_CT_EXITED))           \
        {                               \
            return SR_CT_WAITING;       \
        }      \
        g_curThread->sp -= (ct)->stackSize; \
    } while (0)
#endif



//调用子协程，并返回子协程的返回值
#define SR_CT_CHILD(func)     \
    g_ctReturn=SR_FAIL;  \
    do                        \
    {                         \
        if((g_curThread->sp +(ct)->stackSize + sizeof(SR_CT_T))>=(g_curThread->stack+g_curThread->stackSize)) _OsErrHdl(_OS_ERR_STACK_OF);\
        SR_CT_INIT(((SR_CT_T *)(g_curThread->sp+(ct)->stackSize))); \
        LC_SET((ct)->lc);                \
        g_curThread->sp += (ct)->stackSize;  \
        if (((ret=func) > SR_CT_EXITED))  return SR_CT_WAITING;  \
        g_curThread->sp -= (ct)->stackSize; \
    } while (0)


//内部错误处理函数
void _OsErrHdl(int type);
	
/************协程相关数据结构定义*************/
#define FLAG_STATIC_CB        0x10
#define FLAG_STATIC_STACK     0x20
#define FLAG_MALLOC_CB        0x40

#define FLAG_VALID_MASK       0x8000    //有效掩码，flag最高bit为1，表示该对象有效


#define SR_NAME_LEN           16

#define SR_OS_STACK_SIZE_DEF  128
#define SR_THD_CB_SIZE        sizeof(_THREAD_T)
#define SR_SEM_CB_SIZE        sizeof(_SEM_T)
#define SR_MUTEX_CB_SIZE      sizeof(_MUTEX_T)

//协程状态枚举

#define THD_READY    0  /*!< 协程就绪*/
#define THD_RUNNING  1  /*!< 协程运行中*/
#define THD_SUSPEND  2  /*!< 协程挂起*/
#define THD_EXITED   3  /*!< 协程退出*/



//协程控制句柄
typedef struct _THREAD
{
	char name[16];             /*!< 协程名称*/
	int (*func)(void *args);   /*!< 协程任务函数*/
	void *args;                /*!< 协程任务函数的参数*/
    uint32_t priority;         /*!< 协程优先级*/
	uint16_t stackSize;        /*!< 协程栈大小*/
    uint16_t flags;            /*!< 协程内部flag*/
    uint8_t  state;            /*!< 协程状态*/

    os_slist_node_t list;      /*!< 运行协程链表*/
	os_slist_node_t dltList;   /*!< 待删除协程链表*/
	uint8_t *sp;               /*!< 上下文指针，指向栈空间某处*/
    uint8_t *stack;            /*!< 栈空间指针，指向动态栈dynStack或用户传入的静态栈*/
	uint8_t  dynStack[];       /*!< 动态协程栈空间缓存，柔性数组不占用该结构体空间*/
}_THREAD_T;

typedef void * SR_THREAD_T;

extern _THREAD_T *g_curThread;


#define  SR_GET_CT()   SR_CT_T *ct=((SR_CT_T *)(g_curThread->sp))

#define  SR_ALLOC_STACK(ct,size)  (((g_curThread->sp+sizeof(SR_CT_T)+size)<(g_curThread->stack+g_curThread->stackSize))?((ct)->stackSize=sizeof(SR_CT_T)+size,g_curThread->sp+sizeof(SR_CT_T)):(_OsErrHdl(_OS_ERR_STACK_OF),(void *)0))

//创建协程
SR_THREAD_T SR_OsThreadCreate(char *name,int (*func)(void *args),void *args,uint16_t stackSize,uint8_t priority);


//删除协程
int SR_OsThreadDelete(SR_THREAD_T thd);

//协程返回
#if  0
#define SR_CT_RETURN(ret)     {g_ctReturn=ret;SR_CT_INIT(ct);return SR_CT_EXITED;}

#else
#define SR_CT_RETURN(ret)     return ret;


#endif


//协程调度
void SR_Schedule(void);



/************信号量相关数据结构定义*************/


//信号量控制句柄
struct ct_sem {
    char name[16];   /*!< 名称*/
    uint16_t count;  /*!< 计数*/
    uint16_t maxCnt; /*!< 最大计数*/
    uint16_t flags;  /*!< 内部flag*/

};

typedef struct ct_sem _SEM_T;

//信号量初始化	
#define SR_CT_SEM_INIT(s, c) (s)->count = c
		

//获取信号量
#define SR_CT_SEM_TAKE(ct, s, timeout)   \
  do {						\
    SR_CT_WAIT_TIMEOUT(ct, ((s)->count > 0),timeout);\
    if((s)->count > 0) --(s)->count;				\
  } while(0)

//释放信号量
#define SR_CT_SEM_RELEASE(s) ++(s)->count

/************互斥量相关数据结构定义*****************/
//互斥量控制句柄
struct ct_mutex {
    char name[16];     /*!< 名称*/
    _THREAD_T *owner;  /*!< 互斥量拥有者（协程）*/
    int16_t lock;      /*!< 互斥锁*/
    uint16_t flags;    /*!< 内部flag*/
};

typedef struct ct_mutex _MUTEX_T;

//互斥量初始化	
#define SR_CT_MUTEX_INIT(m) {(m)->lock = 1;(m)->owner = SR_NULL;}
		

//获取互斥量
#define SR_CT_MUTEX_TAKE(ct, m, timeout)   \
  do {						\
    SR_CT_WAIT_TIMEOUT(ct, (((m)->lock == 1)||((m)->owner==g_curThread)),timeout);		\
		if((m)->lock == 1) (m)->owner=g_curThread;	\
		if((m)->owner==g_curThread) --(m)->lock;    \
  } while(0)

//释放互斥量
#define SR_CT_MUTEX_RELEASE(m)    \
	do {						 \
    if(((m)->owner==g_curThread)&&((m)->lock<1)) if((++(m)->lock) == 1) (m)->owner=SR_NULL;	\
  } while(0)
		

#include "cmsis_os2.h"


#endif

