auto-sync

This commit is contained in:
rusEfi 2014-11-16 23:03:45 -06:00
parent 3d38eb5436
commit 7452259f77
6 changed files with 72 additions and 27 deletions

View File

@ -159,7 +159,7 @@ uint64_t getTimeNowUs(void) {
} }
uint64_t getTimeNowNt(void) { uint64_t getTimeNowNt(void) {
return halTime.get(hal_lld_get_counter_value(), false); return halTime.get();
} }
//uint64_t getHalTimer(void) { //uint64_t getHalTimer(void) {
@ -218,7 +218,11 @@ static void onEvenyGeneralMilliseconds(Engine *engine) {
/** /**
* We need to push current value into the 64 bit counter often enough so that we do not miss an overflow * We need to push current value into the 64 bit counter often enough so that we do not miss an overflow
*/ */
halTime.get(hal_lld_get_counter_value(), true); bool alreadyLocked = lockAnyContext();
updateAndSet(&halTime.state, hal_lld_get_counter_value());
if (!alreadyLocked) {
unlockAnyContext();
}
if (!engine->rpmCalculator.isRunning()) if (!engine->rpmCalculator.isRunning())
writeToFlashIfPending(); writeToFlashIfPending();
@ -390,7 +394,6 @@ void initEngineContoller(Engine *engine) {
*/ */
prepareShapes(engine); prepareShapes(engine);
initMalfunctionCentral(); initMalfunctionCentral();
#if EFI_ELECTRONIC_THROTTLE_BODY #if EFI_ELECTRONIC_THROTTLE_BODY

View File

@ -232,7 +232,7 @@ static void triggerInfo(Engine *engine) {
#endif #endif
#if EFI_PROD_CODE #if EFI_PROD_CODE
scheduleMsg(&logger, "maxLockTime=%d", maxLockTime); scheduleMsg(&logger, "maxLockTime=%d / maxTriggerReentraint=%d", maxLockTime, maxTriggerReentraint);
scheduleMsg(&logger, "primary trigger simulator: %s %s freq=%d", scheduleMsg(&logger, "primary trigger simulator: %s %s freq=%d",
hwPortname(boardConfiguration->triggerSimulatorPins[0]), hwPortname(boardConfiguration->triggerSimulatorPins[0]),
pinModeToString(boardConfiguration->triggerSimulatorPinModes[0]), pinModeToString(boardConfiguration->triggerSimulatorPinModes[0]),

View File

@ -252,7 +252,7 @@ static int rtcStartTime;
static void timeInfo(void) { static void timeInfo(void) {
scheduleMsg(&logger, "chTimeNow as seconds = %d", getTimeNowSeconds()); scheduleMsg(&logger, "chTimeNow as seconds = %d", getTimeNowSeconds());
scheduleMsg(&logger, "hal seconds = %d", halTime.get(hal_lld_get_counter_value(), false) / 168000000LL); scheduleMsg(&logger, "hal seconds = %d", halTime.get() / 168000000LL);
#if EFI_RTC #if EFI_RTC
int unix = rtcGetTimeUnixSec(&RTCD1) - rtcStartTime; int unix = rtcGetTimeUnixSec(&RTCD1) - rtcStartTime;

View File

@ -5,8 +5,16 @@
* @author Andrey Belomutskiy, (c) 2012-2014 * @author Andrey Belomutskiy, (c) 2012-2014
*/ */
#include "main.h"
#if (EFI_PROD_CODE || EFI_SIMULATOR)
#define GET_VALUE() hal_lld_get_counter_value()
#else
#define GET_VALUE() 0
#endif
#include "efilib2.h" #include "efilib2.h"
/** /**
* The main use-case of this class is to keep track of a 64-bit global number of CPU ticks from reset. * The main use-case of this class is to keep track of a 64-bit global number of CPU ticks from reset.
* *
@ -18,24 +26,54 @@
* In order for this to function, it's your responsibility to invoke offer() method at least once a second. * In order for this to function, it's your responsibility to invoke offer() method at least once a second.
*/ */
Overflow64Counter::Overflow64Counter() { Overflow64Counter::Overflow64Counter() {
currentBase = 0; state.highBits = 0;
currentValue = 0; state.lowBits = 0;
} }
uint64_t Overflow64Counter::get(uint32_t value, int isPrimaryThread) { /**
// this method is lock-free, only one thread is allowed to commit state * in order to have atomic writes this should be invoked within a critical section
*/
void updateAndSet(State64 *state, uint32_t value) {
if (value < state->lowBits) {
// new value less than previous value means there was an overflow in that 32 bit counter
state->highBits += 0x100000000LL;
}
state->lowBits = value;
}
uint64_t Overflow64Counter::update(uint32_t value) {
updateAndSet(&state, value);
return state.highBits + state.lowBits;
}
// todo: make this a macro? always inline?
uint64_t Overflow64Counter::get() {
/**
* this method is lock-free and thread-safe, that's because the 'update' method
* is atomic with a critical zone requirement.
*
* http://stackoverflow.com/questions/5162673/how-to-read-two-32bit-counters-as-a-64bit-integer-without-race-condition
*/
// these are local copies for thread-safery // these are local copies for thread-safery
// todo: this is still not atomic, so technically not thread safe. // todo: this is still not atomic, so technically not thread safe.
uint32_t localValue = currentValue; uint64_t localH;
uint64_t localBase = currentBase; uint32_t localLow;
if (value < localValue) { while (true) {
// new value less than previous value means there was an overflow in that 32 bit counter localH = state.highBits;
localBase += 0x100000000LL; localLow = state.lowBits;
uint64_t localH2 = state.highBits;
if (localH == localH2)
break;
} }
if (isPrimaryThread) { /**
currentValue = value; * We need to take current counter after making a local 64 bit snapshot
currentBase = localBase; */
uint32_t value = GET_VALUE();
if (value < localLow) {
// new value less than previous value means there was an overflow in that 32 bit counter
localH += 0x100000000LL;
} }
return localBase + value; return localH + value;
} }

View File

@ -10,18 +10,22 @@
#include <stdint.h> #include <stdint.h>
typedef struct {
uint64_t highBits;
uint32_t lowBits;
} State64;
void updateAndSet(State64 *state, uint32_t value);
class Overflow64Counter class Overflow64Counter
{ {
public: public:
Overflow64Counter(); Overflow64Counter();
uint64_t get(uint32_t value, int isPrimaryThread); uint64_t get();
uint64_t update(uint32_t value);
private: State64 state;
uint64_t currentBase;
uint32_t currentValue;
}; };
#endif /* EFILIB2_H_ */ #endif /* EFILIB2_H_ */

View File

@ -41,13 +41,13 @@ void testOverflow64Counter(void) {
print("*************************************** testOverflow64Counter\r\n"); print("*************************************** testOverflow64Counter\r\n");
Overflow64Counter o; Overflow64Counter o;
assertEquals(0, o.get(0, true)); assertEquals(0, o.update(0));
assertEquals(10, o.get(10, true)); assertEquals(10, o.update(10));
assertEquals(20, o.get(20, true)); assertEquals(20, o.update(20));
// overflow // overflow
assertEquals(4294967296, o.get(0, true)); assertEquals(4294967296, o.update(0));
} }
void testCyclicBuffer(void) { void testCyclicBuffer(void) {