[PATCH 34/59] x86: Fix THREAD_GSCOPE_RESET_FLAG build on clang

Uros Bizjak ubizjak@gmail.com
Mon Oct 20 19:09:40 GMT 2025


On Mon, Oct 20, 2025 at 8:47 PM Adhemerval Zanella Netto
<adhemerval.zanella@linaro.org> wrote:
>
>
>
> On 19/10/25 12:21, Uros Bizjak wrote:
> >
> >
> > On 10/17/25 21:13, Adhemerval Zanella wrote:
> >> clang does not support __seg_fs in asm constraint.
> >> ---
> >>   sysdeps/x86_64/nptl/tls.h | 21 +++++++++++++++++----
> >>   1 file changed, 17 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h
> >> index abfeb88054..2c4b9aaa80 100644
> >> --- a/sysdeps/x86_64/nptl/tls.h
> >> +++ b/sysdeps/x86_64/nptl/tls.h
> >> @@ -198,13 +198,26 @@ _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x80,
> >>   # define THREAD_GSCOPE_FLAG_UNUSED 0
> >>   # define THREAD_GSCOPE_FLAG_USED   1
> >>   # define THREAD_GSCOPE_FLAG_WAIT   2
> >> +
> >> +/* clang does not support __seg_fs in asm constraint.  */
> >> +# ifdef __clang__
> >> +#  define XCHGL_GSCOPE(__r)                              \
> >> +   asm volatile ("xchgl %0, %%fs:%P1"                          \
> >> +                 : "=r" (__r)                              \
> >> +                 : "i" (offsetof (struct pthread, header.gscope_flag)),          \
> >> +           "0" (THREAD_GSCOPE_FLAG_UNUSED))
> >
> > This needs a "memory" clobber, because this asm hides memory access
> > from the compiler. Please see the "memory" special clobber argument
> > section in [1].
> >
> > Also, please use the "c" operand modifier instead of "P". Clang allows
> > "c" with "i" constraint and also checks that operand fits "c".
>
> Ack.
>
> >
> > Clang accepts __seg_fs prefixed addresses, it just "forgets" to emit %fs: prefix in the generated code. While this could be considered a bug with clang, the simplest solution is to just conditionally put "%%fs:" prefix in the asm template for clang.
>
> We also need to use a 'i' constraint, clang does not accept 'm' witha
> '((struct pthread __seg_fs *)0)->header.gscope_flag'.

Hm, it works for me, at least for the following testcase:

--cut here--
struct pthread
{
  struct
  {
    int multiple_threads;
    int gscope_flag;
  } header;
  void *__padding[24];
};

int baz(void)
{
  int __res;
  asm volatile ("xchgl %%fs:%1, %0"
        : "=r" (__res)
        : "m" (((struct pthread __seg_fs *)0)->header.gscope_flag),
          "0" (0));
  return __res;
}
--cut here--

$ clang -O2 -c tcbc.c
$ objdump -dr tcbc.o

0000000000000000 <baz>:
  0:   31 c0                   xor    %eax,%eax
  2:   64 87 04 25 04 00 00    xchg   %eax,%fs:0x4
  9:   00
  a:   c3                      ret

$ clang --version
clang version 20.1.8 (Fedora 20.1.8-4.fc42)
Target: x86_64-redhat-linux-gnu

Uros.


More information about the Libc-alpha mailing list