展锐8910DM osiPmSource(TailQ)分析精华

展锐8910DM休眠问题的处理主要在于理解底层osiPmSource是如何链接的,理解了osiPmSource的链接机制也就基本上深入理解了休眠机制的处理大致处理流程;

备注:结合处理8910DM 休眠流程,去梳理8910DM 休眠相关的链表处理工作,文档略显粗糙,但基本上是讲解到了核心流程;



1:先来做static osiPmContext_t gOsiPmCtx全局变量的分析

1:老规矩先上代码:

第一部分:
typedef struct
{
    bool started;
    osiPmSourceHead_t resume_list;
    osiPmSourceHead_t active_list;
    osiPmSourceHead_t inactive_list;
    osiPmSourceHead_t prepare_list;
    osiShutdownRegHead_t shutdown_reg_list;
    osiPmSleep_t sleep;

    uint32_t boot_causes;
    osiBootMode_t boot_mode;
    uint32_t sleep32k_flags;
} osiPmContext_t;

第二部分:

typedef TAILQ_HEAD(osiPmSourceHead, osiPmSource) osiPmSourceHead_t;


#define    TAILQ_HEAD(name, type)                        
struct name {                                
struct type tqh_first;    / first element */            
struct type *tqh_last;    / addr of last next element */        
TRACEBUF                            
}

第三部分:结合上述第二部分理解即可看出osiPmSourceHead_t的本质
struct osiPmSourceHead {                                
struct osiPmSource tqh_first;    / first element */            
struct osiPmSource *tqh_last;    / addr of last next element */        
TRACEBUF                            
}

总结整个static osiPmContext_t gOsiPmCtx结构体的图片:

2:待插入元素typedef struct osiPmSource osiPmSource_t 代码的分析

第一部分:
typedef struct osiPmSource osiPmSource_t;
struct osiPmSource
{
    osiPmSourceIter_t resume_iter;
    osiPmSourceIter_t state_iter;

    uint32_t tag;
    void *cb_ctx;
    bool active;
    osiPmSourceOps_t ops;
};

第二部分:
typedef TAILQ_ENTRY(osiPmSource) osiPmSourceIter_t;


#define    TAILQ_ENTRY(type)                        
struct {                                
struct type tqe_next;    / next element */            
struct type *tqe_prev;    / address of previous next element */    
TRACEBUF                            
}


第三部分:结合第二部分理解typedef TAILQ_ENTRY(osiPmSource) osiPmSourceIter_t;其就相当于
一下结构体

struct {                                
struct osiPmSource   tqe_next;    / next element */            
struct osiPmSource    *tqe_prev;    / address of previous next element */    
TRACEBUF                            
}

总结:struct osiPmSource osiPmSource_t 如下所示

3:初始化流程以及列表插入分析

3.1 第一次初始化

3.2 初始化插入一个元素时

TAILQ_INSERT_TAIL(&d->inactive_list, p, state_iter);

3.3 初始化插入2个元素:

TAILQ_INSERT_TAIL(&d->inactive_list, p, state_iter);

3.4 初始化插入3个元素时:

4:分析一下TAILQ_FOREACH(p, &d->active_list, state_iter)

static osiPmSource_t *prvFindSourceByTag(osiPmContext_t *d, uint32_t tag)
{
    osiPmSource_t *p;
    TAILQ_FOREACH(p, &d->active_list, state_iter)
    {
        if (p->tag == tag)
        return p;
    }
    TAILQ_FOREACH(p, &d->inactive_list, state_iter)
    {
        if (p->tag == tag)
        return p;
    }
    TAILQ_FOREACH(p, &d->prepare_list, state_iter)
    {
        if (p->tag == tag)
        return p;
    }
    return NULL;

}
首先了解一下这里的宏定义:
#define    TAILQ_FOREACH(var, head, field)                    
for ((var) = ((head)->tqh_first);                
(var);                            
(var) = ((var)->field.tqe_next))

总结如下:核心流程TAILQ_FOREACH 如下图所描述

5:分析一下prvSuspend函数

static uint32_t prvSuspend(osiPmContext_t *d, osiSuspendMode_t mode, int64_t sleep_ms)

{

    // when PSM sleep condition isn't satisfied, it will return harmless

    osiShutdown(OSI_SHUTDOWN_PSM_SLEEP);

    OSI_LOGD(0, "deep sleep mode/%d sleep/%u", mode, (unsigned)sleep_ms);

    osiPmSource_t *p;

    //执行suspend list中的回调

    TAILQ_FOREACH_REVERSE(p, &d->resume_list, osiPmSourceHead, resume_iter)

}

#define TAILQ_FOREACH_REVERSE(var, head, headname, field)

for ((var) = ( *( ( (struct headname *)( (head)->tqh_last) )->tqh_last) ); \

(var);

(var) = ( ( ( (struct headname *)( (var)->field.tqe_prev) )->tqh_last) )

5.1:赏析一下TAILQ_FOREACH_REVERSE(p, &d->resume_list, osiPmSourceHead, resume_iter)

TAILQ_FOREACH_REVERSE(p, &d->resume_list, osiPmSourceHead, resume_iter)

我们这边经过转化后

#define TAILQ_FOREACH_REVERSE(var, head, headname, field)

//一句代码干了3件事。太厉害了

for ((var) = ( *( ( (struct osiPmSourceHead *)( (head)->tqh_last) )->tqh_last) ); \

(var);

(var) = ( ( ( (struct osiPmSourceHead *)( (var)->field.tqe_prev) )->tqh_last) ) 5

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值