Hi Ian, Thanks for your input!
I am not familiar with Go runtime internals at all, but the patch below at least compiles for me. Let me know if this works for you too / if there is a better way to do this. The untyped uintptr_t seems to be necessary as otherwise I encountered errors about &sevp escaping to the heap. Sincerely, Sören diff --git a/libgo/go/runtime/os_linux.go b/libgo/go/runtime/os_linux.go index 96fb1788..6653d85e 100644 --- a/libgo/go/runtime/os_linux.go +++ b/libgo/go/runtime/os_linux.go @@ -22,6 +22,8 @@ type mOS struct { profileTimerValid uint32 } +func setProcID(uintptr, int32) + func getProcID() uint64 { return uint64(gettid()) } @@ -365,7 +367,7 @@ func setThreadCPUProfiler(hz int32) { var sevp _sigevent sevp.sigev_notify = _SIGEV_THREAD_ID sevp.sigev_signo = _SIGPROF - *((*int32)(unsafe.Pointer(&sevp._sigev_un))) = int32(mp.procid) + setProcID(uintptr(unsafe.Pointer(&sevp)), int32(mp.procid)) ret := timer_create(_CLOCK_THREAD_CPUTIME_ID, &sevp, &timerid) if ret != 0 { // If we cannot create a timer for this M, leave profileTimerValid false diff --git a/libgo/runtime/go-signal.c b/libgo/runtime/go-signal.c index 528d9b6d..347b24e2 100644 --- a/libgo/runtime/go-signal.c +++ b/libgo/runtime/go-signal.c @@ -183,6 +183,16 @@ setSigactionHandler(struct sigaction* sa, uintptr handler) sa->sa_sigaction = (void*)(handler); } +void setProcID(uintptr_t, int32_t) + __asm__ (GOSYM_PREFIX "runtime.setProcID"); + +void +setProcID(uintptr_t ptr, int32_t v) +{ + struct sigevent *s = (void *)ptr; + s->sigev_notify_thread_id = v; +} + // C code to fetch values from the siginfo_t and ucontext_t pointers // passed to a signal handler. Ian Lance Taylor <i...@golang.org> wrote: > On Fri, Aug 12, 2022 at 10:21 AM Sören Tempel <soe...@soeren-tempel.net> > wrote: > > > > This is one of the few remaining issues regarding musl compatibility for > > gofrontend. Unfortunately, I am not sure how to best fix this one. Hence > > reporting it here. > > > > The setThreadCPUProfiler implementation in libgo/go/runtime/os_linux.go > > contains the following code: > > > > var sevp _sigevent > > sevp.sigev_notify = _SIGEV_THREAD_ID > > sevp.sigev_signo = _SIGPROF > > *((*int32)(unsafe.Pointer(&sevp._sigev_un))) = int32(mp.procid) > > > > I am not entirely sure, but I assume the last line is supposed to access > > the thread ID in struct sigevent. Unfortunately, it does so via the > > glibc-specific _sigev_un member which doesn't work on musl libc (the > > union is named __sev_fields on musl and hence causes a build failure). > > > > A portable way to access the thread ID in struct sigevent is via > > sigev_notify_thread_id which is documented in timer_create(2). This is a > > macro provided in siginfo.h from linux-headers for glibc [1] and in > > signal.h for musl [2]. However, since it is macro it probably requires a > > C wrapper function in order to be usable in libgo. Would be possible to > > add that somehow to libgo or is there an alternative feasible solution > > for this issue? > > I think you're right that a tiny C function is the way to go here. > > Ian