mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-30 02:31:44 +00:00
artf4153 Adds HAL structure memory management
In the current HAL, once the port structures were created, there was no way to free the structures. The way the C++ libraries were written this wasn't a problem, since it grabbed a copy of each and stored them in an array on bootup. However java does not do this, and grabs new ports every time an object is created. This causes memory leaks if an object is ever disposed in java. The same thing looks to be happening in python, and C# does it too currently, but that would change if this gets merged. Adds java memory management fixes Adds memory management to AnalogInput and Analog Output C++ SolenoidPorts and Digital Ports are all hold static arrays with their port pointers (although solenoid overwrites them if a new solenoid on the same module is created), however analog always grabbed new pointers. I would fix the solenoid one, but I don't know what the ideal way to do it would be. Silently ignores free(null) calls by checking passed parameter is non-null. Change-Id: Id32993b57b53f896e46e55c97541d3bd90b52648
This commit is contained in:
committed by
Peter Johnson
parent
e162e4d1c0
commit
de39877efb
@@ -14,12 +14,14 @@ extern "C"
|
||||
{
|
||||
// Analog output functions
|
||||
void* initializeAnalogOutputPort(void* port_pointer, int32_t *status);
|
||||
void freeAnalogOutputPort(void* analog_port_pointer);
|
||||
void setAnalogOutput(void* analog_port_pointer, double voltage, int32_t *status);
|
||||
double getAnalogOutput(void* analog_port_pointer, int32_t *status);
|
||||
bool checkAnalogOutputChannel(uint32_t pin);
|
||||
|
||||
// Analog input functions
|
||||
void* initializeAnalogInputPort(void* port_pointer, int32_t *status);
|
||||
void freeAnalogInputPort(void* analog_port_pointer);
|
||||
bool checkAnalogModule(uint8_t module);
|
||||
bool checkAnalogInputChannel(uint32_t pin);
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ priority_recursive_mutex& spiGetSemaphore(uint8_t port);
|
||||
extern "C"
|
||||
{
|
||||
void* initializeDigitalPort(void* port_pointer, int32_t *status);
|
||||
void freeDigitalPort(void* digital_port_pointer);
|
||||
bool checkPWMChannel(void* digital_port_pointer);
|
||||
bool checkRelayChannel(void* digital_port_pointer);
|
||||
|
||||
|
||||
@@ -211,6 +211,7 @@ extern "C"
|
||||
|
||||
void* getPort(uint8_t pin);
|
||||
void* getPortWithModule(uint8_t module, uint8_t pin);
|
||||
void freePort(void* port);
|
||||
const char* getHALErrorMessage(int32_t code);
|
||||
|
||||
uint16_t getFPGAVersion(int32_t *status);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
extern "C"
|
||||
{
|
||||
void* initializeSolenoidPort(void* port_pointer, int32_t *status);
|
||||
void freeSolenoidPort(void* solenoid_port_pointer);
|
||||
bool checkSolenoidModule(uint8_t module);
|
||||
|
||||
bool getSolenoid(void* solenoid_port_pointer, int32_t *status);
|
||||
|
||||
@@ -71,6 +71,13 @@ void* initializeAnalogInputPort(void* port_pointer, int32_t *status) {
|
||||
return analog_port;
|
||||
}
|
||||
|
||||
void freeAnalogInputPort(void* analog_port_pointer) {
|
||||
AnalogPort* port = (AnalogPort*) analog_port_pointer;
|
||||
if (!port) return;
|
||||
delete port->accumulator;
|
||||
delete port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the analog output port using the given port object.
|
||||
*/
|
||||
@@ -81,9 +88,17 @@ void* initializeAnalogOutputPort(void* port_pointer, int32_t *status) {
|
||||
// Initialize port structure
|
||||
AnalogPort* analog_port = new AnalogPort();
|
||||
analog_port->port = *port;
|
||||
analog_port->accumulator = NULL;
|
||||
return analog_port;
|
||||
}
|
||||
|
||||
void freeAnalogOutputPort(void* analog_port_pointer) {
|
||||
AnalogPort* port = (AnalogPort*) analog_port_pointer;
|
||||
if (!port) return;
|
||||
delete port->accumulator;
|
||||
delete port;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check that the analog module number is valid.
|
||||
@@ -594,8 +609,10 @@ void* initializeAnalogTrigger(void* port_pointer, uint32_t *index, int32_t *stat
|
||||
|
||||
void cleanAnalogTrigger(void* analog_trigger_pointer, int32_t *status) {
|
||||
AnalogTrigger* trigger = (AnalogTrigger*) analog_trigger_pointer;
|
||||
if (!trigger) return;
|
||||
triggers->Free(trigger->index);
|
||||
delete trigger->trigger;
|
||||
freeAnalogInputPort(trigger->port);
|
||||
delete trigger;
|
||||
}
|
||||
|
||||
|
||||
@@ -150,6 +150,11 @@ void* initializeDigitalPort(void* port_pointer, int32_t *status) {
|
||||
return digital_port;
|
||||
}
|
||||
|
||||
void freeDigitalPort(void* digital_port_pointer) {
|
||||
DigitalPort* port = (DigitalPort*) digital_port_pointer;
|
||||
delete port;
|
||||
}
|
||||
|
||||
bool checkPWMChannel(void* digital_port_pointer) {
|
||||
DigitalPort* port = (DigitalPort*) digital_port_pointer;
|
||||
return port->port.pin < kPwmPins;
|
||||
@@ -487,6 +492,7 @@ bool allocatePWMChannel(void* digital_port_pointer, int32_t *status) {
|
||||
|
||||
void freePWMChannel(void* digital_port_pointer, int32_t *status) {
|
||||
DigitalPort* port = (DigitalPort*) digital_port_pointer;
|
||||
if (!port) return;
|
||||
if (!verifyPWMChannel(port, status)) { return; }
|
||||
|
||||
PWMChannels->Free(port->port.pin);
|
||||
@@ -505,6 +511,7 @@ void freePWMChannel(void* digital_port_pointer, int32_t *status) {
|
||||
*/
|
||||
void freeDIO(void* digital_port_pointer, int32_t *status) {
|
||||
DigitalPort* port = (DigitalPort*) digital_port_pointer;
|
||||
if (!port) return;
|
||||
DIOChannels->Free(port->port.pin);
|
||||
}
|
||||
|
||||
@@ -666,13 +673,10 @@ void* initializeCounter(Mode mode, uint32_t *index, int32_t *status) {
|
||||
}
|
||||
|
||||
void freeCounter(void* counter_pointer, int32_t *status) {
|
||||
if (counter_pointer != NULL) {
|
||||
Counter* counter = (Counter*) counter_pointer;
|
||||
delete counter->counter;
|
||||
counters->Free(counter->index);
|
||||
} else {
|
||||
*status = NULL_PARAMETER;
|
||||
}
|
||||
Counter* counter = (Counter*) counter_pointer;
|
||||
if (!counter) return;
|
||||
delete counter->counter;
|
||||
counters->Free(counter->index);
|
||||
}
|
||||
|
||||
void setCounterAverageSize(void* counter_pointer, int32_t size, int32_t *status) {
|
||||
@@ -1004,6 +1008,7 @@ void* initializeEncoder(uint8_t port_a_module, uint32_t port_a_pin, bool port_a_
|
||||
|
||||
void freeEncoder(void* encoder_pointer, int32_t *status) {
|
||||
Encoder* encoder = (Encoder*) encoder_pointer;
|
||||
if (!encoder) return;
|
||||
quadEncoders->Free(encoder->index);
|
||||
delete encoder->encoder;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,12 @@ void* getPortWithModule(uint8_t module, uint8_t pin)
|
||||
return port;
|
||||
}
|
||||
|
||||
void freePort(void* port_pointer)
|
||||
{
|
||||
Port* port = (Port*) port_pointer;
|
||||
delete port;
|
||||
}
|
||||
|
||||
const char* getHALErrorMessage(int32_t code)
|
||||
{
|
||||
switch(code) {
|
||||
|
||||
@@ -33,6 +33,11 @@ void* initializeSolenoidPort(void *port_pointer, int32_t *status) {
|
||||
return solenoid_port;
|
||||
}
|
||||
|
||||
void freeSolenoidPort(void* solenoid_port_pointer) {
|
||||
solenoid_port_t* port = (solenoid_port_t*) solenoid_port_pointer;
|
||||
delete port;
|
||||
}
|
||||
|
||||
bool checkSolenoidModule(uint8_t module) {
|
||||
return module < NUM_MODULE_NUMBERS;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,10 @@ AnalogInput::AnalogInput(uint32_t channel) {
|
||||
/**
|
||||
* Channel destructor.
|
||||
*/
|
||||
AnalogInput::~AnalogInput() { inputs->Free(m_channel); }
|
||||
AnalogInput::~AnalogInput() {
|
||||
freeAnalogInputPort(m_port);
|
||||
inputs->Free(m_channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a sample straight from this channel.
|
||||
|
||||
@@ -50,7 +50,10 @@ AnalogOutput::AnalogOutput(uint32_t channel) {
|
||||
/**
|
||||
* Destructor. Frees analog output resource
|
||||
*/
|
||||
AnalogOutput::~AnalogOutput() { outputs->Free(m_channel); }
|
||||
AnalogOutput::~AnalogOutput() {
|
||||
freeAnalogOutputPort(m_port);
|
||||
outputs->Free(m_channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the analog output
|
||||
|
||||
@@ -33,6 +33,18 @@ JNIEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_AnalogJNI_initializeAnalo
|
||||
return (jlong)analog;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_AnalogJNI
|
||||
* Method: freeAnalogInputPort
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_AnalogJNI_freeAnalogInputPort
|
||||
(JNIEnv * env, jclass, jlong id)
|
||||
{
|
||||
ANALOGJNI_LOG(logDEBUG) << "Port Ptr = " << (void*)id;
|
||||
freeAnalogInputPort((void*)id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_AnalogJNI
|
||||
* Method: initializeAnalogOutputPort
|
||||
@@ -50,6 +62,18 @@ JNIEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_AnalogJNI_initializeAnalo
|
||||
return (jlong)analog;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_AnalogJNI
|
||||
* Method: freeAnalogOutputPort
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_AnalogJNI_freeAnalogOutputPort
|
||||
(JNIEnv * env, jclass, jlong id)
|
||||
{
|
||||
ANALOGJNI_LOG(logDEBUG) << "Port Ptr = " << (void*)id;
|
||||
freeAnalogOutputPort((void*)id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_AnalogJNI
|
||||
* Method: checkAnalogModule
|
||||
|
||||
@@ -34,6 +34,19 @@ JNIEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_DIOJNI_initializeDigitalP
|
||||
return (jlong)dio;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_DIOJNI
|
||||
* Method: freeDigitalPort
|
||||
* Signature: (J)V;
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_DIOJNI_freeDigitalPort
|
||||
(JNIEnv * env, jclass, jlong id)
|
||||
{
|
||||
DIOJNI_LOG(logDEBUG) << "Calling DIOJNI freeDigitalPort";
|
||||
DIOJNI_LOG(logDEBUG) << "Port Ptr = " << (void*)id;
|
||||
freeDigitalPort((void*)id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_DIOJNI
|
||||
* Method: allocateDIO
|
||||
|
||||
@@ -40,4 +40,19 @@ JNIEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_JNIWrapper_getPort
|
||||
return (jlong)port;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_JNIWrapper
|
||||
* Method: freePort
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_JNIWrapper_freePort
|
||||
(JNIEnv * env, jclass, jlong id)
|
||||
{
|
||||
//FILE_LOG(logDEBUG) << "Calling JNIWrapper getPortWithModlue";
|
||||
//FILE_LOG(logDEBUG) << "Module = " << (jint)module;
|
||||
//FILE_LOG(logDEBUG) << "Pin = " << (jint)pin;
|
||||
freePort((void*)id);
|
||||
//FILE_LOG(logDEBUG) << "Port Ptr = " << port;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -41,6 +41,20 @@ JNIEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_SolenoidJNI_initializeSol
|
||||
return (jlong)solenoid_port_pointer;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_SolenoidJNI
|
||||
* Method: freeSolenoidPort
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SolenoidJNI_freeSolenoidPort
|
||||
(JNIEnv *env, jclass, jlong id)
|
||||
{
|
||||
SOLENOIDJNI_LOG(logDEBUG) << "Calling SolenoidJNI initializeSolenoidPort";
|
||||
|
||||
SOLENOIDJNI_LOG(logDEBUG) << "Port Ptr = " << (void*)id;
|
||||
freeSolenoidPort((void*)id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_wpilibj_hal_SolenoidJNI
|
||||
* Method: getPortWithModule
|
||||
|
||||
@@ -77,6 +77,8 @@ public class AnalogInput extends SensorBase implements PIDSource, LiveWindowSend
|
||||
* Channel destructor.
|
||||
*/
|
||||
public void free() {
|
||||
AnalogJNI.freeAnalogInputPort(m_port);
|
||||
m_port = 0;
|
||||
channels.free(m_channel);
|
||||
m_channel = 0;
|
||||
m_accumulatorOffset = 0;
|
||||
|
||||
@@ -52,6 +52,8 @@ public class AnalogOutput extends SensorBase implements LiveWindowSendable {
|
||||
* Channel destructor.
|
||||
*/
|
||||
public void free() {
|
||||
AnalogJNI.freeAnalogOutputPort(m_port);
|
||||
m_port = 0;
|
||||
channels.free(m_channel);
|
||||
m_channel = 0;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,8 @@ public abstract class DigitalSource extends InterruptableSensorBase {
|
||||
public void free() {
|
||||
channels.free(m_channel);
|
||||
DIOJNI.freeDIO(m_port);
|
||||
DIOJNI.freeDigitalPort(m_port);
|
||||
m_port = 0;
|
||||
m_channel = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ public class DoubleSolenoid extends SolenoidBase implements LiveWindowSendable {
|
||||
public synchronized void free() {
|
||||
m_allocated.free(m_moduleNumber * kSolenoidChannels + m_forwardChannel);
|
||||
m_allocated.free(m_moduleNumber * kSolenoidChannels + m_reverseChannel);
|
||||
super.free();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -140,9 +140,12 @@ public class PWM extends SensorBase implements LiveWindowSendable {
|
||||
* Free the resource associated with the PWM channel and set the value to 0.
|
||||
*/
|
||||
public void free() {
|
||||
if (m_port == 0) return;
|
||||
PWMJNI.setPWM(m_port, (short) 0);
|
||||
PWMJNI.freePWMChannel(m_port);
|
||||
PWMJNI.freeDIO(m_port);
|
||||
DIOJNI.freeDigitalPort(m_port);
|
||||
m_port = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -178,6 +178,8 @@ public class Relay extends SensorBase implements MotorSafety, LiveWindowSendable
|
||||
RelayJNI.setRelayReverse(m_port, false);
|
||||
|
||||
DIOJNI.freeDIO(m_port);
|
||||
DIOJNI.freeDigitalPort(m_port);
|
||||
m_port = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -77,6 +77,9 @@ public class Solenoid extends SolenoidBase implements LiveWindowSendable {
|
||||
*/
|
||||
public synchronized void free() {
|
||||
m_allocated.free(m_moduleNumber * kSolenoidChannels + m_channel);
|
||||
SolenoidJNI.freeSolenoidPort(m_solenoid_port);
|
||||
m_solenoid_port = 0;
|
||||
super.free();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,6 +34,17 @@ public abstract class SolenoidBase extends SensorBase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the resources associated with by the solenoid base.
|
||||
*/
|
||||
@Override
|
||||
public void free() {
|
||||
for (int i = 0; i < m_ports.length; i++) {
|
||||
SolenoidJNI.freeSolenoidPort(m_ports[i]);
|
||||
m_ports[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of a solenoid.
|
||||
*
|
||||
|
||||
@@ -34,8 +34,12 @@ public class AnalogJNI extends JNIWrapper {
|
||||
|
||||
public static native long initializeAnalogInputPort(long port_pointer);
|
||||
|
||||
public static native void freeAnalogInputPort(long port_pointer);
|
||||
|
||||
public static native long initializeAnalogOutputPort(long port_pointer);
|
||||
|
||||
public static native void freeAnalogOutputPort(long port_pointer);
|
||||
|
||||
public static native boolean checkAnalogModule(byte module);
|
||||
|
||||
public static native boolean checkAnalogInputChannel(int pin);
|
||||
|
||||
@@ -3,6 +3,8 @@ package edu.wpi.first.wpilibj.hal;
|
||||
public class DIOJNI extends JNIWrapper {
|
||||
public static native long initializeDigitalPort(long port_pointer);
|
||||
|
||||
public static native void freeDigitalPort(long port_pointer);
|
||||
|
||||
public static native boolean allocateDIO(long digital_port_pointer, boolean input);
|
||||
|
||||
public static native void freeDIO(long digital_port_pointer);
|
||||
|
||||
@@ -51,4 +51,6 @@ public class JNIWrapper {
|
||||
public static native long getPortWithModule(byte module, byte pin);
|
||||
|
||||
public static native long getPort(byte pin);
|
||||
|
||||
public static native void freePort(long port_pointer);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package edu.wpi.first.wpilibj.hal;
|
||||
public class SolenoidJNI extends JNIWrapper {
|
||||
public static native long initializeSolenoidPort(long portPointer);
|
||||
|
||||
public static native void freeSolenoidPort(long port_pointer);
|
||||
|
||||
public static native long getPortWithModule(byte module, byte channel);
|
||||
|
||||
public static native void setSolenoid(long port, boolean on);
|
||||
|
||||
Reference in New Issue
Block a user