Why the cli()/noInterrutpt() in millis()

Hi!

Just wondering why cli() is necessary here:

unsigned long millis()
{
	unsigned long m;
	uint8_t oldSREG = SREG;

	// disable interrupts while we read timer0_millis or we might get an
	// inconsistent value (e.g. in the middle of a write to timer0_millis)
	cli();
	m = timer0_millis;
	SREG = oldSREG;

	return m;
}

Isn’t “m = timer0_millis;” one ASM instruction? Then how could the value be inconsistent? Unless the comment means it could happen in the middle of the ISR(TIMER0_OVF_vect) function - but I don’t think that is possible either (because the ISR will always finish before any other code is executed).

I guess I am missing something here :stuck_out_tongue:

Thanks!

ToneArt:
Isn't "m = timer0_millis;" one ASM instruction?

That could only be true on a 32 bit processor.

it could happen in the middle of the ISR(TIMER0_OVF_vect) function

Indeed, the ISR could change the value of the counter in the middle of access to it by millis().

You should always protect multibyte, shared variables from corruption by the cli()/sei() method.

jremington:
Indeed, the ISR could change the value of the counter in the middle of access to it by millis().

You should always protect multibyte, shared variables from corruption by the cli()/sei() method.

No I meant the line "m = timer0_millis;" happenning while the ISR was running :slight_smile: And the other way around I did not think was possiblebut like aarg said - it's 32 bits so maybe the interrupt could happen after reading the first 16 and the value would be inconsistent!

Anyways - that answers my question!

Thanks both for the reply! :smiley: