/****************************************************************************/ /* nschapi.cpp */ /* */ /* Scheduling component API */ /* */ /* Copyright(c) Microsoft Corporation 1996-1999 */ /****************************************************************************/ #include #pragma hdrstop #define TRC_FILE "nschapi" #include #include /****************************************************************************/ /* Name: SCH_Init */ /* */ /* Purpose: Scheduler initialization function. */ /****************************************************************************/ void RDPCALL SHCLASS SCH_Init(void) { DC_BEGIN_FN("SCH_Init"); #define DC_INIT_DATA #include #undef DC_INIT_DATA // ASLEEP mode gets no timer. schPeriods[SCH_MODE_ASLEEP] = SCH_NO_TIMER; // Get scheduling periods that were saved in WD_Open. schPeriods[SCH_MODE_NORMAL] = m_pTSWd->outBufDelay; // If compression is enabled (ie it's a slow link) then crank up the // turbo period to improve responsiveness. if (m_pTSWd->bCompress) { TRC_ALT((TB, "Slow link")); schPeriods[SCH_MODE_TURBO] = SCH_TURBO_PERIOD_SLOW_LINK_DELAY; schTurboModeDuration = SCH_TURBO_MODE_SLOW_LINK_DURATION; m_pShm->sch.MPPCCompressionEst = SCH_MPPC_INIT_EST; } else { TRC_ALT((TB, "Fast link")); schPeriods[SCH_MODE_TURBO] = m_pTSWd->interactiveDelay; schTurboModeDuration = SCH_TURBO_MODE_FAST_LINK_DURATION; // To avoid branching, we set the compression ratio for non-compressed // to the same size as the divisor to create a 1:1 calculation. m_pShm->sch.MPPCCompressionEst = SCH_UNCOMP_BYTES; } TRC_ALT((TB, "Normal period=%u ms, turbo period=%u ms, turbo duration=%u ms", schPeriods[SCH_MODE_NORMAL], schPeriods[SCH_MODE_TURBO], schTurboModeDuration / 10000)); DC_END_FN(); } /****************************************************************************/ // Updates the SHM /****************************************************************************/ void RDPCALL SHCLASS SCH_UpdateShm(void) { DC_BEGIN_FN("SCH_UpdateShm"); m_pShm->sch.schSlowLink = m_pTSWd->bCompress; // Set up packing sizes based on link speed. if (m_pTSWd->bCompress) { m_pShm->sch.SmallPackingSize = SMALL_SLOWLINK_PAYLOAD_SIZE; m_pShm->sch.LargePackingSize = LARGE_SLOWLINK_PAYLOAD_SIZE; } else { m_pShm->sch.SmallPackingSize = SMALL_LAN_PAYLOAD_SIZE; m_pShm->sch.LargePackingSize = LARGE_LAN_PAYLOAD_SIZE; } SET_INCOUNTER(IN_SCH_SMALL_PAYLOAD, m_pShm->sch.SmallPackingSize); SET_INCOUNTER(IN_SCH_LARGE_PAYLOAD, m_pShm->sch.LargePackingSize); DC_END_FN(); } /****************************************************************************/ /* Name: SCH_ContinueScheduling */ /* */ /* Purpose: Called by components when they want periodic scheduling to */ /* continue. They are guaranteed to get at least one more */ /* periodic callback following a call to this function. */ /* If they want further callbacks then they must call this */ /* function again during their periodic processing. */ /* */ /* Params: schedulingMode - either SCH_MODE_NORMAL or SCH_MODE_TURBO */ /* */ /* Operation: - */ /* SCH_MODE_NORMAL triggers periodic processing at 200ms */ /* intervals (5 times a second) */ /* */ /* SCH_MODE_TURBO triggers periodic processing at 100ms */ /* intervals (10 times a second) */ /* */ /* The scheduler automatically drops from SCH_MODE_TURBO back */ /* to SCH_MODE_NORMAL after 1 second of turbo mode processing. */ /* */ /* SCH_MODE_TURBO overrides SCH_MODE_NORMAL, so if calls to */ /* this function are made with SCH_MODE_NORMAL when the */ /* scheduler is in TURBO mode, TURBO mode continues. */ /* */ /* If this function is not called during one pass through */ /* DCS_TimeToDoStuff then the scheduler enters */ /* SLEEP mode - and will not generate any more periodic */ /* callbacks until it is woken by another call to */ /* this function, or until the output accumulation code */ /* IOCtls into the WD again. */ /****************************************************************************/ void RDPCALL SHCLASS SCH_ContinueScheduling(unsigned schedulingMode) { BOOL restart = FALSE; DC_BEGIN_FN("SCH_ContinueScheduling"); TRC_ASSERT( ((schedulingMode == SCH_MODE_NORMAL) || (schedulingMode == SCH_MODE_TURBO)), (TB, "Invalid scheduling state: %u", schedulingMode) ); if (schedulingMode == SCH_MODE_TURBO) { // TURBO mode is often turned off because of packets that need to // be sent out IMMEDIATELY. This makes it very difficult to actually // ask the question, "has input come accross in the last n milliseconds. // This is what we use schInputKickMode for! schInputKickMode = TRUE; } TRC_DBG((TB, "Continue scheduling (%s) -> (%s), InTTDS(%d)", schCurrentMode == SCH_MODE_TURBO ? "Turbo" : schCurrentMode == SCH_MODE_NORMAL ? "Normal" : "Asleep", schedulingMode == SCH_MODE_TURBO ? "Turbo" : schedulingMode == SCH_MODE_NORMAL ? "Normal" : "Asleep", schInTTDS)); if (schCurrentMode == SCH_MODE_TURBO) { // If we're in TURBO mode, then the only interesting event is a // requirement to stay there longer than currently planned. if (schedulingMode == SCH_MODE_TURBO) { COM_GETTICKCOUNT(schLastTurboModeSwitch); TRC_DBG((TB, "New Turbo switch time %lu", schLastTurboModeSwitch)); } } else { if (schedulingMode == SCH_MODE_TURBO) { COM_GETTICKCOUNT(schLastTurboModeSwitch); restart = TRUE; TRC_DBG((TB, "New Turbo switch time %lu", schLastTurboModeSwitch)); } /********************************************************************/ /* We're waking up. If we're not in the middle of a TTDS pass, */ /* then start the new timer straight away. */ /********************************************************************/ if (!schInTTDS && ((schCurrentMode == SCH_MODE_ASLEEP) || restart)) { TRC_DBG((TB, "Starting a timer for %lu ms", schPeriods[schedulingMode])); WDW_StartRITTimer(m_pTSWd, schPeriods[schedulingMode]); } schCurrentMode = schedulingMode; } DC_END_FN(); }