auto-sync

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

View File

@ -159,7 +159,7 @@ uint64_t getTimeNowUs(void) {
}
uint64_t getTimeNowNt(void) {
return halTime.get(hal_lld_get_counter_value(), false);
return halTime.get();
}
//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
*/
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())
writeToFlashIfPending();
@ -390,7 +394,6 @@ void initEngineContoller(Engine *engine) {
*/
prepareShapes(engine);
initMalfunctionCentral();
#if EFI_ELECTRONIC_THROTTLE_BODY

View File

@ -232,7 +232,7 @@ static void triggerInfo(Engine *engine) {
#endif
#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",
hwPortname(boardConfiguration->triggerSimulatorPins[0]),
pinModeToString(boardConfiguration->triggerSimulatorPinModes[0]),

View File

@ -252,7 +252,7 @@ static int rtcStartTime;
static void timeInfo(void) {
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
int unix = rtcGetTimeUnixSec(&RTCD1) - rtcStartTime;

View File

@ -5,8 +5,16 @@
* @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"
/**
* 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.
*/
Overflow64Counter::Overflow64Counter() {
currentBase = 0;
currentValue = 0;
state.highBits = 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
// todo: this is still not atomic, so technically not thread safe.
uint32_t localValue = currentValue;
uint64_t localBase = currentBase;
if (value < localValue) {
// new value less than previous value means there was an overflow in that 32 bit counter
localBase += 0x100000000LL;
uint64_t localH;
uint32_t localLow;
while (true) {
localH = state.highBits;
localLow = state.lowBits;
uint64_t localH2 = state.highBits;
if (localH == localH2)
break;
}
if (isPrimaryThread) {
currentValue = value;
currentBase = localBase;
/**
* We need to take current counter after making a local 64 bit snapshot
*/
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>
typedef struct {
uint64_t highBits;
uint32_t lowBits;
} State64;
void updateAndSet(State64 *state, uint32_t value);
class Overflow64Counter
{
public:
Overflow64Counter();
uint64_t get(uint32_t value, int isPrimaryThread);
uint64_t get();
uint64_t update(uint32_t value);
private:
uint64_t currentBase;
uint32_t currentValue;
State64 state;
};
#endif /* EFILIB2_H_ */

View File

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