Is i++ atomic on the AVR C compilers

Go To Last Post
21 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This sounds like a odd question but is i++ on a volatile int guarantied atomic ?

 

I ask because the GCC often make some extra moves so it can use ADIW which is atomic, but will that always be the case?

 

I know that you can avoid ++ from main but still I will like to know :) 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:
is i++ on a volatile int guarantied atomic ?

The documentation for adiw states:

This instruction operates on the upper four register pairs, and is well suited for operations on the pointer registers.

 

This instruction is not available in all devices.

Therefore there cannot be any guarantee.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I asked in general!

it's only old obsolete parts and those with only 16 registers that don't have ADIW

 

add:

All parts with MOVW also have ADIW. Without MOVW it's hard to make ADIW atomic.

Last Edited: Sun. Nov 21, 2021 - 11:20 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

It may depend...

Definitely NOT atomic if the variable is greater than 16 bits.

If the variable is not kept in a register, then the load, increment, store will not be atomic.

If the variable is kept in a register and ADIW is available, then it may be (probably is) atomic.

David

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

is i++ on a volatile int guarantied atomic ?

Doesn't "volatile int" imply that the variable is in memory?

In that case, given the AVR's load/store architecture, the atomicity has nothing to do with ADIW, and I don't think it's EVER atomic.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Presumably the actual danger lies in the "store". It may well encode something like:

LDS R24, Var
LDS R25, Var + 1
ADIW R24, 1
STS Var, R24
                << Danger is here !
STS Var + 1, R25

Even if the ADIW was split as ADD/ADC I guess that bit would not matter but as soon as you split the write back to storage there's a chance something might interrupt and use "Var" in the meantime.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

westfw wrote:
Doesn't "volatile int" imply that the variable is in memory?

That's a good question!

 

I'm not sure that it does, but ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But if it's a volatile uint8_t variable then it's always atomic, right?

“Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?” - Brian W. Kernighan
“Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.” - Antoine de Saint-Exupery

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't think even that's safe to assume?

 

As already noted, even if the increment operation itself is atomic, there may load & store - which would make the overall operation not atomic.

 

In general 'volatile' has nothing to do with atomicity.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1
LDS R24, Var
                    and also here!!!
LDS R25, Var + 1
ADIW R24, 1
STS Var, R24
                << Danger is here !
STS Var + 1, R25

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The main reason for the hole question is the compiler sometimes make some odd move where a ++ could have been replaced with a 16 bit sub with -1 without any move.

 

But I guess it's a C leftover that all results needs on the "top" so the last result can be reused (I can't remember what it's called). 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

To be honest it's unwise to rely on the compiler's code generation as a new version or a single change to a build switch could ruin everything. If you want an exact sequence of opcodes code it in Asm.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
If you want an exact sequence of opcodes code it in Asm.

Absolutely!

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As I guess most know I normally code in ASM, so I can avoid problems like this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

and that was the reason for this thread, if one can't count on it working don't use it. (and what is clear in the thread it will normally not work, only if variable in register pair, and it

don't seem to be a compiler goal then no one should count on it)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Surely the naive approach might be "it's only atomic if it's wrapped around with an interrupt disable"?

 

Neil

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:
if one can't count on it working don't use it.

Where "it" is the assumption that the operation is atomic.

 

So, when it needs to be atomic, it is up to the programmer to make it so.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

"Dare to be naïve." - Buckminster Fuller

Last Edited: Mon. Nov 22, 2021 - 04:45 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 it is up to the programmer to make it so

Yes that is the hole point, it's not for atomic reasons that compiler make stupid code, it's because it's stupid.

 

I stay to ASM where 16 bit inc can be made atomic in 3 clk. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

On an AVR, i++ by itself is not implicitly atomic, not even if i is a single byte.

The reason is that i++ represents two accesses to i.

A store between them destroys atomicity.

Even if i represents a register,

there is no guarantee that the compiler will use an INC or ADDI for the increment.

Assembly, of course, can make that guarantee.

Dedicating a register can make using anything else difficult.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:
Assembly, of course, can make that guarantee.
... via hooks by some typical computer languages.

Using the GNU Compiler Collection (GCC): __atomic Builtins

[fourth paragraph]

If there is no pattern or mechanism to provide a lock free instruction sequence, a call is made to an external routine with the same parameters to be resolved at run time.

 

"Dare to be naïve." - Buckminster Fuller