Skip to content

K_SPINLOCK() on single core SOC fails to build with optimization -Og #78066

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
tswaehn opened this issue Sep 5, 2024 · 8 comments
Closed

K_SPINLOCK() on single core SOC fails to build with optimization -Og #78066

tswaehn opened this issue Sep 5, 2024 · 8 comments
Assignees
Labels
area: Kernel bug The issue is a bug, or the PR is fixing a bug

Comments

@tswaehn
Copy link
Contributor

tswaehn commented Sep 5, 2024

I actually do not understand and may need a quick guess, where to look.

this compiles without errors

	uint32_t count;

	uint32_t irq = arch_irq_lock();
	count = test();
	arch_irq_unlock(irq);
	printf("incrementing %d\n", count++);

but this:

	uint32_t count;

	struct k_spinlock my_lock;

	K_SPINLOCK(&my_lock) {
		count = test();
	}

	printf("incrementing %d\n", count++);

fails - as far as I understand that should be the same as above.

error: 'count' may be used uninitialized

if you wonder, why I am asking, its about this here:

K_SPINLOCK(&drv_data->rx_lock) {

@tswaehn tswaehn added the bug The issue is a bug, or the PR is fixing a bug label Sep 5, 2024
@tswaehn
Copy link
Contributor Author

tswaehn commented Sep 5, 2024

It turned out hat compiling with -Og produced the bug above, where as -Os is fine. actually I dont understand.

replication procedure:

if you want to test yourself, just add

zephyr_compile_options(-Werror -Og)

to the CMakeLists.txt of your main project, then clear the cmake cache and rebuild.

(and paste the above code to your main.c)

@tswaehn tswaehn closed this as completed Sep 5, 2024
@tswaehn tswaehn reopened this Sep 5, 2024
@tswaehn
Copy link
Contributor Author

tswaehn commented Sep 5, 2024

Actually, shouldn't it be irrelavant which optimization level ?

@tswaehn tswaehn changed the title K_SPINLOCK() on single core soc K_SPINLOCK() on single core SOC fails with optimization -Og Sep 5, 2024
@tswaehn tswaehn changed the title K_SPINLOCK() on single core SOC fails with optimization -Og K_SPINLOCK() on single core SOC fails to build with optimization -Og Sep 5, 2024
@peter-mitsis
Copy link
Collaborator

So far, I have been unable to reproduce this. Which compiler (and version) are you using? Also, what board are you building for?

Thinking aloud ... at its core, K_SPINLOCK is a for-loop construct. If the compiler is generating the warning you described, my initial thoughts are that it is determining that the body of the for-loop might not execute. For that to occur, its local spinlock key __i.key would have a non-initialized value which could then potential be non-zero. However, the way it is constructed, it should have an initial value of 0.

This makes me think that either ...
a) my understanding of how the spinlock key structure is initialized is flawed, or
b) there is a problem in the toolchain being used.

@tswaehn
Copy link
Contributor Author

tswaehn commented Sep 6, 2024

Using RISCV toolchain for qemu from latest zephyr 3.7.99

board: qemu_riscv32/qemu_virt_riscv32

CMakeLists.txt added this at the very bottom

zephyr_compile_options(-Werror -Og)

my main looks like this:

int32_t test(){
  return 42;
}

int main() {
  uint32_t count;

  struct k_spinlock my_lock;

  K_SPINLOCK(&my_lock) {
    count = test();
  }

  printf("incrementing %d\n", count++);

  while(1) {
  }
}

.../src/main.c: In function 'main':
error: 'count' may be used uninitialized 

@peter-mitsis just for the full picture. I agree, that for some reason the compiler seems a little distracted and assumes there is an option where this can be bypassed. however when actually executing and debugging. I never saw it uninitialized. so the real question is why is gcc so cautious about the for loop prediction based on -Og vs -Os

plus there is still an option that I am completely off. and doing stupid things without noticing. so a confirmation from your side is needed to prove, there is something or not.

@andyross
Copy link
Collaborator

andyross commented Sep 6, 2024

Likely[1] this is going to be down to -Og disabling whatever pass was folding/eliding/removing the loop test, so it doesn't know for sure that the loop will execute at least once, thus the assignment to count inside the K_SPINLOCK() can't be proven to be reached, thus the warning.

Obviously the workaround for the specific code in question is just to initialize count at declaration time so the warning can't happen. That may not be acceptable in all cases, but it's at least something to get you unblocked.

Beyond that... I guess my gut says this isn't worth fixing unless we want to enable a "debug build" at that optimization level as an official feature. The workaround is trivial.

But if we do, the form would be to refactor the test expression so that it's always guaranteed to be true the first time it's called.

[1] The other possibility is a toolchain bug, but that's pretty rare.

@peter-mitsis
Copy link
Collaborator

Additional info:

A little extra digging suggests that the reported behavior was introduced somewhere in GCC version 12, as I am not seeing it on GCC version 11. Furthermore, I am not seeing this behavior on any optimization level except -Og (I tried using O0, O1, O2, O3, Oz, Os and Og).

I am thinking that this is a toolchain issue, as it makes little sense to me as to why only that optimization should generate the warning/error. In the meantime, my recommendation would be to employ the suggested workaround.

@andyross
Copy link
Collaborator

Yeah, agreed. I'm going to WONTFIX this. Please reopen with impact details if that's not acceptable.

@tswaehn
Copy link
Contributor Author

tswaehn commented Sep 10, 2024

it took me some time to figure out that the issue comes from compiling with -Og. so just to avoid anybody else wastes a lot of time (like me). is it possible to add something to cmake => "please dont use -Og, there might be issues with the riscv toolchain" ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Kernel bug The issue is a bug, or the PR is fixing a bug
Projects
None yet
Development

No branches or pull requests

4 participants