]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - lincan/src/can_quekern.c
Added support for fasync system call and replacement of spinXXX by can_spinXXX
[lincan.git] / lincan / src / can_quekern.c
index 4ffdaa0b09ac05820ac6581ca71b6ec5a7e647e8..fa7e33c00374a018f42e3621341b7069c207694d 100644 (file)
@@ -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");