diff options
Diffstat (limited to 'REORG.TODO/sysdeps/powerpc/nptl')
-rw-r--r-- | REORG.TODO/sysdeps/powerpc/nptl/Makefile | 20 | ||||
-rw-r--r-- | REORG.TODO/sysdeps/powerpc/nptl/bits/pthreadtypes-arch.h | 79 | ||||
-rw-r--r-- | REORG.TODO/sysdeps/powerpc/nptl/elide.h | 125 | ||||
-rw-r--r-- | REORG.TODO/sysdeps/powerpc/nptl/pthread_spin_lock.c | 43 | ||||
-rw-r--r-- | REORG.TODO/sysdeps/powerpc/nptl/pthread_spin_trylock.c | 41 | ||||
-rw-r--r-- | REORG.TODO/sysdeps/powerpc/nptl/pthread_spin_unlock.c | 27 | ||||
-rw-r--r-- | REORG.TODO/sysdeps/powerpc/nptl/pthreaddef.h | 33 | ||||
-rw-r--r-- | REORG.TODO/sysdeps/powerpc/nptl/tcb-offsets.sym | 32 | ||||
-rw-r--r-- | REORG.TODO/sysdeps/powerpc/nptl/tls.h | 263 |
9 files changed, 663 insertions, 0 deletions
diff --git a/REORG.TODO/sysdeps/powerpc/nptl/Makefile b/REORG.TODO/sysdeps/powerpc/nptl/Makefile new file mode 100644 index 0000000000..13fa630f2f --- /dev/null +++ b/REORG.TODO/sysdeps/powerpc/nptl/Makefile @@ -0,0 +1,20 @@ +# Copyright (C) 2003-2017 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# <http://www.gnu.org/licenses/>. + +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/REORG.TODO/sysdeps/powerpc/nptl/bits/pthreadtypes-arch.h b/REORG.TODO/sysdeps/powerpc/nptl/bits/pthreadtypes-arch.h new file mode 100644 index 0000000000..f29119b794 --- /dev/null +++ b/REORG.TODO/sysdeps/powerpc/nptl/bits/pthreadtypes-arch.h @@ -0,0 +1,79 @@ +/* Machine-specific pthread type layouts. PowerPC version. + Copyright (C) 2003-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _BITS_PTHREADTYPES_ARCH_H +#define _BITS_PTHREADTYPES_ARCH_H 1 + +#include <bits/wordsize.h> + +#if __WORDSIZE == 64 +# define __SIZEOF_PTHREAD_MUTEX_T 40 +# define __SIZEOF_PTHREAD_ATTR_T 56 +# define __SIZEOF_PTHREAD_RWLOCK_T 56 +# define __SIZEOF_PTHREAD_BARRIER_T 32 +#else +# define __SIZEOF_PTHREAD_MUTEX_T 24 +# define __SIZEOF_PTHREAD_ATTR_T 36 +# define __SIZEOF_PTHREAD_RWLOCK_T 32 +# define __SIZEOF_PTHREAD_BARRIER_T 20 +#endif +#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +#define __SIZEOF_PTHREAD_COND_T 48 +#define __SIZEOF_PTHREAD_CONDATTR_T 4 +#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 + +/* Definitions for internal mutex struct. */ +#define __PTHREAD_COMPAT_PADDING_MID +#define __PTHREAD_COMPAT_PADDING_END +#define __PTHREAD_MUTEX_LOCK_ELISION 1 + +#define __LOCK_ALIGNMENT +#define __ONCE_ALIGNMENT + +struct __pthread_rwlock_arch_t +{ + unsigned int __readers; + unsigned int __writers; + unsigned int __wrphase_futex; + unsigned int __writers_futex; + unsigned int __pad3; + unsigned int __pad4; +#if __WORDSIZE == 64 + int __cur_writer; + int __shared; + unsigned char __rwelision; + unsigned char __pad1[7]; + unsigned long int __pad2; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned int __flags; +# define __PTHREAD_RWLOCK_ELISION_EXTRA 0, {0, 0, 0, 0, 0, 0, 0 } +#else + unsigned char __rwelision; + unsigned char __pad2; + unsigned char __shared; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; + int __cur_writer; +# define __PTHREAD_RWLOCK_ELISION_EXTRA 0 +#endif +}; + +#endif /* bits/pthreadtypes.h */ diff --git a/REORG.TODO/sysdeps/powerpc/nptl/elide.h b/REORG.TODO/sysdeps/powerpc/nptl/elide.h new file mode 100644 index 0000000000..1c42814b71 --- /dev/null +++ b/REORG.TODO/sysdeps/powerpc/nptl/elide.h @@ -0,0 +1,125 @@ +/* elide.h: Generic lock elision support for powerpc. + Copyright (C) 2015-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef ELIDE_PPC_H +# define ELIDE_PPC_H + +#ifdef ENABLE_LOCK_ELISION +# include <htm.h> +# include <elision-conf.h> + +/* Get the new value of adapt_count according to the elision + configurations. Returns true if the system should retry again or false + otherwise. */ +static inline bool +__get_new_count (uint8_t *adapt_count, int attempt) +{ + /* A persistent failure indicates that a retry will probably + result in another failure. Use normal locking now and + for the next couple of calls. */ + if (_TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ())) + { + if (__elision_aconf.skip_lock_internal_abort > 0) + *adapt_count = __elision_aconf.skip_lock_internal_abort; + return false; + } + /* Same logic as above, but for a number of temporary failures in a + a row. */ + else if (attempt <= 1 && __elision_aconf.skip_lock_out_of_tbegin_retries > 0 + && __elision_aconf.try_tbegin > 0) + *adapt_count = __elision_aconf.skip_lock_out_of_tbegin_retries; + return true; +} + +/* CONCURRENCY NOTES: + + The evaluation of the macro expression is_lock_free encompasses one or + more loads from memory locations that are concurrently modified by other + threads. For lock elision to work, this evaluation and the rest of the + critical section protected by the lock must be atomic because an + execution with lock elision must be equivalent to an execution in which + the lock would have been actually acquired and released. Therefore, we + evaluate is_lock_free inside of the transaction that represents the + critical section for which we want to use lock elision, which ensures + the atomicity that we require. */ + +/* Returns 0 if the lock defined by is_lock_free was elided. + ADAPT_COUNT is a per-lock state variable. */ +# define ELIDE_LOCK(adapt_count, is_lock_free) \ + ({ \ + int ret = 0; \ + if (adapt_count > 0) \ + (adapt_count)--; \ + else \ + for (int i = __elision_aconf.try_tbegin; i > 0; i--) \ + { \ + if (__libc_tbegin (0)) \ + { \ + if (is_lock_free) \ + { \ + ret = 1; \ + break; \ + } \ + __libc_tabort (_ABORT_LOCK_BUSY); \ + } \ + else \ + if (!__get_new_count (&adapt_count,i)) \ + break; \ + } \ + ret; \ + }) + +# define ELIDE_TRYLOCK(adapt_count, is_lock_free, write) \ + ({ \ + int ret = 0; \ + if (__elision_aconf.try_tbegin > 0) \ + { \ + if (write) \ + __libc_tabort (_ABORT_NESTED_TRYLOCK); \ + ret = ELIDE_LOCK (adapt_count, is_lock_free); \ + } \ + ret; \ + }) + + +static inline bool +__elide_unlock (int is_lock_free) +{ + if (is_lock_free) + { + /* This code is expected to crash when trying to unlock a lock not + held by this thread. More information is available in the + __pthread_rwlock_unlock() implementation. */ + __libc_tend (0); + return true; + } + return false; +} + +# define ELIDE_UNLOCK(is_lock_free) \ + __elide_unlock (is_lock_free) + +# else + +# define ELIDE_LOCK(adapt_count, is_lock_free) 0 +# define ELIDE_TRYLOCK(adapt_count, is_lock_free, write) 0 +# define ELIDE_UNLOCK(is_lock_free) 0 + +#endif /* ENABLE_LOCK_ELISION */ + +#endif diff --git a/REORG.TODO/sysdeps/powerpc/nptl/pthread_spin_lock.c b/REORG.TODO/sysdeps/powerpc/nptl/pthread_spin_lock.c new file mode 100644 index 0000000000..e377feb1cf --- /dev/null +++ b/REORG.TODO/sysdeps/powerpc/nptl/pthread_spin_lock.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2003-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include "pthreadP.h" + +int +pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int __tmp; + + asm volatile ( + "1: lwarx %0,0,%1" MUTEX_HINT_ACQ "\n" + " cmpwi 0,%0,0\n" + " bne- 2f\n" + " stwcx. %2,0,%1\n" + " bne- 2f\n" + __ARCH_ACQ_INSTR "\n" + " .subsection 1\n" + "2: lwzx %0,0,%1\n" + " cmpwi 0,%0,0\n" + " bne 2b\n" + " b 1b\n" + " .previous" + : "=&r" (__tmp) + : "r" (lock), "r" (1) + : "cr0", "memory"); + return 0; +} diff --git a/REORG.TODO/sysdeps/powerpc/nptl/pthread_spin_trylock.c b/REORG.TODO/sysdeps/powerpc/nptl/pthread_spin_trylock.c new file mode 100644 index 0000000000..d81d984237 --- /dev/null +++ b/REORG.TODO/sysdeps/powerpc/nptl/pthread_spin_trylock.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2003-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include "pthreadP.h" + +int +pthread_spin_trylock (pthread_spinlock_t *lock) +{ + unsigned int old; + int err = EBUSY; + + asm ("1: lwarx %0,0,%2" MUTEX_HINT_ACQ "\n" + " cmpwi 0,%0,0\n" + " bne 2f\n" + " stwcx. %3,0,%2\n" + " bne- 1b\n" + " li %1,0\n" + __ARCH_ACQ_INSTR "\n" + "2: " + : "=&r" (old), "=&r" (err) + : "r" (lock), "r" (1), "1" (err) + : "cr0", "memory"); + + return err; +} diff --git a/REORG.TODO/sysdeps/powerpc/nptl/pthread_spin_unlock.c b/REORG.TODO/sysdeps/powerpc/nptl/pthread_spin_unlock.c new file mode 100644 index 0000000000..fa30a82491 --- /dev/null +++ b/REORG.TODO/sysdeps/powerpc/nptl/pthread_spin_unlock.c @@ -0,0 +1,27 @@ +/* pthread_spin_unlock -- unlock a spin lock. PowerPC version. + Copyright (C) 2007-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include "pthreadP.h" +#include <lowlevellock.h> + +int +pthread_spin_unlock (pthread_spinlock_t *lock) +{ + atomic_store_release (lock, 0); + return 0; +} diff --git a/REORG.TODO/sysdeps/powerpc/nptl/pthreaddef.h b/REORG.TODO/sysdeps/powerpc/nptl/pthreaddef.h new file mode 100644 index 0000000000..e3e407a4c4 --- /dev/null +++ b/REORG.TODO/sysdeps/powerpc/nptl/pthreaddef.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2003-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (4 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. The ABI requires 16 + bytes (for both 32-bit and 64-bit PowerPC). */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 4096 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) diff --git a/REORG.TODO/sysdeps/powerpc/nptl/tcb-offsets.sym b/REORG.TODO/sysdeps/powerpc/nptl/tcb-offsets.sym new file mode 100644 index 0000000000..7c9fd33562 --- /dev/null +++ b/REORG.TODO/sysdeps/powerpc/nptl/tcb-offsets.sym @@ -0,0 +1,32 @@ +#include <sysdep.h> +#include <tls.h> +#include <kernel-features.h> + +-- + +-- Abuse tls.h macros to derive offsets relative to the thread register. +# undef __thread_register +# define __thread_register ((void *) 0) +# define thread_offsetof(mem) ((ptrdiff_t) THREAD_SELF + offsetof (struct pthread, mem)) + + +#if TLS_MULTIPLE_THREADS_IN_TCB +MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads) +#endif +TID thread_offsetof (tid) +POINTER_GUARD (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t)) +TAR_SAVE (offsetof (tcbhead_t, tar_save) - TLS_TCB_OFFSET - sizeof (tcbhead_t)) +DSO_SLOT1 (offsetof (tcbhead_t, dso_slot1) - TLS_TCB_OFFSET - sizeof (tcbhead_t)) +DSO_SLOT2 (offsetof (tcbhead_t, dso_slot2) - TLS_TCB_OFFSET - sizeof (tcbhead_t)) +#ifdef __powerpc64__ +TCB_AT_PLATFORM (offsetof (tcbhead_t, at_platform) - TLS_TCB_OFFSET - sizeof(tcbhead_t)) +#endif +TM_CAPABLE (offsetof (tcbhead_t, tm_capable) - TLS_TCB_OFFSET - sizeof (tcbhead_t)) +#ifndef __powerpc64__ +TCB_AT_PLATFORM (offsetof (tcbhead_t, at_platform) - TLS_TCB_OFFSET - sizeof(tcbhead_t)) +PADDING (offsetof (tcbhead_t, padding) - TLS_TCB_OFFSET - sizeof(tcbhead_t)) +#endif +TCB_HWCAP (offsetof (tcbhead_t, hwcap) - TLS_TCB_OFFSET - sizeof (tcbhead_t)) +#ifndef __ASSUME_PRIVATE_FUTEX +PRIVATE_FUTEX_OFFSET thread_offsetof (header.private_futex) +#endif diff --git a/REORG.TODO/sysdeps/powerpc/nptl/tls.h b/REORG.TODO/sysdeps/powerpc/nptl/tls.h new file mode 100644 index 0000000000..7556e7c8b8 --- /dev/null +++ b/REORG.TODO/sysdeps/powerpc/nptl/tls.h @@ -0,0 +1,263 @@ +/* Definition for thread-local data handling. NPTL/PowerPC version. + Copyright (C) 2003-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _TLS_H +#define _TLS_H 1 + +# include <dl-sysdep.h> + +#ifndef __ASSEMBLER__ +# include <stdbool.h> +# include <stddef.h> +# include <stdint.h> +# include <dl-dtv.h> + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif /* __ASSEMBLER__ */ + + +#ifndef __ASSEMBLER__ + +# include <hwcapinfo.h> + +/* Get system call information. */ +# include <sysdep.h> + +/* The TP points to the start of the thread blocks. */ +# define TLS_DTV_AT_TP 1 +# define TLS_TCB_AT_TP 0 + +/* We use the multiple_threads field in the pthread struct */ +#define TLS_MULTIPLE_THREADS_IN_TCB 1 + +/* Get the thread descriptor definition. */ +# include <nptl/descr.h> + + +/* The stack_guard is accessed directly by GCC -fstack-protector code, + so it is a part of public ABI. The dtv and pointer_guard fields + are private. */ +typedef struct +{ + /* Reservation for HWCAP data. To be accessed by GCC in + __builtin_cpu_supports(), so it is a part of public ABI. */ + uint64_t hwcap; + /* Reservation for AT_PLATFORM data. To be accessed by GCC in + __builtin_cpu_is(), so it is a part of public ABI. Since there + are different ABIs for 32 and 64 bit, we put this field in a + previously empty padding space for powerpc64. */ +#ifndef __powerpc64__ + /* Padding to maintain alignment. */ + uint32_t padding; + uint32_t at_platform; +#endif + /* Indicate if HTM capable (ISA 2.07). */ + uint32_t tm_capable; + /* Reservation for AT_PLATFORM data - powerpc64. */ +#ifdef __powerpc64__ + uint32_t at_platform; +#endif + /* Reservation for Dynamic System Optimizer ABI. */ + uintptr_t dso_slot2; + uintptr_t dso_slot1; + /* Reservation for tar register (ISA 2.07). */ + uintptr_t tar_save; + /* GCC split stack support. */ + void *__private_ss; + /* Reservation for the Event-Based Branching ABI. */ + uintptr_t ebb_handler; + uintptr_t ebb_ctx_pointer; + uintptr_t ebb_reserved1; + uintptr_t ebb_reserved2; + uintptr_t pointer_guard; + uintptr_t stack_guard; + dtv_t *dtv; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE 0 + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE 0 + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE \ + (sizeof (struct pthread) \ + + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) + +# ifndef __powerpc64__ +/* Register r2 (tp) is reserved by the ABI as "thread pointer". */ +register void *__thread_register __asm__ ("r2"); +# define PT_THREAD_POINTER PT_R2 +# else +/* Register r13 (tp) is reserved by the ABI as "thread pointer". */ +register void *__thread_register __asm__ ("r13"); +# define PT_THREAD_POINTER PT_R13 +# endif + +/* The following assumes that TP (R2 or R13) points to the end of the + TCB + 0x7000 (per the ABI). This implies that TCB address is + TP - 0x7000. As we define TLS_DTV_AT_TP we can + assume that the pthread struct is allocated immediately ahead of the + TCB. This implies that the pthread_descr address is + TP - (TLS_PRE_TCB_SIZE + 0x7000). */ +# define TLS_TCB_OFFSET 0x7000 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + ((tcbhead_t *) (tcbp))[-1].dtv = dtvp + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) (THREAD_DTV() = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) (((tcbhead_t *) (tcbp))[-1].dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp) \ + ({ \ + __thread_register = (void *) (tcbp) + TLS_TCB_OFFSET; \ + THREAD_SET_TM_CAPABLE (__tcb_hwcap & PPC_FEATURE2_HAS_HTM ? 1 : 0); \ + THREAD_SET_HWCAP (__tcb_hwcap); \ + THREAD_SET_AT_PLATFORM (__tcb_platform); \ + NULL; \ + }) + +/* Value passed to 'clone' for initialization of the thread register. */ +# define TLS_DEFINE_INIT_TP(tp, pd) \ + void *tp = (void *) (pd) + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE; \ + (((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].tm_capable) = \ + THREAD_GET_TM_CAPABLE (); \ + (((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].hwcap) = \ + THREAD_GET_HWCAP (); \ + (((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].at_platform) = \ + THREAD_GET_AT_PLATFORM (); + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) (__thread_register - TLS_TCB_OFFSET))[-1].dtv) + +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF \ + ((struct pthread *) (__thread_register \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + REGISTER (32, 32, PT_THREAD_POINTER * 4, \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) \ + REGISTER (64, 64, PT_THREAD_POINTER * 8, \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) ((void)(descr), (THREAD_SELF)->member) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member, idx) \ + ((void)(descr), (THREAD_SELF)->member[idx]) + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM(descr, member, value) \ + ((void)(descr), (THREAD_SELF)->member = (value)) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ + ((void)(descr), (THREAD_SELF)->member[idx] = (value)) + +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + (((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].stack_guard = (value)) +# define THREAD_COPY_STACK_GUARD(descr) \ + (((tcbhead_t *) ((char *) (descr) \ + + TLS_PRE_TCB_SIZE))[-1].stack_guard \ + = ((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].stack_guard) + +/* Set the stack guard field in TCB head. */ +# define THREAD_GET_POINTER_GUARD() \ + (((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].pointer_guard) +# define THREAD_SET_POINTER_GUARD(value) \ + (THREAD_GET_POINTER_GUARD () = (value)) +# define THREAD_COPY_POINTER_GUARD(descr) \ + (((tcbhead_t *) ((char *) (descr) \ + + TLS_PRE_TCB_SIZE))[-1].pointer_guard \ + = THREAD_GET_POINTER_GUARD()) + +/* tm_capable field in TCB head. */ +# define THREAD_GET_TM_CAPABLE() \ + (((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].tm_capable) +# define THREAD_SET_TM_CAPABLE(value) \ + (THREAD_GET_TM_CAPABLE () = (value)) + +/* hwcap field in TCB head. */ +# define THREAD_GET_HWCAP() \ + (((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].hwcap) +# define THREAD_SET_HWCAP(value) \ + (THREAD_GET_HWCAP () = (value)) + +/* at_platform field in TCB head. */ +# define THREAD_GET_AT_PLATFORM() \ + (((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].at_platform) +# define THREAD_SET_AT_PLATFORM(value) \ + (THREAD_GET_AT_PLATFORM () = (value)) + +/* l_tls_offset == 0 is perfectly valid on PPC, so we have to use some + different value to mean unset l_tls_offset. */ +# define NO_TLS_OFFSET -1 + +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ |