Merge pull request #4538 from hasnainvirk/avoid_mtx_lock

Avoid lock collision b/w SerialBase & UARTSerial
pull/4639/head
Jimmy Brisson 2017-06-26 10:26:53 -05:00 committed by GitHub
commit 17ae9b923e
2 changed files with 47 additions and 28 deletions

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
#if DEVICE_SERIAL
#if (DEVICE_SERIAL && DEVICE_INTERRUPTIN)
#include <errno.h>
#include "UARTSerial.h"
@ -80,16 +80,16 @@ off_t UARTSerial::seek(off_t offset, int whence)
int UARTSerial::sync()
{
lock();
api_lock();
while (!_txbuf.empty()) {
unlock();
api_unlock();
// Doing better than wait would require TxIRQ to also do wake() when becoming empty. Worth it?
wait_ms(1);
lock();
api_lock();
}
unlock();
api_unlock();
return 0;
}
@ -111,16 +111,16 @@ ssize_t UARTSerial::write(const void* buffer, size_t length)
size_t data_written = 0;
const char *buf_ptr = static_cast<const char *>(buffer);
lock();
api_lock();
while (_txbuf.full()) {
if (!_blocking) {
unlock();
api_unlock();
return -EAGAIN;
}
unlock();
api_unlock();
wait_ms(1); // XXX todo - proper wait, WFE for non-rtos ?
lock();
api_lock();
}
while (data_written < length && !_txbuf.full()) {
@ -138,7 +138,7 @@ ssize_t UARTSerial::write(const void* buffer, size_t length)
}
core_util_critical_section_exit();
unlock();
api_unlock();
return data_written;
}
@ -149,16 +149,16 @@ ssize_t UARTSerial::read(void* buffer, size_t length)
char *ptr = static_cast<char *>(buffer);
lock();
api_lock();
while (_rxbuf.empty()) {
if (!_blocking) {
unlock();
api_unlock();
return -EAGAIN;
}
unlock();
api_unlock();
wait_ms(1); // XXX todo - proper wait, WFE for non-rtos ?
lock();
api_lock();
}
while (data_read < length && !_rxbuf.empty()) {
@ -166,7 +166,7 @@ ssize_t UARTSerial::read(void* buffer, size_t length)
data_read++;
}
unlock();
api_unlock();
return data_read;
}
@ -205,12 +205,24 @@ short UARTSerial::poll(short events) const {
return revents;
}
void UARTSerial::lock(void)
void UARTSerial::lock()
{
// This is the override for SerialBase.
// No lock required as we only use SerialBase from interrupt or from
// inside our own critical section.
}
void UARTSerial::unlock()
{
// This is the override for SerialBase.
}
void UARTSerial::api_lock(void)
{
_mutex.lock();
}
void UARTSerial::unlock(void)
void UARTSerial::api_unlock(void)
{
_mutex.unlock();
}
@ -262,4 +274,4 @@ void UARTSerial::tx_irq(void)
} //namespace mbed
#endif //DEVICE_SERIAL
#endif //(DEVICE_SERIAL && DEVICE_INTERRUPTIN)

View File

@ -19,7 +19,7 @@
#include "platform/platform.h"
#if DEVICE_SERIAL
#if (DEVICE_SERIAL && DEVICE_INTERRUPTIN) || defined(DOXYGEN_ONLY)
#include "FileHandle.h"
#include "SerialBase.h"
@ -58,7 +58,7 @@ public:
/** Write the contents of a buffer to a file
*
* @param buffer The buffer to write from
* @param size The number of bytes to write
* @param length The number of bytes to write
* @return The number of bytes written, negative error on failure
*/
virtual ssize_t write(const void* buffer, size_t length);
@ -72,17 +72,11 @@ public:
* * If any data is available, call returns immediately
*
* @param buffer The buffer to read in to
* @param size The number of bytes to read
* @param length The number of bytes to read
* @return The number of bytes read, 0 at end of file, negative error on failure
*/
virtual ssize_t read(void* buffer, size_t length);
/** Acquire mutex */
virtual void lock(void);
/** Release mutex */
virtual void unlock(void);
/** Close a file
*
* @return 0 on success, negative error code on failure
@ -159,6 +153,18 @@ public:
private:
/** SerialBase lock override */
virtual void lock(void);
/** SerialBase unlock override */
virtual void unlock(void);
/** Acquire mutex */
virtual void api_lock(void);
/** Release mutex */
virtual void api_unlock(void);
/** Software serial buffers
* By default buffer size is 256 for TX and 256 for RX. Configurable through mbed_app.json
*/
@ -191,8 +197,9 @@ private:
void wake(void);
void dcd_irq(void);
};
} //namespace mbed
#endif //DEVICE_SERIAL
#endif //(DEVICE_SERIAL && DEVICE_INTERRUPTIN) || defined(DOXYGEN_ONLY)
#endif //MBED_UARTSERIAL_H