mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-22 19:00:07 +00:00
Update.
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.
This commit is contained in:
parent
3b985826ca
commit
f036e569ac
@ -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
|
||||
|
93
nptl/sysdeps/alpha/elf/pt-initfini.c
Normal file
93
nptl/sysdeps/alpha/elf/pt-initfini.c
Normal file
@ -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\
|
||||
");
|
45
nptl/sysdeps/alpha/pthread_spin_lock.S
Normal file
45
nptl/sysdeps/alpha/pthread_spin_lock.S
Normal file
@ -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
|
46
nptl/sysdeps/alpha/pthread_spin_trylock.S
Normal file
46
nptl/sysdeps/alpha/pthread_spin_trylock.S
Normal file
@ -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
|
38
nptl/sysdeps/alpha/pthreaddef.h
Normal file
38
nptl/sysdeps/alpha/pthreaddef.h
Normal file
@ -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))
|
46
nptl/sysdeps/alpha/td_ta_map_lwp2thr.c
Normal file
46
nptl/sysdeps/alpha/td_ta_map_lwp2thr.c
Normal file
@ -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;
|
||||
}
|
146
nptl/sysdeps/alpha/tls.h
Normal file
146
nptl/sysdeps/alpha/tls.h
Normal file
@ -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 */
|
2
nptl/sysdeps/unix/sysv/linux/alpha/Makefile
Normal file
2
nptl/sysdeps/unix/sysv/linux/alpha/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
# pull in __syscall_error routine, __sigprocmask, __syscall_rt_sigaction
|
||||
libpthread-routines += ptw-sysdep ptw-sigprocmask ptw-rt_sigaction
|
155
nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
Normal file
155
nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h
Normal file
@ -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 */
|
37
nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h
Normal file
37
nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h
Normal file
@ -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;
|
24
nptl/sysdeps/unix/sysv/linux/alpha/createthread.c
Normal file
24
nptl/sysdeps/unix/sysv/linux/alpha/createthread.c
Normal file
@ -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>
|
30
nptl/sysdeps/unix/sysv/linux/alpha/fork.c
Normal file
30
nptl/sysdeps/unix/sysv/linux/alpha/fork.c
Normal file
@ -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"
|
218
nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h
Normal file
218
nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h
Normal file
@ -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 */
|
25
nptl/sysdeps/unix/sysv/linux/alpha/pt-vfork.S
Normal file
25
nptl/sysdeps/unix/sysv/linux/alpha/pt-vfork.S
Normal file
@ -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)
|
96
nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c
Normal file
96
nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c
Normal file
@ -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)
|
5
nptl/sysdeps/unix/sysv/linux/alpha/sem_post.c
Normal file
5
nptl/sysdeps/unix/sysv/linux/alpha/sem_post.c
Normal file
@ -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"
|
157
nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h
Normal file
157
nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user