打印
[程序源码]

你把UML用在mcu或者linux开发上面了吗?

[复制链接]
楼主: keer_zu
手机看帖
扫描二维码
随时随地手机跟帖
21
keer_zu|  楼主 | 2014-5-8 10:14 | 只看该作者 回帖奖励 |倒序浏览
现在的21比起老坛子的时候,闷多了啊!不比当年了啊。老版主都上哪里了?

使用特权

评论回复
22
lxyppc| | 2014-5-8 13:23 | 只看该作者
现在都追求短平快,这些东西不要说设计
能看得懂就不错了

使用特权

评论回复
23
keer_zu|  楼主 | 2014-5-8 13:35 | 只看该作者
这样复用性强,模块儿化程度高。团队开发的分工更明确,调试也可以各司其职。
周期当然会更短,效率更高。看不懂是不习惯,这样做可读性更高。具体实践的号召力,已经使我身边已经有更多人开始采用这样的方式了。

使用特权

评论回复
24
lzlz70707| | 2014-5-8 14:46 | 只看该作者
MCU主要做控制用,程序关注流程和算法多一些。

使用特权

评论回复
25
keer_zu|  楼主 | 2014-5-8 16:45 | 只看该作者
这个不排斥流程和算法吧。采用已经验证过的设计模式,减少重复劳动。在设计上,这样的分析和设计既降低了复杂性,又能突出问题的重点,让功能更明确,性能更有保证。

使用特权

评论回复
26
keer_zu|  楼主 | 2014-5-9 15:46 | 只看该作者

存放一开始就申请好的缓冲区,避免频繁无止境malloc带来系统不可预料的错误。




/********************** buffer queue ******************************/
_BUF_QUEUE_T *_buf_q_init(unsigned int q_size,unsigned int buf_size)
{
        int i,ret;
        //unsigned int count = 0;
        unsigned char *buf;
        _BUF_QUEUE_T *q;
       
        if(q_size == 0 || buf_size == 0){
                printf("%s: err para!\n",__FUNCTION__);
                return ERR_PARA;
        }
       
        q = (_BUF_QUEUE_T *)malloc(sizeof(_BUF_QUEUE_T));
        if(q == NULL){
                printf("%s:  _BUF_QUEUE_T malloc err!\n",__FUNCTION__);
                return NULL;
        }

        pthread_mutex_init(&q->mutex,NULL);

        q->_buf_size = buf_size;
        q->_q_size = q_size;

        q->front = 0;
        q->rear = 0;

        q->_buf_p = (unsigned char **)malloc(sizeof(unsigned char *) * q->_q_size);
        if(q->_buf_p == NULL){
                printf("%s:  q->_buf_p malloc err!\n",__FUNCTION__);
                return NULL;
        }

        do{
                buf = (unsigned char *)malloc(q->_buf_size);
                if(buf == NULL){
                        printf("%s:  buf_q->_buf_p[i] malloc err!\n",__FUNCTION__);
                        return NULL;
                }
                ret = q_buf_insert(q,buf);
                //count ++;
                //_DBG("+++++q_size:%d  count:%d\n",q->_q_size,count);
        }while(ret == QUE_OK);

        free(buf);

        return q;
}

int _q_buf_is_full(_BUF_QUEUE_T *q)
{
        if(q == NULL)
                return QUE_ERR;
       
        if(q->front == (q->rear + 1) % q->_q_size)
                return QUE_TURN;  
        else  
                return QUE_FALSE;  
}

unsigned char *get_free_q_buf(_BUF_QUEUE_T *q)
{
        if(!_q_buf_is_full(q)){
                return q->_buf_p[q->rear];
        }else
                return NULL;
}

int q_buf_insert(_BUF_QUEUE_T *q,unsigned char *buf)
{
        if(q == NULL)
                return QUE_ERR;  
       
        if(_q_buf_is_full(q))
                return QUE_ERR;  

        PTHREAD_LOCK(&q->mutex);
        q->_buf_p[q->rear] = buf;  
        q->rear = (q->rear + 1) % q->_q_size;
        PTHREAD_UNLOCK(&q->mutex);
        usleep(100);
//        EXIT_CRITICAL();

       
        return QUE_OK;  

}

int _q_buf_is_empty(_BUF_QUEUE_T *q)
{
        if(q == NULL)
                return QUE_ERR;
       
        if(q->front == q->rear) //
                return QUE_TURN;  
        else  
                return QUE_FALSE;  
}



unsigned char *get_q_buf(_BUF_QUEUE_T *q)
{
        unsigned char *buf;
       
        if(q == NULL)
                return NULL;
       
        if(_q_buf_is_empty(q))
                return NULL;

        PTHREAD_LOCK(&q->mutex);
        buf = q->_buf_p[q->front];  
        q->front  = (q->front  + 1) % q->_q_size;
        PTHREAD_UNLOCK(&q->mutex);
        usleep(100);

       
        return buf;       
}

int _buf_q_deinit(_BUF_QUEUE_T *q)
{
        int i;
       
        if(q == NULL){
                printf("%s: err para!\n",__FUNCTION__);
                return ERR_PARA;
        }

        pthread_mutex_destroy(&q->mutex);

        for(i = 0;i < q->_q_size;i ++){
                if(q->_buf_p[i] != NULL){
                        free(q->_buf_p[i]);
                }
        }

        if(q->_buf_p != NULL){
                free(q->_buf_p);
        }

        free(q);
        q = NULL;

        return OK;
}

使用特权

评论回复
27
keer_zu|  楼主 | 2014-5-9 15:54 | 只看该作者
用来存放消息的环形缓冲队列。用于接收和处理去耦合。

/********************** buffer queue ******************************/
M_BUF_QUEUE_T *m_buf_q_init(unsigned int q_size,unsigned int buf_size)
{
        int i;
        M_BUF_QUEUE_T *q;
       
        if(q_size == 0 || buf_size == 0){
                printf("%s: err para!\n",__FUNCTION__);
                return ERR_PARA;
        }
       
        q = (M_BUF_QUEUE_T *)malloc(sizeof(M_BUF_QUEUE_T));
        if(q == NULL){
                printf("%s:  _BUF_QUEUE_T malloc err!\n",__FUNCTION__);
                return NULL;
        }

        q->_buf_size = buf_size;
        q->_q_size = q_size;

        q->_buf_p = (unsigned char **)malloc(sizeof(unsigned char *) * q->_q_size);
        if(q->_buf_p == NULL){
                printf("%s:  q->_buf_p malloc err!\n",__FUNCTION__);
                return NULL;
        }

        for(i = 0;i < q->_q_size;i ++){
                q->_buf_p[i] = (unsigned char *)malloc(q->_buf_size);
                if(q->_buf_p[i] == NULL){
                        printf("%s:  buf_q->_buf_p[i] malloc err!\n",__FUNCTION__);
                        return NULL;
                }
        }

        q->front = 0;
        q->rear = 0;

        return q;
}

int m_q_buf_is_full(M_BUF_QUEUE_T *q)
{
        if(q == NULL)
                return QUE_ERR;
       
        if(q->front == (q->rear + 1) % q->_buf_size) //
                return QUE_TURN;  
        else  
                return QUE_FALSE;  
}

unsigned char *get_m_free_q_buf(M_BUF_QUEUE_T *q)
{
        if(!m_q_buf_is_full(q)){
                return q->_buf_p[q->rear];
        }else
                return NULL;
}

int m_q_buf_insert(M_BUF_QUEUE_T *q)
{
        if(q == NULL)
                return QUE_ERR;  
       
        if(m_q_buf_is_full(q))
                return QUE_ERR;  


        q->rear = (q->rear + 1) % q->_buf_size; //

       
        return QUE_OK;  

}

int m_q_buf_is_empty(M_BUF_QUEUE_T *q)
{
        if(q == NULL)
                return QUE_ERR;
       
        if(q->front == q->rear) //
                return QUE_TURN;  
        else  
                return QUE_FALSE;  
}

unsigned char *get_m_process_q_buf(M_BUF_QUEUE_T *q)
{
        if(!m_q_buf_is_empty(q)){

                return q->_buf_p[q->front];
        }else
                return NULL;
}

int process_m_q_buf_delete(M_BUF_QUEUE_T *q)
{  
        if(q == NULL)
                return QUE_ERR;
       
        if(m_q_buf_is_empty(q))
                return QUE_ERR;

        q->front  = (q->front  + 1) % q->_buf_size;  


       
        return QUE_OK;       
}

int m_buf_q_deinit(M_BUF_QUEUE_T *q)
{
        int i;
       
        if(q == NULL){
                printf("%s: err para!\n",__FUNCTION__);
                return ERR_PARA;
        }

        for(i = 0;i < q->_q_size;i ++){
                if(q->_buf_p[i] != NULL){
                        free(q->_buf_p[i]);
                }
        }

        if(q->_buf_p != NULL){
                free(q->_buf_p);
        }

        free(q);
        q = NULL;

        return OK;
}

使用特权

评论回复
28
keer_zu|  楼主 | 2014-5-9 15:55 | 只看该作者
第一个队列:
typedef struct{
        unsigned char *cmd_para[FRAME_BUF_Q_SIZE];
        int front;
        int rear;
}PARA_BUF_QUEUE_T;

使用特权

评论回复
29
keer_zu|  楼主 | 2014-5-9 15:55 | 只看该作者
typedef struct{
        unsigned int _q_size;
        unsigned _buf_size;
        unsigned char **_buf_p;
        int front;
        int rear;
}M_BUF_QUEUE_T;

使用特权

评论回复
30
keer_zu|  楼主 | 2014-5-9 15:55 | 只看该作者
后边一个:
typedef struct{
        pthread_mutex_t mutex;
        unsigned int _q_size;
        unsigned int _buf_size;
        unsigned char **_buf_p;
        int front;
        int rear;
}_BUF_QUEUE_T;

使用特权

评论回复
31
keer_zu|  楼主 | 2014-5-9 17:04 | 只看该作者

使用特权

评论回复
32
keer_zu|  楼主 | 2014-5-10 07:34 | 只看该作者
自己顶一下吧,找感兴趣者

使用特权

评论回复
33
keer_zu|  楼主 | 2014-5-10 09:02 | 只看该作者
linux下的list.h提供的双链表和哈希表,被内核很多重要数据结构使用。好多linux应用工程师将他用在自己的应用程序,来构建需要的数据结构。讲他用于mcu,如msp430,还有cotex-mx核的mcu,发现很好用。

使用特权

评论回复
34
keer_zu|  楼主 | 2014-5-10 09:08 | 只看该作者
双链表:


#define prefetch(x) ((void)x)
#define LIST_POISON1  0x0
#define LIST_POISON2  0x0

#ifdef __compiler_offsetof
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif

#define container_of(ptr, type, member) ({ \
        const typeof( ((type *)0)->member ) *__mptr = (ptr); \
        (type *)( (char *)__mptr - offsetof(type,member) );})


/*
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/

struct list_head {
        struct list_head *next, *prev;
};

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
        struct list_head name = LIST_HEAD_INIT(name)

static inline void INIT_LIST_HEAD(struct list_head *list)
{
        list->next = list;
        list->prev = list;
}

/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
#ifndef CONFIG_DEBUG_LIST
static inline void __list_add(struct list_head *new,
                              struct list_head *prev,
                              struct list_head *next)
{
        next->prev = new;
        new->next = next;
        new->prev = prev;
        prev->next = new;
}
#else
extern void __list_add(struct list_head *new,
                              struct list_head *prev,
                              struct list_head *next);
#endif

/**
* list_add - add a new entry
* a- new: new entry to be added
* a- head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
#ifndef CONFIG_DEBUG_LIST
static inline void list_add(struct list_head *new, struct list_head *head)
{
        __list_add(new, head, head->next);
}
#else
extern void list_add(struct list_head *new, struct list_head *head);
#endif


/**
* list_add_tail - add a new entry
* a- new: new entry to be added
* a- head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
        __list_add(new, head->prev, head);
}

/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_add_rcu(struct list_head * new,
                struct list_head * prev, struct list_head * next)
{
        new->next = next;
        new->prev = prev;
        smp_wmb();
        next->prev = new;
        prev->next = new;
}

/**
* list_add_rcu - add a new entry to rcu-protected list
* a- new: new entry to be added
* a- head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*
* The caller must take whatever precautions are necessary
* (such as holding appropriate locks) to avoid racing
* with another list-mutation primitive, such as list_add_rcu()
* or list_del_rcu(), running on this same list.
* However, it is perfectly legal to run concurrently with
* the _rcu list-traversal primitives, such as
* list_for_each_entry_rcu().
*/
static inline void list_add_rcu(struct list_head *new, struct list_head *head)
{
        __list_add_rcu(new, head, head->next);
}

/**
* list_add_tail_rcu - add a new entry to rcu-protected list
* a- new: new entry to be added
* a- head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*
* The caller must take whatever precautions are necessary
* (such as holding appropriate locks) to avoid racing
* with another list-mutation primitive, such as list_add_tail_rcu()
* or list_del_rcu(), running on this same list.
* However, it is perfectly legal to run concurrently with
* the _rcu list-traversal primitives, such as
* list_for_each_entry_rcu().
*/
static inline void list_add_tail_rcu(struct list_head *new,
                                        struct list_head *head)
{
        __list_add_rcu(new, head->prev, head);
}

/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
        next->prev = prev;
        prev->next = next;
}

/**
* list_del - deletes entry from list.
* a- entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
#ifndef CONFIG_DEBUG_LIST
static inline void list_del(struct list_head *entry)
{
        __list_del(entry->prev, entry->next);
        entry->next = LIST_POISON1;
        entry->prev = LIST_POISON2;
}
#else
extern void list_del(struct list_head *entry);
#endif

/**
* list_del_rcu - deletes entry from list without re-initialization
* a- entry: the element to delete from the list.
*
* Note: list_empty() on entry does not return true after this,
* the entry is in an undefined state. It is useful for RCU based
* lockfree traversal.
*
* In particular, it means that we can not poison the forward
* pointers that may still be used for walking the list.
*
* The caller must take whatever precautions are necessary
* (such as holding appropriate locks) to avoid racing
* with another list-mutation primitive, such as list_del_rcu()
* or list_add_rcu(), running on this same list.
* However, it is perfectly legal to run concurrently with
* the _rcu list-traversal primitives, such as
* list_for_each_entry_rcu().
*
* Note that the caller is not permitted to immediately free
* the newly deleted entry.  Instead, either synchronize_rcu()
* or call_rcu() must be used to defer freeing until an RCU
* grace period has elapsed.
*/
static inline void list_del_rcu(struct list_head *entry)
{
        __list_del(entry->prev, entry->next);
        entry->prev = LIST_POISON2;
}

/**
* list_replace - replace old entry by new one
* a- old : the element to be replaced
* a- new : the new element to insert
*
* If a- old was empty, it will be overwritten.
*/
static inline void list_replace(struct list_head *old,
                                struct list_head *new)
{
        new->next = old->next;
        new->next->prev = new;
        new->prev = old->prev;
        new->prev->next = new;
}

static inline void list_replace_init(struct list_head *old,
                                        struct list_head *new)
{
        list_replace(old, new);
        INIT_LIST_HEAD(old);
}

/**
* list_replace_rcu - replace old entry by new one
* a- old : the element to be replaced
* a- new : the new element to insert
*
* The a- old entry will be replaced with the a- new entry atomically.
* Note: a- old should not be empty.
*/
static inline void list_replace_rcu(struct list_head *old,
                                struct list_head *new)
{
        new->next = old->next;
        new->prev = old->prev;
        smp_wmb();
        new->next->prev = new;
        new->prev->next = new;
        old->prev = LIST_POISON2;
}

/**
* list_del_init - deletes entry from list and reinitialize it.
* a- entry: the element to delete from the list.
*/
static inline void list_del_init(struct list_head *entry)
{
        __list_del(entry->prev, entry->next);
        INIT_LIST_HEAD(entry);
}

/**
* list_move - delete from one list and add as another's head
* a- list: the entry to move
* a- head: the head that will precede our entry
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
        __list_del(list->prev, list->next);
        list_add(list, head);
}

/**
* list_move_tail - delete from one list and add as another's tail
* a- list: the entry to move
* a- head: the head that will follow our entry
*/
static inline void list_move_tail(struct list_head *list,
                                  struct list_head *head)
{
        __list_del(list->prev, list->next);
        list_add_tail(list, head);
}

/**
* list_is_last - tests whether a- list is the last entry in list a- head
* a- list: the entry to test
* a- head: the head of the list
*/
static inline int list_is_last(const struct list_head *list,
                                const struct list_head *head)
{
        return list->next == head;
}

/**
* list_empty - tests whether a list is empty
* a- head: the list to test.
*/
static inline int list_empty(const struct list_head *head)
{
        return head->next == head;
}

/**
* list_empty_careful - tests whether a list is empty and not being modified
* a- head: the list to test
*
* Description:
* tests whether a list is empty _and_ checks that no other CPU might be
* in the process of modifying either member (next or prev)
*
* NOTE: using list_empty_careful() without synchronization
* can only be safe if the only activity that can happen
* to the list entry is list_del_init(). Eg. it cannot be used
* if another CPU could re-list_add() it.
*/
static inline int list_empty_careful(const struct list_head *head)
{
        struct list_head *next = head->next;
        return (next == head) && (next == head->prev);
}

static inline void __list_splice(struct list_head *list,
                                 struct list_head *head)
{
        struct list_head *first = list->next;
        struct list_head *last = list->prev;
        struct list_head *at = head->next;

        first->prev = head;
        head->next = first;

        last->next = at;
        at->prev = last;
}

/**
* list_splice - join two lists
* a- list: the new list to add.
* a- head: the place to add it in the first list.
*/
static inline void list_splice(struct list_head *list, struct list_head *head)
{
        if (!list_empty(list))
                __list_splice(list, head);
}

/**
* list_splice_init - join two lists and reinitialise the emptied list.
* a- list: the new list to add.
* a- head: the place to add it in the first list.
*
* The list at a- list is reinitialised
*/
static inline void list_splice_init(struct list_head *list,
                                    struct list_head *head)
{
        if (!list_empty(list)) {
                __list_splice(list, head);
                INIT_LIST_HEAD(list);
        }
}

/**
* list_splice_init_rcu - splice an RCU-protected list into an existing list.
* a- list:        the RCU-protected list to splice
* a- head:        the place in the list to splice the first list into
* a- sync:        function to sync: synchronize_rcu(), synchronize_sched(), ...
*
* a- head can be RCU-read traversed concurrently with this function.
*
* Note that this function blocks.
*
* Important note: the caller must take whatever action is necessary to
*        prevent any other updates to a- head.  In principle, it is possible
*        to modify the list as soon as sync() begins execution.
*        If this sort of thing becomes necessary, an alternative version
*        based on call_rcu() could be created.  But only if -really-
*        needed -- there is no shortage of RCU API members.
*/
static inline void list_splice_init_rcu(struct list_head *list,
                                        struct list_head *head,
                                        void (*sync)(void))
{
        struct list_head *first = list->next;
        struct list_head *last = list->prev;
        struct list_head *at = head->next;

        if (list_empty(head))
                return;

        /* "first" and "last" tracking list, so initialize it. */

        INIT_LIST_HEAD(list);

        /*
         * At this point, the list body still points to the source list.
         * Wait for any readers to finish using the list before splicing
         * the list body into the new list.  Any new readers will see
         * an empty list.
         */

        sync();

        /*
         * Readers are finished with the source list, so perform splice.
         * The order is important if the new list is global and accessible
         * to concurrent RCU readers.  Note that RCU readers are not
         * permitted to traverse the prev pointers without excluding
         * this function.
         */

        last->next = at;
        smp_wmb();
        head->next = first;
        first->prev = head;
        at->prev = last;
}

/**
* list_entry - get the struct for this entry
* a- ptr:        the &struct list_head pointer.
* a- type:        the type of the struct this is embedded in.
* a- member:        the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
        container_of(ptr, type, member)

/**
* list_first_entry - get the first element from a list
* a- ptr:        the list head to take the element from.
* a- type:        the type of the struct this is embedded in.
* a- member:        the name of the list_struct within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_first_entry(ptr, type, member) \
        list_entry((ptr)->next, type, member)

使用特权

评论回复
35
keer_zu|  楼主 | 2014-5-10 09:10 | 只看该作者
双链表:

/**
* list_for_each        -        iterate over a list
* a- pos:        the &struct list_head to use as a loop cursor.
* a- head:        the head for your list.
*/
#define list_for_each(pos, head) \
        for (pos = (head)->next; prefetch(pos->next), pos != (head); \
                pos = pos->next)

/**
* __list_for_each        -        iterate over a list
* a- pos:        the &struct list_head to use as a loop cursor.
* a- head:        the head for your list.
*
* This variant differs from list_for_each() in that it's the
* simplest possible list iteration code, no prefetching is done.
* Use this for code that knows the list to be very short (empty
* or 1 entry) most of the time.
*/
#define __list_for_each(pos, head) \
        for (pos = (head)->next; pos != (head); pos = pos->next)

/**
* list_for_each_prev        -        iterate over a list backwards
* a- pos:        the &struct list_head to use as a loop cursor.
* a- head:        the head for your list.
*/
#define list_for_each_prev(pos, head) \
        for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
                pos = pos->prev)

/**
* list_for_each_safe - iterate over a list safe against removal of list entry
* a- pos:        the &struct list_head to use as a loop cursor.
* a- n:                another &struct list_head to use as temporary storage
* a- head:        the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
        for (pos = (head)->next, n = pos->next; pos != (head); \
                pos = n, n = pos->next)

/**
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
* a- pos:        the &struct list_head to use as a loop cursor.
* a- n:                another &struct list_head to use as temporary storage
* a- head:        the head for your list.
*/
#define list_for_each_prev_safe(pos, n, head) \
        for (pos = (head)->prev, n = pos->prev; \
             prefetch(pos->prev), pos != (head); \
             pos = n, n = pos->prev)

/**
* list_for_each_entry        -        iterate over list of given type
* a- pos:        the type * to use as a loop cursor.
* a- head:        the head for your list.
* a- member:        the name of the list_struct within the struct.
*/
#define list_for_each_entry(pos, head, member)                                \
        for (pos = list_entry((head)->next, typeof(*pos), member);        \
             prefetch(pos->member.next), &pos->member != (head);         \
             pos = list_entry(pos->member.next, typeof(*pos), member))

/**
* list_for_each_entry_reverse - iterate backwards over list of given type.
* a- pos:        the type * to use as a loop cursor.
* a- head:        the head for your list.
* a- member:        the name of the list_struct within the struct.
*/
#define list_for_each_entry_reverse(pos, head, member)                        \
        for (pos = list_entry((head)->prev, typeof(*pos), member);        \
             prefetch(pos->member.prev), &pos->member != (head);         \
             pos = list_entry(pos->member.prev, typeof(*pos), member))

/**
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
* a- pos:        the type * to use as a start point
* a- head:        the head of the list
* a- member:        the name of the list_struct within the struct.
*
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
*/
#define list_prepare_entry(pos, head, member) \
        ((pos) ? : list_entry(head, typeof(*pos), member))

/**
* list_for_each_entry_continue - continue iteration over list of given type
* a- pos:        the type * to use as a loop cursor.
* a- head:        the head for your list.
* a- member:        the name of the list_struct within the struct.
*
* Continue to iterate over list of given type, continuing after
* the current position.
*/
#define list_for_each_entry_continue(pos, head, member)                 \
        for (pos = list_entry(pos->member.next, typeof(*pos), member);        \
             prefetch(pos->member.next), &pos->member != (head);        \
             pos = list_entry(pos->member.next, typeof(*pos), member))

/**
* list_for_each_entry_continue_reverse - iterate backwards from the given point
* a- pos:        the type * to use as a loop cursor.
* a- head:        the head for your list.
* a- member:        the name of the list_struct within the struct.
*
* Start to iterate over list of given type backwards, continuing after
* the current position.
*/
#define list_for_each_entry_continue_reverse(pos, head, member)                \
        for (pos = list_entry(pos->member.prev, typeof(*pos), member);        \
             prefetch(pos->member.prev), &pos->member != (head);        \
             pos = list_entry(pos->member.prev, typeof(*pos), member))

/**
* list_for_each_entry_from - iterate over list of given type from the current point
* a- pos:        the type * to use as a loop cursor.
* a- head:        the head for your list.
* a- member:        the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing from current position.
*/
#define list_for_each_entry_from(pos, head, member)                         \
        for (; prefetch(pos->member.next), &pos->member != (head);        \
             pos = list_entry(pos->member.next, typeof(*pos), member))

/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* a- pos:        the type * to use as a loop cursor.
* a- n:                another type * to use as temporary storage
* a- head:        the head for your list.
* a- member:        the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member)                        \
        for (pos = list_entry((head)->next, typeof(*pos), member),        \
                n = list_entry(pos->member.next, typeof(*pos), member);        \
             &pos->member != (head);                                         \
             pos = n, n = list_entry(n->member.next, typeof(*n), member))

/**
* list_for_each_entry_safe_continue
* a- pos:        the type * to use as a loop cursor.
* a- n:                another type * to use as temporary storage
* a- head:        the head for your list.
* a- member:        the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing after current point,
* safe against removal of list entry.
*/
#define list_for_each_entry_safe_continue(pos, n, head, member)                 \
        for (pos = list_entry(pos->member.next, typeof(*pos), member),                 \
                n = list_entry(pos->member.next, typeof(*pos), member);                \
             &pos->member != (head);                                                \
             pos = n, n = list_entry(n->member.next, typeof(*n), member))

/**
* list_for_each_entry_safe_from
* a- pos:        the type * to use as a loop cursor.
* a- n:                another type * to use as temporary storage
* a- head:        the head for your list.
* a- member:        the name of the list_struct within the struct.
*
* Iterate over list of given type from current point, safe against
* removal of list entry.
*/
#define list_for_each_entry_safe_from(pos, n, head, member)                         \
        for (n = list_entry(pos->member.next, typeof(*pos), member);                \
             &pos->member != (head);                                                \
             pos = n, n = list_entry(n->member.next, typeof(*n), member))

/**
* list_for_each_entry_safe_reverse
* a- pos:        the type * to use as a loop cursor.
* a- n:                another type * to use as temporary storage
* a- head:        the head for your list.
* a- member:        the name of the list_struct within the struct.
*
* Iterate backwards over list of given type, safe against removal
* of list entry.
*/
#define list_for_each_entry_safe_reverse(pos, n, head, member)                \
        for (pos = list_entry((head)->prev, typeof(*pos), member),        \
                n = list_entry(pos->member.prev, typeof(*pos), member);        \
             &pos->member != (head);                                         \
             pos = n, n = list_entry(n->member.prev, typeof(*n), member))

/**
* list_for_each_rcu        -        iterate over an rcu-protected list
* a- pos:        the &struct list_head to use as a loop cursor.
* a- head:        the head for your list.
*
* This list-traversal primitive may safely run concurrently with
* the _rcu list-mutation primitives such as list_add_rcu()
* as long as the traversal is guarded by rcu_read_lock().
*/
#define list_for_each_rcu(pos, head) \
        for (pos = (head)->next; \
                prefetch(rcu_dereference(pos)->next), pos != (head); \
                pos = pos->next)

#define __list_for_each_rcu(pos, head) \
        for (pos = (head)->next; \
                rcu_dereference(pos) != (head); \
                pos = pos->next)

/**
* list_for_each_safe_rcu
* a- pos:        the &struct list_head to use as a loop cursor.
* a- n:                another &struct list_head to use as temporary storage
* a- head:        the head for your list.
*
* Iterate over an rcu-protected list, safe against removal of list entry.
*
* This list-traversal primitive may safely run concurrently with
* the _rcu list-mutation primitives such as list_add_rcu()
* as long as the traversal is guarded by rcu_read_lock().
*/
#define list_for_each_safe_rcu(pos, n, head) \
        for (pos = (head)->next; \
                n = rcu_dereference(pos)->next, pos != (head); \
                pos = n)

/**
* list_for_each_entry_rcu        -        iterate over rcu list of given type
* a- pos:        the type * to use as a loop cursor.
* a- head:        the head for your list.
* a- member:        the name of the list_struct within the struct.
*
* This list-traversal primitive may safely run concurrently with
* the _rcu list-mutation primitives such as list_add_rcu()
* as long as the traversal is guarded by rcu_read_lock().
*/
#define list_for_each_entry_rcu(pos, head, member) \
        for (pos = list_entry((head)->next, typeof(*pos), member); \
                prefetch(rcu_dereference(pos)->member.next), \
                        &pos->member != (head); \
                pos = list_entry(pos->member.next, typeof(*pos), member))


/**
* list_for_each_continue_rcu
* a- pos:        the &struct list_head to use as a loop cursor.
* a- head:        the head for your list.
*
* Iterate over an rcu-protected list, continuing after current point.
*
* This list-traversal primitive may safely run concurrently with
* the _rcu list-mutation primitives such as list_add_rcu()
* as long as the traversal is guarded by rcu_read_lock().
*/
#define list_for_each_continue_rcu(pos, head) \
        for ((pos) = (pos)->next; \
                prefetch(rcu_dereference((pos))->next), (pos) != (head); \
                (pos) = (pos)->next)

使用特权

评论回复
36
keer_zu|  楼主 | 2014-5-10 09:10 | 只看该作者
哈希表:

/*
* Double linked lists with a single pointer list head.
* Mostly useful for hash tables where the two pointer list head is
* too wasteful.
* You lose the ability to access the tail in O(1).
*/

struct hlist_head {
        struct hlist_node *first;
};

struct hlist_node {
        struct hlist_node *next, **pprev;
};

#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
        h->next = NULL;
        h->pprev = NULL;
}

static inline int hlist_unhashed(const struct hlist_node *h)
{
        return !h->pprev;
}

static inline int hlist_empty(const struct hlist_head *h)
{
        return !h->first;
}

static inline void __hlist_del(struct hlist_node *n)
{
        struct hlist_node *next = n->next;
        struct hlist_node **pprev = n->pprev;
        *pprev = next;
        if (next)
                next->pprev = pprev;
}

static inline void hlist_del(struct hlist_node *n)
{
        __hlist_del(n);
        n->next = LIST_POISON1;
        n->pprev = LIST_POISON2;
}

/**
* hlist_del_rcu - deletes entry from hash list without re-initialization
* a- n: the element to delete from the hash list.
*
* Note: list_unhashed() on entry does not return true after this,
* the entry is in an undefined state. It is useful for RCU based
* lockfree traversal.
*
* In particular, it means that we can not poison the forward
* pointers that may still be used for walking the hash list.
*
* The caller must take whatever precautions are necessary
* (such as holding appropriate locks) to avoid racing
* with another list-mutation primitive, such as hlist_add_head_rcu()
* or hlist_del_rcu(), running on this same list.
* However, it is perfectly legal to run concurrently with
* the _rcu list-traversal primitives, such as
* hlist_for_each_entry().
*/
static inline void hlist_del_rcu(struct hlist_node *n)
{
        __hlist_del(n);
        n->pprev = LIST_POISON2;
}

static inline void hlist_del_init(struct hlist_node *n)
{
        if (!hlist_unhashed(n)) {
                __hlist_del(n);
                INIT_HLIST_NODE(n);
        }
}

/**
* hlist_replace_rcu - replace old entry by new one
* a- old : the element to be replaced
* a- new : the new element to insert
*
* The a- old entry will be replaced with the a- new entry atomically.
*/
static inline void hlist_replace_rcu(struct hlist_node *old,
                                        struct hlist_node *new)
{
        struct hlist_node *next = old->next;

        new->next = next;
        new->pprev = old->pprev;
        smp_wmb();
        if (next)
                new->next->pprev = &new->next;
        *new->pprev = new;
        old->pprev = LIST_POISON2;
}

static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
        struct hlist_node *first = h->first;
        n->next = first;
        if (first)
                first->pprev = &n->next;
        h->first = n;
        n->pprev = &h->first;
}


/**
* hlist_add_head_rcu
* a- n: the element to add to the hash list.
* a- h: the list to add to.
*
* Description:
* Adds the specified element to the specified hlist,
* while permitting racing traversals.
*
* The caller must take whatever precautions are necessary
* (such as holding appropriate locks) to avoid racing
* with another list-mutation primitive, such as hlist_add_head_rcu()
* or hlist_del_rcu(), running on this same list.
* However, it is perfectly legal to run concurrently with
* the _rcu list-traversal primitives, such as
* hlist_for_each_entry_rcu(), used to prevent memory-consistency
* problems on Alpha CPUs.  Regardless of the type of CPU, the
* list-traversal primitive must be guarded by rcu_read_lock().
*/
static inline void hlist_add_head_rcu(struct hlist_node *n,
                                        struct hlist_head *h)
{
        struct hlist_node *first = h->first;
        n->next = first;
        n->pprev = &h->first;
        smp_wmb();
        if (first)
                first->pprev = &n->next;
        h->first = n;
}

/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
                                        struct hlist_node *next)
{
        n->pprev = next->pprev;
        n->next = next;
        next->pprev = &n->next;
        *(n->pprev) = n;
}

static inline void hlist_add_after(struct hlist_node *n,
                                        struct hlist_node *next)
{
        next->next = n->next;
        n->next = next;
        next->pprev = &n->next;

        if(next->next)
                next->next->pprev  = &next->next;
}

/**
* hlist_add_before_rcu
* a- n: the new element to add to the hash list.
* a- next: the existing element to add the new element before.
*
* Description:
* Adds the specified element to the specified hlist
* before the specified node while permitting racing traversals.
*
* The caller must take whatever precautions are necessary
* (such as holding appropriate locks) to avoid racing
* with another list-mutation primitive, such as hlist_add_head_rcu()
* or hlist_del_rcu(), running on this same list.
* However, it is perfectly legal to run concurrently with
* the _rcu list-traversal primitives, such as
* hlist_for_each_entry_rcu(), used to prevent memory-consistency
* problems on Alpha CPUs.
*/
static inline void hlist_add_before_rcu(struct hlist_node *n,
                                        struct hlist_node *next)
{
        n->pprev = next->pprev;
        n->next = next;
        smp_wmb();
        next->pprev = &n->next;
        *(n->pprev) = n;
}

/**
* hlist_add_after_rcu
* a- prev: the existing element to add the new element after.
* a- n: the new element to add to the hash list.
*
* Description:
* Adds the specified element to the specified hlist
* after the specified node while permitting racing traversals.
*
* The caller must take whatever precautions are necessary
* (such as holding appropriate locks) to avoid racing
* with another list-mutation primitive, such as hlist_add_head_rcu()
* or hlist_del_rcu(), running on this same list.
* However, it is perfectly legal to run concurrently with
* the _rcu list-traversal primitives, such as
* hlist_for_each_entry_rcu(), used to prevent memory-consistency
* problems on Alpha CPUs.
*/
static inline void hlist_add_after_rcu(struct hlist_node *prev,
                                       struct hlist_node *n)
{
        n->next = prev->next;
        n->pprev = &prev->next;
        smp_wmb();
        prev->next = n;
        if (n->next)
                n->next->pprev = &n->next;
}

#define hlist_entry(ptr, type, member) container_of(ptr,type,member)

#define hlist_for_each(pos, head) \
        for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
             pos = pos->next)

#define hlist_for_each_safe(pos, n, head) \
        for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
             pos = n)

/**
* hlist_for_each_entry        - iterate over list of given type
* a- tpos:        the type * to use as a loop cursor.
* a- pos:        the &struct hlist_node to use as a loop cursor.
* a- head:        the head for your list.
* a- member:        the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry(tpos, pos, head, member)                         \
        for (pos = (head)->first;                                         \
             pos && ({ prefetch(pos->next); 1;}) &&                         \
                ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
             pos = pos->next)

/**
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point
* a- tpos:        the type * to use as a loop cursor.
* a- pos:        the &struct hlist_node to use as a loop cursor.
* a- member:        the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_continue(tpos, pos, member)                 \
        for (pos = (pos)->next;                                                 \
             pos && ({ prefetch(pos->next); 1;}) &&                         \
                ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
             pos = pos->next)

/**
* hlist_for_each_entry_from - iterate over a hlist continuing from current point
* a- tpos:        the type * to use as a loop cursor.
* a- pos:        the &struct hlist_node to use as a loop cursor.
* a- member:        the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_from(tpos, pos, member)                         \
        for (; pos && ({ prefetch(pos->next); 1;}) &&                         \
                ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
             pos = pos->next)

/**
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* a- tpos:        the type * to use as a loop cursor.
* a- pos:        the &struct hlist_node to use as a loop cursor.
* a- n:                another &struct hlist_node to use as temporary storage
* a- head:        the head for your list.
* a- member:        the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_safe(tpos, pos, n, head, member)                  \
        for (pos = (head)->first;                                         \
             pos && ({ n = pos->next; 1; }) &&                                  \
                ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
             pos = n)

/**
* hlist_for_each_entry_rcu - iterate over rcu list of given type
* a- tpos:        the type * to use as a loop cursor.
* a- pos:        the &struct hlist_node to use as a loop cursor.
* a- head:        the head for your list.
* a- member:        the name of the hlist_node within the struct.
*
* This list-traversal primitive may safely run concurrently with
* the _rcu list-mutation primitives such as hlist_add_head_rcu()
* as long as the traversal is guarded by rcu_read_lock().
*/
#define hlist_for_each_entry_rcu(tpos, pos, head, member)                 \
        for (pos = (head)->first;                                         \
             rcu_dereference(pos) && ({ prefetch(pos->next); 1;}) &&         \
                ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
             pos = pos->next)

使用特权

评论回复
37
keer_zu|  楼主 | 2014-5-11 18:21 | 只看该作者
哈希表的使用实例:

对于需要执行命令字的自定义协议,将命令字做为哈希表索引ID,将执行函数放入哈希表项,通过具体命令字调用具体函数。扩展方便。

使用特权

评论回复
38
keer_zu|  楼主 | 2014-5-11 18:23 | 只看该作者
函数调用哈希操作实例。
1.定义:

struct func_head
{
        struct hlist_head head;
};


typedef struct func_node
{
        unsigned short id;
/*
        DATA_PROCESS_FUN func_process;
        CMD_ACK_FUNC func_ack;
*/
        void *param;//param;
        struct hlist_node node;
}func_node_t;

typedef struct func_hlist{
        struct func_head *head_array;
        unsigned int head_array_len;

        int (*init)(struct func_hlist *);
        int (*deinit)(struct func_hlist *);
        int (*add_func_node)(struct func_hlist *,struct func_node *);
        int (*del_func_node)(struct func_hlist *,unsigned int);
        struct func_node *(*get_func_node)(struct func_hlist *,unsigned int);
       
}func_hlist_t;

int init_func_hlist(func_node_t *func_node_array,func_hlist_t *func_hlist);

使用特权

评论回复
39
keer_zu|  楼主 | 2014-5-11 18:24 | 只看该作者
2.函数定义

#include <stddef.h>
#include "sys.h"
#include "func_hlist.h"

static int process_hlist_init(func_hlist_t *hlist)
{
        int i;
       
        struct func_head *pos;
       
        pos = hlist->head_array;
        for(i = 0;i < hlist->head_array_len;i ++){
                INIT_HLIST_HEAD(&pos->head);
                pos ++;
        }

        return OK;
}


static int process_hlist_deinit(func_hlist_t *hlist)
{

        return OK;
}


static int process_hlist_add(func_hlist_t *hlist,struct func_node *func_node)
{
        INIT_HLIST_NODE(&func_node->node);
        hlist_add_head(&func_node->node,&(hlist->head_array + DATA_MOD(func_node->id,hlist->head_array_len))->head);

        return OK;
}



static int process_hlist_del(func_hlist_t *fhlist,unsigned int id)
{
        //int ret,i;
       
        struct func_node *FuncNode;
        struct hlist_node *pos;
       
       
        hlist_for_each(pos,&(fhlist->head_array+ DATA_MOD(id,fhlist->head_array_len))->head){

                const struct hlist_node *__mptr = pos;
                FuncNode = (struct func_node *)((char *)__mptr - offsetof(struct func_node,node) );
               
                if(FuncNode->id == id){
                        hlist_del(pos);
                        break;
                }
        }

        return OK;
}

static struct func_node *process_hlist_get(func_hlist_t *fhlist,unsigned int id)
{

        struct func_node *FuncNode;
        struct hlist_node *pos;
        struct hlist_head *h;
        h = &(fhlist->head_array+ DATA_MOD(id,fhlist->head_array_len))->head;
       

        hlist_for_each(pos,/*&(fhlist->head_array+ DATA_MOD(id,fhlist->head_array_len))->head*/h){
               
                const struct hlist_node *__mptr = pos;
                FuncNode = (struct func_node *)((char *)__mptr - offsetof(struct func_node,node) );
               
                if(FuncNode->id == id){
                        return FuncNode;
                }
        }

        return NULL;
}


/************************* gloabal *********************/
int init_func_hlist(func_node_t *func_node_array,func_hlist_t *func_hlist)
{
        func_node_t *pos;
       
        if(func_node_array == NULL || func_hlist == NULL)
                return ERR;
       
        for(pos = func_node_array;pos->param != NULL;pos ++){
                func_hlist->add_func_node(func_hlist,pos);
        }

        return OK;
}

/************************** picking protocol function hlist ********************************/
#define G_PICK_ARRAY_SIZE 50

struct func_head esl_hlist_head[G_PICK_ARRAY_SIZE];

func_hlist_t g_esl_func = {
        esl_hlist_head,
        G_PICK_ARRAY_SIZE,
        process_hlist_init,
        process_hlist_deinit,
        process_hlist_add,
        process_hlist_del,
        process_hlist_get
};

使用特权

评论回复
40
keer_zu|  楼主 | 2014-5-11 18:26 | 只看该作者
使用:

a.初始化

static int esl_init(struct esl_protocol *proto,unsigned int net_type)
{
        unsigned char i;

       
        if(proto == NULL ){
                return ERR_PARA;
        }


        proto->fun_h->init(proto->fun_h);

        switch(net_type){
                case NET_TYPE_485:
                        init_func_hlist(esl_cmd_func_node_array_485,proto->fun_h);
                        break;
                case NET_TYPE_CAN:
                        init_func_hlist(esl_cmd_func_node_array_can,proto->fun_h);
                        break;
                default:
                        printf("%s: err net_type!\n",__FUNCTION__);
                        return ERR;
        }
       
       
       
       
        return OK;
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则