]> sourceware.org Git - glibc.git/commitdiff
Update.
authorUlrich Drepper <drepper@redhat.com>
Tue, 1 Jul 2003 20:23:15 +0000 (20:23 +0000)
committerUlrich Drepper <drepper@redhat.com>
Tue, 1 Jul 2003 20:23:15 +0000 (20:23 +0000)
2003-07-01  Richard Henderson  <rth@redhat.com>

* sysdeps/alpha/elf/pt-initfini.c: New file.
* sysdeps/alpha/pthread_spin_lock.S: New file.
* sysdeps/alpha/pthread_spin_trylock.S: New file.
* sysdeps/alpha/pthreaddef.h: New file.
* sysdeps/alpha/td_ta_map_lwp2thr.c: New file.
* sysdeps/alpha/tls.h: New file.
* sysdeps/unix/sysv/linux/alpha/Makefile: New file.
* sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: New file.
* sysdeps/unix/sysv/linux/alpha/bits/semaphore.h: New file.
* sysdeps/unix/sysv/linux/alpha/createthread.c: New file.
* sysdeps/unix/sysv/linux/alpha/fork.c: New file.
* sysdeps/unix/sysv/linux/alpha/lowlevellock.h: New file.
* sysdeps/unix/sysv/linux/alpha/pt-vfork.S: New file.
* sysdeps/unix/sysv/linux/alpha/pthread_once.c: New file.
* sysdeps/unix/sysv/linux/alpha/sem_post.c: New file.
* sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h: New file.

17 files changed:
nptl/ChangeLog
nptl/sysdeps/alpha/elf/pt-initfini.c [new file with mode: 0644]
nptl/sysdeps/alpha/pthread_spin_lock.S [new file with mode: 0644]
nptl/sysdeps/alpha/pthread_spin_trylock.S [new file with mode: 0644]
nptl/sysdeps/alpha/pthreaddef.h [new file with mode: 0644]
nptl/sysdeps/alpha/td_ta_map_lwp2thr.c [new file with mode: 0644]
nptl/sysdeps/alpha/tls.h [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/alpha/Makefile [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/alpha/createthread.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/alpha/fork.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/alpha/pt-vfork.S [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/alpha/sem_post.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h [new file with mode: 0644]

index 509f23a58bffed149a55443a0d0b1cf7e057bfaf..4a976c4555e49ccaf971e2560ae19125dfe5345a 100644 (file)
@@ -1,3 +1,22 @@
+2003-07-01  Richard Henderson  <rth@redhat.com>
+
+       * sysdeps/alpha/elf/pt-initfini.c: New file.
+       * sysdeps/alpha/pthread_spin_lock.S: New file.
+       * sysdeps/alpha/pthread_spin_trylock.S: New file.
+       * sysdeps/alpha/pthreaddef.h: New file.
+       * sysdeps/alpha/td_ta_map_lwp2thr.c: New file.
+       * sysdeps/alpha/tls.h: New file.
+       * sysdeps/unix/sysv/linux/alpha/Makefile: New file.
+       * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: New file.
+       * sysdeps/unix/sysv/linux/alpha/bits/semaphore.h: New file.
+       * sysdeps/unix/sysv/linux/alpha/createthread.c: New file.
+       * sysdeps/unix/sysv/linux/alpha/fork.c: New file.
+       * sysdeps/unix/sysv/linux/alpha/lowlevellock.h: New file.
+       * sysdeps/unix/sysv/linux/alpha/pt-vfork.S: New file.
+       * sysdeps/unix/sysv/linux/alpha/pthread_once.c: New file.
+       * sysdeps/unix/sysv/linux/alpha/sem_post.c: New file.
+       * sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h: New file.
+
 2003-07-01  Ulrich Drepper  <drepper@redhat.com>
 
        * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Add correct
diff --git a/nptl/sysdeps/alpha/elf/pt-initfini.c b/nptl/sysdeps/alpha/elf/pt-initfini.c
new file mode 100644 (file)
index 0000000..d48c571
--- /dev/null
@@ -0,0 +1,93 @@
+/* Special .init and .fini section support for Alpha.  NPTL version.
+   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.  */
+
+/* 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.
+
+   This differs from what would be generated by the generic code in that
+   we save and restore the GP within the function.  In order for linker
+   relaxation to work, the value in the GP register on exit from a function
+   must be valid for the function entry point.  Normally, a function is
+   contained within one object file and this is not an issue, provided
+   that the function reloads the gp after making any function calls.
+   However, _init and _fini are constructed from pieces of many object
+   files, all of which may have different GP values.  So we must reload
+   the GP value from crti.o in crtn.o.  */
+
+__asm__ ("                                             \n\
+#include \"defs.h\"                                    \n\
+                                                       \n\
+/*@HEADER_ENDS*/                                       \n\
+                                                       \n\
+/*@_init_PROLOG_BEGINS*/                               \n\
+       .section .init, \"ax\", @progbits               \n\
+       .globl  _init                                   \n\
+       .ent    _init                                   \n\
+_init:                                                 \n\
+       ldgp    $29, 0($27)                             \n\
+       subq    $30, 16, $30                            \n\
+       stq     $26, 0($30)                             \n\
+       stq     $29, 8($30)                             \n\
+       .prologue 1                                     \n\
+       bsr     $26, __pthread_initialize_minimal_internal !samegp \n\
+       .align 3                                        \n\
+       .end    _init                                   \n\
+       .size   _init, 0                                \n\
+/*@_init_PROLOG_ENDS*/                                 \n\
+                                                       \n\
+/*@_init_EPILOG_BEGINS*/                               \n\
+       .section .init, \"ax\", @progbits               \n\
+       ldq     $26, 0($30)                             \n\
+       ldq     $29, 8($30)                             \n\
+       addq    $30, 16, $30                            \n\
+       ret                                             \n\
+/*@_init_EPILOG_ENDS*/                                 \n\
+                                                       \n\
+/*@_fini_PROLOG_BEGINS*/                               \n\
+       .section .fini, \"ax\", @progbits               \n\
+       .globl  _fini                                   \n\
+       .ent    _fini                                   \n\
+_fini:                                                 \n\
+       ldgp    $29, 0($27)                             \n\
+       subq    $30, 16, $30                            \n\
+       stq     $26, 0($30)                             \n\
+       stq     $29, 8($30)                             \n\
+       .prologue 1                                     \n\
+       .align 3                                        \n\
+       .end    _fini                                   \n\
+       .size   _fini, 0                                \n\
+/*@_fini_PROLOG_ENDS*/                                 \n\
+                                                       \n\
+/*@_fini_EPILOG_BEGINS*/                               \n\
+       .section .fini, \"ax\", @progbits               \n\
+       ldq     $26, 0($30)                             \n\
+       ldq     $29, 8($30)                             \n\
+       addq    $30, 16, $30                            \n\
+       ret                                             \n\
+/*@_fini_EPILOG_ENDS*/                                 \n\
+                                                       \n\
+/*@TRAILER_BEGINS*/                                    \n\
+");
diff --git a/nptl/sysdeps/alpha/pthread_spin_lock.S b/nptl/sysdeps/alpha/pthread_spin_lock.S
new file mode 100644 (file)
index 0000000..ce6cd41
--- /dev/null
@@ -0,0 +1,45 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson  <rth@twiddle.net>, 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.  */
+
+
+       .text
+       .align  4
+
+       .globl  pthread_spin_lock
+       .ent    pthread_spin_lock
+pthread_spin_lock:
+       .frame  $sp, 0, $26, 0
+       .prologue 0
+
+0:     ldl_l   $1, 0($16)
+       lda     $2, 1
+       lda     $0, 0
+       bne     $1, 1f
+
+       stl_c   $2, 0($16)
+       beq     $2, 1f
+       mb
+       ret
+
+1:     ldl     $1, 0($16)
+       bne     $1, 1b
+       unop
+       br      0b
+
+       .end    pthread_spin_lock
diff --git a/nptl/sysdeps/alpha/pthread_spin_trylock.S b/nptl/sysdeps/alpha/pthread_spin_trylock.S
new file mode 100644 (file)
index 0000000..0948da6
--- /dev/null
@@ -0,0 +1,46 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson  <rth@twiddle.net>, 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.  */
+
+
+#define _ERRNO_H 1
+#include <bits/errno.h>
+
+       .text
+       .align  4
+
+       .globl  pthread_spin_trylock
+       .ent    pthread_spin_trylock
+pthread_spin_trylock:
+       .frame  $sp, 0, $26, 0
+       .prologue 0
+
+0:     ldl_l   $1, 0($16)
+       lda     $2, 1
+       lda     $0, EBUSY
+       bne     $1, 1f
+
+       stl_c   $2, 0($16)
+       beq     $2, 2f
+       mb
+       lda     $0, 0
+
+1:     ret
+2:     br      0b
+
+       .end    pthread_spin_trylock
diff --git a/nptl/sysdeps/alpha/pthreaddef.h b/nptl/sysdeps/alpha/pthreaddef.h
new file mode 100644 (file)
index 0000000..26c4daf
--- /dev/null
@@ -0,0 +1,38 @@
+/* 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.  */
+
+/* Default stack size.  */
+#define ARCH_STACK_DEFAULT_SIZE        (4 * 1024 * 1024)
+
+/* Required stack pointer alignment at beginning.  The ABI requires 16.  */
+#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)
+
+/* XXX Until we have a better place keep the definitions here.  */
+
+/* While there is no such syscall.  */
+#define __exit_thread_inline(val) \
+  INLINE_SYSCALL (exit, 1, (val))
diff --git a/nptl/sysdeps/alpha/td_ta_map_lwp2thr.c b/nptl/sysdeps/alpha/td_ta_map_lwp2thr.c
new file mode 100644 (file)
index 0000000..b30b10b
--- /dev/null
@@ -0,0 +1,46 @@
+/* Which thread is running on an LWP?  PowerPC version.
+   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.  */
+
+#include "thread_dbP.h"
+#include <tls.h>
+
+
+td_err_e
+td_ta_map_lwp2thr (const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th)
+{
+  LOG ("td_ta_map_lwp2thr");
+
+  /* Test whether the TA parameter is ok.  */
+  if (! ta_ok (ta))
+    return TD_BADTA;
+
+  prgregset_t regs;
+  if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK)
+    return TD_ERR;
+
+  /* The uniq value is stored in slot 33 in recent gdb; it isn't stored
+     anywhere otherwise.  */
+  th->th_unique = ((void *) regs[32]
+                  - TLS_TCB_OFFSET - TLS_TCB_SIZE - TLS_PRE_TCB_SIZE);
+
+  /* Found it.  Now complete the `td_thrhandle_t' object.  */
+  th->th_ta_p = (td_thragent_t *) ta;
+
+  return TD_OK;
+}
diff --git a/nptl/sysdeps/alpha/tls.h b/nptl/sysdeps/alpha/tls.h
new file mode 100644 (file)
index 0000000..1718b3e
--- /dev/null
@@ -0,0 +1,146 @@
+/* Definition for thread-local data handling.  NPTL/Alpha version.
+   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.  */
+
+#ifndef _TLS_H
+#define _TLS_H 1
+
+# include <dl-sysdep.h>
+
+#ifndef __ASSEMBLER__
+# include <stddef.h>
+# include <stdint.h>
+
+/* Type for the dtv.  */
+typedef union dtv
+{
+  size_t counter;
+  void *pointer;
+} dtv_t;
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+#endif /* __ASSEMBLER__ */
+
+
+/* We require TLS support in the tools.  */
+#ifndef HAVE_TLS_SUPPORT
+# error "TLS support is required."
+#endif
+
+/* Signal that TLS support is available.  */
+# define USE_TLS       1
+
+#ifndef __ASSEMBLER__
+
+/* Get system call information.  */
+# include <sysdep.h>
+
+/* The TP points to the start of the thread blocks.  */
+# define TLS_DTV_AT_TP 1
+
+/* Get the thread descriptor definition.  */
+# include <nptl/descr.h>
+
+/* This layout is actually wholly private and not affected by the ABI.
+   Nor does it overlap the pthread data structure, so we need nothing
+   extra here at all.  */
+typedef struct
+{
+  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)))
+
+/* 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).  */
+/* ??? PPC uses offset 0x7000; seems like a good idea for alpha too,
+   but binutils not yet changed to match.  */
+# define TLS_TCB_OFFSET        0
+
+/* 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, secondcall) \
+  (__builtin_set_thread_pointer ((void *) (tcbp) + TLS_TCB_OFFSET), NULL)
+
+/* Return the address of the dtv for the current thread.  */
+# define THREAD_DTV() \
+     (((tcbhead_t *) (__builtin_thread_pointer () - TLS_TCB_OFFSET))[-1].dtv)
+
+/* Return the thread descriptor for the current thread.  */
+# define THREAD_SELF \
+    ((struct pthread *) (__builtin_thread_pointer () \
+                        - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE))
+
+/* Identifier for the current thread.  THREAD_SELF is usable but
+   sometimes more expensive than necessary as in this case.  */
+# define THREAD_ID (__builtin_thread_pointer ())
+
+/* 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))
+
+/* 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
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* tls.h */
diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/Makefile b/nptl/sysdeps/unix/sysv/linux/alpha/Makefile
new file mode 100644 (file)
index 0000000..8c80840
--- /dev/null
@@ -0,0 +1,2 @@
+# pull in __syscall_error routine, __sigprocmask, __syscall_rt_sigaction
+libpthread-routines += ptw-sysdep ptw-sigprocmask ptw-rt_sigaction
diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
new file mode 100644 (file)
index 0000000..bd5ab97
--- /dev/null
@@ -0,0 +1,155 @@
+/* Machine-specific pthread type layouts.  Alpha version.
+   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.  */
+
+#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
+   deliberately not exposed.  */
+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 deliberately not exposed.  */
+typedef union
+{
+  struct
+  {
+    int __lock;
+    unsigned int __count;
+    int __owner;
+    unsigned int __nusers;
+    /* 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];
+  int __align;
+} pthread_mutexattr_t;
+
+
+/* Data structure for conditional variable handling.  The structure of
+   the attribute type is deliberately not exposed.  */
+typedef union
+{
+  struct
+  {
+    int __lock;
+    int __clock;
+    unsigned long long int __total_seq;
+    unsigned long long int __wakeup_seq;
+    unsigned long long int __woken_seq;
+    void *__mutex;
+  } __data;
+  char __size[__SIZEOF_PTHREAD_COND_T];
+  long long int __align;
+} pthread_cond_t;
+
+typedef union
+{
+  char __size[__SIZEOF_PTHREAD_CONDATTR_T];
+  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 deliberately not exposed.  */
+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;
+    int __writer;
+
+    unsigned int __reserved[6];
+    /* 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/alpha/bits/semaphore.h b/nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h
new file mode 100644 (file)
index 0000000..65298fa
--- /dev/null
@@ -0,0 +1,37 @@
+/* Machine-specific POSIX semaphore type layouts.  Alpha version.
+   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.  */
+
+#ifndef _SEMAPHORE_H
+# error "Never use <bits/semaphore.h> directly; include <semaphore.h> 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/alpha/createthread.c b/nptl/sysdeps/unix/sysv/linux/alpha/createthread.c
new file mode 100644 (file)
index 0000000..b29c57b
--- /dev/null
@@ -0,0 +1,24 @@
+/* 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.  */
+
+/* Value passed to 'clone' for initialization of the thread register.  */
+#define TLS_VALUE ((void *) (pd) \
+                  + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE)
+
+/* Get the real implementation.         */
+#include <nptl/sysdeps/pthread/createthread.c>
diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/fork.c b/nptl/sysdeps/unix/sysv/linux/alpha/fork.c
new file mode 100644 (file)
index 0000000..ca85fc0
--- /dev/null
@@ -0,0 +1,30 @@
+/* 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.  */
+
+#include <sched.h>
+#include <signal.h>
+#include <sysdep.h>
+#include <tls.h>
+
+
+#define ARCH_FORK()                                                    \
+  INLINE_SYSCALL (clone, 5,                                            \
+                 CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD,  \
+                 NULL, NULL, &THREAD_SELF->tid, NULL)
+
+#include "../fork.c"
diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h
new file mode 100644 (file)
index 0000000..e286ef3
--- /dev/null
@@ -0,0 +1,218 @@
+/* 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 Libr   \ary; 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 <time.h>
+#include <sys/param.h>
+#include <bits/pthreadtypes.h>
+#include <atomic.h>
+
+
+#define __NR_futex             394
+#define FUTEX_WAIT             0
+#define FUTEX_WAKE             1
+#define FUTEX_REQUEUE          3
+
+/* Initializer for compatibility lock. */
+#define LLL_MUTEX_LOCK_INITIALIZER (0)
+
+#define lll_futex_wait(futexp, val) \
+  ({                                                                         \
+    INTERNAL_SYSCALL_DECL (__err);                                           \
+    long int __ret;                                                          \
+    __ret = INTERNAL_SYSCALL (futex, __err, 4,                               \
+                             (futexp), FUTEX_WAIT, (val), 0);                \
+    INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret: 0;                              \
+  })
+
+#define lll_futex_timed_wait(futexp, val, timespec) \
+  ({                                                                         \
+    INTERNAL_SYSCALL_DECL (__err);                                           \
+    long int __ret;                                                          \
+    __ret = INTERNAL_SYSCALL (futex, __err, 4,                               \
+                             (futexp), FUTEX_WAIT, (val), (timespec));       \
+    INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret: 0;                              \
+  })
+
+#define lll_futex_wake(futexp, nr) \
+  ({                                                                         \
+    INTERNAL_SYSCALL_DECL (__err);                                           \
+    long int __ret;                                                          \
+    __ret = INTERNAL_SYSCALL (futex, __err, 4,                               \
+                             (futexp), FUTEX_WAKE, (nr), 0);                 \
+    INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret: 0;                              \
+  })
+
+#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex) \
+  ({                                                                         \
+    INTERNAL_SYSCALL_DECL (__err);                                           \
+    long int __ret;                                                          \
+                                                                             \
+    __ret = INTERNAL_SYSCALL (futex, __err, 5,                               \
+                             (futexp), FUTEX_REQUEUE, (nr_wake), (nr_move),  \
+                             (mutex));                                       \
+    INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret: 0;                              \
+  })
+
+/* Set *futex to 1 if it is 0, atomically.  Returns the old value */
+#define __lll_trylock(futex) \
+  ({ int __oldval, __temp;                                             \
+     __asm __volatile (                                                        \
+       "1:     ldl_l   %[__oldval], %[__mem]\n"                        \
+       "       lda     %[__temp], 1\n"                                 \
+       "       bne     %[__oldval], 2f\n"                              \
+       "       stl_c   %[__temp], %[__mem]\n"                          \
+       "       beq     %[__temp], 1b\n"                                \
+               __MB                                                    \
+       "2:"                                                            \
+       : [__oldval] "=&r" (__oldval),                                  \
+         [__temp] "=&r" (__temp)                                       \
+       : [__mem] "m" (*(futex))                                        \
+       : "memory");                                                    \
+     __oldval;                                                         \
+  })
+
+#define lll_mutex_trylock(lock)        __lll_trylock (&(lock))
+
+
+extern void __lll_lock_wait (int *futex, int val) attribute_hidden;
+
+#define lll_mutex_lock(lock) \
+  (void) ({                                                            \
+    int *__futex = &(lock);                                            \
+    int __val = atomic_exchange_and_add (__futex, 1);                  \
+    atomic_full_barrier();                                             \
+    if (__builtin_expect (__val != 0, 0))                              \
+      __lll_lock_wait (__futex, __val);                                        \
+  })
+
+#define lll_mutex_cond_lock(lock) \
+  (void) ({                                                            \
+    int *__futex = &(lock);                                            \
+    int __val = atomic_exchange_and_add (__futex, 2);                  \
+    atomic_full_barrier();                                             \
+    if (__builtin_expect (__val != 0, 0))                              \
+      /* Note, the val + 1 is kind of ugly here.  __lll_lock_wait will \
+        add 1 again.  But we added 2 to the futex value so this is the \
+        right value which will be passed to the kernel.  */            \
+      __lll_lock_wait (__futex, __val + 1);                            \
+  })
+
+extern int __lll_timedlock_wait
+       (int *futex, int val, const struct timespec *) attribute_hidden;
+
+#define lll_mutex_timedlock(lock, abstime) \
+  ({ int *__futex = &(lock);                                           \
+     int __val = atomic_exchange_and_add (__futex, 1);                 \
+     atomic_full_barrier();                                            \
+     if (__builtin_expect (__val != 0, 0))                             \
+       __val = __lll_timedlock_wait (__futex, __val, (abstime));       \
+     __val;                                                            \
+  })
+
+#define lll_mutex_unlock(lock) \
+  ((void) ({                                                           \
+    int *__futex = &(lock), __val;                                     \
+    atomic_write_barrier();                                            \
+    __val = atomic_exchange_rel (__futex, 0);                          \
+    if (__builtin_expect (__val > 1, 0))                               \
+      lll_futex_wake (__futex, 1);                                     \
+  }))
+
+#define lll_mutex_unlock_force(lock) \
+  ((void) ({                                                           \
+    int *__futex = &(lock);                                            \
+    atomic_write_barrier();                                            \
+    *__futex = 0;                                                      \
+    atomic_full_barrier();                                             \
+    lll_futex_wake (__futex, 1);                                       \
+  }))
+
+#define lll_mutex_islocked(futex) \
+  (futex != 0)
+
+
+/* Our internal lock implementation is identical to the binary-compatible
+   mutex implementation. */
+
+/* Type for lock object.  */
+typedef int lll_lock_t;
+
+/* Initializers for lock.  */
+#define LLL_LOCK_INITIALIZER           (0)
+#define LLL_LOCK_INITIALIZER_LOCKED    (1)
+
+extern int lll_unlock_wake_cb (int *__futex) attribute_hidden;
+
+/* The states of a lock are:
+    0  -  untaken
+    1  -  taken by one user
+   >1  -  taken by more users */
+
+#define lll_trylock(lock)      lll_mutex_trylock (lock)
+#define lll_lock(lock)         lll_mutex_lock (lock)
+#define lll_unlock(lock)       lll_mutex_unlock (lock)
+#define lll_islocked(lock)     lll_mutex_islocked (lock)
+
+/* The kernel notifies a process which 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. */
+#define lll_wait_tid(tid) \
+  do {                                                                       \
+    __typeof (tid) __tid;                                                    \
+    while ((__tid = (tid)) != 0)                                             \
+      lll_futex_wait (&(tid), __tid);                                        \
+  } while (0)
+
+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;                                                                   \
+  })
+
+
+/* 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/alpha/pt-vfork.S b/nptl/sysdeps/unix/sysv/linux/alpha/pt-vfork.S
new file mode 100644 (file)
index 0000000..4a2df42
--- /dev/null
@@ -0,0 +1,25 @@
+/* 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.  */
+
+#include <sysdep-cancel.h>
+
+PSEUDO(__vfork, vfork, 0)
+       ret
+PSEUDO_END (__vfork)
+
+weak_alias (__vfork, vfork)
diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c b/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c
new file mode 100644 (file)
index 0000000..82f72de
--- /dev/null
@@ -0,0 +1,96 @@
+/* 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.  */
+
+#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);
+}
+
+int
+__pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
+{
+  for (;;)
+    {
+      int oldval;
+      int newval;
+      int tmp;
+
+      /* Pseudo code:
+        newval = __fork_generation | 1;
+        oldval = *once_control;
+        if ((oldval & 2) == 0)
+          *once_control = newval;
+        Do this atomically.
+      */
+      newval = __fork_generation | 1;
+      __asm __volatile (
+               "1:     ldl_l   %0, %2\n"
+               "       and     %0, 2, %1\n"
+               "       bne     %1, 2f\n"
+               "       mov     %3, %1\n"
+               "       stl_c   %1, %2\n"
+               "       beq     %1, 1b\n"
+               "2:     mb"
+               : "=&r" (oldval), "=&r" (tmp), "=m" (*once_control)
+               : "r" (newval), "m" (*once_control));
+
+      /* Check if the initializer has already been done.  */
+      if ((oldval & 2) != 0)
+       return 0;
+
+      /* Check if another thread already runs the initializer. */
+      if ((oldval & 1) == 0)
+       break;
+
+      /* Check whether the initializer execution was interrupted by a fork.  */
+      if (oldval != newval)
+       break;
+
+      /* Same generation, some other thread was faster. Wait.  */
+      lll_futex_wait (once_control, oldval);
+    }
+
+  /* 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 to take the bottom 2 bits from 01 to 10.  */
+  atomic_exchange_and_add (once_control, 1);
+
+  /* Wake up all other threads.  */
+  lll_futex_wake (once_control, INT_MAX);
+
+  return 0;
+}
+weak_alias (__pthread_once, pthread_once)
+strong_alias (__pthread_once, __pthread_once_internal)
diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/sem_post.c b/nptl/sysdeps/unix/sysv/linux/alpha/sem_post.c
new file mode 100644 (file)
index 0000000..27fd817
--- /dev/null
@@ -0,0 +1,5 @@
+/* ??? This is an ass-backwards way to do this.  We should simply define
+   the acquire/release semantics of atomic_exchange_and_add.  And even if
+   we don't do this, we should be using atomic_full_barrier or otherwise.  */
+#define __lll_rel_instr  "mb"
+#include "../sem_post.c"
diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h
new file mode 100644 (file)
index 0000000..1b27e27
--- /dev/null
@@ -0,0 +1,157 @@
+/* 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.  */
+
+#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
+
+# ifdef PROF
+#  define PSEUDO_PROF                          \
+       .set noat;                              \
+       lda     AT, _mcount;                    \
+       jsr     AT, (AT), _mcount;              \
+       .set at
+# else
+#  define PSEUDO_PROF
+# endif
+
+/* ??? Assumes that nothing comes between PSEUDO and PSEUDO_END
+   besides "ret".  */
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args)                      \
+       .globl name;                                            \
+       .align 4;                                               \
+       .type name, @function;                                  \
+       .usepv name, std;                                       \
+       cfi_startproc;                                          \
+__LABEL(name)                                                  \
+       ldgp    gp, 0(pv);                                      \
+       PSEUDO_PROF;                                            \
+       PSEUDO_PREPARE_ARGS                                     \
+       SINGLE_THREAD_P(t0);                                    \
+       bne     t0, $pseudo_cancel;                             \
+       lda     v0, SYS_ify(syscall_name);                      \
+       call_pal PAL_callsys;                                   \
+       bne     a3, SYSCALL_ERROR_LABEL;                        \
+__LABEL($pseudo_ret)                                           \
+       .subsection 2;                                          \
+__LABEL($pseudo_cancel)                                                \
+       subq    sp, 64, sp;                                     \
+       cfi_def_cfa_offset(64);                                 \
+       stq     ra, 0(sp);                                      \
+       cfi_offset(ra, -64);                                    \
+       SAVE_ARGS_##args;                                       \
+       CENABLE;                                                \
+       LOAD_ARGS_##args;                                       \
+       lda     v0, SYS_ify(syscall_name);                      \
+       call_pal PAL_callsys;                                   \
+       stq     v0, 8(sp);                                      \
+       bne     a3, $multi_error;                               \
+       CDISABLE;                                               \
+       ldq     ra, 0(sp);                                      \
+       ldq     v0, 8(sp);                                      \
+       addq    sp, 64, sp;                                     \
+       cfi_remember_state;                                     \
+       cfi_restore(ra);                                        \
+       cfi_def_cfa_offset(0);                                  \
+       ret;                                                    \
+       cfi_restore_state;                                      \
+__LABEL($multi_error)                                          \
+       CDISABLE;                                               \
+       ldq     ra, 0(sp);                                      \
+       ldq     v0, 8(sp);                                      \
+       addq    sp, 64, sp;                                     \
+       cfi_restore(ra);                                        \
+       cfi_def_cfa_offset(0);                                  \
+__LABEL($syscall_error)                                                \
+       SYSCALL_ERROR_HANDLER;                                  \
+       .previous
+
+# undef PSEUDO_END
+# define PSEUDO_END(sym)                                       \
+       .subsection 2;                                          \
+       cfi_endproc;                                            \
+       .size sym, .-sym
+
+# define SAVE_ARGS_0   /* Nothing.  */
+# define SAVE_ARGS_1   SAVE_ARGS_0; stq a0, 8(sp)
+# define SAVE_ARGS_2   SAVE_ARGS_1; stq a1, 16(sp)
+# define SAVE_ARGS_3   SAVE_ARGS_2; stq a2, 24(sp)
+# define SAVE_ARGS_4   SAVE_ARGS_3; stq a3, 32(sp)
+# define SAVE_ARGS_5   SAVE_ARGS_4; stq a4, 40(sp)
+# define SAVE_ARGS_6   SAVE_ARGS_5; stq a5, 48(sp)
+
+# define LOAD_ARGS_0   /* Nothing.  */
+# define LOAD_ARGS_1   LOAD_ARGS_0; ldq a0, 8(sp)
+# define LOAD_ARGS_2   LOAD_ARGS_1; ldq a1, 16(sp)
+# define LOAD_ARGS_3   LOAD_ARGS_2; ldq a2, 24(sp)
+# define LOAD_ARGS_4   LOAD_ARGS_3; ldq a3, 32(sp)
+# define LOAD_ARGS_5   LOAD_ARGS_4; ldq a4, 40(sp)
+# define LOAD_ARGS_6   LOAD_ARGS_5; ldq a5, 48(sp)
+
+# ifdef IS_IN_libpthread
+#  define __local_enable_asynccancel   __pthread_enable_asynccancel
+#  define __local_disable_asynccancel  __pthread_disable_asynccancel
+#  define __local_multiple_threads     __pthread_multiple_threads
+# elif !defined NOT_IN_libc
+#  define __local_enable_asynccancel   __libc_enable_asynccancel
+#  define __local_disable_asynccancel  __libc_disable_asynccancel
+#  define __local_multiple_threads     __libc_multiple_threads
+# elif defined IS_IN_librt
+#  define __local_enable_asynccancel   __librt_enable_asynccancel
+#  define __local_disable_asynccancel  __librt_disable_asynccancel
+# else
+#  error Unsupported library
+# endif
+
+# ifdef PIC
+#  define CENABLE      bsr ra, __local_enable_asynccancel !samegp
+#  define CDISABLE     bsr ra, __local_disable_asynccancel !samegp
+# else
+#  define CENABLE      jsr ra, __local_enable_asynccancel; ldgp ra, 0(gp)
+#  define CDISABLE     jsr ra, __local_disable_asynccancel; ldgp ra, 0(gp)
+# endif
+
+# 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)
+#  elif defined(PIC)
+#   define SINGLE_THREAD_P(reg)  ldl reg, __local_multiple_threads(gp) !gprel
+#  else
+#   define SINGLE_THREAD_P(reg)                                        \
+       ldah    reg, __local_multiple_threads(gp) !gprelhigh;   \
+       ldl     reg, __local_multiple_threads(reg) !gprellow
+#  endif
+# else
+#  ifndef __ASSEMBLER__
+#   define SINGLE_THREAD_P \
+       __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+                                  header.multiple_threads) == 0, 1)
+#  else
+#   error Not done
+#  endif
+# endif
+
+#endif
This page took 0.087216 seconds and 5 git commands to generate.