X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/c6d6f58c34e1b6a4c03d1e86d1abf48eeb6f5624..91dfab84182937b62ef64cb12d8e4f89e6d5c3ec:/lincan/src/can_quekern.c diff --git a/lincan/src/can_quekern.c b/lincan/src/can_quekern.c index 4ffdaa0..fa7e33c 100644 --- a/lincan/src/can_quekern.c +++ b/lincan/src/can_quekern.c @@ -37,7 +37,7 @@ extern int processlocal; void canque_dead_func(unsigned long data); /* Support for dead ends structures left after client close */ -spinlock_t canque_dead_func_lock; +can_spinlock_t canque_dead_func_lock; LIST_HEAD(canque_dead_ends); /* retrieved by list_entry(canque_dead_ends.next,struct canque_ends_t,dead_peers) */ LIST_HEAD(canque_dead_edges); @@ -49,48 +49,44 @@ DECLARE_TASKLET(canque_dead_tl, canque_dead_func, 0); static inline struct canque_edge_t *canque_dead_edges_cut_first(void) { - unsigned long flags; + can_spin_irqflags_t flags; struct canque_edge_t *edge; - spin_lock_irqsave(&canque_dead_func_lock, flags); + can_spin_lock_irqsave(&canque_dead_func_lock, flags); if(list_empty(&canque_dead_edges)) edge=NULL; else{ edge=list_entry(canque_dead_edges.next,struct canque_edge_t,inpeers); list_del(&edge->inpeers); } - spin_unlock_irqrestore(&canque_dead_func_lock, flags); + can_spin_unlock_irqrestore(&canque_dead_func_lock, flags); return edge; } void canque_dead_func(unsigned long data) { - unsigned long flags; + can_spin_irqflags_t flags; struct canque_edge_t *qedge; struct canque_ends_t *qends; struct list_head *entry; - int i; while((qedge=canque_dead_edges_cut_first())){ DEBUGQUE("edge %d disposed\n",qedge->edge_num); kfree(qedge); } - spin_lock_irqsave(&canque_dead_func_lock, flags); + can_spin_lock_irqsave(&canque_dead_func_lock, flags); entry=canque_dead_ends.next; - spin_unlock_irqrestore(&canque_dead_func_lock,flags); + can_spin_unlock_irqrestore(&canque_dead_func_lock,flags); while(entry!=&canque_dead_ends){ qends=list_entry(canque_dead_ends.next,struct canque_ends_t,dead_peers); entry=entry->next; if(!list_empty(&qends->inlist)) continue; - if(!list_empty(&qends->idle)) + if(!list_empty(&qends->outlist)) continue; - for(i=CANQUEUE_PRIO_NR;i--;) - if(!list_empty(&qends->active[i])) - continue; - spin_lock_irqsave(&canque_dead_func_lock, flags); + can_spin_lock_irqsave(&canque_dead_func_lock, flags); list_del(&qends->dead_peers); - spin_unlock_irqrestore(&canque_dead_func_lock,flags); + can_spin_unlock_irqrestore(&canque_dead_func_lock,flags); DEBUGQUE("ends structure disposed\n"); kfree(qends); } @@ -100,7 +96,7 @@ void canque_dead_func(unsigned long data) void canque_edge_do_dead(struct canque_edge_t *edge, int dead_fl) { - unsigned long flags; + can_spin_irqflags_t flags; if(dead_fl) return; @@ -109,19 +105,19 @@ void canque_edge_do_dead(struct canque_edge_t *edge, int dead_fl) return; } - spin_lock_irqsave(&canque_dead_func_lock, flags); + can_spin_lock_irqsave(&canque_dead_func_lock, flags); list_add(&edge->inpeers,&canque_dead_edges); - spin_unlock_irqrestore(&canque_dead_func_lock, flags); + can_spin_unlock_irqrestore(&canque_dead_func_lock, flags); tasklet_schedule(&canque_dead_tl); } /*if(qends->ends_flags & CAN_ENDSF_DEAD){ - spin_lock_irqsave(&canque_dead_func_lock, flags); + can_spin_lock_irqsave(&canque_dead_func_lock, flags); list_del(&qends->dead_peers); list_add(&qends->dead_peers,&canque_dead_ends); - spin_unlock_irqrestore(&canque_dead_func_lock, flags); + can_spin_unlock_irqrestore(&canque_dead_func_lock, flags); tasklet_schedule(&canque_dead_tl); }*/ @@ -144,9 +140,17 @@ void canqueue_notify_kern(struct canque_ends_t *qends, struct canque_edge_t *qed break; case CANQUEUE_NOTIFY_SPACE: wake_up(&qends->endinfo.fileinfo.writeq); + #ifdef CAN_ENABLE_KERN_FASYNC + /* Asynchronous I/O processing */ + kill_fasync(&qends->endinfo.fileinfo.fasync, SIGIO, POLL_OUT); + #endif /*CAN_ENABLE_KERN_FASYNC*/ break; case CANQUEUE_NOTIFY_PROC: wake_up(&qends->endinfo.fileinfo.readq); + #ifdef CAN_ENABLE_KERN_FASYNC + /* Asynchronous I/O processing */ + kill_fasync(&qends->endinfo.fileinfo.fasync, SIGIO, POLL_IN); + #endif /*CAN_ENABLE_KERN_FASYNC*/ break; case CANQUEUE_NOTIFY_NOUSR: wake_up(&qends->endinfo.fileinfo.readq); @@ -174,6 +178,10 @@ int canqueue_ends_init_kern(struct canque_ends_t *qends) init_waitqueue_head(&qends->endinfo.fileinfo.readq); init_waitqueue_head(&qends->endinfo.fileinfo.writeq); init_waitqueue_head(&qends->endinfo.fileinfo.emptyq); + #ifdef CAN_ENABLE_KERN_FASYNC + qends->endinfo.fileinfo.fasync=NULL; + #endif /*CAN_ENABLE_KERN_FASYNC*/ + qends->notify=canqueue_notify_kern; DEBUGQUE("canqueue_ends_init_kern\n"); return 0; @@ -259,7 +267,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); + can_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"); @@ -278,6 +286,8 @@ struct canque_edge_t *canque_new_edge_kern(int slotsnr) return qedge; } +#ifdef USE_SYNC_DISCONNECT_EDGE_KERN + /** * canqueue_disconnect_edge_kern - disconnect edge from communicating entities with wait * @qends: ends structure belonging to calling communication object @@ -315,11 +325,11 @@ int canqueue_disconnect_edge_kern(struct canque_ends_t *qends, struct canque_edg int canqueue_disconnect_list_kern(struct canque_ends_t *qends, struct list_head *list) { struct canque_edge_t *edge; - unsigned long flags; + can_spin_irqflags_t flags; for(;;){ - spin_lock_irqsave(&qends->ends_lock,flags); + can_spin_lock_irqsave(&qends->ends_lock,flags); if(list_empty(list)){ - spin_unlock_irqrestore(&qends->ends_lock,flags); + can_spin_unlock_irqrestore(&qends->ends_lock,flags); return 0; } if(list == &qends->inlist) @@ -327,7 +337,7 @@ int canqueue_disconnect_list_kern(struct canque_ends_t *qends, struct list_head else edge=list_entry(list->next,struct canque_edge_t,outpeers); atomic_inc(&edge->edge_used); - spin_unlock_irqrestore(&qends->ends_lock,flags); + can_spin_unlock_irqrestore(&qends->ends_lock,flags); if(canqueue_disconnect_edge_kern(qends, edge)>=0) { /* Free edge memory */ canque_fifo_done(&edge->fifo); @@ -342,20 +352,8 @@ int canqueue_disconnect_list_kern(struct canque_ends_t *qends, struct list_head } } -void canqueue_block_list(struct canque_ends_t *qends, struct list_head *list) -{ - struct canque_edge_t *edge; - struct list_head *entry; - - /* 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); - } -} +#endif /*USE_SYNC_DISCONNECT_EDGE_KERN*/ + int canqueue_ends_sync_all_kern(struct canque_ends_t *qends) { @@ -368,27 +366,6 @@ int canqueue_ends_sync_all_kern(struct canque_ends_t *qends) return 0; } -int canqueue_ends_done_inends(struct canque_ends_t *qends, int send_rest) -{ - struct canque_edge_t *edge; - - canque_for_each_inedge(qends, edge){ - canque_notify_bothends(edge, CANQUEUE_NOTIFY_DEAD_WANTED); - if(send_rest){ - canque_edge_incref(edge); - if(!canque_fifo_test_and_set_fl(&edge->fifo, FREEONEMPTY)){ - if(!canque_fifo_test_fl(&edge->fifo, EMPTY)) - continue; - if(!canque_fifo_test_and_clear_fl(&edge->fifo, FREEONEMPTY)) - continue; - } - canque_edge_decref(edge); - } - } - return list_empty(&qends->inlist)?0:1; -} - - /** * canqueue_ends_dispose_kern - finalizing of the ends structure for Linux kernel clients * @qends: pointer to ends structure @@ -399,41 +376,31 @@ int canqueue_ends_done_inends(struct canque_ends_t *qends, int send_rest) */ int canqueue_ends_dispose_kern(struct canque_ends_t *qends, int sync) { - unsigned long flags; - int i; + can_spin_irqflags_t flags; int delayed; DEBUGQUE("canqueue_ends_dispose_kern\n"); - spin_lock_irqsave(&qends->ends_lock,flags); - canqueue_block_list(qends, &qends->idle); - for(i=CANQUEUE_PRIO_NR;--i>=0;){ - canqueue_block_list(qends, &qends->active[i]); - } - canqueue_block_list(qends, &qends->idle); - canqueue_block_list(qends, &qends->inlist); - spin_unlock_irqrestore(&qends->ends_lock,flags); + canqueue_block_inlist(qends); + canqueue_block_outlist(qends); /*Wait for sending of all pending messages in the output FIFOs*/ if(sync) canqueue_ends_sync_all_kern(qends); - /* Finish all outgoing edges listed in inends */ - delayed=canqueue_ends_done_inends(qends, 1); - - delayed|=canqueue_disconnect_list_kern(qends, &qends->idle); - for(i=CANQUEUE_PRIO_NR;--i>=0;){ - delayed|=canqueue_disconnect_list_kern(qends, &qends->active[i]); - } + /* Finish or kill all outgoing edges listed in inends */ + delayed=canqueue_ends_kill_inlist(qends, 1); + /* Kill all incoming edges listed in outends */ + delayed|=canqueue_ends_kill_outlist(qends); wake_up(&qends->endinfo.fileinfo.readq); wake_up(&qends->endinfo.fileinfo.writeq); wake_up(&qends->endinfo.fileinfo.emptyq); if(delayed){ - spin_lock_irqsave(&canque_dead_func_lock, flags); + can_spin_lock_irqsave(&canque_dead_func_lock, flags); qends->ends_flags |= CAN_ENDSF_DEAD; list_add(&qends->dead_peers,&canque_dead_ends); - spin_unlock_irqrestore(&canque_dead_func_lock, flags); + can_spin_unlock_irqrestore(&canque_dead_func_lock, flags); tasklet_schedule(&canque_dead_tl); DEBUGQUE("canqueue_ends_dispose_kern delayed\n");