X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/c6d6f58c34e1b6a4c03d1e86d1abf48eeb6f5624..94b8e4f0425cebad0a186daf054168fa6910f9b8:/lincan/include/can_queue.h diff --git a/lincan/include/can_queue.h b/lincan/include/can_queue.h index 5951186..264fce5 100644 --- a/lincan/include/can_queue.h +++ b/lincan/include/can_queue.h @@ -269,10 +269,13 @@ struct chip_t; * @filtid: the possible CAN message identifiers filter. * @filtmask: the filter mask, the comparison considers only * @filtid bits corresponding to set bits in the @filtmask field. - * @inpeers: the lists of all peer FIFOs connected by their + * @inpeers: the lists of all peers FIFOs connected by their * input side (@inends) to the same terminal (@struct canque_ends_t). - * @outpeers: the lists of all peer FIFOs connected by their + * @outpeers: the lists of all peers FIFOs connected by their * output side (@outends) to the same terminal (@struct canque_ends_t). + * @activepeers: the lists of peers FIFOs connected by their + * output side (@outends) to the same terminal (@struct canque_ends_t) + * with same priority and active state. * @inends: the pointer to the FIFO input side terminal (@struct canque_ends_t). * @outends: the pointer to the FIFO output side terminal (@struct canque_ends_t). * @edge_used: the atomic usage counter, mainly used for safe destruction of the edge. @@ -289,6 +292,7 @@ struct canque_edge_t { unsigned long filtmask; struct list_head inpeers; struct list_head outpeers; + struct list_head activepeers; struct canque_ends_t *inends; struct canque_ends_t *outends; atomic_t edge_used; @@ -328,6 +332,7 @@ struct canque_ends_t { struct list_head active[CANQUEUE_PRIO_NR]; struct list_head idle; struct list_head inlist; + struct list_head outlist; spinlock_t ends_lock; /* spin_lock_irqsave / spin_lock_irqrestore */ void (*notify)(struct canque_ends_t *qends, struct canque_edge_t *qedge, int what); void *context; @@ -419,8 +424,8 @@ void canque_activate_edge(struct canque_ends_t *inends, struct canque_edge_t *qe spin_lock(&outends->ends_lock); spin_lock(&qedge->fifo.fifo_lock); if(!canque_fifo_test_fl(&qedge->fifo,EMPTY)){ - list_del(&qedge->outpeers); - list_add_tail(&qedge->outpeers,&outends->active[qedge->edge_prio]); + list_del(&qedge->activepeers); + list_add_tail(&qedge->activepeers,&outends->active[qedge->edge_prio]); } spin_unlock(&qedge->fifo.fifo_lock); spin_unlock(&outends->ends_lock); @@ -479,6 +484,9 @@ int canqueue_connect_edge(struct canque_edge_t *qedge, struct canque_ends_t *ine int canqueue_ends_init_gen(struct canque_ends_t *qends); +void canqueue_block_inlist(struct canque_ends_t *qends); + +void canqueue_block_outlist(struct canque_ends_t *qends); /* edge reference and traversal functions */ @@ -566,6 +574,59 @@ struct canque_edge_t *canque_next_inedge(struct canque_ends_t *qends, struct can #define canque_for_each_inedge(qends, edge) \ for(edge=canque_first_inedge(qends);edge;edge=canque_next_inedge(qends, edge)) +static inline +struct canque_edge_t *canque_first_outedge(struct canque_ends_t *qends) +{ + unsigned long flags; + struct list_head *entry; + struct canque_edge_t *edge; + + spin_lock_irqsave(&qends->ends_lock, flags); + entry=qends->outlist.next; + skip_dead: + if(entry != &qends->outlist) { + edge=list_entry(entry,struct canque_edge_t,outpeers); + if(canque_fifo_test_fl(&edge->fifo,DEAD)) { + entry=entry->next; + goto skip_dead; + } + canque_edge_incref(edge); + } else { + edge=NULL; + } + spin_unlock_irqrestore(&qends->ends_lock, flags); + return edge; +} + + +static inline +struct canque_edge_t *canque_next_outedge(struct canque_ends_t *qends, struct canque_edge_t *edge) +{ + unsigned long flags; + struct list_head *entry; + struct canque_edge_t *next; + + spin_lock_irqsave(&qends->ends_lock, flags); + entry=edge->outpeers.next; + skip_dead: + if(entry != &qends->outlist) { + next=list_entry(entry,struct canque_edge_t,outpeers); + if(canque_fifo_test_fl(&edge->fifo,DEAD)) { + entry=entry->next; + goto skip_dead; + } + canque_edge_incref(next); + } else { + next=NULL; + } + spin_unlock_irqrestore(&qends->ends_lock, flags); + canque_edge_decref(edge); + return next; +} + +#define canque_for_each_outedge(qends, edge) \ + for(edge=canque_first_outedge(qends);edge;edge=canque_next_outedge(qends, edge)) + /* Linux kernel specific functions */ struct canque_edge_t *canque_new_edge_kern(int slotsnr);