Skip to content
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

runtime: implement __sync libcalls as critical sections #2307

Merged
merged 1 commit into from
Dec 28, 2021

Conversation

niaow
Copy link
Member

@niaow niaow commented Nov 22, 2021

This change implements __sync atomic polyfill libcalls by disabling interrupts.
This was previously done in a limited capacity on some targets, but this change uses a go:generate to emit all of the calls on all microcontroller targets.

@niaow
Copy link
Member Author

niaow commented Nov 22, 2021

At this point it seems to pass all tests. However, this should probably be extended so that everything that can be tested.
Right now:

  1. The min/max atomics are not tested (and unfortunately not documented properly anywhere I thought of looking)
  2. Various bitwise atomics are not tested

Copy link
Member

@aykevl aykevl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

At this point it seems to pass all tests. However, this should probably be extended so that everything that can be tested. Right now:

  1. The min/max atomics are not tested (and unfortunately not documented properly anywhere I thought of looking)

  2. Various bitwise atomics are not tested

I think it's best to leave those out. If we don't use them, there isn't really a reason to write atomic functions for them. It looks like we only use add, cas, load, store, and swap, and only for 2, 4, and 8 bytes in size.

@niaow
Copy link
Member Author

niaow commented Nov 23, 2021

I think it's best to leave those out. If we don't use them, there isn't really a reason to write atomic functions for them. It looks like we only use add, cas, load, store, and swap, and only for 2, 4, and 8 bytes in size.

I was less worried about us directly using them, and more worried about cgo'ed code or an LLVM optimization generating them. However, searching through the llvm-project code, I can't find a way for that to happen. I think I will just comment it out for now in case this turns up later.

@niaow
Copy link
Member Author

niaow commented Nov 23, 2021

Hmm. Actually, it looks like it may be necessary to leave the bitwise atomics in for cgo.

@niaow
Copy link
Member Author

niaow commented Nov 23, 2021

Hmm. This is not close to ready - this seems to be quite a bit more complicated.

@niaow
Copy link
Member Author

niaow commented Dec 12, 2021

I think it's best to leave those out. If we don't use them, there isn't really a reason to write atomic functions for them.

So I looked into this and concluded that while we don't, cgo'ed code can potentially. I am adding some tests through CGo for the ones which can be easily hit.

@niaow
Copy link
Member Author

niaow commented Dec 12, 2021

Or specifically the bitwise atomics. The min/max atomics are not currently accessible so I am leaving them out for now.

@niaow
Copy link
Member Author

niaow commented Dec 12, 2021

Hmm. It looks like we might need to flush stdout, and also like something is ignoring the -std=c11.

package main

// #include "atomic.h"
// #cgo CFLAGS: -std=c11
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clang defaults to -std=gnu17, so I don't think this is needed. Source: https://clang.llvm.org/docs/UsersManual.html#differences-between-various-standard-modes

@aykevl
Copy link
Member

aykevl commented Dec 17, 2021

So I looked into this and concluded that while we don't, cgo'ed code can potentially. I am adding some tests through CGo for the ones which can be easily hit.

Yes, that's possible. I can't see why LLVM would generate different atomic instructions but it's definitely possible for C code to do so. Still, that's IMHO not needed yet - but I'm also not against adding support for it in advance (I just don't see the need).

@niaow
Copy link
Member Author

niaow commented Dec 17, 2021

I can't see why LLVM would generate different atomic instructions

These atomic libcalls all correspond to parts of the stdatomic.h standard library in C11 (except for nand which I think I left in by accident).

Still, that's IMHO not needed yet

Alright, I will split C atomics support out into another PR at a later time.

This change implements __sync atomic polyfill libcalls by disabling interrupts.
This was previously done in a limited capacity on some targets, but this change uses a go:generate to emit all of the calls on all microcontroller targets.
@niaow
Copy link
Member Author

niaow commented Dec 17, 2021

The old version has been preserved at https://github.com/niaow/tinygo/tree/critical-atomics-old

@niaow niaow changed the title WIP: runtime: implement __sync libcalls as critical sections runtime: implement __sync libcalls as critical sections Dec 17, 2021
@niaow niaow marked this pull request as ready for review December 17, 2021 16:00
@niaow
Copy link
Member Author

niaow commented Dec 17, 2021

Note that some atomics still do not work on AVR (but this seems out of scope):

[niaow@finch tinygo]$ build/tinygo build -size short -o test.hex -target=arduino ./testdata/atomic.go
LLVM ERROR: Cannot generate unaligned atomic store

@niaow niaow requested a review from aykevl December 19, 2021 20:54
Copy link
Member

@aykevl aykevl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks!

@aykevl aykevl merged commit 9fa667c into tinygo-org:dev Dec 28, 2021
@aykevl aykevl mentioned this pull request Dec 30, 2021
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants