diff --git a/GSM/GSML1FEC.cpp b/GSM/GSML1FEC.cpp index d3db880..71cadba 100644 --- a/GSM/GSML1FEC.cpp +++ b/GSM/GSML1FEC.cpp @@ -243,6 +243,7 @@ void L1Encoder::rollForward() // This implements GSM 05.02 Clause 7 for the transmit side. mPrevWriteTime = mNextWriteTime; mTotalFrames++; + ScopedLock lock(mWriteTimeLock,__FILE__,__LINE__); // (pat) Protects getNextWriteTime. mNextWriteTime.rollForward(mMapping.frameMapping(mTotalFrames),mMapping.repeatLength()); } @@ -316,7 +317,6 @@ const L1Decoder* L1Encoder::sibling() const return mParent->decoder(); } - void L1Encoder::resync(bool force) { // If the encoder's clock is far from the current BTS clock, @@ -328,11 +328,20 @@ void L1Encoder::resync(bool force) mNextWriteTime = now; mNextWriteTime.TN(mTN); mTotalFrames = 0; // (pat 4-2014) Make sure we start at beginning of mapping. - mNextWriteTime.rollForward(mMapping.frameMapping(mTotalFrames),mMapping.repeatLength()); + { ScopedLock lock(mWriteTimeLock,__FILE__,__LINE__); // (pat) Protects getNextWriteTime. + mNextWriteTime.rollForward(mMapping.frameMapping(mTotalFrames),mMapping.repeatLength()); + } OBJLOG(DEBUG) <<"L1Encoder RESYNC "<< " next=" << mNextWriteTime << " now=" << now; } } +Time L1Encoder::getNextWriteTime() +{ + resync(); + ScopedLock lock(mWriteTimeLock,__FILE__,__LINE__); + return mNextWriteTime; +} + void L1Encoder::waitToSend() const { @@ -2279,7 +2288,9 @@ void TCHFACCHL1Encoder::dispatch() // Most channels do not need this, becuase they are entirely data-driven // from above. TCH/FACCH, however, must feed the interleaver on time. if (!encActive()) { - mNextWriteTime += 26; + { ScopedLock lock(mWriteTimeLock,__FILE__,__LINE__); // (pat) Protects getNextWriteTime. + mNextWriteTime += 26; + } gBTS.clock().wait(mNextWriteTime); return; } diff --git a/GSM/GSML1FEC.h b/GSM/GSML1FEC.h index 28783b8..bdc83dd 100644 --- a/GSM/GSML1FEC.h +++ b/GSM/GSML1FEC.h @@ -110,6 +110,7 @@ class L1Encoder { //@} /**@name Multithread access control and data shared across threads. */ + // (pat) It is not being used effectively. //@{ mutable Mutex mEncLock; //@} @@ -127,6 +128,9 @@ class L1Encoder { GSM::Time mPrevWriteTime; ///< timestamp of previous generated burst GSM::Time mNextWriteTime; ///< timestamp of next generated burst + // (pat 10-2014) Another thread calls getNextWriteTime so we must protect places that write to mNextWriteTime. + mutable Mutex mWriteTimeLock; + volatile bool mRunning; ///< true while the service loop is running Bool_z mEncActive; ///< true between open() and close() Bool_z mEncEverActive; // true if the encoder has ever been active. @@ -210,7 +214,7 @@ class L1Encoder { const L1FEC* parent() const { return mParent; } L1FEC* parent() { return mParent; } - GSM::Time getNextWriteTime() { resync(); return mNextWriteTime; } + GSM::Time getNextWriteTime(); protected: