auto-sync
This commit is contained in:
parent
6b84da1f57
commit
aeac9d6732
|
@ -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
|
||||
|
|
|
@ -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]),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue