Adding thread safety

Making our LoRaWAN stack thread safe. If RTOS is not present, locks
don't do anything. ScopedLock is used to automate the lock release on
context expiry.
pull/6808/head
Hasnain Virk 2018-05-03 18:40:50 +03:00
parent a331c4b59a
commit a75af9799e
4 changed files with 53 additions and 0 deletions

View File

@ -34,95 +34,114 @@ LoRaWANInterface::~LoRaWANInterface()
lorawan_status_t LoRaWANInterface::initialize(EventQueue *queue) lorawan_status_t LoRaWANInterface::initialize(EventQueue *queue)
{ {
Lock lock(*this);
return _lw_stack.initialize_mac_layer(queue); return _lw_stack.initialize_mac_layer(queue);
} }
lorawan_status_t LoRaWANInterface::connect() lorawan_status_t LoRaWANInterface::connect()
{ {
Lock lock(*this);
return _lw_stack.connect(); return _lw_stack.connect();
} }
lorawan_status_t LoRaWANInterface::connect(const lorawan_connect_t &connect) lorawan_status_t LoRaWANInterface::connect(const lorawan_connect_t &connect)
{ {
Lock lock(*this);
return _lw_stack.connect(connect); return _lw_stack.connect(connect);
} }
lorawan_status_t LoRaWANInterface::disconnect() lorawan_status_t LoRaWANInterface::disconnect()
{ {
Lock lock(*this);
return _lw_stack.shutdown(); return _lw_stack.shutdown();
} }
lorawan_status_t LoRaWANInterface::add_link_check_request() lorawan_status_t LoRaWANInterface::add_link_check_request()
{ {
Lock lock(*this);
return _lw_stack.set_link_check_request(); return _lw_stack.set_link_check_request();
} }
void LoRaWANInterface::remove_link_check_request() void LoRaWANInterface::remove_link_check_request()
{ {
Lock lock(*this);
_lw_stack.remove_link_check_request(); _lw_stack.remove_link_check_request();
} }
lorawan_status_t LoRaWANInterface::set_datarate(uint8_t data_rate) lorawan_status_t LoRaWANInterface::set_datarate(uint8_t data_rate)
{ {
Lock lock(*this);
return _lw_stack.set_channel_data_rate(data_rate); return _lw_stack.set_channel_data_rate(data_rate);
} }
lorawan_status_t LoRaWANInterface::set_confirmed_msg_retries(uint8_t count) lorawan_status_t LoRaWANInterface::set_confirmed_msg_retries(uint8_t count)
{ {
Lock lock(*this);
return _lw_stack.set_confirmed_msg_retry(count); return _lw_stack.set_confirmed_msg_retry(count);
} }
lorawan_status_t LoRaWANInterface::enable_adaptive_datarate() lorawan_status_t LoRaWANInterface::enable_adaptive_datarate()
{ {
Lock lock(*this);
return _lw_stack.enable_adaptive_datarate(true); return _lw_stack.enable_adaptive_datarate(true);
} }
lorawan_status_t LoRaWANInterface::disable_adaptive_datarate() lorawan_status_t LoRaWANInterface::disable_adaptive_datarate()
{ {
Lock lock(*this);
return _lw_stack.enable_adaptive_datarate(false); return _lw_stack.enable_adaptive_datarate(false);
} }
lorawan_status_t LoRaWANInterface::set_channel_plan(const lorawan_channelplan_t &channel_plan) lorawan_status_t LoRaWANInterface::set_channel_plan(const lorawan_channelplan_t &channel_plan)
{ {
Lock lock(*this);
return _lw_stack.add_channels(channel_plan); return _lw_stack.add_channels(channel_plan);
} }
lorawan_status_t LoRaWANInterface::get_channel_plan(lorawan_channelplan_t &channel_plan) lorawan_status_t LoRaWANInterface::get_channel_plan(lorawan_channelplan_t &channel_plan)
{ {
Lock lock(*this);
return _lw_stack.get_enabled_channels(channel_plan); return _lw_stack.get_enabled_channels(channel_plan);
} }
lorawan_status_t LoRaWANInterface::remove_channel(uint8_t id) lorawan_status_t LoRaWANInterface::remove_channel(uint8_t id)
{ {
Lock lock(*this);
return _lw_stack.remove_a_channel(id); return _lw_stack.remove_a_channel(id);
} }
lorawan_status_t LoRaWANInterface::remove_channel_plan() lorawan_status_t LoRaWANInterface::remove_channel_plan()
{ {
Lock lock(*this);
return _lw_stack.drop_channel_list(); return _lw_stack.drop_channel_list();
} }
int16_t LoRaWANInterface::send(uint8_t port, const uint8_t* data, uint16_t length, int flags) int16_t LoRaWANInterface::send(uint8_t port, const uint8_t* data, uint16_t length, int flags)
{ {
Lock lock(*this);
return _lw_stack.handle_tx(port, data, length, flags); return _lw_stack.handle_tx(port, data, length, flags);
} }
int16_t LoRaWANInterface::receive(uint8_t port, uint8_t* data, uint16_t length, int flags) int16_t LoRaWANInterface::receive(uint8_t port, uint8_t* data, uint16_t length, int flags)
{ {
Lock lock(*this);
return _lw_stack.handle_rx(data, length, port, flags, true); return _lw_stack.handle_rx(data, length, port, flags, true);
} }
int16_t LoRaWANInterface::receive(uint8_t* data, uint16_t length, uint8_t& port, int& flags) int16_t LoRaWANInterface::receive(uint8_t* data, uint16_t length, uint8_t& port, int& flags)
{ {
Lock lock(*this);
return _lw_stack.handle_rx(data, length, port, flags, false); return _lw_stack.handle_rx(data, length, port, flags, false);
} }
lorawan_status_t LoRaWANInterface::add_app_callbacks(lorawan_app_callbacks_t *callbacks) lorawan_status_t LoRaWANInterface::add_app_callbacks(lorawan_app_callbacks_t *callbacks)
{ {
Lock lock(*this);
return _lw_stack.set_lora_callbacks(callbacks); return _lw_stack.set_lora_callbacks(callbacks);
} }
lorawan_status_t LoRaWANInterface::set_device_class(const device_class_t device_class) lorawan_status_t LoRaWANInterface::set_device_class(const device_class_t device_class)
{ {
Lock lock(*this);
return _lw_stack.set_device_class(device_class); return _lw_stack.set_device_class(device_class);
} }

View File

@ -19,6 +19,7 @@
#define LORAWANINTERFACE_H_ #define LORAWANINTERFACE_H_
#include "platform/Callback.h" #include "platform/Callback.h"
#include "platform/ScopedLock.h"
#include "LoRaWANStack.h" #include "LoRaWANStack.h"
#include "LoRaRadio.h" #include "LoRaRadio.h"
#include "LoRaWANBase.h" #include "LoRaWANBase.h"
@ -435,7 +436,13 @@ public:
*/ */
virtual lorawan_status_t set_device_class(const device_class_t device_class); virtual lorawan_status_t set_device_class(const device_class_t device_class);
void lock(void) { _lw_stack.lock(); }
void unlock(void) { _lw_stack.unlock(); }
private: private:
typedef mbed::ScopedLock<LoRaWANInterface> Lock;
LoRaWANStack _lw_stack; LoRaWANStack _lw_stack;
}; };

View File

@ -44,6 +44,7 @@
#include "events/EventQueue.h" #include "events/EventQueue.h"
#include "platform/Callback.h" #include "platform/Callback.h"
#include "platform/NonCopyable.h" #include "platform/NonCopyable.h"
#include "platform/ScopedLock.h"
#include "lorastack/mac/LoRaMac.h" #include "lorastack/mac/LoRaMac.h"
#include "system/LoRaWANTimer.h" #include "system/LoRaWANTimer.h"
@ -395,7 +396,11 @@ public:
*/ */
lorawan_status_t set_device_class(const device_class_t& device_class); lorawan_status_t set_device_class(const device_class_t& device_class);
void lock(void) { _loramac.lock(); }
void unlock(void) { _loramac.unlock(); }
private: private:
typedef mbed::ScopedLock<LoRaWANStack> Lock;
/** /**
* Checks if the user provided port is valid or not * Checks if the user provided port is valid or not
*/ */

View File

@ -51,7 +51,11 @@
#include "LoRaMacChannelPlan.h" #include "LoRaMacChannelPlan.h"
#include "LoRaMacCommand.h" #include "LoRaMacCommand.h"
#include "LoRaMacCrypto.h" #include "LoRaMacCrypto.h"
#if MBED_CONF_RTOS_PRESENT
#include "rtos/Mutex.h"
#endif
#include "platform/ScopedLock.h"
class LoRaMac { class LoRaMac {
@ -422,6 +426,24 @@ private:
*/ */
void on_mac_state_check_timer_event(void); void on_mac_state_check_timer_event(void);
/**
* These locks trample through to the upper layers and make
* the stack thread safe.
*/
#if MBED_CONF_RTOS_PRESENT
void lock(void) { osStatus status = _mutex.lock(); MBED_ASSERT(status == osOK); }
void unlock(void) { osStatus status = _mutex.unlock(); MBED_ASSERT(status == osOK); }
#else
void lock(void) { }
void unlock(void) { }
#endif
private:
typedef mbed::ScopedLock<LoRaMac> Lock;
#if MBED_CONF_RTOS_PRESENT
rtos::Mutex _mutex;
#endif
/** /**
* Function executed on duty cycle delayed Tx timer event * Function executed on duty cycle delayed Tx timer event
*/ */