-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
gollvm: find a better way to deal with g #37295
Comments
Personally I'd really like a way to let the backend not cache TLS addresses in GCC and LLVM. I don't think this is specific to Go. In C, if you use
I thought about that. The tricky thing is that the libgo runtime uses C for many things, including external C code, libbacktrace, libffi, libgcc, and syscall wrappers from libc. If we reserve a register globally, all these C code need to be compiled in a special way. Or we have to have some wrapper that save/restore the reserved register at C library boundaries.
I'm not sure how this is going to work. Also, the C code seems to need special compilation. Maybe a possibility is with the current approach, and add a machine-IR pass, runs after CSE, that inlines getg calls back in. This will be machine dependent. And I'm not sure if this can be done for gccgo. |
Hi Cherry, I also thought about many possible solutions, including:
Here is an example on Linux/arm64:
compile the above getg.c file with "clang -O2 -o getg getg.c".
As you can see, getg_new is inlined, which also avoids the optimization problem of CSE. Then we don't need the GoSafeGetg pass any more. I'm not familiar with x86 assembly, so I didn't write a x86 example, but I think This approach applies to other architectures. |
Inline assembly may not apply to dynamic linking 😢 |
Change https://golang.org/cl/228737 mentions this issue: |
Currently, gollvm stores the current g in tls. The runtime.getg () function returns the current g. This function will be inlined for better performance and the inlining will be disabled by GoSafeGetg pass in some situations. Cherry described this situation in this pass:
A practical example of this situation: gofrontend/chan.go#154
By removing the inlining of the second and subsequent getg functions in a block, GoSafeGetg pass fixed this issue on linux/amd64. But on Linux / arm64, llvm performs cache optimization on the tls base address across the entire function range, so the g obtained by the second and subsequent getg in the above situation may still be wrong.
As I know, this kind of optimization is common in llvm and gcc, and it seems to be correct and very good for c / c ++. Before c / c ++ introduced a concept like goroutine, I think this optimization will not be changed. Please refer to similar issues: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=26461, https://bugs.llvm.org/show_bug.cgi?id=19177.
Currently gollvm only supports linux / amd64 and linux / arm64, but as more platforms are supported in the future, I think this issue will be a problem on more platforms, so I think we need to find a better way to store the current g.
At present, the methods I can think of are as follows:
@thanm @cherrymui @ianlancetaylor Any suggestions ?
The text was updated successfully, but these errors were encountered: