Esempio n. 1
0
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();
	}
}
Esempio n. 2
0
// 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
}
Esempio n. 3
0
/**
 * 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();
	}
}
Esempio n. 4
0
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();
	}
}
Esempio n. 5
0
/**
 * 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();
	}
}
Esempio n. 6
0
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();
}
Esempio n. 7
0
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();
	}
}
Esempio n. 8
0
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();
}
Esempio n. 9
0
/**
 * 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();
}
Esempio n. 10
0
void Executor::onTimerCallback() {
	lockAnyContext();
	doExecute();
	scheduleTimerCallback();
	unlockAnyContext();
}
Esempio n. 11
0
/**
 * 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();
}
Esempio n. 12
0
void unlockOutputBuffer(void) {
	unlockAnyContext();
}