diff -r 000000000000 -r c40eb8fe8501 wlan_bearer/wlanldd/wlan_symbian/osa_symbian/src/osatimer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wlan_bearer/wlanldd/wlan_symbian/osa_symbian/src/osatimer.cpp Tue Feb 02 02:03:13 2010 +0200 @@ -0,0 +1,302 @@ +/* +* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: WlanTimer implementation +* +*/ + +/* +* %version: 10 % +*/ + +#include "osa_includeme.h" + +#include + +#include "osatimer.h" +#include "osa.h" + +// mask value to check is timer periodic or not +const TUint KPeriodicTimerMask( 1 << 1 ); +// mask value to check if timer is running +const TUint KTimerRunningMask( 1 << 2 ); + + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +WlanTimer::WlanTimer( WlanOsa& aOsa, void* aDfcQueue ) + : iTimerDfc( WlanTimer::TimerTrigger, this, 0 ), + iOsa( aOsa ), + iNTimer( ), + iTimerClient( NULL ), + iTimeoutInMicroSeconds( 0 ), + iCtx( 0 ), + iFlags( 0 ), + iRefCnt( 1 ) + { + TraceDump(INFO_LEVEL | TIMER_LEVEL, ("[WLAN] WlanTimer() ctor +")); + + MWlanOsa::Assert( + reinterpret_cast(WLAN_FILE), __LINE__, + aDfcQueue != NULL ); + + iTimerDfc.SetDfcQ( reinterpret_cast(aDfcQueue) ); + Validate(); + + TraceDump(INFO_LEVEL | TIMER_LEVEL, ("[WLAN] WlanTimer() ctor -")); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +WlanTimer::~WlanTimer() + { + TraceDump(INFO_LEVEL | TIMER_LEVEL, ("[WLAN] WlanTimer() dtor +")); + + if ( iRefCnt != 0 ) + { + TraceDump(CRIT_LEVEL, (("[WLAN] error: Timer destroyed while " + "active - delete used directly?"))); + MWlanOsa::Assert( + reinterpret_cast(WLAN_FILE), __LINE__ ); + } + + TraceDump(INFO_LEVEL | TIMER_LEVEL, ("[WLAN] WlanTimer() dtor -")); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void WlanTimer::TimerTrigger( TAny* aPtr ) + { + WlanTimer* timer = reinterpret_cast< WlanTimer* >( aPtr ); + timer->TimerTrigger(); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void WlanTimer::TimerTrigger() + { + WlanOsa &osa = iOsa; + + TraceDump(INFO_LEVEL | TIMER_LEVEL, ("[WLAN] WlanTimer::TimerTrigger +")); + + // get hold of the global mutex + iOsa.MutexAcquire(); + + if (iFlags & KTimerRunningMask) + { + if ( iFlags & KPeriodicTimerMask ) + { + // a periodic timer was requested - re-arm the timer for the next + // run now. + const TInt ticks( + NKern::TimerTicks( iTimeoutInMicroSeconds / 1000 )); + TraceDump(TIMER_LEVEL, (("[WLAN] timer ticks: %d"), ticks)); + + // on arming the timer, add a reference to it - the reference + // shall be cleared upon the completion callback execution. + RefAdd(); + const TInt ret (iNTimer.Again( ticks )); + + if ( ret != KErrNone ) + { + TraceDump(CRIT_LEVEL, (("[WLAN] error: ret %d"), ret)); + MWlanOsa::Assert( + reinterpret_cast(WLAN_FILE), __LINE__ ); + RefDel(); + } + } + else + { + // clear the timer running mask + iFlags &= (~KTimerRunningMask); + } + + TraceDump(TIMER_LEVEL, + (("[WLAN] current system time: %d"), Kern::SystemTime())); + TraceDump(TIMER_LEVEL, + (("[WLAN] timer client address: 0x%08x"), iTimerClient)); + TraceDump(TIMER_LEVEL, + (("[WLAN] call timer callback with context: %d"), iCtx)); + + // execute the timer client call back function + iTimerClient->OnTimeout( iCtx ); + } + + // a reference was added for this timer instance upon arming of the + // timer - here, we must remove that reference - and possibly delete + // the object instance if we were last to hold reference to it. + // NOTE! here the reference count may become zero (if the + // TimerDestroy OSA method was called for the instance prior to this + // handler executing) and hence the instance may be deleted upon this + // call. do not touch instance data after this call. + RefDel(); + + // release the global mutex - do not use the "iOsa" as the instance + // may now have been deleted, instead use a local reference. + osa.MutexRelease(); + + TraceDump(INFO_LEVEL | TIMER_LEVEL, ("[WLAN] WlanTimer::TimerTrigger -")); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void WlanTimer::Enqueue( + MWlanTimerClient& aTimerClient, + TInt aCtx, + TInt aTimeoutInMicroSeconds, + TBool aPeriodic ) + { + + if ( iFlags & KTimerRunningMask ) + { + // ignore the call if the timer is already running + TraceDump(INFO_LEVEL | TIMER_LEVEL, + (("[WLAN] WlanTimer::Enqueue: + addr: 0x%08x: " + "Timer already enqueued, no effect."), this)); + } + else + { + TraceDump(INFO_LEVEL | TIMER_LEVEL, + (("[WLAN] WlanTimer::Enqueue: + addr: 0x%08x"), this)); + TraceDump(TIMER_LEVEL, + (("[WLAN] timeout in microseconds: %d"), aTimeoutInMicroSeconds)); + TraceDump(TIMER_LEVEL, (("[WLAN] periodic: %d"), aPeriodic)); + + // store timer parameters + iFlags = KTimerRunningMask; + iTimerClient = &aTimerClient; + iCtx = aCtx; + + if ( aPeriodic ) + { + iFlags |= KPeriodicTimerMask; + } + + const TInt KMinTimeout = 1000; + + // the timeout minimum is 1000 us + if (aTimeoutInMicroSeconds < KMinTimeout) + { + iTimeoutInMicroSeconds = KMinTimeout; + } + else + { + // adding 999 here will allow the us timeout to be rounded + // up to the next full ms, guaranteeing at least the timeout + // requested, no less. + iTimeoutInMicroSeconds = aTimeoutInMicroSeconds + 999; + } + + // arm the timer (using ms instead of us for the unit) + const TInt ticks( NKern::TimerTicks( iTimeoutInMicroSeconds / 1000 )); + + TraceDump(TIMER_LEVEL, (("[WLAN] timeout in ticks: %d"), ticks)); + TraceDump(TIMER_LEVEL, + (("[WLAN] current system time: %d"), Kern::SystemTime())); + + // add reference to the timer instance - this reference will be + // removed once the timeout event has been handled + RefAdd(); + const TInt ret( iNTimer.OneShot( ticks, iTimerDfc )); + + if ( ret != KErrNone ) + { + TraceDump(CRIT_LEVEL, (("[WLAN] error: ret %d"), ret)); + MWlanOsa::Assert( + reinterpret_cast(WLAN_FILE), __LINE__ ); + RefDel(); + } + } + + TraceDump(INFO_LEVEL | TIMER_LEVEL, + (("[WLAN] WlanTimer::Enqueue: - addr: 0x%08x: "), this)); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void WlanTimer::Dequeue() + { + TraceDump(INFO_LEVEL | TIMER_LEVEL, + (("[WLAN] WlanTimer::Dequeue: + addr: 0x%08x"), this)); + + if ( iFlags & KTimerRunningMask ) + { + iFlags = 0; + + if ( iNTimer.Cancel()) + { + // if cancellation of the timer succeeds, remove a reference from + // the timer instance - as this will not be done in the timeout + // handler now. NOTE! that here the reference count should never + // reach zero (instance exists + the timer is running == 2) + RefDel(); + + } + // if the cancellation of the timer failed above, the DFC is most + // likely already executing - attempting to cancel it here would + // be wasting of clock cycles. + // + // the most common scenario is that the timer cancel succeeds. for + // the rare cases of a failure, we just let the DFC execute, and + // do nothing (the flags are cleared.) + } + else + { + TraceDump(INFO_LEVEL | TIMER_LEVEL, + (("[WLAN] WlanTimer::Dequeue: Timer is not running."))); + } + + TraceDump(INFO_LEVEL | TIMER_LEVEL, + (("[WLAN] WlanTimer::Dequeue: - addr: 0x%08x"), this)); + } + + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void WlanTimer::RefDel(void) + { + // decrement the reference counter + iRefCnt --; + + if (iRefCnt == 0) + { + // referees have reached zero, the object is abandoned, and + // shall be deleted + WlanTimer *timer = this; + delete timer; + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void WlanTimer::RefAdd(void) + { + // increment the reference counter + iRefCnt ++; + }