Prevent DeepSleepLock from leaving sleep locked

Add _lock_count to DeepSleepLock and use this to prevent deep sleep
from staying locked when the DeepSleepLock objected is destroyed after
an unbalanced number of calls to lock and unlock.
pull/5220/head
Russ Butler 2017-09-28 16:20:15 -05:00
parent c60194fdfd
commit f0ac234da7
1 changed files with 24 additions and 4 deletions

View File

@ -16,7 +16,9 @@
#ifndef MBED_DEEPSLEEPLOCK_H #ifndef MBED_DEEPSLEEPLOCK_H
#define MBED_DEEPSLEEPLOCK_H #define MBED_DEEPSLEEPLOCK_H
#include <limits.h>
#include "platform/mbed_sleep.h" #include "platform/mbed_sleep.h"
#include "platform/mbed_critical.h"
namespace mbed { namespace mbed {
@ -36,30 +38,48 @@ namespace mbed {
* @endcode * @endcode
*/ */
class DeepSleepLock { class DeepSleepLock {
private:
uint16_t _lock_count;
public: public:
DeepSleepLock() DeepSleepLock(): _lock_count(1)
{ {
sleep_manager_lock_deep_sleep(); sleep_manager_lock_deep_sleep();
} }
~DeepSleepLock() ~DeepSleepLock()
{ {
if (_lock_count) {
sleep_manager_unlock_deep_sleep(); sleep_manager_unlock_deep_sleep();
} }
}
/** Mark the start of a locked deep sleep section /** Mark the start of a locked deep sleep section
*/ */
void lock() void lock()
{ {
uint16_t count = core_util_atomic_incr_u16(&_lock_count, 1);
if (1 == count) {
sleep_manager_lock_deep_sleep(); sleep_manager_lock_deep_sleep();
} }
if (0 == count) {
error("DeepSleepLock overflow (> USHRT_MAX)");
}
}
/** Mark the end of a locked deep sleep section /** Mark the end of a locked deep sleep section
*/ */
void unlock() void unlock()
{ {
uint16_t count = core_util_atomic_decr_u16(&_lock_count, 1);
if (count == 0) {
sleep_manager_unlock_deep_sleep(); sleep_manager_unlock_deep_sleep();
} }
if (count == USHRT_MAX) {
core_util_critical_section_exit();
error("DeepSleepLock underflow (< 0)");
}
}
}; };
} }