diff -r 2d65c2f76d7b -r 947f0dc9f7a8 kerneltest/e32test/dma/dmasim.cpp --- a/kerneltest/e32test/dma/dmasim.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/dma/dmasim.cpp Fri Apr 16 16:24:37 2010 +0300 @@ -355,31 +355,69 @@ public: static void StartEmulation(); static void StopEmulation(); + static TBool InISR(); + static void Synchronize(); private: enum { KPeriod = 1 }; // in ms + enum { EDmaSimIdle=0u, EDmaSimStarted=1u, EDmaSimInISR=2u, EDmaSimStopping=0x80000000u }; static void TickCB(TAny* aThis); static NTimer Timer; + static volatile TInt StartStop; }; NTimer DmacSim::Timer; +volatile TInt DmacSim::StartStop; void DmacSim::StartEmulation() { + __DMA_ASSERTA(StartStop==EDmaSimIdle); new (&Timer) NTimer(&TickCB, 0); + __e32_atomic_store_ord32(&StartStop, EDmaSimStarted); __DMA_ASSERTA(Timer.OneShot(KPeriod, EFalse) == KErrNone); } void DmacSim::StopEmulation() { - Timer.Cancel(); + TInt orig = __e32_atomic_tas_ord32(&StartStop, (TInt)EDmaSimStarted, (TInt)EDmaSimStopping, 0); + if (orig == EDmaSimIdle) + return; // wasn't running + // loop until we succeed in cancelling the timer or the timer callback + // notices that we are shutting down + while (!Timer.Cancel() && __e32_atomic_load_acq32(&StartStop)!=EDmaSimIdle) + {} + __e32_atomic_store_ord32(&StartStop, EDmaSimIdle); } void DmacSim::TickCB(TAny*) { - DmacSb::DoTransfer(); - DmacDb::DoTransfer(); - DmacSg::DoTransfer(); - __DMA_ASSERTA(Timer.Again(KPeriod) == KErrNone); + TInt orig = (TInt)__e32_atomic_ior_acq32(&StartStop, EDmaSimInISR); + if (orig >= 0) + { + DmacSb::DoTransfer(); + DmacDb::DoTransfer(); + DmacSg::DoTransfer(); + } + orig = (TInt)__e32_atomic_and_rel32(&StartStop, (TUint32)~EDmaSimInISR); + if (orig < 0) + { + __e32_atomic_store_rel32(&StartStop, EDmaSimIdle); + return; + } + TInt r = Timer.Again(KPeriod); + if (r == KErrArgument) + r = Timer.OneShot(KPeriod); + __DMA_ASSERTA(r == KErrNone); + } + +TBool DmacSim::InISR() + { + return __e32_atomic_load_acq32(&StartStop) & EDmaSimInISR; + } + +void DmacSim::Synchronize() + { + while (InISR()) + {} } ////////////////////////////////////////////////////////////////////////////// @@ -436,6 +474,7 @@ void DSimSbController::StopTransfer(const TDmaChannel& aChannel) { __e32_atomic_and_ord32(&DmacSb::ControlStatus[aChannel.PslId()], (TUint32)~DmacSb::ECsRun); + DmacSim::Synchronize(); } @@ -536,6 +575,7 @@ void DSimDbController::StopTransfer(const TDmaChannel& aChannel) { __e32_atomic_and_ord32(&DmacDb::ControlStatus[aChannel.PslId()], (TUint32)~(DmacDb::ECsRun|DmacDb::ECsPrg)); + DmacSim::Synchronize(); } @@ -666,6 +706,7 @@ void DSimSgController::StopTransfer(const TDmaChannel& aChannel) { __e32_atomic_and_ord32(&DmacSg::ChannelControl[aChannel.PslId()], (TUint32)~DmacSg::EChannelBitRun); + DmacSim::Synchronize(); }