1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-12-24 17:51:17 +03:00

Move remaining S390 code out of nptl/.

This commit is contained in:
Roland McGrath
2014-06-26 09:31:11 -07:00
parent 39507e4a6c
commit 52ae23b4bf
29 changed files with 81 additions and 22 deletions

View File

@@ -22,3 +22,16 @@ ifeq (yes,$(build-shared))
sysdep_routines += v1-longjmp_chk
endif
endif
ifeq ($(subdir),nptl)
ifeq ($(enable-lock-elision),yes)
libpthread-sysdep_routines += elision-lock elision-unlock elision-timed \
elision-trylock
elision-CFLAGS = -mhtm
CFLAGS-elision-lock.c = $(elision-CFLAGS)
CFLAGS-elision-timed.c = $(elision-CFLAGS)
CFLAGS-elision-trylock.c = $(elision-CFLAGS)
CFLAGS-elision-unlock.c = $(elision-CFLAGS)
endif
endif

View File

@@ -8,3 +8,9 @@ libc {
__vdso_clock_getres;
}
}
libpthread {
GLIBC_2.19 {
longjmp; siglongjmp;
}
}

View File

@@ -0,0 +1,82 @@
/* Lock elision tunable parameters.
Copyright (C) 2014 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 <config.h>
#include <pthreadP.h>
#include <elision-conf.h>
#include <unistd.h>
#include <dl-procinfo.h>
/* Reasonable initial tuning values, may be revised in the future.
This is a conservative initial value. */
struct elision_config __elision_aconf =
{
/* How often to not attempt to use elision if a transaction aborted
because the lock is already acquired. Expressed in number of lock
acquisition attempts. */
.skip_lock_busy = 3,
/* How often to not attempt to use elision if a transaction aborted due
to reasons other than other threads' memory accesses. Expressed in
number of lock acquisition attempts. */
.skip_lock_internal_abort = 3,
/* How often to not attempt to use elision if a lock used up all retries
without success. Expressed in number of lock acquisition attempts. */
.skip_lock_out_of_tbegin_retries = 3,
/* How often we try using elision if there is chance for the transaction
to finish execution (e.g., it wasn't aborted due to the lock being
already acquired. */
.try_tbegin = 3,
/* Same as SKIP_LOCK_INTERNAL_ABORT but for trylock. */
.skip_trylock_internal_abort = 3,
};
/* Force elision for all new locks. This is used to decide whether existing
DEFAULT locks should be automatically upgraded to elision in
pthread_mutex_lock(). Disabled for suid programs. Only used when elision
is available. */
int __pthread_force_elision attribute_hidden = 0;
/* Initialize elison. */
static void
elision_init (int argc __attribute__ ((unused)),
char **argv __attribute__ ((unused)),
char **environ)
{
/* Set when the CPU and the kernel supports transactional execution.
When false elision is never attempted. */
int elision_available = (GLRO (dl_hwcap) & HWCAP_S390_TE) ? 1 : 0;
__pthread_force_elision = __libc_enable_secure ? 0 : elision_available;
}
#ifdef SHARED
# define INIT_SECTION ".init_array"
# define MAYBE_CONST
#else
# define INIT_SECTION ".preinit_array"
# define MAYBE_CONST const
#endif
void (*MAYBE_CONST __pthread_init_array []) (int, char **, char **)
__attribute__ ((section (INIT_SECTION), aligned (sizeof (void *)))) =
{
&elision_init
};

View File

@@ -0,0 +1,44 @@
/* Lock elision tunable parameters.
Copyright (C) 2014 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/>. */
#ifdef ENABLE_LOCK_ELISION
#ifndef _ELISION_CONF_H
#define _ELISION_CONF_H 1
#include <pthread.h>
#include <time.h>
/* Should make sure there is no false sharing on this. */
struct elision_config
{
int skip_lock_busy;
int skip_lock_internal_abort;
int skip_lock_out_of_tbegin_retries;
int try_tbegin;
int skip_trylock_internal_abort;
};
extern struct elision_config __elision_aconf attribute_hidden;
extern int __pthread_force_elision attribute_hidden;
/* Tell the test suite to test elision for this architecture. */
#define HAVE_ELISION 1
#endif
#endif

View File

@@ -0,0 +1,119 @@
/* Elided pthread mutex lock.
Copyright (C) 2014 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 <pthread.h>
#include <pthreadP.h>
#include <lowlevellock.h>
#include <htmintrin.h>
#include <elision-conf.h>
#include <stdint.h>
#if !defined(LLL_LOCK) && !defined(EXTRAARG)
/* Make sure the configuration code is always linked in for static
libraries. */
#include "elision-conf.c"
#endif
#ifndef EXTRAARG
#define EXTRAARG
#endif
#ifndef LLL_LOCK
#define LLL_LOCK(a,b) lll_lock(a,b), 0
#endif
#define aconf __elision_aconf
/* Adaptive lock using transactions.
By default the lock region is run as a transaction, and when it
aborts or the lock is busy the lock adapts itself. */
int
__lll_lock_elision (int *futex, short *adapt_count, EXTRAARG int private)
{
if (*adapt_count > 0)
{
/* Lost updates are possible, but harmless. Due to races this might lead
to *adapt_count becoming less than zero. */
(*adapt_count)--;
goto use_lock;
}
__asm__ volatile (".machinemode \"zarch_nohighgprs\"\n\t"
".machine \"all\""
: : : "memory");
int try_tbegin;
for (try_tbegin = aconf.try_tbegin;
try_tbegin > 0;
try_tbegin--)
{
unsigned status;
if (__builtin_expect
((status = __builtin_tbegin((void *)0)) == _HTM_TBEGIN_STARTED, 1))
{
if (*futex == 0)
return 0;
/* Lock was busy. Fall back to normal locking. */
if (__builtin_expect (__builtin_tx_nesting_depth (), 1))
{
/* In a non-nested transaction there is no need to abort,
which is expensive. */
__builtin_tend ();
if (aconf.skip_lock_busy > 0)
*adapt_count = aconf.skip_lock_busy;
goto use_lock;
}
else /* nesting depth is > 1 */
{
/* A nested transaction will abort eventually because it
cannot make any progress before *futex changes back to 0.
So we may as well abort immediately.
This persistently aborts the outer transaction to force
the outer mutex use the default lock instead of retrying
with transactions until the try_tbegin of the outer mutex
is zero.
The adapt_count of this inner mutex is not changed,
because using the default lock with the inner mutex
would abort the outer transaction.
*/
__builtin_tabort (_HTM_FIRST_USER_ABORT_CODE | 1);
}
}
else
{
if (status != _HTM_TBEGIN_TRANSIENT)
{
/* A persistent abort (cc 1 or 3) indicates that a retry is
probably futile. Use the normal locking now and for the
next couple of calls.
Be careful to avoid writing to the lock. */
if (aconf.skip_lock_internal_abort > 0)
*adapt_count = aconf.skip_lock_internal_abort;
goto use_lock;
}
}
}
/* Same logic as above, but for for a number of temporary failures in a
row. */
if (aconf.skip_lock_out_of_tbegin_retries > 0 && aconf.try_tbegin > 0)
*adapt_count = aconf.skip_lock_out_of_tbegin_retries;
use_lock:
return LLL_LOCK ((*futex), private);
}

View File

@@ -0,0 +1,26 @@
/* Lock elision timed lock.
Copyright (C) 2014 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 <time.h>
#include <elision-conf.h>
#include <lowlevellock.h>
#define __lll_lock_elision __lll_timedlock_elision
#define EXTRAARG const struct timespec *t,
#undef LLL_LOCK
#define LLL_LOCK(a, b) lll_timedlock(a, t, b)
#include "elision-lock.c"

View File

@@ -0,0 +1,94 @@
/* Elided pthread mutex trylock.
Copyright (C) 2014 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 <pthread.h>
#include <pthreadP.h>
#include <lowlevellock.h>
#include <htmintrin.h>
#include <elision-conf.h>
#define aconf __elision_aconf
/* Try to elide a futex trylock. FUTEX is the futex variable. ADAPT_COUNT is
the adaptation counter in the mutex. */
int
__lll_trylock_elision (int *futex, short *adapt_count)
{
__asm__ volatile (".machinemode \"zarch_nohighgprs\"\n\t"
".machine \"all\""
: : : "memory");
/* Implement POSIX semantics by forbiding nesting elided trylocks.
Sorry. After the abort the code is re-executed
non transactional and if the lock was already locked
return an error. */
if (__builtin_tx_nesting_depth () > 0)
{
/* Note that this abort may terminate an outermost transaction that
was created outside glibc.
This persistently aborts the current transactions to force
them to use the default lock instead of retrying transactions
until their try_tbegin is zero.
*/
__builtin_tabort (_HTM_FIRST_USER_ABORT_CODE | 1);
}
/* Only try a transaction if it's worth it. */
if (*adapt_count <= 0)
{
unsigned status;
if (__builtin_expect
((status = __builtin_tbegin ((void *)0)) == _HTM_TBEGIN_STARTED, 1))
{
if (*futex == 0)
return 0;
/* Lock was busy. Fall back to normal locking. */
/* Since we are in a non-nested transaction there is no need to abort,
which is expensive. */
__builtin_tend ();
/* Note: Changing the adapt_count here might abort a transaction on a
different cpu, but that could happen anyway when the futex is
acquired, so there's no need to check the nesting depth here. */
if (aconf.skip_lock_busy > 0)
*adapt_count = aconf.skip_lock_busy;
}
else
{
if (status != _HTM_TBEGIN_TRANSIENT)
{
/* A persistent abort (cc 1 or 3) indicates that a retry is
probably futile. Use the normal locking now and for the
next couple of calls.
Be careful to avoid writing to the lock. */
if (aconf.skip_trylock_internal_abort > 0)
*adapt_count = aconf.skip_trylock_internal_abort;
}
}
/* Could do some retries here. */
}
else
{
/* Lost updates are possible, but harmless. Due to races this might lead
to *adapt_count becoming less than zero. */
(*adapt_count)--;
}
return lll_trylock (*futex);
}

View File

@@ -0,0 +1,38 @@
/* Commit an elided pthread lock.
Copyright (C) 2014 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
__lll_unlock_elision(int *futex, int private)
{
/* If the lock is free, we elided the lock earlier. This does not
necessarily mean that we are in a transaction, because the user code may
have closed the transaction, but that is impossible to detect reliably. */
if (*futex == 0)
{
__asm__ volatile (".machinemode \"zarch_nohighgprs\"\n\t"
".machine \"all\""
: : : "memory");
__builtin_tend();
}
else
lll_unlock ((*futex), private);
return 0;
}

View File

@@ -0,0 +1,33 @@
/* Automatic enabling of elision for mutexes
Copyright (C) 2014 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/>. */
#ifdef ENABLE_LOCK_ELISION
/* Check for elision on this lock without upgrading. */
#define DO_ELISION(m) \
(__pthread_force_elision \
&& (m->__data.__kind & PTHREAD_MUTEX_NO_ELISION_NP) == 0) \
/* Automatically enable elision for existing user lock kinds. */
#define FORCE_ELISION(m, s) \
if (__pthread_force_elision \
&& (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \
{ \
mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP; \
s; \
}
#endif

View File

@@ -0,0 +1,39 @@
/* Clean up stack frames unwound by longjmp. Linux/s390 version.
Copyright (C) 2003-2014 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 <setjmp.h>
#include <stddef.h>
#include <pthreadP.h>
extern void __pthread_cleanup_upto (__jmp_buf env, char *targetframe);
#pragma weak __pthread_cleanup_upto
void
_longjmp_unwind (jmp_buf env, int val)
{
char local_var;
#ifdef SHARED
if (__libc_pthread_functions_init)
PTHFCT_CALL (ptr___pthread_cleanup_upto, (env->__jmpbuf, &local_var));
#else
if (__pthread_cleanup_upto != NULL)
__pthread_cleanup_upto (env->__jmpbuf, &local_var);
#endif
}

View File

@@ -0,0 +1,390 @@
/* Copyright (C) 2003-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Martin Schwidefsky <schwidefsky@de.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/>. */
#ifndef _LOWLEVELLOCK_H
#define _LOWLEVELLOCK_H 1
#include <time.h>
#include <sys/param.h>
#include <bits/pthreadtypes.h>
#include <atomic.h>
#include <kernel-features.h>
#define SYS_futex 238
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
#define FUTEX_REQUEUE 3
#define FUTEX_CMP_REQUEUE 4
#define FUTEX_WAKE_OP 5
#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1)
#define FUTEX_LOCK_PI 6
#define FUTEX_UNLOCK_PI 7
#define FUTEX_TRYLOCK_PI 8
#define FUTEX_WAIT_BITSET 9
#define FUTEX_WAKE_BITSET 10
#define FUTEX_WAIT_REQUEUE_PI 11
#define FUTEX_CMP_REQUEUE_PI 12
#define FUTEX_PRIVATE_FLAG 128
#define FUTEX_CLOCK_REALTIME 256
#define FUTEX_BITSET_MATCH_ANY 0xffffffff
/* Values for 'private' parameter of locking macros. Yes, the
definition seems to be backwards. But it is not. The bit will be
reversed before passing to the system call. */
#define LLL_PRIVATE 0
#define LLL_SHARED FUTEX_PRIVATE_FLAG
#if !defined NOT_IN_libc || defined IS_IN_rtld
/* In libc.so or ld.so all futexes are private. */
# ifdef __ASSUME_PRIVATE_FUTEX
# define __lll_private_flag(fl, private) \
((fl) | FUTEX_PRIVATE_FLAG)
# else
# define __lll_private_flag(fl, private) \
((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))
# endif
#else
# ifdef __ASSUME_PRIVATE_FUTEX
# define __lll_private_flag(fl, private) \
(((fl) | FUTEX_PRIVATE_FLAG) ^ (private))
# else
# define __lll_private_flag(fl, private) \
(__builtin_constant_p (private) \
? ((private) == 0 \
? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \
: (fl)) \
: ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \
& THREAD_GETMEM (THREAD_SELF, header.private_futex))))
# endif
#endif
#define lll_futex_wait(futex, val, private) \
lll_futex_timed_wait (futex, val, NULL, private)
#define lll_futex_timed_wait(futexp, val, timespec, private) \
({ \
INTERNAL_SYSCALL_DECL (__err); \
\
INTERNAL_SYSCALL (futex, __err, 4, (futexp), \
__lll_private_flag (FUTEX_WAIT, private), \
(val), (timespec)); \
})
#define lll_futex_timed_wait_bitset(futexp, val, timespec, clockbit, private) \
({ \
INTERNAL_SYSCALL_DECL (__err); \
int __op = FUTEX_WAIT_BITSET | clockbit; \
\
INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
__lll_private_flag (__op, private), \
(val), (timespec), NULL /* Unused. */, \
FUTEX_BITSET_MATCH_ANY); \
})
#define lll_futex_wake(futexp, nr, private) \
({ \
INTERNAL_SYSCALL_DECL (__err); \
\
INTERNAL_SYSCALL (futex, __err, 4, (futexp), \
__lll_private_flag (FUTEX_WAKE, private), \
(nr), 0); \
})
#define lll_robust_dead(futexv, private) \
do \
{ \
int *__futexp = &(futexv); \
\
atomic_or (__futexp, FUTEX_OWNER_DIED); \
lll_futex_wake (__futexp, 1, private); \
} \
while (0)
/* Returns non-zero if error happened, zero if success. */
#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \
({ \
INTERNAL_SYSCALL_DECL (__err); \
long int __ret; \
\
__ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
__lll_private_flag (FUTEX_CMP_REQUEUE, private),\
(nr_wake), (nr_move), (mutex), (val)); \
INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
})
/* Returns non-zero if error happened, zero if success. */
#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \
({ \
INTERNAL_SYSCALL_DECL (__err); \
long int __ret; \
\
__ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
__lll_private_flag (FUTEX_WAKE_OP, private), \
(nr_wake), (nr_wake2), (futexp2), \
FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \
INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
})
/* Priority Inheritance support. */
#define lll_futex_wait_requeue_pi(futexp, val, mutex, private) \
lll_futex_timed_wait_requeue_pi (futexp, val, NULL, 0, mutex, private)
#define lll_futex_timed_wait_requeue_pi(futexp, val, timespec, clockbit, \
mutex, private) \
({ \
INTERNAL_SYSCALL_DECL (__err); \
int __op = FUTEX_WAIT_REQUEUE_PI | clockbit; \
\
INTERNAL_SYSCALL (futex, __err, 5, (futexp), \
__lll_private_flag (__op, private), \
(val), (timespec), mutex); \
})
#define lll_futex_cmp_requeue_pi(futexp, nr_wake, nr_move, mutex, val, priv) \
({ \
INTERNAL_SYSCALL_DECL (__err); \
long int __ret; \
\
__ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
__lll_private_flag (FUTEX_CMP_REQUEUE_PI, priv),\
(nr_wake), (nr_move), (mutex), (val)); \
INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
})
#define lll_compare_and_swap(futex, oldval, newval, operation) \
do { \
__typeof (futex) __futex = (futex); \
__asm __volatile (" l %1,%0\n" \
"0: " operation "\n" \
" cs %1,%2,%0\n" \
" jl 0b\n" \
"1:" \
: "=Q" (*__futex), "=&d" (oldval), "=&d" (newval) \
: "m" (*__futex) : "cc", "memory" ); \
} while (0)
static inline int
__attribute__ ((always_inline))
__lll_trylock (int *futex)
{
unsigned int old;
__asm __volatile ("cs %0,%3,%1"
: "=d" (old), "=Q" (*futex)
: "0" (0), "d" (1), "m" (*futex) : "cc", "memory" );
return old != 0;
}
#define lll_trylock(futex) __lll_trylock (&(futex))
static inline int
__attribute__ ((always_inline))
__lll_cond_trylock (int *futex)
{
unsigned int old;
__asm __volatile ("cs %0,%3,%1"
: "=d" (old), "=Q" (*futex)
: "0" (0), "d" (2), "m" (*futex) : "cc", "memory" );
return old != 0;
}
#define lll_cond_trylock(futex) __lll_cond_trylock (&(futex))
static inline int
__attribute__ ((always_inline))
__lll_robust_trylock (int *futex, int id)
{
unsigned int old;
__asm __volatile ("cs %0,%3,%1"
: "=d" (old), "=Q" (*futex)
: "0" (0), "d" (id), "m" (*futex) : "cc", "memory" );
return old != 0;
}
#define lll_robust_trylock(futex, id) \
__lll_robust_trylock (&(futex), id)
extern void __lll_lock_wait_private (int *futex) attribute_hidden;
extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden;
static inline void
__attribute__ ((always_inline))
__lll_lock (int *futex, int private)
{
if (__glibc_unlikely (atomic_compare_and_exchange_bool_acq (futex, 1, 0)))
{
if (__builtin_constant_p (private) && private == LLL_PRIVATE)
__lll_lock_wait_private (futex);
else
__lll_lock_wait (futex, private);
}
}
#define lll_lock(futex, private) __lll_lock (&(futex), private)
static inline int
__attribute__ ((always_inline))
__lll_robust_lock (int *futex, int id, int private)
{
int result = 0;
if (__builtin_expect (atomic_compare_and_exchange_bool_acq (futex, id, 0),
0))
result = __lll_robust_lock_wait (futex, private);
return result;
}
#define lll_robust_lock(futex, id, private) \
__lll_robust_lock (&(futex), id, private)
static inline void
__attribute__ ((always_inline))
__lll_cond_lock (int *futex, int private)
{
if (__glibc_unlikely (atomic_compare_and_exchange_bool_acq (futex, 2, 0)))
__lll_lock_wait (futex, private);
}
#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private)
#define lll_robust_cond_lock(futex, id, private) \
__lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private)
extern int __lll_timedlock_wait
(int *futex, const struct timespec *, int private) attribute_hidden;
extern int __lll_robust_timedlock_wait
(int *futex, const struct timespec *, int private) attribute_hidden;
static inline int
__attribute__ ((always_inline))
__lll_timedlock (int *futex, const struct timespec *abstime, int private)
{
int result = 0;
if (__glibc_unlikely (atomic_compare_and_exchange_bool_acq (futex, 1, 0)))
result = __lll_timedlock_wait (futex, abstime, private);
return result;
}
#define lll_timedlock(futex, abstime, private) \
__lll_timedlock (&(futex), abstime, private)
#ifdef ENABLE_LOCK_ELISION
extern int __lll_timedlock_elision
(int *futex, short *adapt_count, const struct timespec *timeout, int private)
attribute_hidden;
# define lll_timedlock_elision(futex, adapt_count, timeout, private) \
__lll_timedlock_elision(&(futex), &(adapt_count), timeout, private)
#endif
static inline int
__attribute__ ((always_inline))
__lll_robust_timedlock (int *futex, const struct timespec *abstime,
int id, int private)
{
int result = 0;
if (__builtin_expect (atomic_compare_and_exchange_bool_acq (futex, id, 0),
0))
result = __lll_robust_timedlock_wait (futex, abstime, private);
return result;
}
#define lll_robust_timedlock(futex, abstime, id, private) \
__lll_robust_timedlock (&(futex), abstime, id, private)
#define __lll_unlock(futex, private) \
(void) \
({ int __oldval; \
int __newval = 0; \
int *__futexp = (futex); \
\
lll_compare_and_swap (__futexp, __oldval, __newval, "slr %2,%2"); \
if (__glibc_unlikely (__oldval > 1)) \
lll_futex_wake (__futexp, 1, private); \
})
#define lll_unlock(futex, private) __lll_unlock(&(futex), private)
#define __lll_robust_unlock(futex, private) \
(void) \
({ int __oldval; \
int __newval = 0; \
int *__futexp = (futex); \
\
lll_compare_and_swap (__futexp, __oldval, __newval, "slr %2,%2"); \
if (__glibc_unlikely (__oldval & FUTEX_WAITERS)) \
lll_futex_wake (__futexp, 1, private); \
})
#define lll_robust_unlock(futex, private) \
__lll_robust_unlock(&(futex), private)
#define lll_islocked(futex) \
(futex != 0)
/* Initializers for lock. */
#define LLL_LOCK_INITIALIZER (0)
#define LLL_LOCK_INITIALIZER_LOCKED (1)
/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
wakeup when the clone terminates. The memory location contains the
thread ID while the clone is running and is reset to zero
afterwards. */
#define __lll_wait_tid(ptid) \
do \
{ \
int __tid; \
\
while ((__tid = *ptid) != 0) \
lll_futex_wait (ptid, __tid, LLL_SHARED); \
} \
while (0)
#define lll_wait_tid(tid) __lll_wait_tid(&(tid))
extern int __lll_timedwait_tid (int *, const struct timespec *)
attribute_hidden;
#define lll_timedwait_tid(tid, abstime) \
({ \
int __res = 0; \
if ((tid) != 0) \
__res = __lll_timedwait_tid (&(tid), (abstime)); \
__res; \
})
#ifdef ENABLE_LOCK_ELISION
extern int __lll_lock_elision (int *futex, short *adapt_count, int private)
attribute_hidden;
extern int __lll_unlock_elision(int *futex, int private)
attribute_hidden;
extern int __lll_trylock_elision(int *futex, short *adapt_count)
attribute_hidden;
# define lll_lock_elision(futex, adapt_count, private) \
__lll_lock_elision (&(futex), &(adapt_count), private)
# define lll_unlock_elision(futex, private) \
__lll_unlock_elision (&(futex), private)
# define lll_trylock_elision(futex, adapt_count) \
__lll_trylock_elision(&(futex), &(adapt_count))
#endif
#endif /* lowlevellock.h */

View File

@@ -0,0 +1,63 @@
/* Copyright (C) 2013 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/>.
This is a copy of pthread/pt-longjmp.c made for extending the
jmpbuf structure on System z. */
#include <setjmp.h>
#include <stdlib.h>
#include <bits/wordsize.h>
#include "pthreadP.h"
#include <shlib-compat.h>
#if defined SHARED && SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_19)
/* The __v1 version prototypes are declared in v1-setjmp.h which
cannot be included together with setjmp.h. So we put the
prototypes here manually. */
extern void __v1__libc_siglongjmp (sigjmp_buf env, int val)
__attribute__ ((noreturn));
extern void __v1__libc_longjmp (sigjmp_buf env, int val)
__attribute__ ((noreturn));
void __v1_siglongjmp (sigjmp_buf env, int val)
{
__v1__libc_siglongjmp (env, val);
}
void __v1_longjmp (jmp_buf env, int val)
{
__v1__libc_longjmp (env, val);
}
compat_symbol (libpthread, __v1_longjmp, longjmp, GLIBC_2_0);
compat_symbol (libpthread, __v1_siglongjmp, siglongjmp, GLIBC_2_0);
#endif /* defined SHARED && SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_19)) */
void
__v2_longjmp (jmp_buf env, int val)
{
__libc_longjmp (env, val);
}
void
__v2_siglongjmp (jmp_buf env, int val)
{
__libc_siglongjmp (env, val);
}
versioned_symbol (libpthread, __v2_longjmp, longjmp, GLIBC_2_19);
versioned_symbol (libpthread, __v2_siglongjmp, siglongjmp, GLIBC_2_19);

View File

@@ -0,0 +1,22 @@
/* Copyright (C) 2014 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/>. */
/* The cond lock is not actually elided yet, but we still need to handle
already elided locks. */
#include <elision-conf.h>
#include <nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c>

View File

@@ -0,0 +1,22 @@
/* Elided version of pthread_mutex_lock.
Copyright (C) 2014 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 <elision-conf.h>
#include <force-elision.h>
#include <nptl/pthread_mutex_lock.c>

View File

@@ -0,0 +1,22 @@
/* Elided version of pthread_mutex_timedlock.
Copyright (C) 2014 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 <elision-conf.h>
#include <force-elision.h>
#include <nptl/pthread_mutex_timedlock.c>

View File

@@ -0,0 +1,22 @@
/* Elided version of pthread_mutex_trylock.
Copyright (C) 2014 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 <elision-conf.h>
#include <force-elision.h>
#include <nptl/pthread_mutex_trylock.c>

View File

@@ -0,0 +1,110 @@
/* Copyright (C) 2003-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Martin Schwidefsky <schwidefsky@de.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"
#include <lowlevellock.h>
unsigned long int __fork_generation attribute_hidden;
static void
clear_once_control (void *arg)
{
pthread_once_t *once_control = (pthread_once_t *) arg;
*once_control = 0;
lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
}
int
__pthread_once (once_control, init_routine)
pthread_once_t *once_control;
void (*init_routine) (void);
{
while (1)
{
int oldval;
int newval;
/* Pseudo code:
oldval = *once_control;
if ((oldval & 2) == 0)
{
newval = (oldval & 3) | __fork_generation | 1;
*once_control = newval;
}
Do this atomically. */
__asm __volatile (" l %1,%0\n"
"0: lhi %2,2\n"
" tml %1,2\n"
" jnz 1f\n"
" nr %2,%1\n"
" ahi %2,1\n"
" o %2,%3\n"
" cs %1,%2,%0\n"
" jl 0b\n"
"1:"
: "=Q" (*once_control), "=&d" (oldval), "=&d" (newval)
: "m" (__fork_generation), "m" (*once_control)
: "cc" );
/* Check if the initialized has already been done. */
if ((oldval & 2) != 0)
break;
/* Check if another thread already runs the initializer. */
if ((oldval & 1) != 0)
{
/* Check whether the initializer execution was interrupted
by a fork. */
if (((oldval ^ newval) & -4) == 0)
{
/* Same generation, some other thread was faster. Wait. */
lll_futex_wait (once_control, newval, LLL_PRIVATE);
continue;
}
}
/* This thread is the first here. Do the initialization.
Register a cleanup handler so that in case the thread gets
interrupted the initialization can be restarted. */
pthread_cleanup_push (clear_once_control, once_control);
init_routine ();
pthread_cleanup_pop (0);
/* Add one to *once_control. */
__asm __volatile (" l %1,%0\n"
"0: lr %2,%1\n"
" ahi %2,1\n"
" cs %1,%2,%0\n"
" jl 0b\n"
: "=Q" (*once_control), "=&d" (oldval), "=&d" (newval)
: "m" (*once_control) : "cc" );
/* Wake up all other threads. */
lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
break;
}
return 0;
}
weak_alias (__pthread_once, pthread_once)
hidden_def (__pthread_once)

View File

@@ -0,0 +1,139 @@
/* Copyright (C) 2003-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.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 <sysdep.h>
#include <tls.h>
#ifndef __ASSEMBLER__
# include <nptl/pthreadP.h>
#endif
#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
# undef PSEUDO
# define PSEUDO(name, syscall_name, args) \
.text; \
L(pseudo_cancel): \
cfi_startproc; \
STM_##args \
stm %r12,%r15,48(%r15); \
cfi_offset (%r15, -36); \
cfi_offset (%r14, -40); \
cfi_offset (%r13, -44); \
cfi_offset (%r12, -48); \
lr %r14,%r15; \
ahi %r15,-96; \
cfi_adjust_cfa_offset (96); \
st %r14,0(%r15); \
basr %r13,0; \
0: l %r1,1f-0b(%r13); \
bas %r14,0(%r1,%r13); \
lr %r0,%r2; \
LM_##args \
.if SYS_ify (syscall_name) < 256; \
svc SYS_ify (syscall_name); \
.else; \
lhi %r1,SYS_ify (syscall_name); \
svc 0; \
.endif; \
LR7_##args \
l %r1,2f-0b(%r13); \
lr %r12,%r2; \
lr %r2,%r0; \
bas %r14,0(%r1,%r13); \
lr %r2,%r12; \
lm %r12,%r15,48+96(%r15); \
cfi_endproc; \
j L(pseudo_check); \
1: .long CENABLE-0b; \
2: .long CDISABLE-0b; \
ENTRY(name) \
SINGLE_THREAD_P(%r1) \
jne L(pseudo_cancel); \
.type __##syscall_name##_nocancel,@function; \
.globl __##syscall_name##_nocancel; \
__##syscall_name##_nocancel: \
DO_CALL(syscall_name, args); \
L(pseudo_check): \
lhi %r4,-4095; \
clr %r2,%r4; \
jnl SYSCALL_ERROR_LABEL; \
.size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \
L(pseudo_end):
# ifdef IS_IN_libpthread
# define CENABLE __pthread_enable_asynccancel
# define CDISABLE __pthread_disable_asynccancel
# elif !defined NOT_IN_libc
# define CENABLE __libc_enable_asynccancel
# define CDISABLE __libc_disable_asynccancel
# elif defined IS_IN_librt
# define CENABLE __librt_enable_asynccancel
# define CDISABLE __librt_disable_asynccancel
# else
# error Unsupported library
# endif
#define STM_0 /* Nothing */
#define STM_1 st %r2,8(%r15);
#define STM_2 stm %r2,%r3,8(%r15);
#define STM_3 stm %r2,%r4,8(%r15);
#define STM_4 stm %r2,%r5,8(%r15);
#define STM_5 stm %r2,%r5,8(%r15);
#define STM_6 stm %r2,%r7,8(%r15);
#define LM_0 /* Nothing */
#define LM_1 l %r2,8+96(%r15);
#define LM_2 lm %r2,%r3,8+96(%r15);
#define LM_3 lm %r2,%r4,8+96(%r15);
#define LM_4 lm %r2,%r5,8+96(%r15);
#define LM_5 lm %r2,%r5,8+96(%r15);
#define LM_6 lm %r2,%r5,8+96(%r15); \
cfi_offset (%r7, -68); \
l %r7,96+96(%r15);
#define LR7_0 /* Nothing */
#define LR7_1 /* Nothing */
#define LR7_2 /* Nothing */
#define LR7_3 /* Nothing */
#define LR7_4 /* Nothing */
#define LR7_5 /* Nothing */
#define LR7_6 l %r7,28+96(%r15); \
cfi_restore (%r7);
# ifndef __ASSEMBLER__
# define SINGLE_THREAD_P \
__builtin_expect (THREAD_GETMEM (THREAD_SELF, \
header.multiple_threads) == 0, 1)
# else
# define SINGLE_THREAD_P(reg) \
ear reg,%a0; \
icm reg,15,MULTIPLE_THREADS_OFFSET(reg);
# endif
#elif !defined __ASSEMBLER__
# define SINGLE_THREAD_P (1)
# define NO_CANCELLATION 1
#endif
#ifndef __ASSEMBLER__
# define RTLD_SINGLE_THREAD_P \
__builtin_expect (THREAD_GETMEM (THREAD_SELF, \
header.multiple_threads) == 0, 1)
#endif

View File

@@ -5,3 +5,11 @@ libc {
__frame_state_for; __register_frame_info_table;
}
}
librt {
GLIBC_2.3.3 {
# Changed timer_t.
timer_create; timer_delete; timer_getoverrun; timer_gettime;
timer_settime;
}
}

View File

@@ -0,0 +1,152 @@
/* Copyright (C) 2003-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.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 <sysdep.h>
#include <tls.h>
#ifndef __ASSEMBLER__
# include <nptl/pthreadP.h>
#endif
#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
# undef PSEUDO
# define PSEUDO(name, syscall_name, args) \
.text; \
L(pseudo_cancel): \
cfi_startproc; \
STM_##args \
stmg %r13,%r15,104(%r15); \
cfi_offset (%r15,-40); \
cfi_offset (%r14,-48); \
cfi_offset (%r13,-56); \
lgr %r14,%r15; \
aghi %r15,-160; \
cfi_adjust_cfa_offset (160); \
stg %r14,0(%r15); \
brasl %r14,CENABLE; \
lgr %r0,%r2; \
LM_##args \
.if SYS_ify (syscall_name) < 256; \
svc SYS_ify (syscall_name); \
.else; \
lghi %r1,SYS_ify (syscall_name); \
svc 0; \
.endif; \
LR7_##args \
lgr %r13,%r2; \
lgr %r2,%r0; \
brasl %r14,CDISABLE; \
lgr %r2,%r13; \
lmg %r13,%r15,104+160(%r15); \
cfi_endproc; \
j L(pseudo_check); \
ENTRY(name) \
SINGLE_THREAD_P \
jne L(pseudo_cancel); \
.type __##syscall_name##_nocancel,@function; \
.globl __##syscall_name##_nocancel; \
__##syscall_name##_nocancel: \
DO_CALL(syscall_name, args); \
L(pseudo_check): \
lghi %r4,-4095; \
clgr %r2,%r4; \
jgnl SYSCALL_ERROR_LABEL; \
.size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \
L(pseudo_end):
# ifdef IS_IN_libpthread
# define CENABLE __pthread_enable_asynccancel
# define CDISABLE __pthread_disable_asynccancel
# define __local_multiple_threads __pthread_multiple_threads
# elif !defined NOT_IN_libc
# define CENABLE __libc_enable_asynccancel
# define CDISABLE __libc_disable_asynccancel
# define __local_multiple_threads __libc_multiple_threads
# elif defined IS_IN_librt
# define CENABLE __librt_enable_asynccancel
# define CDISABLE __librt_disable_asynccancel
# else
# error Unsupported library
# endif
#define STM_0 /* Nothing */
#define STM_1 stg %r2,16(%r15);
#define STM_2 stmg %r2,%r3,16(%r15);
#define STM_3 stmg %r2,%r4,16(%r15);
#define STM_4 stmg %r2,%r5,16(%r15);
#define STM_5 stmg %r2,%r5,16(%r15);
#define STM_6 stmg %r2,%r7,16(%r15);
#define LM_0 /* Nothing */
#define LM_1 lg %r2,16+160(%r15);
#define LM_2 lmg %r2,%r3,16+160(%r15);
#define LM_3 lmg %r2,%r4,16+160(%r15);
#define LM_4 lmg %r2,%r5,16+160(%r15);
#define LM_5 lmg %r2,%r5,16+160(%r15);
#define LM_6 lmg %r2,%r5,16+160(%r15); \
cfi_offset (%r7, -104); \
lg %r7,160+160(%r15);
#define LR7_0 /* Nothing */
#define LR7_1 /* Nothing */
#define LR7_2 /* Nothing */
#define LR7_3 /* Nothing */
#define LR7_4 /* Nothing */
#define LR7_5 /* Nothing */
#define LR7_6 lg %r7,56+160(%r15); \
cfi_restore (%r7);
# if defined IS_IN_libpthread || !defined NOT_IN_libc
# ifndef __ASSEMBLER__
extern int __local_multiple_threads attribute_hidden;
# define SINGLE_THREAD_P \
__builtin_expect (__local_multiple_threads == 0, 1)
# else
# define SINGLE_THREAD_P \
larl %r1,__local_multiple_threads; \
icm %r0,15,0(%r1);
# endif
# else
# ifndef __ASSEMBLER__
# define SINGLE_THREAD_P \
__builtin_expect (THREAD_GETMEM (THREAD_SELF, \
header.multiple_threads) == 0, 1)
# else
# define SINGLE_THREAD_P \
ear %r1,%a0; \
sllg %r1,%r1,32; \
ear %r1,%a1; \
icm %r1,15,MULTIPLE_THREADS_OFFSET(%r1);
# endif
# endif
#elif !defined __ASSEMBLER__
# define SINGLE_THREAD_P (1)
# define NO_CANCELLATION 1
#endif
#ifndef __ASSEMBLER__
# define RTLD_SINGLE_THREAD_P \
__builtin_expect (THREAD_GETMEM (THREAD_SELF, \
header.multiple_threads) == 0, 1)
#endif

View File

@@ -0,0 +1 @@
#include <sysdeps/unix/sysv/linux/x86_64/timer_create.c>

View File

@@ -0,0 +1 @@
#include <sysdeps/unix/sysv/linux/x86_64/timer_delete.c>

View File

@@ -0,0 +1 @@
#include <sysdeps/unix/sysv/linux/x86_64/timer_getoverr.c>

View File

@@ -0,0 +1 @@
#include <sysdeps/unix/sysv/linux/x86_64/timer_gettime.c>

View File

@@ -0,0 +1 @@
#include <sysdeps/unix/sysv/linux/x86_64/timer_settime.c>