#1876 Unifies reentrant lock between tuners and frequency controller. (#1901)

Co-authored-by: sheirerd <sheirerd@ainfosec.com>
This commit is contained in:
Denny Sheirer
2024-05-04 05:29:54 -04:00
committed by GitHub
parent aa8d449140
commit cbe451a793
10 changed files with 79 additions and 101 deletions

View File

@@ -1417,8 +1417,6 @@ public class P25TrafficChannelManager extends TrafficChannelManager implements I
mAvailablePhase1TrafficChannelQueue.clear();
mAvailablePhase2TrafficChannelQueue.clear();
//TODO: debug
mLog.info("TCM - Stopping and clearing channel grant event maps");
mTS1ChannelGrantEventMap.clear();
mTS2ChannelGrantEventMap.clear();
}

View File

@@ -42,15 +42,18 @@ import java.util.concurrent.locks.ReentrantLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Base tuner controller implementation.
*/
public abstract class TunerController implements Tunable, ISourceEventProcessor, ISourceEventListener,
INativeBufferProvider, Listener<INativeBuffer>, ITunerErrorListener
{
private final static Logger mLog = LoggerFactory.getLogger(TunerController.class);
//Protects access to the native buffer broadcaster for adding, removing or checking for listener count.
protected ReentrantLock mBufferListenerLock = new ReentrantLock();
private ReentrantLock mBufferListenerLock = new ReentrantLock();
private ReentrantLock mLock = new ReentrantLock();
protected Broadcaster<INativeBuffer> mNativeBufferBroadcaster = new Broadcaster();
protected FrequencyController mFrequencyController;
private int mMiddleUnusableHalfBandwidth;
private int mMeasuredFrequencyError;
@@ -74,6 +77,26 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
mFrequencyErrorCorrectionManager = new FrequencyErrorCorrectionManager(this);
}
/**
* Lock for controlling configuration access to this tuner controller and any embedded tuner to ensure that
* configuration changes happen atomically. There are at least two threads that can touch this controller:
*
* A: channel processing that changes the center tuned frequency and frequency correction.
* b: user ui thread that can touch any of the frequency correction and gain controls.
*
* Generally, we'll lock on each of the primary configuration change points - getter and setter for:
* Frequency
* Frequency Correction
* Sample Rate
* Gain Controls
*
* @return lock for controlling access to tuner controller and em
*/
public ReentrantLock getLock()
{
return mLock;
}
/**
* Updates the frequency controller with the new minimum and maximum values.
* @param minimum frequency Hertz
@@ -85,17 +108,6 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
mFrequencyController.setMaximumFrequency(maximum);
}
/**
* Lock for the frequency controller. This should only be used by the channel source manager to lock access to the
* frequency controller while creating a channel source, to block multi-threaded access to the frequency controller
* which might put the center tuned frequency value in an indeterminant state.
* @return frequency controller lock
*/
public ReentrantLock getFrequencyControllerLock()
{
return mFrequencyController.getFrequencyControllerLock();
}
/**
* Frequency correction manager for this tuner controller.
*/
@@ -292,12 +304,12 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
{
try
{
getFrequencyControllerLock().lock();
getLock().lock();
mFrequencyController.setFrequency(frequency);
}
finally
{
getFrequencyControllerLock().unlock();
getLock().unlock();
}
}
@@ -318,12 +330,12 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
try
{
getFrequencyControllerLock().lock();
getLock().lock();
canTune = mFrequencyController.canTune(frequency);
}
finally
{
getFrequencyControllerLock().unlock();
getLock().unlock();
}
return canTune;
@@ -341,12 +353,12 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
try
{
getFrequencyControllerLock().lock();
getLock().lock();
correction = mFrequencyController.getFrequencyCorrection();
}
finally
{
getFrequencyControllerLock().unlock();
getLock().unlock();
}
return correction;
@@ -356,12 +368,12 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
{
try
{
getFrequencyControllerLock().lock();
getLock().lock();
mFrequencyController.setFrequencyCorrection(correction);
}
finally
{
getFrequencyControllerLock().unlock();
getLock().unlock();
}
}
@@ -375,12 +387,12 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
try
{
getFrequencyControllerLock().lock();
getLock().lock();
minimum = mFrequencyController.getMinimumFrequency();
}
finally
{
getFrequencyControllerLock().unlock();
getLock().unlock();
}
return minimum;
@@ -394,12 +406,12 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
{
try
{
getFrequencyControllerLock().lock();
getLock().lock();
mFrequencyController.setMinimumFrequency(minimum);
}
finally
{
getFrequencyControllerLock().unlock();
getLock().unlock();
}
}
@@ -413,12 +425,12 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
try
{
getFrequencyControllerLock().lock();
getLock().lock();
maximum = mFrequencyController.getMaximumFrequency();
}
finally
{
getFrequencyControllerLock().unlock();
getLock().unlock();
}
return maximum;
@@ -432,12 +444,12 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
{
try
{
getFrequencyControllerLock().lock();
getLock().lock();
mFrequencyController.setMaximumFrequency(maximum);
}
finally
{
getFrequencyControllerLock().unlock();
getLock().unlock();
}
}
@@ -447,12 +459,12 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
try
{
getFrequencyControllerLock().lock();
getLock().lock();
minTuned = mFrequencyController.getFrequency() - (getUsableBandwidth() / 2);
}
finally
{
getFrequencyControllerLock().unlock();
getLock().unlock();
}
return minTuned;
@@ -464,12 +476,12 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
try
{
getFrequencyControllerLock().lock();
getLock().lock();
maxTuned = mFrequencyController.getFrequency() + (getUsableBandwidth() / 2);
}
finally
{
getFrequencyControllerLock().unlock();
getLock().unlock();
}
return maxTuned;

View File

@@ -65,7 +65,6 @@ public abstract class FCDTunerController extends TunerController
private FCDConfiguration mConfiguration = new FCDConfiguration();
protected ComplexMixer mComplexMixer;
private ReentrantLock mListenerLock = new ReentrantLock();
/**
* Generic FCD tuner controller - contains functionality common across both
@@ -126,7 +125,7 @@ public abstract class FCDTunerController extends TunerController
@Override
public void addBufferListener(Listener<INativeBuffer> listener)
{
mListenerLock.lock();
getLock().lock();
try
{
@@ -139,7 +138,7 @@ public abstract class FCDTunerController extends TunerController
}
finally
{
mListenerLock.unlock();
getLock().unlock();
}
}
@@ -150,7 +149,7 @@ public abstract class FCDTunerController extends TunerController
@Override
public void removeBufferListener(Listener<INativeBuffer> listener)
{
mListenerLock.lock();
getLock().lock();
try
{
@@ -167,7 +166,7 @@ public abstract class FCDTunerController extends TunerController
}
finally
{
mListenerLock.unlock();
getLock().unlock();
}
}
@@ -460,7 +459,7 @@ public abstract class FCDTunerController extends TunerController
*/
public void setTunedFrequency(long frequency) throws SourceException
{
mListenerLock.lock();
getLock().lock();
try
{
@@ -473,7 +472,7 @@ public abstract class FCDTunerController extends TunerController
}
finally
{
mListenerLock.unlock();
getLock().unlock();
}
}

View File

@@ -22,11 +22,12 @@ import io.github.dsheirer.source.ISourceEventProcessor;
import io.github.dsheirer.source.InvalidFrequencyException;
import io.github.dsheirer.source.SourceEvent;
import io.github.dsheirer.source.SourceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FrequencyController
{
@@ -42,11 +43,6 @@ public class FrequencyController
private boolean mSampleRateLocked = false;
private List<ISourceEventProcessor> mProcessors = new ArrayList<>();
/**
* Lock protecting access to frequency control plane, source event processor subscriptions and event broadcasting
*/
private ReentrantLock mLock = new ReentrantLock();
/**
* Constructs an instance
* @param tunable that can be controlled by this frequency controller.
@@ -56,15 +52,6 @@ public class FrequencyController
mTunable = tunable;
}
/**
* Lock for controlling access to frequency control plane, event processor subscriptions and source event broadcasts.
*/
public ReentrantLock getFrequencyControllerLock()
{
return mLock;
}
/**
* Prepare for disposal of this instance.
*/
@@ -294,7 +281,7 @@ public class FrequencyController
*/
public void addSourceEventProcessor(ISourceEventProcessor processor)
{
mLock.lock();
mTunable.getLock().lock();
try
{
@@ -305,7 +292,7 @@ public class FrequencyController
}
finally
{
mLock.unlock();
mTunable.getLock().unlock();
}
}
@@ -314,7 +301,7 @@ public class FrequencyController
*/
public void removeSourceEventProcessor(ISourceEventProcessor processor)
{
mLock.lock();
mTunable.getLock().lock();
try
{
@@ -322,7 +309,7 @@ public class FrequencyController
}
finally
{
mLock.unlock();
mTunable.getLock().unlock();
}
}
@@ -354,7 +341,7 @@ public class FrequencyController
public void broadcast(SourceEvent event) throws SourceException
{
mLock.lock();
mTunable.getLock().lock();
try
{
@@ -365,13 +352,18 @@ public class FrequencyController
}
finally
{
mLock.unlock();
mTunable.getLock().unlock();
}
}
public interface Tunable
{
/**
* Reentrant lock to synchronize threaded access to tuner controls.
*/
ReentrantLock getLock();
/**
* Gets the tuned frequency of the device
*/

View File

@@ -116,7 +116,7 @@ public class HeterodyneChannelSourceManager extends ChannelSourceManager
try
{
mTunerController.getFrequencyControllerLock().lock();
mTunerController.getLock().lock();
if(CenterFrequencyCalculator.canTune(tunerChannel, mTunerController, mTunerChannels))
{
try
@@ -150,7 +150,7 @@ public class HeterodyneChannelSourceManager extends ChannelSourceManager
}
finally
{
mTunerController.getFrequencyControllerLock().unlock();
mTunerController.getLock().unlock();
}
return source;

View File

@@ -106,7 +106,7 @@ public class PassThroughSourceManager extends ChannelSourceManager
try
{
mTunerController.getFrequencyControllerLock().lock();
mTunerController.getLock().lock();
PassThroughChannelSource channelSource = new PassThroughChannelSource(new SourceEventProxy(),
mTunerController, tunerChannel, threadName);
@@ -116,7 +116,7 @@ public class PassThroughSourceManager extends ChannelSourceManager
}
finally
{
mTunerController.getFrequencyControllerLock().unlock();
mTunerController.getLock().unlock();
}
return source;

View File

@@ -431,7 +431,7 @@ public class PolyphaseChannelSourceManager extends ChannelSourceManager
try
{
mTunerController.getFrequencyControllerLock().lock();
mTunerController.getLock().lock();
if(isTunable(tunerChannel))
{
//Get a new set of currently tuned channels
@@ -478,7 +478,7 @@ public class PolyphaseChannelSourceManager extends ChannelSourceManager
}
finally
{
mTunerController.getFrequencyControllerLock().unlock();
mTunerController.getLock().unlock();
}
return tunerChannelSource;

View File

@@ -67,7 +67,6 @@ public class RTL2832TunerController extends USBTunerController
private EmbeddedTuner mEmbeddedTuner;
private long mTunedFrequency = 0;
private boolean mBiasTEnabled = false;
private ReentrantLock mLock = new ReentrantLock();
/**
* Abstract tuner controller device. Use the static gettype() method
@@ -79,28 +78,6 @@ public class RTL2832TunerController extends USBTunerController
super(bus, portAddress, tunerErrorListener);
}
/**
* Lock for controlling configuration access to this tuner controller and the embedded tuner to ensure that
* configuration changes involving multiple USB control messages can happen atomically. There are at least two
* threads that can touch this controller:
*
* A: channel processing that changes the center tuned frequency and frequency correction.
* b: user ui thread that can touch any of the frequency correction and gain controls.
*
* Generally, we'll lock on each of the primary configuration change points - getter and setter for:
* Frequency
* Frequency Correction
* Sample Rate
* Gain Controls
*
* @return lock for controlling access to tuner controller and em
*/
private ReentrantLock getLock()
{
return mLock;
}
@Override
protected INativeBufferFactory getNativeBufferFactory()
{

View File

@@ -185,7 +185,7 @@ public abstract class RspTunerController<I extends IControlRsp> extends TunerCon
@Override
public void addBufferListener(Listener<INativeBuffer> listener)
{
mBufferListenerLock.lock();
getLock().lock();
try
{
@@ -198,7 +198,7 @@ public abstract class RspTunerController<I extends IControlRsp> extends TunerCon
}
finally
{
mBufferListenerLock.unlock();
getLock().unlock();
}
}
@@ -209,7 +209,7 @@ public abstract class RspTunerController<I extends IControlRsp> extends TunerCon
@Override
public void removeBufferListener(Listener<INativeBuffer> listener)
{
mBufferListenerLock.lock();
getLock().lock();
try
{
@@ -222,7 +222,7 @@ public abstract class RspTunerController<I extends IControlRsp> extends TunerCon
}
finally
{
mBufferListenerLock.unlock();
getLock().unlock();
}
}

View File

@@ -477,7 +477,7 @@ public abstract class USBTunerController extends TunerController
{
if(isRunning())
{
mBufferListenerLock.lock();
getLock().lock();
try
{
@@ -492,7 +492,7 @@ public abstract class USBTunerController extends TunerController
}
finally
{
mBufferListenerLock.unlock();
getLock().unlock();
}
}
}
@@ -503,7 +503,7 @@ public abstract class USBTunerController extends TunerController
@Override
public void removeBufferListener(Listener<INativeBuffer> listener)
{
mBufferListenerLock.lock();
getLock().lock();
try
{
@@ -516,7 +516,7 @@ public abstract class USBTunerController extends TunerController
}
finally
{
mBufferListenerLock.unlock();
getLock().unlock();
}
}