X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/b34a548a5dfd2f0b068fd835a4cd51680d851068..fb2dd0f20bd6264291dccb5e97609a23cae2fd1a:/lincan/src/can_quertl.c diff --git a/lincan/src/can_quertl.c b/lincan/src/can_quertl.c index 45129b4..0a6fa40 100644 --- a/lincan/src/can_quertl.c +++ b/lincan/src/can_quertl.c @@ -28,8 +28,9 @@ extern int processlocal; struct list_head canque_pending_edges_list; can_spinlock_t canque_pending_edges_lock; +unsigned long canqueue_rtl2lin_pend; -static int canqueue_rtl_irq = 0; +int canqueue_rtl_irq = 0; void canqueue_rtl2lin_handler(int irq, void *ignore, struct pt_regs *ignoreregs) @@ -75,6 +76,9 @@ canqueue_rtl2lin_handler(int irq, void *ignore, struct pt_regs *ignoreregs) can_spin_unlock_irqrestore (&canque_pending_edges_lock, flags); + if(test_and_clear_bit(CAN_RTL2LIN_PEND_DEAD_b,&canqueue_rtl2lin_pend)) + tasklet_schedule(&canque_dead_tl); + return; } @@ -119,6 +123,111 @@ int canqueue_rtl2lin_check_and_pend(struct canque_ends_t *qends, } +/** + * canque_get_inslot4id_wait_rtl - find or wait for best outgoing edge and slot for given ID + * @qends: ends structure belonging to calling communication object + * @qedgep: place to store pointer to found edge + * @slotp: place to store pointer to allocated slot + * @cmd: command type for slot + * @id: communication ID of message to send into edge + * @prio: optional priority of message + * + * Same as canque_get_inslot4id(), except, that it waits for free slot + * in case, that queue is full. Function is specific for Linux userspace clients. + * Return Value: If there is no usable edge negative value is returned. + */ +int canque_get_inslot4id_wait_rtl(struct canque_ends_t *qends, + struct canque_edge_t **qedgep, struct canque_slot_t **slotp, + int cmd, unsigned long id, int prio) +{ + rtl_irqstate_t flags; + int ret; + unsigned old_age; + rtl_sigset_t sigset; + + old_age=atomic_read(&qends->endinfo.rtlinfo.rtl_writeq_age); + while((ret=canque_get_inslot4id(qends,qedgep,slotp,cmd,id,prio))==-1){ + rtl_sigemptyset(&sigset); + rtl_spin_lock_irqsave(&qends->endinfo.rtlinfo.rtl_lock, flags); + if(old_age == atomic_read(&qends->endinfo.rtlinfo.rtl_writeq_age)) + sigset=rtl_wait_sleep(&qends->endinfo.rtlinfo.rtl_writeq, &qends->endinfo.rtlinfo.rtl_lock); + rtl_spin_unlock_irqrestore(&qends->endinfo.rtlinfo.rtl_lock, flags); + if(RTL_SIGINTR(&sigset)) + return -1; + old_age=atomic_read(&qends->endinfo.rtlinfo.rtl_writeq_age); + } + + return ret; +} + + +/** + * canque_get_outslot_wait_rtl - receive or wait for ready slot for given ends + * @qends: ends structure belonging to calling communication object + * @qedgep: place to store pointer to found edge + * @slotp: place to store pointer to received slot + * + * The same as canque_test_outslot(), except it waits in the case, that there is + * no ready slot for given ends. Function is specific for Linux userspace clients. + * Return Value: Negative value informs, that there is no ready output + * slot for given ends. Positive value is equal to the command + * slot has been allocated by the input side. + */ +int canque_get_outslot_wait_rtl(struct canque_ends_t *qends, + struct canque_edge_t **qedgep, struct canque_slot_t **slotp) +{ + rtl_irqstate_t flags; + int ret; + unsigned old_age; + rtl_sigset_t sigset; + + old_age=atomic_read(&qends->endinfo.rtlinfo.rtl_readq_age); + while((ret=canque_test_outslot(qends,qedgep,slotp))==-1){ + rtl_sigemptyset(&sigset); + rtl_spin_lock_irqsave(&qends->endinfo.rtlinfo.rtl_lock, flags); + if(old_age == atomic_read(&qends->endinfo.rtlinfo.rtl_readq_age)) + sigset=rtl_wait_sleep(&qends->endinfo.rtlinfo.rtl_readq, &qends->endinfo.rtlinfo.rtl_lock); + rtl_spin_unlock_irqrestore(&qends->endinfo.rtlinfo.rtl_lock, flags); + if(RTL_SIGINTR(&sigset)) + return -1; + old_age=atomic_read(&qends->endinfo.rtlinfo.rtl_readq_age); + } + return ret; +} + + +/** + * canque_sync_wait_rtl - wait for all slots processing + * @qends: ends structure belonging to calling communication object + * @qedge: pointer to edge + * + * Functions waits for ends transition into empty state. + * Return Value: Positive value indicates, that edge empty state has been reached. + * Negative or zero value informs about interrupted wait or other problem. + */ +int canque_sync_wait_rtl(struct canque_ends_t *qends, struct canque_edge_t *qedge) +{ + rtl_irqstate_t flags; + int ret; + unsigned old_age; + rtl_sigset_t sigset; + + old_age=atomic_read(&qends->endinfo.rtlinfo.rtl_emptyq_age); + while(!(ret=canque_fifo_test_fl(&qedge->fifo,EMPTY)?1:0)){ + rtl_sigemptyset(&sigset); + rtl_spin_lock_irqsave(&qends->endinfo.rtlinfo.rtl_lock, flags); + if(old_age == atomic_read(&qends->endinfo.rtlinfo.rtl_emptyq_age)) + sigset=rtl_wait_sleep(&qends->endinfo.rtlinfo.rtl_emptyq, &qends->endinfo.rtlinfo.rtl_lock); + rtl_spin_unlock_irqrestore(&qends->endinfo.rtlinfo.rtl_lock, flags); + if(RTL_SIGINTR(&sigset)) + return -1; + old_age=atomic_read(&qends->endinfo.rtlinfo.rtl_emptyq_age); + } + + return ret; +} + + /** * canque_fifo_init_rtl - initialize one CAN FIFO * @fifo: pointer to the FIFO structure @@ -138,6 +247,7 @@ int canque_fifo_init_rtl(struct canque_fifo_t *fifo, int slotsnr) return canque_fifo_init_slots(fifo); } + /** * canque_fifo_done_rtl - frees slots allocated for CAN FIFO * @fifo: pointer to the FIFO structure @@ -207,6 +317,7 @@ void canqueue_notify_rtl(struct canque_ends_t *qends, struct canque_edge_t *qedg switch(what){ case CANQUEUE_NOTIFY_EMPTY: rtl_spin_lock_irqsave(&qends->endinfo.rtlinfo.rtl_lock, flags); + atomic_inc(&qends->endinfo.rtlinfo.rtl_emptyq_age); rtl_wait_wakeup(&qends->endinfo.rtlinfo.rtl_emptyq); rtl_spin_unlock_irqrestore(&qends->endinfo.rtlinfo.rtl_lock, flags); if(canque_fifo_test_and_clear_fl(&qedge->fifo, FREEONEMPTY)) @@ -214,19 +325,28 @@ void canqueue_notify_rtl(struct canque_ends_t *qends, struct canque_edge_t *qedg break; case CANQUEUE_NOTIFY_SPACE: rtl_spin_lock_irqsave(&qends->endinfo.rtlinfo.rtl_lock, flags); + atomic_inc(&qends->endinfo.rtlinfo.rtl_writeq_age); rtl_wait_wakeup(&qends->endinfo.rtlinfo.rtl_writeq); rtl_spin_unlock_irqrestore(&qends->endinfo.rtlinfo.rtl_lock, flags); break; case CANQUEUE_NOTIFY_PROC: rtl_spin_lock_irqsave(&qends->endinfo.rtlinfo.rtl_lock, flags); + atomic_inc(&qends->endinfo.rtlinfo.rtl_readq_age); rtl_wait_wakeup(&qends->endinfo.rtlinfo.rtl_readq); rtl_spin_unlock_irqrestore(&qends->endinfo.rtlinfo.rtl_lock, flags); break; case CANQUEUE_NOTIFY_NOUSR: rtl_spin_lock_irqsave(&qends->endinfo.rtlinfo.rtl_lock, flags); + + atomic_inc(&qends->endinfo.rtlinfo.rtl_readq_age); rtl_wait_wakeup(&qends->endinfo.rtlinfo.rtl_readq); + + atomic_inc(&qends->endinfo.rtlinfo.rtl_writeq_age); rtl_wait_wakeup(&qends->endinfo.rtlinfo.rtl_writeq); + + atomic_inc(&qends->endinfo.rtlinfo.rtl_emptyq_age); rtl_wait_wakeup(&qends->endinfo.rtlinfo.rtl_emptyq); + rtl_spin_unlock_irqrestore(&qends->endinfo.rtlinfo.rtl_lock, flags); break; case CANQUEUE_NOTIFY_DEAD_WANTED: