From b33e61633a10a233510f6f49b97b7e2ad15c7311 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 11 Mar 2003 09:30:37 +0000 Subject: * sysdeps/generic/dl-sysdep.c (_dl_important_hwcaps): If CNT == 1, allocate space even for the trailing '/'. Reported by John Reiser . * sysdeps/unix/sysv/linux/ia64/sysdep.h (LOAD_ARGS_6, ASM_ARGS_6, ASM_CLOBBERS_6): Define. (ASM_CLOBBERS_5): Use ASM_CLOBBERS_6. * sysdeps/unix/sysv/linux/ia64/clone2.S (__clone2): Reorder arguments to match IA-32 order. * sysdeps/unix/sysv/linux/i386/clone.S: Fix comment. --- .../unix/sysv/linux/ia64/bits/pthreadtypes.h | 153 +++++++++++++ nptl/sysdeps/unix/sysv/linux/ia64/bits/semaphore.h | 39 ++++ nptl/sysdeps/unix/sysv/linux/ia64/createthread.c | 26 +++ nptl/sysdeps/unix/sysv/linux/ia64/fork.c | 31 +++ .../unix/sysv/linux/ia64/libc-lowlevellock.c | 19 ++ .../unix/sysv/linux/ia64/libc-lowlevelmutex.c | 21 ++ nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.c | 85 +++++++ nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h | 251 +++++++++++++++++++++ nptl/sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c | 100 ++++++++ nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c | 108 +++++++++ nptl/sysdeps/unix/sysv/linux/ia64/pt-vfork.S | 44 ++++ nptl/sysdeps/unix/sysv/linux/ia64/pthread_once.c | 97 ++++++++ nptl/sysdeps/unix/sysv/linux/ia64/sem_post.c | 51 +++++ nptl/sysdeps/unix/sysv/linux/ia64/sem_timedwait.c | 91 ++++++++ nptl/sysdeps/unix/sysv/linux/ia64/sem_trywait.c | 50 ++++ nptl/sysdeps/unix/sysv/linux/ia64/sem_wait.c | 63 ++++++ nptl/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h | 115 ++++++++++ 17 files changed, 1344 insertions(+) create mode 100644 nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h create mode 100644 nptl/sysdeps/unix/sysv/linux/ia64/bits/semaphore.h create mode 100644 nptl/sysdeps/unix/sysv/linux/ia64/createthread.c create mode 100644 nptl/sysdeps/unix/sysv/linux/ia64/fork.c create mode 100644 nptl/sysdeps/unix/sysv/linux/ia64/libc-lowlevellock.c create mode 100644 nptl/sysdeps/unix/sysv/linux/ia64/libc-lowlevelmutex.c create mode 100644 nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.c create mode 100644 nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h create mode 100644 nptl/sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c create mode 100644 nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c create mode 100644 nptl/sysdeps/unix/sysv/linux/ia64/pt-vfork.S create mode 100644 nptl/sysdeps/unix/sysv/linux/ia64/pthread_once.c create mode 100644 nptl/sysdeps/unix/sysv/linux/ia64/sem_post.c create mode 100644 nptl/sysdeps/unix/sysv/linux/ia64/sem_timedwait.c create mode 100644 nptl/sysdeps/unix/sysv/linux/ia64/sem_trywait.c create mode 100644 nptl/sysdeps/unix/sysv/linux/ia64/sem_wait.c create mode 100644 nptl/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (limited to 'nptl/sysdeps/unix/sysv/linux/ia64') diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h new file mode 100644 index 0000000000..ebe2818d4b --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h @@ -0,0 +1,153 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#define __SIZEOF_PTHREAD_ATTR_T 56 +#define __SIZEOF_PTHREAD_MUTEX_T 40 +#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +#define __SIZEOF_PTHREAD_COND_T 48 +#define __SIZEOF_PTHREAD_CONDATTR_T 4 +#define __SIZEOF_PTHREAD_RWLOCK_T 56 +#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +#define __SIZEOF_PTHREAD_BARRIER_T 32 +#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 + + +/* Thread identifiers. The structure of the attribute type is not + exposed on purpose. */ +typedef struct __opaque_pthread *pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +/* Data structures for mutex handling. The structure of the attribute + type is not exposed on purpose. */ +typedef union +{ + struct + { + int __lock; + unsigned int __count; + struct pthread *__owner; + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; + } __data; + char __size[__SIZEOF_PTHREAD_MUTEX_T]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; + long int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling. The structure of + the attribute type is not exposed on purpose. */ +typedef union +{ + struct + { + int __lock; + unsigned long long int __total_seq; + unsigned long long int __wakeup_seq; + unsigned long long int __woken_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + long int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#ifdef __USE_UNIX98 +/* Data structure for read-write lock variable handling. The + structure of the attribute type is not exposed on purpose. */ +typedef union +{ +struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + pthread_t __writer; + unsigned long int __pad1; + unsigned long int __pad2; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned int __flags; + } __data; + char __size[__SIZEOF_PTHREAD_RWLOCK_T]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; + long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type. The structure of the type is + deliberately not exposed. */ +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIER_T]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; + int __align; +} pthread_barrierattr_t; +#endif + + +#endif /* bits/pthreadtypes.h */ diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/bits/semaphore.h b/nptl/sysdeps/unix/sysv/linux/ia64/bits/semaphore.h new file mode 100644 index 0000000000..cfb9c31e7e --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/ia64/bits/semaphore.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEMAPHORE_H +# error "Never use directly; include instead." +#endif + + +#define __SIZEOF_SEM_T 32 + + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX ((int) ((~0u) >> 1)) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/createthread.c b/nptl/sysdeps/unix/sysv/linux/ia64/createthread.c new file mode 100644 index 0000000000..8ac06e8101 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/ia64/createthread.c @@ -0,0 +1,26 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek . + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Value passed to 'clone' for initialization of the thread register. */ +#define TLS_VALUE (pd + 1) + +#define ARCH_CLONE __clone2 + +/* Get the real implementation. */ +#include diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/fork.c b/nptl/sysdeps/unix/sysv/linux/ia64/fork.c new file mode 100644 index 0000000000..b8d00bd98a --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/ia64/fork.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +#define ARCH_FORK() \ + INLINE_SYSCALL (clone2, 6, \ + CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, \ + NULL, 0, &THREAD_SELF->tid, NULL, NULL) + +#include "../fork.c" diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/libc-lowlevellock.c b/nptl/sysdeps/unix/sysv/linux/ia64/libc-lowlevellock.c new file mode 100644 index 0000000000..58b4832f34 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/ia64/libc-lowlevellock.c @@ -0,0 +1,19 @@ +/* Copyright (C) 2003 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Not needed. lll_mutex_* implementation is the same as lll_*. */ diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/libc-lowlevelmutex.c b/nptl/sysdeps/unix/sysv/linux/ia64/libc-lowlevelmutex.c new file mode 100644 index 0000000000..b2bf0cf862 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/ia64/libc-lowlevelmutex.c @@ -0,0 +1,21 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* No difference to lowlevelmutex.c */ +#include "lowlevelmutex.c" diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.c b/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.c new file mode 100644 index 0000000000..651fb88598 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.c @@ -0,0 +1,85 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +int +lll_unlock_wake_cb (futex) + int *futex; +{ + int oldval; + int val = *futex; + + do + oldval = val; + while ((val = lll_compare_and_swap (futex, oldval, 0)) != oldval); + if (oldval > 1) + lll_futex_wake (futex, 1); + return 0; +} +hidden_proto (lll_unlock_wake_cb) + + +int +___lll_timedwait_tid (ptid, abstime) + int *ptid; + const struct timespec *abstime; +{ + int tid; + + if (abstime == NULL || abstime->tv_nsec >= 1000000000) + return EINVAL; + + /* Repeat until thread terminated. */ + while ((tid = *ptid) != 0) + { + /* Get current time. */ + struct timeval tv; + gettimeofday (&tv, NULL); + + /* Determine relative timeout. */ + struct timespec rt; + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + rt.tv_sec--; + } + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait until thread terminates. */ + int err = lll_futex_timed_wait (ptid, tid, &rt); + + /* Woken due to timeout? */ + if (err == -ETIMEDOUT) + /* Yes. */ + return ETIMEDOUT; + } + + return 0; +} + +hidden_proto (___lll_timedwait_tid) diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h new file mode 100644 index 0000000000..8fcc7f15ac --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/ia64/lowlevellock.h @@ -0,0 +1,251 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#include +#include +#include +#include + +#define SYS_futex 1230 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +/* Initializer for compatibility lock. */ +#define LLL_MUTEX_LOCK_INITIALIZER (0) + +#define lll_futex_clobbers \ + "out4", "out5", "out6", "out7", \ + /* Non-stacked integer registers, minus r8, r10, r15. */ \ + "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18", \ + "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", \ + "r28", "r29", "r30", "r31", \ + /* Predicate registers. */ \ + "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \ + /* Non-rotating fp registers. */ \ + "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \ + /* Branch registers. */ \ + "b6", "b7", \ + "memory" + +#define lll_futex_wait(futex, val) \ + ({ \ + register unsigned long int __o0 asm ("out0") \ + = (unsigned long int) (futex); \ + register unsigned long int __o1 asm ("out1") = FUTEX_WAIT; \ + register unsigned long int __o2 asm ("out2") = (unsigned long int) (val);\ + register unsigned long int __o3 asm ("out3") = 0ul; \ + register unsigned long int __r8 asm ("r8"); \ + register unsigned long int __r10 asm ("r10"); \ + register unsigned long int __r15 asm ("r15") = SYS_futex; \ + \ + __asm __volatile ("break %3;;" \ + : "=r" (__r8), "=r" (__r10), "=r" (__r15) \ + : "i" (0x100000), "2" (__r15), "r" (__o0), "r" (__o1), \ + "r" (__o2), "r" (__o3) \ + : lll_futex_clobbers); \ + __r10 == -1 ? -__r8 : __r8; \ + }) + + +#define lll_futex_timed_wait(futex, val, timespec) \ + ({ \ + register unsigned long int __o0 asm ("out0") \ + = (unsigned long int) (futex); \ + register unsigned long int __o1 asm ("out1") = FUTEX_WAIT; \ + register unsigned long int __o2 asm ("out2") = (unsigned long int) (val);\ + register unsigned long int __o3 asm ("out3") \ + = (unsigned long int) (timespec); \ + register unsigned long int __r8 asm ("r8"); \ + register unsigned long int __r10 asm ("r10"); \ + register unsigned long int __r15 asm ("r15") = SYS_futex; \ + \ + __asm __volatile ("break %3;;" \ + : "=r" (__r8), "=r" (__r10), "=r" (__r15) \ + : "i" (0x100000), "2" (__r15), "r" (__o0), "r" (__o1), \ + "r" (__o2), "r" (__o3) \ + : lll_futex_clobbers); \ + __r10 == -1 ? -__r8 : __r8; \ + }) + + +#define lll_futex_wake(futex, nr) \ + ({ \ + register unsigned long int __o0 asm ("out0") \ + = (unsigned long int) (futex); \ + register unsigned long int __o1 asm ("out1") = FUTEX_WAKE; \ + register unsigned long int __o2 asm ("out2") = (unsigned long int) (nr); \ + register unsigned long int __r8 asm ("r8"); \ + register unsigned long int __r10 asm ("r10"); \ + register unsigned long int __r15 asm ("r15") = SYS_futex; \ + \ + __asm __volatile ("break %3;;" \ + : "=r" (__r8), "=r" (__r10), "=r" (__r15) \ + : "i" (0x100000), "2" (__r15), "r" (__o0), "r" (__o1), \ + "r" (__o2) \ + : "out3", lll_futex_clobbers); \ + __r10 == -1 ? -__r8 : __r8; \ + }) + +#define lll_compare_and_swap(futex, oldval, newval) \ + __sync_val_compare_and_swap_si ((futex), (oldval), (newval)) + +static inline int +__attribute__ ((always_inline)) +__lll_mutex_trylock (int *futex) +{ + return lll_compare_and_swap (futex, 0, 1) != 0; +} +#define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex)) + + +extern void ___lll_mutex_lock (int *, int) attribute_hidden; + + +static inline void +__attribute__ ((always_inline)) +__lll_mutex_lock (int *futex) +{ + int oldval; + int val = *futex; + + do + oldval = val; + while ((val = lll_compare_and_swap (futex, oldval, oldval + 1)) != oldval); + if (oldval > 0) + ___lll_mutex_lock (futex, oldval + 1); +} +#define lll_mutex_lock(futex) __lll_mutex_lock (&(futex)) + + +extern int ___lll_mutex_timedlock (int *, const struct timespec *, int) + attribute_hidden; + + +static inline int +__attribute__ ((always_inline)) +__lll_mutex_timedlock (int *futex, const struct timespec *abstime) +{ + int oldval; + int val = *futex; + int result = 0; + + do + oldval = val; + while ((val = lll_compare_and_swap (futex, oldval, oldval + 1)) != oldval); + if (oldval > 0) + result = ___lll_mutex_timedlock (futex, abstime, oldval + 1); + + return result; +} +#define lll_mutex_timedlock(futex, abstime) \ + __lll_mutex_timedlock (&(futex), abstime) + + +static inline void +__attribute__ ((always_inline)) +__lll_mutex_unlock (int *futex) +{ + int oldval; + int val = *futex; + + do + oldval = val; + while ((val = lll_compare_and_swap (futex, oldval, 0)) != oldval); + if (oldval > 1) + lll_futex_wake (futex, 1); +} +#define lll_mutex_unlock(futex) __lll_mutex_unlock(&(futex)) + +#define lll_mutex_islocked(futex) \ + (futex != 0) + + +/* We have a separate internal lock implementation which is not tied + to binary compatibility. We can use the lll_mutex_*. */ + +/* Type for lock object. */ +typedef int lll_lock_t; + +extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; + +/* Initializers for lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) + +#define lll_trylock(futex) lll_mutex_trylock (futex) +#define lll_lock(futex) lll_mutex_lock (futex) +#define lll_unlock(futex) lll_mutex_unlock (futex) +#define lll_islocked(futex) lll_mutex_islocked (futex) + + +/* The kernel notifies a process with uses CLONE_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. */ +static inline void +__attribute__ ((always_inline)) +__lll_wait_tid (int *ptid) +{ + int tid; + + while ((tid = *ptid) != 0) + lll_futex_wait (ptid, tid); +} +#define lll_wait_tid(tid) __lll_wait_tid(&(tid)) + + +extern int ___lll_timedwait_tid (int *, const struct timespec *) + attribute_hidden; +static inline int +__attribute__ ((always_inline)) +__lll_timedwait_tid (int *ptid, const struct timespec *abstime) +{ + if (*ptid == 0) + return 0; + + return ___lll_timedwait_tid (ptid, abstime); +} +#define lll_timedwait_tid(tid, abstime) __lll_timedwait_tid (&(tid), abstime) + + +/* Conditional variable handling. */ + +extern void __lll_cond_wait (pthread_cond_t *cond) + attribute_hidden; +extern int __lll_cond_timedwait (pthread_cond_t *cond, + const struct timespec *abstime) + attribute_hidden; +extern void __lll_cond_wake (pthread_cond_t *cond) + attribute_hidden; +extern void __lll_cond_broadcast (pthread_cond_t *cond) + attribute_hidden; + +#define lll_cond_wait(cond) \ + __lll_cond_wait (cond) +#define lll_cond_timedwait(cond, abstime) \ + __lll_cond_timedwait (cond, abstime) +#define lll_cond_wake(cond) \ + __lll_cond_wake (cond) +#define lll_cond_broadcast(cond) \ + __lll_cond_broadcast (cond) + +#endif /* lowlevellock.h */ diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c b/nptl/sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c new file mode 100644 index 0000000000..7ab67ca56c --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c @@ -0,0 +1,100 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +void +___lll_mutex_lock (futex, newval) + int *futex; + int newval; +{ + int oldval, val; + + do + { + lll_futex_wait (futex, newval); + val = *futex; + do + oldval = val; + while ((val = lll_compare_and_swap (futex, oldval, oldval + 1)) + != oldval); + newval = val + 1; + } + while (val != 0); + + *futex = 2; +} +hidden_proto (___lll_mutex_lock) + + +int +___lll_mutex_timedlock (futex, abstime, newval) + int *futex; + const struct timespec *abstime; + int newval; +{ + /* Reject invalid timeouts. */ + if (abstime->tv_nsec >= 1000000000) + return EINVAL; + + int oldval, val; + do + { + /* Get the current time. */ + struct timeval tv; + gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + struct timespec rt; + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait. */ + int err = lll_futex_timed_wait (futex, newval, &rt); + + /* If timed out return with an appropriate error. */ + if (err == -ETIMEDOUT) + return ETIMEDOUT; + + val = *futex; + do + oldval = val; + while ((val = lll_compare_and_swap (futex, oldval, oldval + 1)) + != oldval); + newval = val + 1; + } + while (val != 0); + + *futex = 2; + + return 0; +} +hidden_proto (___lll_mutex_timedlock) diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c b/nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c new file mode 100644 index 0000000000..6155183be3 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/ia64/pt-initfini.c @@ -0,0 +1,108 @@ +/* Special .init and .fini section support for ia64. NPTL version. + Copyright (C) 2000, 2001, 2002, 2003 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +__asm__ ("\n\ +\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ + .section .init\n\ + .align 16\n\ + .global _init#\n\ + .proc _init#\n\ +_init:\n\ + alloc r34 = ar.pfs, 0, 3, 0, 0\n\ + mov r32 = r12\n\ + mov r33 = b0\n\ + adds r12 = -16, r12\n\ + ;;\n\ +/* we could use r35 to save gp, but we use the stack since that's what\n\ + * all the other init routines will do --davidm 00/04/05 */\n\ + st8 [r12] = gp, -16\n\ + br.call.sptk.many b0 = __pthread_initialize_minimal_internal# ;;\n\ + ;;\n\ + adds r12 = 16, r12\n\ + ;;\n\ + ld8 gp = [r12]\n\ + ;;\n\ + .align 16\n\ + .endp _init#\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ + .section .init\n\ + .regstk 0,2,0,0\n\ + mov r12 = r32\n\ + mov ar.pfs = r34\n\ + mov b0 = r33\n\ + br.ret.sptk.many b0\n\ + .endp _init#\n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ + .section .fini\n\ + .align 16\n\ + .global _fini#\n\ + .proc _fini#\n\ +_fini:\n\ + alloc r34 = ar.pfs, 0, 3, 0, 0\n\ + mov r32 = r12\n\ + mov r33 = b0\n\ + adds r12 = -16, r12\n\ + ;;\n\ + .align 16\n\ + .endp _fini#\n\ +\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ + .section .fini\n\ + mov r12 = r32\n\ + mov ar.pfs = r34\n\ + mov b0 = r33\n\ + br.ret.sptk.many b0\n\ + .endp _fini#\n\ +\n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\n\ + .weak __gmon_start__#\n\ +"); diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/pt-vfork.S b/nptl/sysdeps/unix/sysv/linux/ia64/pt-vfork.S new file mode 100644 index 0000000000..7be80e9033 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/ia64/pt-vfork.S @@ -0,0 +1,44 @@ +/* Copyright (C) 2000, 2002, 2003 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#include +#define _SIGNAL_H +#include + +/* The following are defined in linux/sched.h, which unfortunately */ +/* is not safe for inclusion in an assembly file. */ +#define CLONE_VM 0x00000100 /* set if VM shared between processes */ +#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */ + +/* pid_t vfork(void); */ +/* Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0) */ + +ENTRY(__vfork) + alloc r2=ar.pfs,0,0,2,0 + mov out0=CLONE_VM+CLONE_VFORK+SIGCHLD + mov out1=0 /* Standard sp value. */ + ;; + DO_CALL (SYS_ify (clone)) + cmp.eq p6,p0=-1,r10 + ;; +(p6) br.cond.spnt.few __syscall_error + ret +PSEUDO_END(__vfork) + +weak_alias (__vfork, vfork) diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/pthread_once.c b/nptl/sysdeps/unix/sysv/linux/ia64/pthread_once.c new file mode 100644 index 0000000000..e5cb6132d9 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/ia64/pthread_once.c @@ -0,0 +1,97 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include + + +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); +} + + +int +__pthread_once (once_control, init_routine) + pthread_once_t *once_control; + void (*init_routine) (void); +{ + while (1) + { + int oldval, val, newval; + + val = *once_control; + do + { + /* Check if the initialized has already been done. */ + if ((val & 2) != 0) + return 0; + + oldval = val; + newval = (oldval & 3) | __fork_generation | 1; + } + while ((val = lll_compare_and_swap (once_control, oldval, newval)) + != oldval); + + /* 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); + 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. */ + val = *once_control; + do + oldval = val; + while ((val = lll_compare_and_swap (once_control, oldval, oldval + 1)) + != oldval); + + /* Wake up all other threads. */ + lll_futex_wake (once_control, INT_MAX); + break; + } + + return 0; +} +weak_alias (__pthread_once, pthread_once) +strong_alias (__pthread_once, __pthread_once_internal) diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/sem_post.c b/nptl/sysdeps/unix/sysv/linux/ia64/sem_post.c new file mode 100644 index 0000000000..5a7596288b --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/ia64/sem_post.c @@ -0,0 +1,51 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#include + + +int +__new_sem_post (sem_t *sem) +{ + int oldval, val; + int err; + + val = *(int *) sem; + do + oldval = val; + while ((val = lll_compare_and_swap ((int *) sem, oldval, oldval + 1)) + != oldval); + err = lll_futex_wake ((int *) sem, oldval + 1); + if (err < 0) + { + __set_errno (-err); + return -1; + } + return 0; +} +versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1); +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +strong_alias (__new_sem_post, __old_sem_post) +compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0); +#endif diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/ia64/sem_timedwait.c new file mode 100644 index 0000000000..85b4e3ce5c --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/ia64/sem_timedwait.c @@ -0,0 +1,91 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#include + + +int +sem_timedwait (sem, abstime) + sem_t *sem; + const struct timespec *abstime; +{ + int oldval, val; + + val = *(int *) sem; + do + { + while (__builtin_expect (val == 0, 0)) + { + /* Check for invalid timeout values. */ + if (abstime->tv_nsec >= 1000000000) + { + __set_errno (EINVAL); + return -1; + } + + /* Get the current time. */ + struct timeval tv; + (void) gettimeofday(&tv, NULL); + + /* Compute the relative timeout. */ + struct timespec rt; + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + /* Already timed out. */ + if (rt.tv_sec < 0) + { + __set_errno (ETIMEDOUT); + return -1; + } + + /* Do wait. */ + int err = lll_futex_timed_wait ((int *) sem, 0, &rt); + + /* Returned after timing out? */ + if (err == -ETIMEDOUT) + { + __set_errno (ETIMEDOUT); + return -1; + } + + /* Handle EINTR. */ + if (err != 0 && err != -EWOULDBLOCK) + { + __set_errno (-err); + return -1; + } + + val = *(int *) sem; + } + oldval = val; + } + while ((val = lll_compare_and_swap ((int *) sem, oldval, oldval - 1)) + != oldval); + return 0; +} diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/sem_trywait.c b/nptl/sysdeps/unix/sysv/linux/ia64/sem_trywait.c new file mode 100644 index 0000000000..a07d3468a3 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/ia64/sem_trywait.c @@ -0,0 +1,50 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#include + + +int +__new_sem_trywait (sem_t *sem) +{ + int oldval, val = *(int *) sem; + + do + { + if (__builtin_expect (val == 0, 0)) + { + __set_errno (EAGAIN); + return -1; + } + oldval = val; + } + while ((val = lll_compare_and_swap ((int *) sem, oldval, oldval - 1)) + != oldval); + return 0; +} +versioned_symbol (libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1); +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +strong_alias (__new_sem_trywait, __old_sem_trywait) +compat_symbol (libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0); +#endif diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/ia64/sem_wait.c new file mode 100644 index 0000000000..5409237513 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/ia64/sem_wait.c @@ -0,0 +1,63 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#include + + +int +__new_sem_wait (sem_t *sem) +{ + int oldval, val; + + /* Atomically decrement semaphore counter if it is > 0. */ + val = *(int *) sem; + do + { + while (__builtin_expect (val == 0, 0)) + { + /* Do wait. */ + int err = lll_futex_wait ((int *) sem, 0); + + /* Handle EINTR. */ + if (err != 0 && err != -EWOULDBLOCK) + { + __set_errno (-err); + return -1; + } + + val = *(int *) sem; + } + oldval = val; + } + while ((val = lll_compare_and_swap ((int *) sem, oldval, oldval - 1)) + != oldval); + + return 0; +} + +versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1); +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +strong_alias (__new_sem_wait, __old_sem_wait) +compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0); +#endif diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h new file mode 100644 index 0000000000..62c693c3b1 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h @@ -0,0 +1,115 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ +.text; \ +ENTRY (name) \ + adds r14 = MULTIPLE_THREADS_OFFSET, r13;; \ + ld4 r14 = [r14]; \ + mov r15 = SYS_ify(syscall_name);; \ + cmp4.ne p6, p7 = 0, r14; \ +(p6) br.cond.spnt .Lpseudo_cancel;; \ + break __BREAK_SYSCALL;; \ + cmp.eq p6,p0=-1,r10; \ +(p6) br.cond.spnt.few __syscall_error; \ + ret;; \ +.Lpseudo_cancel: \ + .prologue; \ + .regstk args, 5, args, 0; \ + .save ar.pfs, loc0; \ + alloc loc0 = ar.pfs, args, 5, args, 0; \ + .save rp, loc1; \ + mov loc1 = rp;; \ + .body; \ + CENABLE;; \ + mov loc2 = r8; \ + COPY_ARGS_##args \ + mov r15 = SYS_ify(syscall_name); \ + break __BREAK_SYSCALL;; \ + mov loc3 = r8; \ + mov loc4 = r10; \ + mov out0 = loc2; \ + CDISABLE;; \ + cmp.eq p6,p0=-1,loc4; \ +(p6) br.cond.spnt.few __syscall_error_##args; \ + mov r8 = loc3; \ + mov rp = loc1; \ + mov ar.pfs = loc0; \ +.Lpseudo_end: \ + ret; \ + .endp name; \ +.section .gnu.linkonce.t.__syscall_error_##args, "ax"; \ + .align 32; \ + .proc __syscall_error_##args; \ + .global __syscall_error_##args; \ + .hidden __syscall_error_##args; \ +__syscall_error_##args: \ + .prologue; \ + .regstk args, 5, args, 0; \ + .save ar.pfs, loc0; \ + .save rp, loc1; \ + .body; \ + mov loc4 = r1;; \ + br.call.sptk.many b0 = __errno_location;; \ + st4 [r8] = loc3; \ + mov r1 = loc4; \ + mov rp = loc1; \ + mov r8 = -1; \ + mov ar.pfs = loc0 + +# ifdef IS_IN_libpthread +# define CENABLE br.call.sptk.many b0 = __pthread_enable_asynccancel +# define CDISABLE br.call.sptk.many b0 = __pthread_disable_asynccancel +# else +# define CENABLE br.call.sptk.many b0 = __libc_enable_asynccancel +# define CDISABLE br.call.sptk.many b0 = __libc_disable_asynccancel +# endif + +#define COPY_ARGS_0 /* Nothing */ +#define COPY_ARGS_1 COPY_ARGS_0 mov out0 = in0; +#define COPY_ARGS_2 COPY_ARGS_1 mov out1 = in1; +#define COPY_ARGS_3 COPY_ARGS_2 mov out2 = in2; +#define COPY_ARGS_4 COPY_ARGS_3 mov out3 = in3; +#define COPY_ARGS_5 COPY_ARGS_4 mov out4 = in4; +#define COPY_ARGS_6 COPY_ARGS_5 mov out5 = in5; +#define COPY_ARGS_7 COPY_ARGS_6 mov out6 = in6; + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + adds r14 = MULTIPLE_THREADS_OFFSET, r13 ;; ld4 r14 = [r14] ;; cmp4.ne p6, p7 = 0, r14 +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif -- cgit 1.4.1