]> 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 55e8063bbc02db73f6ea5686da6e81003665aecf..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,22 +49,22 @@ 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;
@@ -74,9 +74,9 @@ void canque_dead_func(unsigned long data)
                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;
@@ -84,9 +84,9 @@ void canque_dead_func(unsigned long data)
                        continue;
                if(!list_empty(&qends->outlist))
                        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);
        }
@@ -96,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;
        
@@ -105,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);
 }*/
 
@@ -140,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);
@@ -170,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;
@@ -255,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");
@@ -274,7 +286,7 @@ struct canque_edge_t *canque_new_edge_kern(int slotsnr)
        return qedge;
 }
 
-#ifdef USE_DELAYED_DISCONNECT_EDGE_KERN
+#ifdef USE_SYNC_DISCONNECT_EDGE_KERN
 
 /**
  * canqueue_disconnect_edge_kern - disconnect edge from communicating entities with wait
@@ -313,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)
@@ -325,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);
@@ -340,7 +352,7 @@ int canqueue_disconnect_list_kern(struct canque_ends_t *qends, struct list_head
        }
 }
 
-#endif /*USE_DELAYED_DISCONNECT_EDGE_KERN*/
+#endif /*USE_SYNC_DISCONNECT_EDGE_KERN*/
 
 
 int canqueue_ends_sync_all_kern(struct canque_ends_t *qends)
@@ -354,38 +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;
-}
-
-
-int canqueue_ends_done_outends(struct canque_ends_t *qends)
-{
-       struct canque_edge_t *edge;
-       
-       canque_for_each_outedge(qends, edge){
-               canque_notify_bothends(edge, CANQUEUE_NOTIFY_DEAD_WANTED);
-       }
-       return list_empty(&qends->outlist)?0:1;
-}
-
-
 /**
  * canqueue_ends_dispose_kern - finalizing of the ends structure for Linux kernel clients
  * @qends: pointer to ends structure
@@ -396,7 +376,7 @@ int canqueue_ends_done_outends(struct canque_ends_t *qends)
  */
 int canqueue_ends_dispose_kern(struct canque_ends_t *qends, int sync)
 {
-       unsigned long flags;
+       can_spin_irqflags_t flags;
        int delayed;
 
        DEBUGQUE("canqueue_ends_dispose_kern\n");
@@ -407,20 +387,20 @@ int canqueue_ends_dispose_kern(struct canque_ends_t *qends, int sync)
        if(sync)
                canqueue_ends_sync_all_kern(qends);
        
-       /* Finish all outgoing edges listed in inends */
-       delayed=canqueue_ends_done_inends(qends, 1);
-
-       delayed|=canqueue_ends_done_outends(qends);
+       /* 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");