/*-------------------------------------------------------------------------- \brief vos_timer_stop() - Stop a vOSS Timer The \a vos_timer_stop() function stops a timer that has been started but has not expired, essentially cancelling the 'start' request. After a timer is stopped, it goes back to the state it was in after it was created and can be started again via a call to vos_timer_start(). \param timer - the timer object to be stopped \return VOS_STATUS_SUCCESS - timer was successfully stopped. VOS_STATUS_E_INVAL - The value specified by timer is invalid. VOS_STATUS_E_FAULT - timer is an invalid pointer. \sa ------------------------------------------------------------------------*/ VOS_STATUS vos_timer_stop ( vos_timer_t *timer ) { unsigned long flags; VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, "%s: Timer Addr inside voss_stop : 0x%p",__func__,timer ); // Check for invalid pointer if ( NULL == timer ) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s Null timer pointer being passed", __func__); VOS_ASSERT(0); return VOS_STATUS_E_INVAL; } // Check if timer refers to an uninitialized object if ( LINUX_TIMER_COOKIE != timer->platformInfo.cookie ) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: Cannot stop uninitialized timer",__func__); if ( LINUX_INVALID_TIMER_COOKIE != timer->platformInfo.cookie ) { VOS_ASSERT(0); } return VOS_STATUS_E_INVAL; } // Ensure the timer state is correct spin_lock_irqsave( &timer->platformInfo.spinlock,flags ); if ( VOS_TIMER_STATE_RUNNING != timer->state ) { spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags ); VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH, "%s: Cannot stop timer in state = %d", __func__, timer->state); return VOS_STATUS_SUCCESS; } timer->state = VOS_TIMER_STATE_STOPPED; del_timer(&(timer->platformInfo.Timer)); spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags ); tryAllowingSleep( timer->type ); return VOS_STATUS_SUCCESS; }
static void vos_linux_timer_callback ( v_U32_t data ) { vos_timer_t *timer = ( vos_timer_t *)data; vos_msg_t msg; VOS_STATUS vStatus; unsigned long flags; vos_timer_callback_t callback=NULL; v_PVOID_t userData=NULL; int threadId; VOS_TIMER_TYPE type=VOS_TIMER_TYPE_SW; VOS_ASSERT(timer); if (timer == NULL) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s Null pointer passed in!",__func__); return; } threadId = timer->platformInfo.threadID; spin_lock_irqsave( &timer->platformInfo.spinlock,flags ); switch ( timer->state ) { case VOS_TIMER_STATE_STARTING: // we are in this state because someone just started the timer, MM timer // got started and expired, but the time content have not bee updated // this is a rare race condition! timer->state = VOS_TIMER_STATE_STOPPED; vStatus = VOS_STATUS_E_ALREADY; break; case VOS_TIMER_STATE_STOPPED: vStatus = VOS_STATUS_E_ALREADY; break; case VOS_TIMER_STATE_UNUSED: vStatus = VOS_STATUS_E_EXISTS; break; case VOS_TIMER_STATE_RUNNING: // need to go to stop state here because the call-back function may restart // timer (to emulate periodic timer) timer->state = VOS_TIMER_STATE_STOPPED; // copy the relevant timer information to local variables; // once we exist from this critical section, the timer content may be modified // by other tasks callback = timer->callback; userData = timer->userData; threadId = timer->platformInfo.threadID; type = timer->type; vStatus = VOS_STATUS_SUCCESS; break; default: VOS_ASSERT(0); vStatus = VOS_STATUS_E_FAULT; break; } spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags ); if ( VOS_STATUS_SUCCESS != vStatus ) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "TIMER callback called in a wrong state=%d", timer->state); return; } tryAllowingSleep( type ); if (callback == NULL) { VOS_ASSERT(0); VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: No TIMER callback, Could not enqueue timer to any queue", __func__); return; } // If timer has expired then call vos_client specific callback if ( vos_sched_is_tx_thread( threadId ) ) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, "TIMER callback: running on TX thread"); //Serialize to the Tx thread sysBuildMessageHeader( SYS_MSG_ID_TX_TIMER, &msg ); msg.bodyptr = callback; msg.bodyval = (v_U32_t)userData; if(vos_tx_mq_serialize( VOS_MQ_ID_SYS, &msg ) == VOS_STATUS_SUCCESS) return; } else if ( vos_sched_is_rx_thread( threadId ) ) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, "TIMER callback: running on RX thread"); //Serialize to the Rx thread sysBuildMessageHeader( SYS_MSG_ID_RX_TIMER, &msg ); msg.bodyptr = callback; msg.bodyval = (v_U32_t)userData; if(vos_rx_mq_serialize( VOS_MQ_ID_SYS, &msg ) == VOS_STATUS_SUCCESS) return; } else { VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, "TIMER callback: running on MC thread"); // Serialize to the MC thread sysBuildMessageHeader( SYS_MSG_ID_MC_TIMER, &msg ); msg.bodyptr = callback; msg.bodyval = (v_U32_t)userData; if(vos_mq_post_message( VOS_MQ_ID_SYS, &msg ) == VOS_STATUS_SUCCESS) return; } VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: Could not enqueue timer to any queue", __func__); VOS_ASSERT(0); }
static void vos_linux_timer_callback ( v_U32_t data ) { vos_timer_t *timer = ( vos_timer_t *)data; vos_msg_t msg; VOS_STATUS vStatus; unsigned long flags; vos_timer_callback_t callback=NULL; v_PVOID_t userData=NULL; int threadId; VOS_TIMER_TYPE type=VOS_TIMER_TYPE_SW; VOS_ASSERT(timer); if (timer == NULL) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s Null pointer passed in!",__func__); return; } threadId = timer->platformInfo.threadID; spin_lock_irqsave( &timer->platformInfo.spinlock,flags ); switch ( timer->state ) { case VOS_TIMER_STATE_STARTING: // // // timer->state = VOS_TIMER_STATE_STOPPED; vStatus = VOS_STATUS_E_ALREADY; break; case VOS_TIMER_STATE_STOPPED: vStatus = VOS_STATUS_E_ALREADY; break; case VOS_TIMER_STATE_UNUSED: vStatus = VOS_STATUS_E_EXISTS; break; case VOS_TIMER_STATE_RUNNING: // // timer->state = VOS_TIMER_STATE_STOPPED; // // // callback = timer->callback; userData = timer->userData; threadId = timer->platformInfo.threadID; type = timer->type; vStatus = VOS_STATUS_SUCCESS; break; default: VOS_ASSERT(0); vStatus = VOS_STATUS_E_FAULT; break; } spin_unlock_irqrestore( &timer->platformInfo.spinlock,flags ); if ( VOS_STATUS_SUCCESS != vStatus ) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "TIMER callback called in a wrong state=%d", timer->state); return; } tryAllowingSleep( type ); if (callback == NULL) { VOS_ASSERT(0); VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: No TIMER callback, Could not enqueue timer to any queue", __func__); return; } // if ( vos_sched_is_tx_thread( threadId ) ) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, "TIMER callback: running on TX thread"); // sysBuildMessageHeader( SYS_MSG_ID_TX_TIMER, &msg ); msg.bodyptr = callback; msg.bodyval = (v_U32_t)userData; if(vos_tx_mq_serialize( VOS_MQ_ID_SYS, &msg ) == VOS_STATUS_SUCCESS) return; } else if ( vos_sched_is_rx_thread( threadId ) ) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, "TIMER callback: running on RX thread"); // sysBuildMessageHeader( SYS_MSG_ID_RX_TIMER, &msg ); msg.bodyptr = callback; msg.bodyval = (v_U32_t)userData; if(vos_rx_mq_serialize( VOS_MQ_ID_SYS, &msg ) == VOS_STATUS_SUCCESS) return; } else { VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, "TIMER callback: running on MC thread"); // sysBuildMessageHeader( SYS_MSG_ID_MC_TIMER, &msg ); msg.bodyptr = callback; msg.bodyval = (v_U32_t)userData; if(vos_mq_post_message( VOS_MQ_ID_SYS, &msg ) == VOS_STATUS_SUCCESS) return; } VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: Could not enqueue timer to any queue", __func__); VOS_ASSERT(0); }