static void doScheduleForLater(scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param) { int delaySt = MY_US2ST(delayUs); if (delaySt <= 0) { /** * in case of zero delay, we should invoke the callback */ callback(param); return; } bool alreadyLocked = lockAnyContext(); scheduling->callback = callback; scheduling->param = param; int isArmed = chVTIsArmedI(&scheduling->timer); if (isArmed) { /** * timer reuse is normal for example in case of sudden RPM increase */ chVTResetI(&scheduling->timer); } #if EFI_SIMULATOR if (callback == (schfunc_t)&seTurnPinLow) { printf("setTime cb=seTurnPinLow p=%d\r\n", (int)param); } else { // printf("setTime cb=%d p=%d\r\n", (int)callback, (int)param); } #endif /* EFI_SIMULATOR */ chVTSetI(&scheduling->timer, delaySt, (vtfunc_t)timerCallback, scheduling); if (!alreadyLocked) { unlockAnyContext(); } }
// todo: make this a macro? always inline? efitime_t Overflow64Counter::get() { #if EFI_PROD_CODE bool alreadyLocked = lockAnyContext(); efitime_t localH = state.highBits; uint32_t localLow = state.lowBits; uint32_t value = GET_TIMESTAMP(); if (value < localLow) { // new value less than previous value means there was an overflow in that 32 bit counter localH += 0x100000000LL; } efitime_t result = localH + value; if (!alreadyLocked) { unlockAnyContext(); } return result; #else /** * 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 */ efitime_t localH; uint32_t localLow; int counter = 0; while (true) { localH = state.highBits; localLow = state.lowBits; efitime_t localH2 = state.highBits; if (localH == localH2) break; #if EFI_PROD_CODE || defined(__DOXYGEN__) if (counter++ == 10000) chDbgPanic("lock-free frozen"); #endif /* EFI_PROD_CODE */ } /** * We need to take current counter after making a local 64 bit snapshot */ uint32_t value = GET_TIMESTAMP(); if (value < localLow) { // new value less than previous value means there was an overflow in that 32 bit counter localH += 0x100000000LL; } return localH + value; #endif }
/** * this method acquires system lock to guard the shared intermediateLoggingBuffer memory stream */ void vappendPrintf(Logging *logging, const char *fmt, va_list arg) { efiAssertVoid(getRemainingStack(chThdSelf()) > 128, "lowstck#5b"); if (!intermediateLoggingBufferInited) { firmwareError("intermediateLoggingBufferInited not inited!"); return; } int wasLocked = lockAnyContext(); vappendPrintfI(logging, fmt, arg); if (!wasLocked) { unlockAnyContext(); } }
void chVTSetAny(virtual_timer_t *vtp, systime_t time, vtfunc_t vtfunc, void *par) { bool wasLocked = lockAnyContext(); /** * todo: this could be simplified once we migrate to ChibiOS 3.0 * See http://www.chibios.org/dokuwiki/doku.php?id=chibios:howtos:porting_from_2_to_3 */ if (chVTIsArmedI(vtp)) { chVTResetI(vtp); } chVTSetI(vtp, time, vtfunc, par); if (!wasLocked) { unlockAnyContext(); } }
/** * this whole method is executed under syslock so that we can have multiple threads use the same shared buffer * in order to reduce memory usage */ void scheduleMsg(Logging *logging, const char *fmt, ...) { efiAssertVoid(logging != NULL, "logging NULL"); int wasLocked = lockAnyContext(); resetLogging(logging); // todo: is 'reset' really needed here? appendMsgPrefix(logging); va_list ap; va_start(ap, fmt); vappendPrintf(logging, fmt, ap); va_end(ap); appendMsgPostfix(logging); scheduleLogging(logging); if (!wasLocked) { unlockAnyContext(); } }
void scheduleTask(const char *prefix, scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param) { int delaySt = delayUs * CH_FREQUENCY / 1000000; if (delaySt == 0) { /** * in case of zero delay, we should invoke the callback */ callback(param); return; } lockAnyContext(); int isArmed = chVTIsArmedI(&scheduling->timer); if (isArmed) chVTResetI(&scheduling->timer); chVTSetI(&scheduling->timer, delaySt, (vtfunc_t)callback, param); unlockAnyContext(); }
void Executor::scheduleByTime(const bool monitorReuse, scheduling_s *scheduling, efitimeus_t timeUs, schfunc_t callback, void *param) { // if (delayUs < 0) { // firmwareError(OBD_PCM_Processor_Fault, "Negative delayUs %s: %d", prefix, delayUs); // return; // } // if (delayUs == 0) { // callback(param); // return; // } if (!reentrantFlag) { // this would guard the queue and disable interrupts lockAnyContext(); } bool needToResetTimer = queue.insertTask(scheduling, US2NT(timeUs), callback, param); if (!reentrantFlag) { doExecute(); if (needToResetTimer) { scheduleTimerCallback(); } unlockAnyContext(); } }
static void periodicSlowCallback(Engine *engine) { efiAssertVoid(getRemainingStack(chThdSelf()) > 64, "lowStckOnEv"); #if EFI_PROD_CODE /** * We need to push current value into the 64 bit counter often enough so that we do not miss an overflow */ bool alreadyLocked = lockAnyContext(); updateAndSet(&halTime.state, hal_lld_get_counter_value()); if (!alreadyLocked) { unlockAnyContext(); } #endif if (!engine->rpmCalculator.isRunning()) { #if (EFI_PROD_CODE && EFI_ENGINE_CONTROL && EFI_INTERNAL_FLASH) || defined(__DOXYGEN__) writeToFlashIfPending(); #endif resetAccel(); } if (versionForConfigurationListeners.isOld()) { updateAccelParameters(); engine->engineState.warmupAfrPid.reset(); } engine->watchdog(); engine->updateSlowSensors(); #if (EFI_PROD_CODE && EFI_FSIO) || defined(__DOXYGEN__) runFsio(); #endif cylinderCleanupControl(engine); scheduleNextSlowInvocation(); }
/** * Some configuration changes require full firmware reset. * Once day we will write graceful shutdown, but that would be one day. */ void scheduleReset(void) { scheduleMsg(&logging, "Rebooting in 5 seconds..."); lockAnyContext(); chVTSetI(&resetTimer, 5 * CH_FREQUENCY, (vtfunc_t) rebootNow, NULL); unlockAnyContext(); }
void Executor::onTimerCallback() { lockAnyContext(); doExecute(); scheduleTimerCallback(); unlockAnyContext(); }
#endif /* EFI_TUNER_STUDIO */ FsioState::FsioState() { #if EFI_ENABLE_ENGINE_WARNING isEngineWarning = FALSE; #endif #if EFI_ENABLE_CRITICAL_ENGINE_STOP isCriticalEngineCondition = FALSE; #endif } void Engine::initializeTriggerShape(Logging *logger DECLARE_ENGINE_PARAMETER_SUFFIX) { #if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT #if !EFI_UNIT_TEST // we have a confusing threading model so some synchronization would not hurt bool alreadyLocked = lockAnyContext(); #endif /* EFI_UNIT_TEST */ TRIGGER_SHAPE(initializeTriggerShape(logger, engineConfiguration->operationMode, engineConfiguration->useOnlyRisingEdgeForTrigger, &engineConfiguration->trigger)); if (!TRIGGER_SHAPE(shapeDefinitionError)) { /** * this instance is used only to initialize 'this' TriggerShape instance * #192 BUG real hardware trigger events could be coming even while we are initializing trigger */ initState.resetTriggerState(); calculateTriggerSynchPoint(&ENGINE(triggerCentral.triggerShape), &initState PASS_ENGINE_PARAMETER_SUFFIX);
/** * Some configuration changes require full firmware reset. * Once day we will write graceful shutdown, but that would be one day. */ static void scheduleReboot(void) { scheduleMsg(&sharedLogger, "Rebooting in 5 seconds..."); lockAnyContext(); chVTSetI(&resetTimer, MS2ST(5000), (vtfunc_t) rebootNow, NULL); unlockAnyContext(); }
bool lockOutputBuffer(void) { return lockAnyContext(); }