X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/9dc9a6da64e783bbac5a87c5086c4dfc3ea25226..8c0ae37c63dd4bc42fcb84da2eeb4a4978a2ebc0:/lincan/src/can_queue.c diff --git a/lincan/src/can_queue.c b/lincan/src/can_queue.c index ad6160c..83b0839 100644 --- a/lincan/src/can_queue.c +++ b/lincan/src/can_queue.c @@ -239,6 +239,7 @@ int canque_filter_msg2edges(struct canque_ends_t *qends, struct canmsg_t *msg) edge=list_entry(entry,struct canque_edge_t,inpeers); if(canque_fifo_test_fl(&edge->fifo,BLOCK)||canque_fifo_test_fl(&edge->fifo,DEAD)) continue; + /* FIXME: the next comparison should be outside of ends lock */ if((msg->id^edge->filtid)&edge->filtmask) continue; atomic_inc(&edge->edge_used); @@ -483,6 +484,7 @@ struct canque_edge_t *canque_new_edge_kern(int slotsnr) if(qedge == NULL) return NULL; memset(qedge,0,sizeof(struct canque_edge_t)); + spin_lock_init(&qedge->fifo.fifo_lock); if(canque_fifo_init_slots(&qedge->fifo, slotsnr)<0){ kfree(qedge); DEBUGQUE("canque_new_edge_kern failed\n"); @@ -530,8 +532,12 @@ int canqueue_disconnect_edge(struct canque_edge_t *qedge) { int ret; unsigned long flags; - spin_lock_irqsave(&qedge->inends->ends_lock,flags); - spin_lock(&qedge->outends->ends_lock); + struct canque_ends_t *inends, *outends; + + inends=qedge->inends; + if(inends) spin_lock_irqsave(&inends->ends_lock,flags); + outends=qedge->outends; + if(outends) spin_lock(&outends->ends_lock); spin_lock(&qedge->fifo.fifo_lock); if(atomic_read(&qedge->edge_used)==0) { if(qedge->outends){ @@ -545,8 +551,8 @@ int canqueue_disconnect_edge(struct canque_edge_t *qedge) ret=1; } else ret=-1; spin_unlock(&qedge->fifo.fifo_lock); - spin_unlock(&qedge->outends->ends_lock); - spin_unlock_irqrestore(&qedge->inends->ends_lock,flags); + if(outends) spin_unlock(&outends->ends_lock); + if(inends) spin_unlock_irqrestore(&inends->ends_lock,flags); DEBUGQUE("canqueue_disconnect_edge %d returned %d\n",qedge->edge_num,ret); return ret; } @@ -602,20 +608,15 @@ void canqueue_block_list(struct canque_ends_t *qends, struct list_head *list) { struct canque_edge_t *edge; struct list_head *entry; - unsigned long flags; - spin_lock_irqsave(&qends->ends_lock, flags); + /* has to be called with qends->ends_lock already locked */ list_for_each(entry,&qends->inlist){ if(list == &qends->inlist) edge=list_entry(list->next,struct canque_edge_t,inpeers); else edge=list_entry(list->next,struct canque_edge_t,outpeers); canque_fifo_set_fl(&edge->fifo,BLOCK); - /*spin_unlock_irqrestore(&qends->ends_lock, flags);*/ - /* Loop can be break by interrupts and preempts there */ - /*spin_lock_irqsave(&qends->ends_lock, flags);*/ } - spin_unlock_irqrestore(&qends->ends_lock, flags); }