golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
124.25k stars 17.7k forks source link

runtime: use register instead of TLS for G pointer for darwin/arm and darwin/arm64 #24793

Open randall77 opened 6 years ago

randall77 commented 6 years ago

Need to decide how to handle TLS on darwin/arm. On x86, TLS was moved from a pthread_get/setspecific implementation to a reserved (by Apple) slot in the TLS (see #23617). That's not possible for arm/arm64 so we still use the old method. Since these archs have more registers, we should probably just reserve a register for the G pointer.

Reserving a register might invalidate some existing assembly code. Kind of a wrench in the plan, need to investigate how bad it might be.

Or maybe someone can think of a better solution.

We might need a solution before we can do #17490 for arm.

cherrymui commented 6 years ago

I think we already do reserve a G register on ARM and ARM64, regardless of OS. This is R10 on ARM, and R28 on ARM64. TLS is only used when crossing Go-C boundary, where we save G register to a TLS slot when calling to C, and reload it when entering Go code, as C code may clobber our G register.

randall77 commented 6 years ago

Maybe this is unnecessary then.

eliasnaur commented 6 years ago

The pthread_get/set magic is still present in runtime/cgo/gcc_darwin_arm*.c so I wouldn't qualify that as unnecessary.

@cherrymui given that we only use the TLS slot for Cgo, could we use a callee-saved register for G and thus avoid the TLS slot (and the save/restore) altogether?

cherrymui commented 6 years ago

I haven't looked into the code in detail, but I'm not sure callee-saved register is enough. C code can still temporarily use the register, and a signal can happen at this point. The signal handler, runtime.sigtramp needs to look at the G register to tell whether/which Go stack we are on.

bcmills commented 6 years ago

Backing up one level: why does runtime.sigtramp need to know which goroutine is running if we're in a C call?

ianlancetaylor commented 6 years ago

I'm not sure I completely understand the question, but see the sigtramp code in runtime/sys_darwin_arm.s and runtime/sys_darwin_arm64.s. It does today examine the g register, which it loads out of the TLS slot.

cherrymui commented 6 years ago

Besides signal handler, another place where we need G is when Go calls C which calls back to Go. There we want to use the same G, I think.

aclements commented 5 years ago

What's the status of this? Is there actually a bug here?

eliasnaur commented 5 years ago

17490 is fixed, even for iOS, so the remaining bug is that we're relying on an undocumented assumption that a TLS slot allocated by pthread_key_create is located at some positive offset from the TLS base. See https://github.com/golang/go/blob/59ea685ce96a696281e56badd80d2e5dd618b0b0/src/runtime/cgo/gcc_darwin_arm64.c#L31-L45

We recently had to remove a similar assumption for Android (https://github.com/golang/go/issues/29674).

Since we use a register for g on arm and arm64 the appropriate fix for this issue is probably to call pthread_getspecific and pthread_setspecific when entering or exiting C code.