[PATCH v3 1/4] x86: Simplify TCB access expressions

H.J. Lu hjl.tools@gmail.com
Wed Oct 8 02:59:00 GMT 2025


On Wed, Oct 1, 2025 at 8:31 PM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> Replace manual cast with a direct `(__typeof(*descr) __seg_gs *)0`
> dereference to access `member`.  This avoids redundant
> `offsetof(struct pthread, member)` and improves readability while
> preserving semantics.
>
> Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
> ---
> v2: Add volatile to the inner cast and drop the outer cast.
> ---
>  sysdeps/i386/nptl/tcb-access.h   | 15 +++++----------
>  sysdeps/i386/nptl/tls.h          |  5 ++---
>  sysdeps/x86_64/nptl/tcb-access.h | 15 +++++----------
>  sysdeps/x86_64/nptl/tls.h        |  5 ++---
>  4 files changed, 14 insertions(+), 26 deletions(-)
>
> diff --git a/sysdeps/i386/nptl/tcb-access.h b/sysdeps/i386/nptl/tcb-access.h
> index 2a7f9d2a57..5bb58c37fa 100644
> --- a/sysdeps/i386/nptl/tcb-access.h
> +++ b/sysdeps/i386/nptl/tcb-access.h
> @@ -23,8 +23,7 @@
>                      || sizeof (descr->member) == 4                           \
>                      || sizeof (descr->member) == 8,                          \
>                      "size of per-thread data");                              \
> -     (*(__typeof (descr->member) __seg_gs *)                                 \
> -      offsetof (struct pthread, member));                                    \
> +     ((__typeof (*descr) __seg_gs *)0)->member;                                      \
>    })
>
>  #define THREAD_GETMEM_VOLATILE(descr, member) \
> @@ -33,8 +32,7 @@
>                      || sizeof (descr->member) == 4                           \
>                      || sizeof (descr->member) == 8,                          \
>                      "size of per-thread data");                              \
> -     (*(volatile __typeof (descr->member) __seg_gs *)                        \
> -      offsetof (struct pthread, member));                                    \
> +     ((volatile __typeof (*descr) __seg_gs *)0)->member;                     \
>    })
>
>  /* Same as THREAD_GETMEM, but the member offset can be non-constant.  */
> @@ -44,8 +42,7 @@
>                      || sizeof (descr->member[0]) == 4                        \
>                      || sizeof (descr->member[0]) == 8,                       \
>                      "size of per-thread data");                              \
> -     (*(__typeof (descr->member[0]) __seg_gs *)                                      \
> -      offsetof (struct pthread, member[idx]));                               \
> +     ((__typeof (*descr) __seg_gs *)0)->member[idx];                         \
>    })
>
>  /* Set member of the thread descriptor directly.  */
> @@ -55,8 +52,7 @@
>                      || sizeof (descr->member) == 4                           \
>                      || sizeof (descr->member) == 8,                          \
>                      "size of per-thread data");                              \
> -     (*(__typeof (descr->member) __seg_gs *)                                 \
> -      offsetof (struct pthread, member) = (value));                          \
> +     ((__typeof (*descr) __seg_gs *)0)->member = (value);                    \
>    })
>
>  /* Same as THREAD_SETMEM, but the member offset can be non-constant.  */
> @@ -66,6 +62,5 @@
>                      || sizeof (descr->member[0]) == 4                        \
>                      || sizeof (descr->member[0]) == 8,                       \
>                      "size of per-thread data");                              \
> -     (*(__typeof (descr->member[0]) __seg_gs *)                                      \
> -      offsetof (struct pthread, member[idx]) = (value));                     \
> +     ((__typeof (*descr) __seg_gs *)0)->member[idx] = (value);               \
>    })
> diff --git a/sysdeps/i386/nptl/tls.h b/sysdeps/i386/nptl/tls.h
> index 5c266c7191..7b297d4043 100644
> --- a/sysdeps/i386/nptl/tls.h
> +++ b/sysdeps/i386/nptl/tls.h
> @@ -223,7 +223,7 @@ tls_fill_user_desc (union user_desc_init *desc,
>
>  /* Return the thread descriptor for the current thread.  */
>  # define THREAD_SELF \
> -  (*(struct pthread *__seg_gs *) offsetof (struct pthread, header.self))
> +  (*(struct pthread *__seg_gs *)&((struct pthread __seg_gs *)0)->header.self)
>
>  /* Magic for libthread_db to know how to do THREAD_SELF.  */
>  # define DB_THREAD_SELF \
> @@ -257,8 +257,7 @@ tls_fill_user_desc (union user_desc_init *desc,
>      { int __res;                                                             \
>        asm volatile ("xchgl %1, %0"                                           \
>                     : "=r" (__res)                                            \
> -                   : "m" (*(int __seg_gs *)                                  \
> -                          offsetof (struct pthread, header.gscope_flag)),    \
> +                   : "m" (((struct pthread __seg_gs *)0)->header.gscope_flag), \
>                       "0" (THREAD_GSCOPE_FLAG_UNUSED));                       \
>        if (__res == THREAD_GSCOPE_FLAG_WAIT)                                  \
>         lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE);    \
> diff --git a/sysdeps/x86_64/nptl/tcb-access.h b/sysdeps/x86_64/nptl/tcb-access.h
> index 445f328ac2..7a418f945f 100644
> --- a/sysdeps/x86_64/nptl/tcb-access.h
> +++ b/sysdeps/x86_64/nptl/tcb-access.h
> @@ -23,8 +23,7 @@
>                      || sizeof (descr->member) == 4                           \
>                      || sizeof (descr->member) == 8,                          \
>                      "size of per-thread data");                              \
> -     (*(__typeof (descr->member) __seg_fs *)                                 \
> -      offsetof (struct pthread, member));                                    \
> +     ((__typeof (*descr) __seg_fs *)0)->member;                                      \
>    })
>
>  #define THREAD_GETMEM_VOLATILE(descr, member) \
> @@ -33,8 +32,7 @@
>                      || sizeof (descr->member) == 4                           \
>                      || sizeof (descr->member) == 8,                          \
>                      "size of per-thread data");                              \
> -     (*(volatile __typeof (descr->member) __seg_fs *)                        \
> -      offsetof (struct pthread, member));                                    \
> +     ((volatile __typeof (*descr) __seg_fs *)0)->member;                     \
>    })
>
>  /* Same as THREAD_GETMEM, but the member offset can be non-constant.  */
> @@ -44,8 +42,7 @@
>                      || sizeof (descr->member[0]) == 4                        \
>                      || sizeof (descr->member[0]) == 8,                       \
>                      "size of per-thread data");                              \
> -     (*(__typeof (descr->member[0]) __seg_fs *)                                      \
> -      offsetof (struct pthread, member[idx]));                               \
> +     ((__typeof (*descr) __seg_fs *)0)->member[idx];                         \
>    })
>
>  /* Set member of the thread descriptor directly.  */
> @@ -55,8 +52,7 @@
>                      || sizeof (descr->member) == 4                           \
>                      || sizeof (descr->member) == 8,                          \
>                      "size of per-thread data");                              \
> -     (*(__typeof (descr->member) __seg_fs *)                                 \
> -      offsetof (struct pthread, member) = (value));                          \
> +     ((__typeof (*descr) __seg_fs *)0)->member = (value);                    \
>    })
>
>  /* Same as THREAD_SETMEM, but the member offset can be non-constant.  */
> @@ -66,6 +62,5 @@
>                      || sizeof (descr->member[0]) == 4                        \
>                      || sizeof (descr->member[0]) == 8,                       \
>                      "size of per-thread data");                              \
> -     (*(__typeof (descr->member[0]) __seg_fs *)                                      \
> -      offsetof (struct pthread, member[idx]) = (value));                     \
> +     ((__typeof (*descr) __seg_fs *)0)->member[idx] = (value);               \
>    })
> diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h
> index cf41430050..abfeb88054 100644
> --- a/sysdeps/x86_64/nptl/tls.h
> +++ b/sysdeps/x86_64/nptl/tls.h
> @@ -170,7 +170,7 @@ _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x80,
>
>  /* Return the thread descriptor for the current thread.  */
>  # define THREAD_SELF \
> -  (*(struct pthread *__seg_fs *) offsetof (struct pthread, header.self))
> +  (*(struct pthread *__seg_fs *)&((struct pthread __seg_fs *)0)->header.self)
>
>  /* Magic for libthread_db to know how to do THREAD_SELF.  */
>  # define DB_THREAD_SELF_INCLUDE  <sys/reg.h> /* For the FS constant.  */
> @@ -203,8 +203,7 @@ _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x80,
>      { int __res;                                                             \
>        asm volatile ("xchgl %1, %0"                                           \
>                     : "=r" (__res)                                            \
> -                   : "m" (*(int __seg_fs *)                                  \
> -                          offsetof (struct pthread, header.gscope_flag)),    \
> +                   : "m" (((struct pthread __seg_fs *)0)->header.gscope_flag), \
>                       "0" (THREAD_GSCOPE_FLAG_UNUSED));                       \
>        if (__res == THREAD_GSCOPE_FLAG_WAIT)                                  \
>         lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE);    \
> --
> 2.51.0
>

LGTM.

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>

Thanks.

-- 
H.J.


More information about the Libc-alpha mailing list