mirror of
git://sourceware.org/git/glibc.git
synced 2024-11-21 01:12:26 +08:00
2003-03-17 Roland McGrath <roland@redhat.com>
PowerPC port contributed by Paul Mackerras <paulus@samba.org>. * sysdeps/pthread/pthread_spin_init.c: New file. * sysdeps/pthread/pthread_spin_unlock.c: New file. * sysdeps/powerpc/Makefile: New file. * sysdeps/powerpc/pthread_spin_lock.c: New file. * sysdeps/powerpc/pthread_spin_trylock.c: New file. * sysdeps/powerpc/pthreaddef.h: New file. * sysdeps/powerpc/tcb-offsets.sym: New file. * sysdeps/powerpc/td_ta_map_lwp2thr.c: New file. * sysdeps/powerpc/tls.h: New file. * sysdeps/powerpc/bits/atomic.h: New file. * sysdeps/unix/sysv/linux/libc-lowlevelmutex.c: New file. * sysdeps/unix/sysv/linux/libc-lowlevellock.c: New file. * sysdeps/unix/sysv/linux/lowlevellock.c: New file. * sysdeps/unix/sysv/linux/sem_post.c: New file. * sysdeps/unix/sysv/linux/sem_timedwait.c: New file. * sysdeps/unix/sysv/linux/sem_trywait.c: New file. * sysdeps/unix/sysv/linux/powerpc/Makefile: New file. * sysdeps/unix/sysv/linux/powerpc/createthread.c: New file. * sysdeps/unix/sysv/linux/powerpc/fork.c: New file. * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: New file. * sysdeps/unix/sysv/linux/powerpc/pt-vfork.S: New file. * sysdeps/unix/sysv/linux/powerpc/pthread_once.c: New file. * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: New file. * sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h: New file. * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: New file. * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: New file.
This commit is contained in:
parent
5778033ffc
commit
f3c13160fe
21
nptl/sysdeps/powerpc/Makefile
Normal file
21
nptl/sysdeps/powerpc/Makefile
Normal file
@ -0,0 +1,21 @@
|
||||
# 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.
|
||||
|
||||
ifeq ($(subdir),csu)
|
||||
gen-as-const-headers += tcb-offsets.sym
|
||||
endif
|
116
nptl/sysdeps/powerpc/bits/atomic.h
Normal file
116
nptl/sysdeps/powerpc/bits/atomic.h
Normal file
@ -0,0 +1,116 @@
|
||||
/* Atomic operations. PowerPC version.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int8_t atomic8_t;
|
||||
typedef uint8_t uatomic8_t;
|
||||
typedef int_fast8_t atomic_fast8_t;
|
||||
typedef uint_fast8_t uatomic_fast8_t;
|
||||
|
||||
typedef int16_t atomic16_t;
|
||||
typedef uint16_t uatomic16_t;
|
||||
typedef int_fast16_t atomic_fast16_t;
|
||||
typedef uint_fast16_t uatomic_fast16_t;
|
||||
|
||||
typedef int32_t atomic32_t;
|
||||
typedef uint32_t uatomic32_t;
|
||||
typedef int_fast32_t atomic_fast32_t;
|
||||
typedef uint_fast32_t uatomic_fast32_t;
|
||||
|
||||
typedef int64_t atomic64_t;
|
||||
typedef uint64_t uatomic64_t;
|
||||
typedef int_fast64_t atomic_fast64_t;
|
||||
typedef uint_fast64_t uatomic_fast64_t;
|
||||
|
||||
typedef intptr_t atomicptr_t;
|
||||
typedef uintptr_t uatomicptr_t;
|
||||
typedef intmax_t atomic_max_t;
|
||||
typedef uintmax_t uatomic_max_t;
|
||||
|
||||
|
||||
#define __arch_compare_and_exchange_8_acq(mem, newval, oldval) \
|
||||
(abort (), 0)
|
||||
|
||||
#define __arch_compare_and_exchange_16_acq(mem, newval, oldval) \
|
||||
(abort (), 0)
|
||||
|
||||
#ifdef UP
|
||||
#define __ARCH_ACQ_INSTR ""
|
||||
#define __ARCH_REL_INSTR ""
|
||||
#else
|
||||
#define __ARCH_ACQ_INSTR "isync"
|
||||
#define __ARCH_REL_INSTR "sync"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX At present these have both acquire and release semantics.
|
||||
* Ultimately we should do separate _acq and _rel versions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* XXX this may not work properly on 64-bit if the register
|
||||
* containing oldval has the high half non-zero for some reason.
|
||||
*/
|
||||
#define __arch_compare_and_exchange_32_acq(mem, newval, oldval) \
|
||||
({ \
|
||||
unsigned int __tmp; \
|
||||
__asm __volatile (__ARCH_REL_INSTR "\n" \
|
||||
"1: lwarx %0,0,%1\n" \
|
||||
" subf. %0,%2,%0\n" \
|
||||
" bne 2f\n" \
|
||||
" stwcx. %3,0,%1\n" \
|
||||
" bne- 1b\n" \
|
||||
"2: " __ARCH_ACQ_INSTR \
|
||||
: "=&r" (__tmp) \
|
||||
: "r" (mem), "r" (oldval), "r" (newval) \
|
||||
: "cr0", "memory"); \
|
||||
__tmp != 0; \
|
||||
})
|
||||
|
||||
#ifdef __powerpc64__
|
||||
#define __arch_compare_and_exchange_64_acq(mem, newval, oldval) \
|
||||
({ \
|
||||
unsigned long __tmp; \
|
||||
__asm __volatile (__ARCH_REL_INSTR "\n" \
|
||||
"1: ldarx %0,0,%1\n" \
|
||||
" subf. %0,%2,%0\n" \
|
||||
" bne 2f\n" \
|
||||
" stdcx. %3,0,%1\n" \
|
||||
" bne- 1b\n" \
|
||||
"2: " __ARCH_ACQ_INSTR \
|
||||
: "=&r" (__tmp) \
|
||||
: "r" (mem), "r" (oldval), "r" (newval) \
|
||||
: "cr0", "memory"); \
|
||||
__tmp != 0; \
|
||||
})
|
||||
|
||||
#else /* powerpc32 */
|
||||
#define __arch_compare_and_exchange_64_acq(mem, newval, oldval) \
|
||||
(abort (), 0)
|
||||
#endif
|
||||
|
||||
#define atomic_full_barrier() __asm ("sync" ::: "memory")
|
||||
#ifdef __powerpc64__
|
||||
#define atomic_read_barrier() __asm ("lwsync" ::: "memory")
|
||||
#else
|
||||
#define atomic_read_barrier() __asm ("sync" ::: "memory")
|
||||
#endif
|
||||
#define atomic_write_barrier() __asm ("eieio" ::: "memory")
|
45
nptl/sysdeps/powerpc/pthread_spin_lock.c
Normal file
45
nptl/sysdeps/powerpc/pthread_spin_lock.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include "pthreadP.h"
|
||||
|
||||
int
|
||||
pthread_spin_lock (lock)
|
||||
pthread_spinlock_t *lock;
|
||||
{
|
||||
unsigned int __tmp;
|
||||
|
||||
asm volatile (
|
||||
"1: lwarx %0,0,%1\n"
|
||||
" cmpwi 0,%0,0\n"
|
||||
" bne- 2f\n"
|
||||
" stwcx. %2,0,%1\n"
|
||||
" bne- 2f\n"
|
||||
" isync\n"
|
||||
" .subsection 1\n"
|
||||
"2: lwzx %0,0,%1\n"
|
||||
" cmpwi 0,%0,0\n"
|
||||
" bne 2b\n"
|
||||
" b 1b\n"
|
||||
" .previous"
|
||||
: "=&r" (__tmp)
|
||||
: "r" (lock), "r" (1)
|
||||
: "cr0", "memory");
|
||||
return 0;
|
||||
}
|
43
nptl/sysdeps/powerpc/pthread_spin_trylock.c
Normal file
43
nptl/sysdeps/powerpc/pthread_spin_trylock.c
Normal file
@ -0,0 +1,43 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <errno.h>
|
||||
#include "pthreadP.h"
|
||||
|
||||
int
|
||||
pthread_spin_trylock (lock)
|
||||
pthread_spinlock_t *lock;
|
||||
{
|
||||
unsigned int old;
|
||||
int err = EBUSY;
|
||||
|
||||
asm ("1: lwarx %0,0,%2\n"
|
||||
" cmpwi 0,%0,0\n"
|
||||
" bne 2f\n"
|
||||
" stwcx. %3,0,%2\n"
|
||||
" bne- 1b\n"
|
||||
" li %1,0\n"
|
||||
" isync\n"
|
||||
"2: "
|
||||
: "=&r" (old), "=&r" (err)
|
||||
: "r" (lock), "r" (1), "1" (err)
|
||||
: "cr0", "memory");
|
||||
|
||||
return err;
|
||||
}
|
44
nptl/sysdeps/powerpc/pthreaddef.h
Normal file
44
nptl/sysdeps/powerpc/pthreaddef.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* 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
|
||||
bytes (for both 32-bit and 64-bit PowerPC). */
|
||||
#define STACK_ALIGN 16
|
||||
|
||||
/* Minimal stack size after allocating thread descriptor and guard size. */
|
||||
#define MINIMAL_REST_STACK 4096
|
||||
|
||||
/* Alignment requirement for TCB. */
|
||||
#define TCB_ALIGNMENT 16
|
||||
|
||||
/* The signal used for asynchronous cancelation. */
|
||||
#define SIGCANCEL __SIGRTMIN
|
||||
|
||||
|
||||
/* 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))
|
13
nptl/sysdeps/powerpc/tcb-offsets.sym
Normal file
13
nptl/sysdeps/powerpc/tcb-offsets.sym
Normal file
@ -0,0 +1,13 @@
|
||||
#include <sysdep.h>
|
||||
#include <tls.h>
|
||||
|
||||
--
|
||||
|
||||
-- Abuse tls.h macros to derive offsets relative to the thread register.
|
||||
# undef __thread_register
|
||||
# define __thread_register ((void *) 0)
|
||||
# define thread_offsetof(mem) ((void *) &THREAD_SELF->mem - (void *) 0)
|
||||
|
||||
#if TLS_MULTIPLE_THREADS_IN_TCB
|
||||
MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads)
|
||||
#endif
|
44
nptl/sysdeps/powerpc/td_ta_map_lwp2thr.c
Normal file
44
nptl/sysdeps/powerpc/td_ta_map_lwp2thr.c
Normal file
@ -0,0 +1,44 @@
|
||||
/* 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;
|
||||
|
||||
th->th_unique = ((void *) regs[PT_THREAD_POINTER]
|
||||
- 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;
|
||||
}
|
152
nptl/sysdeps/powerpc/tls.h
Normal file
152
nptl/sysdeps/powerpc/tls.h
Normal file
@ -0,0 +1,152 @@
|
||||
/* Definition for thread-local data handling. NPTL/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. */
|
||||
|
||||
#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
|
||||
|
||||
/* For 32-bit, we use the multiple_threads field in the pthread struct */
|
||||
#ifndef __powerpc64__
|
||||
# define TLS_MULTIPLE_THREADS_IN_TCB 1
|
||||
#endif
|
||||
|
||||
/* 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 sizeof (tcbhead_t)
|
||||
|
||||
/* Alignment requirements for the initial TCB. */
|
||||
# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
|
||||
|
||||
/* This is the size of the TCB. */
|
||||
# define TLS_TCB_SIZE sizeof (tcbhead_t)
|
||||
|
||||
/* Alignment requirements for the TCB. */
|
||||
# define TLS_TCB_ALIGN __alignof__ (tcbhead_t)
|
||||
|
||||
/* This is the size we need before TCB. */
|
||||
# define TLS_PRE_TCB_SIZE sizeof (struct pthread)
|
||||
|
||||
/* XXX if __alignof__ (struct pthread) > __alignof (tcbhead_t)
|
||||
we could be in trouble. -- paulus */
|
||||
|
||||
# ifndef __powerpc64__
|
||||
/* Register r2 (tp) is reserved by the ABI as "thread pointer". */
|
||||
register void *__thread_register __asm__ ("r2");
|
||||
# define PT_THREAD_POINTER PT_R2
|
||||
# else
|
||||
/* Register r13 (tp) is reserved by the ABI as "thread pointer". */
|
||||
register void *__thread_register __asm__ ("r13");
|
||||
# define PT_THREAD_POINTER PT_R13
|
||||
# endif
|
||||
|
||||
/* The following assumes that TP (R2 or R13) points to the end of the
|
||||
TCB + 0x7000 (per the ABI). This implies that TCB address is
|
||||
TP-(TLS_TCB_SIZE + 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 + TLS_TCB_SIZE + 0x7000). */
|
||||
# define TLS_TCB_OFFSET 0x7000
|
||||
|
||||
/* Install the dtv pointer. The pointer passed is to the element with
|
||||
index -1 which contain the length. */
|
||||
# define INSTALL_DTV(tcbp, dtvp) \
|
||||
((tcbhead_t *) (tcbp))->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))->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) \
|
||||
(__thread_register = (void *) (tcbp) + TLS_TCB_OFFSET + TLS_TCB_SIZE, NULL)
|
||||
|
||||
/* Return the address of the dtv for the current thread. */
|
||||
# define THREAD_DTV() \
|
||||
(((tcbhead_t *) (__thread_register - TLS_TCB_OFFSET - TLS_TCB_SIZE))->dtv)
|
||||
|
||||
/* Return the thread descriptor for the current thread. */
|
||||
# define THREAD_SELF \
|
||||
((struct pthread *) (__thread_register \
|
||||
- TLS_TCB_OFFSET - TLS_TCB_SIZE - TLS_PRE_TCB_SIZE))
|
||||
|
||||
/* Read member of the thread descriptor directly. */
|
||||
# define THREAD_GETMEM(descr, member) ((void)(descr), (THREAD_SELF)->member)
|
||||
|
||||
/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
|
||||
# define THREAD_GETMEM_NC(descr, member, idx) \
|
||||
((void)(descr), (THREAD_SELF)->member[idx])
|
||||
|
||||
/* Set member of the thread descriptor directly. */
|
||||
# define THREAD_SETMEM(descr, member, value) \
|
||||
((void)(descr), (THREAD_SELF)->member = (value))
|
||||
|
||||
/* Same as THREAD_SETMEM, but the member offset can be non-constant. */
|
||||
# define THREAD_SETMEM_NC(descr, member, idx, value) \
|
||||
((void)(descr), (THREAD_SELF)->member[idx] = (value))
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#endif /* tls.h */
|
28
nptl/sysdeps/pthread/pthread_spin_init.c
Normal file
28
nptl/sysdeps/pthread/pthread_spin_init.c
Normal file
@ -0,0 +1,28 @@
|
||||
/* pthread_spin_init -- initialize a spin lock. Generic version.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include "pthreadP.h"
|
||||
|
||||
int
|
||||
pthread_spin_init (pthread_spinlock_t *lock, int pshared)
|
||||
{
|
||||
*lock = 0;
|
||||
return 0;
|
||||
}
|
30
nptl/sysdeps/pthread/pthread_spin_unlock.c
Normal file
30
nptl/sysdeps/pthread/pthread_spin_unlock.c
Normal file
@ -0,0 +1,30 @@
|
||||
/* pthread_spin_unlock -- unlock a spin lock. Generic version.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include "pthreadP.h"
|
||||
#include <atomic.h>
|
||||
|
||||
int
|
||||
pthread_spin_unlock (pthread_spinlock_t *lock)
|
||||
{
|
||||
atomic_full_barrier ();
|
||||
*lock = 0;
|
||||
return 0;
|
||||
}
|
21
nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c
Normal file
21
nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c
Normal file
@ -0,0 +1,21 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
/* No difference to lowlevellock.c, except we lose a couple of functions. */
|
||||
#include "lowlevellock.c"
|
1
nptl/sysdeps/unix/sysv/linux/libc-lowlevelmutex.c
Normal file
1
nptl/sysdeps/unix/sysv/linux/libc-lowlevelmutex.c
Normal file
@ -0,0 +1 @@
|
||||
/* Nothing needed here in fact. */
|
140
nptl/sysdeps/unix/sysv/linux/lowlevellock.c
Normal file
140
nptl/sysdeps/unix/sysv/linux/lowlevellock.c
Normal file
@ -0,0 +1,140 @@
|
||||
/* low level locking for pthread library. Generic futex-using version.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevellock.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
|
||||
void
|
||||
__lll_lock_wait (int *futex, int val)
|
||||
{
|
||||
do {
|
||||
lll_futex_wait (futex, val+1);
|
||||
} while ((val = __lll_add (futex, 1)) != 0);
|
||||
*futex = 2;
|
||||
}
|
||||
hidden_proto (__lll_lock_wait)
|
||||
|
||||
|
||||
int
|
||||
__lll_timedlock_wait (int *futex, int val, const struct timespec *abstime)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Reject invalid timeouts. */
|
||||
if (abstime->tv_nsec >= 1000000000)
|
||||
return EINVAL;
|
||||
|
||||
do
|
||||
{
|
||||
struct timeval tv;
|
||||
struct timespec rt;
|
||||
int sec, nsec;
|
||||
|
||||
/* Get the current time. */
|
||||
__gettimeofday (&tv, NULL);
|
||||
|
||||
/* Compute relative timeout. */
|
||||
sec = abstime->tv_sec - tv.tv_sec;
|
||||
nsec = abstime->tv_nsec - tv.tv_usec * 1000;
|
||||
if (nsec < 0)
|
||||
{
|
||||
nsec += 1000000000;
|
||||
--sec;
|
||||
}
|
||||
|
||||
/* Already timed out? */
|
||||
err = -ETIMEDOUT;
|
||||
if (sec < 0)
|
||||
break;
|
||||
|
||||
/* Wait. */
|
||||
rt.tv_sec = sec;
|
||||
rt.tv_nsec = nsec;
|
||||
err = lll_futex_timed_wait (futex, val+1, &rt);
|
||||
} while (err == 0 && (val = __lll_add (futex, 1)) != 0);
|
||||
|
||||
*futex = 2;
|
||||
return -err;
|
||||
}
|
||||
hidden_proto (__lll_timedlock_wait)
|
||||
|
||||
|
||||
/* These don't get included in libc.so */
|
||||
#ifdef IS_IN_libpthread
|
||||
int
|
||||
lll_unlock_wake_cb (int *futex)
|
||||
{
|
||||
__lll_add (futex, 1);
|
||||
return 0;
|
||||
}
|
||||
hidden_proto (lll_unlock_wake_cb)
|
||||
|
||||
|
||||
int
|
||||
__lll_timedwait_tid (int *tidp, const struct timespec *abstime)
|
||||
{
|
||||
int tid;
|
||||
int err = 0;
|
||||
|
||||
if (abstime == NULL || abstime->tv_nsec >= 1000000000)
|
||||
return EINVAL;
|
||||
|
||||
/* Repeat until thread terminated. */
|
||||
while ((tid = *tidp) != 0)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct timespec rt;
|
||||
int sec, nsec;
|
||||
|
||||
/* Get the current time. */
|
||||
__gettimeofday (&tv, NULL);
|
||||
|
||||
/* Compute relative timeout. */
|
||||
sec = abstime->tv_sec - tv.tv_sec;
|
||||
nsec = abstime->tv_nsec - tv.tv_usec * 1000;
|
||||
if (nsec < 0)
|
||||
{
|
||||
nsec += 1000000000;
|
||||
--sec;
|
||||
}
|
||||
|
||||
/* Already timed out? */
|
||||
err = -ETIMEDOUT;
|
||||
if (sec < 0)
|
||||
break;
|
||||
|
||||
/* Wait. */
|
||||
rt.tv_sec = sec;
|
||||
rt.tv_nsec = nsec;
|
||||
|
||||
/* Wait until thread terminates. */
|
||||
err = lll_futex_timed_wait (tidp, tid, &rt);
|
||||
if (err != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return -err;
|
||||
}
|
||||
|
||||
hidden_proto (__lll_timedwait_tid)
|
||||
#endif
|
2
nptl/sysdeps/unix/sysv/linux/powerpc/Makefile
Normal file
2
nptl/sysdeps/unix/sysv/linux/powerpc/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
# pull in __syscall_error routine
|
||||
libpthread-routines += sysdep
|
167
nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
Normal file
167
nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h
Normal file
@ -0,0 +1,167 @@
|
||||
/* Machine-specific pthread type layouts. PowerPC version.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, 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
|
||||
|
||||
#include <bits/wordsize.h>
|
||||
|
||||
#if __WORDSIZE == 64
|
||||
# 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
|
||||
#else
|
||||
# define __SIZEOF_PTHREAD_ATTR_T 36
|
||||
# define __SIZEOF_PTHREAD_MUTEX_T 24
|
||||
# define __SIZEOF_PTHREAD_MUTEXATTR_T 4
|
||||
# define __SIZEOF_PTHREAD_COND_T 48
|
||||
# define __SIZEOF_PTHREAD_CONDATTR_T 4
|
||||
# define __SIZEOF_PTHREAD_RWLOCK_T 32
|
||||
# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
|
||||
# define __SIZEOF_PTHREAD_BARRIER_T 20
|
||||
# define __SIZEOF_PTHREAD_BARRIERATTR_T 4
|
||||
#endif
|
||||
|
||||
|
||||
/* 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;
|
||||
struct pthread *__owner;
|
||||
/* KIND must stay at this position in the structure to maintain
|
||||
binary compatibility. */
|
||||
int __kind;
|
||||
} __data;
|
||||
char __size[__SIZEOF_PTHREAD_MUTEX_T];
|
||||
long int __align;
|
||||
} pthread_mutex_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
|
||||
long int __align;
|
||||
} pthread_mutexattr_t;
|
||||
|
||||
|
||||
/* Data structure for conditional variable handling. The structure of
|
||||
the attribute type is deliberately not exposed. */
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int __lock;
|
||||
int __pad;
|
||||
unsigned long long int __total_seq;
|
||||
unsigned long long int __wakeup_seq;
|
||||
unsigned long long int __woken_seq;
|
||||
} __data;
|
||||
char __size[__SIZEOF_PTHREAD_COND_T];
|
||||
long int __align;
|
||||
} pthread_cond_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
char __size[__SIZEOF_PTHREAD_CONDATTR_T];
|
||||
long int __align;
|
||||
} pthread_condattr_t;
|
||||
|
||||
|
||||
/* Keys for thread-specific data */
|
||||
typedef unsigned int pthread_key_t;
|
||||
|
||||
|
||||
/* Once-only execution */
|
||||
typedef int pthread_once_t;
|
||||
|
||||
|
||||
#ifdef __USE_UNIX98
|
||||
/* Data structure for read-write lock variable handling. The
|
||||
structure of the attribute type is 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;
|
||||
pthread_t __writer;
|
||||
/* 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 */
|
44
nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h
Normal file
44
nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* Machine-specific POSIX semaphore type layouts. PowerPC version.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, 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
|
||||
|
||||
#include <bits/wordsize.h>
|
||||
|
||||
#if __WORDSIZE == 64
|
||||
# define __SIZEOF_SEM_T 32
|
||||
#else
|
||||
# define __SIZEOF_SEM_T 16
|
||||
#endif
|
||||
|
||||
/* 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;
|
25
nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c
Normal file
25
nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c
Normal file
@ -0,0 +1,25 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Paul Mackerras <paulus@au.ibm.com>.
|
||||
|
||||
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_TCB_SIZE + TLS_PRE_TCB_SIZE)
|
||||
|
||||
/* Get the real implementation. */
|
||||
#include <nptl/sysdeps/pthread/createthread.c>
|
1
nptl/sysdeps/unix/sysv/linux/powerpc/fork.c
Normal file
1
nptl/sysdeps/unix/sysv/linux/powerpc/fork.c
Normal file
@ -0,0 +1 @@
|
||||
#include "../i386/fork.c"
|
224
nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
Normal file
224
nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
Normal file
@ -0,0 +1,224 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C 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>
|
||||
|
||||
#define __NR_futex 221
|
||||
#define FUTEX_WAIT 0
|
||||
#define FUTEX_WAKE 1
|
||||
|
||||
/* 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; \
|
||||
})
|
||||
|
||||
#ifdef UP
|
||||
#define __lll_acq_instr ""
|
||||
#define __lll_rel_instr ""
|
||||
#else
|
||||
#define __lll_acq_instr "isync"
|
||||
#define __lll_rel_instr "sync"
|
||||
#endif
|
||||
|
||||
/* Set *futex to 1 if it is 0, atomically. Returns the old value */
|
||||
#define __lll_trylock(futex) \
|
||||
({ int __val; \
|
||||
__asm __volatile ("1: lwarx %0,0,%2\n" \
|
||||
" cmpwi 0,%0,0\n" \
|
||||
" bne 2f\n" \
|
||||
" stwcx. %3,0,%2\n" \
|
||||
" bne- 1b\n" \
|
||||
"2: " __lll_acq_instr \
|
||||
: "=&r" (__val), "=m" (*futex) \
|
||||
: "r" (futex), "r" (1), "1" (*futex) \
|
||||
: "cr0", "memory"); \
|
||||
__val; \
|
||||
})
|
||||
|
||||
#define lll_mutex_trylock(lock) __lll_trylock(&(lock))
|
||||
|
||||
/* Add inc to *futex atomically and return the old value. */
|
||||
#define __lll_add(futex, inc) \
|
||||
({ int __val, __tmp; \
|
||||
__asm __volatile ("1: lwarx %0,0,%3\n" \
|
||||
" addi %1,%0,%4\n" \
|
||||
" stwcx. %1,0,%3\n" \
|
||||
" bne- 1b" \
|
||||
: "=&b" (__val), "=&r" (__tmp), "=m" (*futex) \
|
||||
: "r" (futex), "I" (inc), "2" (*futex) \
|
||||
: "cr0"); \
|
||||
__val; \
|
||||
})
|
||||
|
||||
extern void __lll_lock_wait (int *futex, int val) attribute_hidden;
|
||||
|
||||
#define lll_mutex_lock(lock) \
|
||||
(void) ({ \
|
||||
int *__futex = &(lock); \
|
||||
int __val = __lll_add (__futex, 1); \
|
||||
__asm __volatile (__lll_acq_instr ::: "memory"); \
|
||||
if (__builtin_expect (__val != 0, 0)) \
|
||||
__lll_lock_wait (__futex, __val); \
|
||||
})
|
||||
|
||||
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 = __lll_add (__futex, 1); \
|
||||
__asm __volatile (__lll_acq_instr ::: "memory"); \
|
||||
if (__builtin_expect (__val != 0, 0)) \
|
||||
__val = __lll_timedlock_wait (__futex, __val, (abstime)); \
|
||||
__val; \
|
||||
})
|
||||
|
||||
#define lll_mutex_unlock(lock) \
|
||||
(void) ({ \
|
||||
int *__futex = &(lock); \
|
||||
__asm __volatile (__lll_rel_instr ::: "memory"); \
|
||||
int __val = __lll_add (__futex, -1); \
|
||||
if (__builtin_expect (__val != 1, 0)) \
|
||||
{ \
|
||||
*__futex = 0; \
|
||||
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; \
|
||||
})
|
||||
|
||||
|
||||
/* Decrement *futex if it is > 0, and return the old value */
|
||||
#define __lll_dec_if_positive(futex) \
|
||||
({ int __val, __tmp; \
|
||||
__asm __volatile ("1: lwarx %0,0,%3\n" \
|
||||
" cmpwi 0,%0,0\n" \
|
||||
" addi %1,%0,-1\n" \
|
||||
" ble 2f\n" \
|
||||
" stwcx. %1,0,%3\n" \
|
||||
" bne- 1b\n" \
|
||||
"2: " __lll_acq_instr \
|
||||
: "=&b" (__val), "=&r" (__tmp), "=m" (*futex) \
|
||||
: "r" (futex), "2" (*futex) \
|
||||
: "cr0"); \
|
||||
__val; \
|
||||
})
|
||||
|
||||
|
||||
/* 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 */
|
102
nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h
Normal file
102
nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h
Normal file
@ -0,0 +1,102 @@
|
||||
/* Cancellable system call stubs. Linux/PowerPC version.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Franz Sirl <Franz.Sirl-kernel@lauterbach.com>, 2003.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, 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
|
||||
|
||||
# undef PSEUDO
|
||||
# define PSEUDO(name, syscall_name, args) \
|
||||
.section ".text"; \
|
||||
ENTRY (name) \
|
||||
SINGLE_THREAD_P; \
|
||||
bne- .Lpseudo_cancel; \
|
||||
DO_CALL (SYS_ify (syscall_name)); \
|
||||
PSEUDO_RET; \
|
||||
.Lpseudo_cancel: \
|
||||
stwu 1,-48(1); \
|
||||
mflr 9; \
|
||||
stw 9,52(1); \
|
||||
DOCARGS_##args; /* save syscall args around CENABLE. */ \
|
||||
CENABLE; \
|
||||
stw 3,16(1); /* store CENABLE return value (MASK). */ \
|
||||
UNDOCARGS_##args; /* restore syscall args. */ \
|
||||
DO_CALL (SYS_ify (syscall_name)); \
|
||||
mfcr 0; /* save CR/R3 around CDISABLE. */ \
|
||||
stw 3,8(1); \
|
||||
stw 0,12(1); \
|
||||
lwz 3,16(1); /* pass MASK to CDISABLE. */ \
|
||||
CDISABLE; \
|
||||
lwz 4,52(1); \
|
||||
lwz 0,12(1); /* restore CR/R3. */ \
|
||||
lwz 3,8(1); \
|
||||
mtlr 4; \
|
||||
mtcr 0; \
|
||||
addi 1,1,48;
|
||||
|
||||
# define DOCARGS_0
|
||||
# define UNDOCARGS_0
|
||||
|
||||
# define DOCARGS_1 stw 3,20(1); DOCARGS_0
|
||||
# define UNDOCARGS_1 lwz 3,20(1); UNDOCARGS_0
|
||||
|
||||
# define DOCARGS_2 stw 4,24(1); DOCARGS_1
|
||||
# define UNDOCARGS_2 lwz 4,24(1); UNDOCARGS_1
|
||||
|
||||
# define DOCARGS_3 stw 5,28(1); DOCARGS_2
|
||||
# define UNDOCARGS_3 lwz 5,28(1); UNDOCARGS_2
|
||||
|
||||
# define DOCARGS_4 stw 6,32(1); DOCARGS_3
|
||||
# define UNDOCARGS_4 lwz 6,32(1); UNDOCARGS_3
|
||||
|
||||
# define DOCARGS_5 stw 7,36(1); DOCARGS_4
|
||||
# define UNDOCARGS_5 lwz 7,36(1); UNDOCARGS_4
|
||||
|
||||
# define DOCARGS_6 stw 8,40(1); DOCARGS_5
|
||||
# define UNDOCARGS_6 lwz 8,40(1); UNDOCARGS_5
|
||||
|
||||
# ifdef IS_IN_libpthread
|
||||
# define CENABLE bl JUMPTARGET(__pthread_enable_asynccancel)
|
||||
# define CDISABLE bl JUMPTARGET(__pthread_disable_asynccancel)
|
||||
# else
|
||||
# define CENABLE bl JUMPTARGET(__libc_enable_asynccancel)
|
||||
# define CDISABLE bl JUMPTARGET(__libc_disable_asynccancel)
|
||||
# endif
|
||||
|
||||
# ifndef __ASSEMBLER__
|
||||
# define SINGLE_THREAD_P \
|
||||
__builtin_expect (THREAD_GETMEM (THREAD_SELF, \
|
||||
header.multiple_threads) == 0, 1)
|
||||
# else
|
||||
# define SINGLE_THREAD_P \
|
||||
lwz 10,MULTIPLE_THREADS_OFFSET(2); \
|
||||
cmpwi 10,0
|
||||
# endif
|
||||
|
||||
#elif !defined __ASSEMBLER__
|
||||
|
||||
/* This code should never be used but we define it anyhow. */
|
||||
# define SINGLE_THREAD_P (1)
|
||||
|
||||
#endif
|
102
nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
Normal file
102
nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
Normal file
@ -0,0 +1,102 @@
|
||||
/* Cancellable system call stubs. Linux/PowerPC64 version.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Franz Sirl <Franz.Sirl-kernel@lauterbach.com>, 2003.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, 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
|
||||
|
||||
# undef PSEUDO
|
||||
# define PSEUDO(name, syscall_name, args) \
|
||||
.section ".text"; \
|
||||
ENTRY (name) \
|
||||
SINGLE_THREAD_P; \
|
||||
bne- .Lpseudo_cancel; \
|
||||
DO_CALL (SYS_ify (syscall_name)); \
|
||||
PSEUDO_RET; \
|
||||
.Lpseudo_cancel: \
|
||||
stdu 1,-128(1); \
|
||||
mflr 9; \
|
||||
std 9,128+16(1); \
|
||||
DOCARGS_##args; /* save syscall args around CENABLE. */ \
|
||||
CENABLE; \
|
||||
std 3,72(1); /* store CENABLE return value (MASK). */ \
|
||||
UNDOCARGS_##args; /* restore syscall args. */ \
|
||||
DO_CALL (SYS_ify (syscall_name)); \
|
||||
mfcr 0; /* save CR/R3 around CDISABLE. */ \
|
||||
std 3,64(1); \
|
||||
std 0,8(1); \
|
||||
ld 3,72(1); /* pass MASK to CDISABLE. */ \
|
||||
CDISABLE; \
|
||||
ld 9,128+16(1); \
|
||||
ld 0,8(1); /* restore CR/R3. */ \
|
||||
ld 3,64(1); \
|
||||
mtlr 9; \
|
||||
mtcr 0; \
|
||||
addi 1,1,128;
|
||||
|
||||
# define DOCARGS_0
|
||||
# define UNDOCARGS_0
|
||||
|
||||
# define DOCARGS_1 std 3,80(1); DOCARGS_0
|
||||
# define UNDOCARGS_1 ld 3,80(1); UNDOCARGS_0
|
||||
|
||||
# define DOCARGS_2 std 4,88(1); DOCARGS_1
|
||||
# define UNDOCARGS_2 ld 4,88(1); UNDOCARGS_1
|
||||
|
||||
# define DOCARGS_3 std 5,96(1); DOCARGS_2
|
||||
# define UNDOCARGS_3 ld 5,96(1); UNDOCARGS_2
|
||||
|
||||
# define DOCARGS_4 std 6,104(1); DOCARGS_3
|
||||
# define UNDOCARGS_4 ld 6,104(1); UNDOCARGS_3
|
||||
|
||||
# define DOCARGS_5 std 7,112(1); DOCARGS_4
|
||||
# define UNDOCARGS_5 ld 7,112(1); UNDOCARGS_4
|
||||
|
||||
# define DOCARGS_6 std 8,120(1); DOCARGS_5
|
||||
# define UNDOCARGS_6 ld 8,120(1); UNDOCARGS_5
|
||||
|
||||
# ifdef IS_IN_libpthread
|
||||
# define CENABLE bl JUMPTARGET(__pthread_enable_asynccancel)
|
||||
# define CDISABLE bl JUMPTARGET(__pthread_disable_asynccancel)
|
||||
# else
|
||||
# define CENABLE bl JUMPTARGET(__libc_enable_asynccancel)
|
||||
# define CDISABLE bl JUMPTARGET(__libc_disable_asynccancel)
|
||||
# endif
|
||||
|
||||
# ifndef __ASSEMBLER__
|
||||
# define SINGLE_THREAD_P \
|
||||
__builtin_expect (THREAD_GETMEM (THREAD_SELF, multiple_threads) \
|
||||
== 0, 1)
|
||||
# else
|
||||
# define SINGLE_THREAD_P \
|
||||
lwz 10,MULTIPLE_THREADS_OFFSET(13); \
|
||||
cmpdi 10,0
|
||||
# endif
|
||||
|
||||
#elif !defined __ASSEMBLER__
|
||||
|
||||
/* This code should never be used but we define it anyhow. */
|
||||
# define SINGLE_THREAD_P (1)
|
||||
|
||||
#endif
|
35
nptl/sysdeps/unix/sysv/linux/powerpc/pt-vfork.S
Normal file
35
nptl/sysdeps/unix/sysv/linux/powerpc/pt-vfork.S
Normal file
@ -0,0 +1,35 @@
|
||||
/* 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>
|
||||
#define _ERRNO_H 1
|
||||
#include <bits/errno.h>
|
||||
#include <kernel-features.h>
|
||||
|
||||
/* Clone the calling process, but without copying the whole address space.
|
||||
The calling process is suspended until the new process exits or is
|
||||
replaced by a call to `execve'. Return -1 for errors, 0 to the new process,
|
||||
and the process ID of the new process to the old process. */
|
||||
|
||||
ENTRY (__vfork)
|
||||
DO_CALL (SYS_ify (vfork));
|
||||
PSEUDO_RET
|
||||
|
||||
PSEUDO_END (__vfork)
|
||||
|
||||
weak_alias (__vfork, vfork)
|
99
nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c
Normal file
99
nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c
Normal file
@ -0,0 +1,99 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, 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: lwarx %0,0,%3\n"
|
||||
" andi. %1,%0,2\n"
|
||||
" bne 2f\n"
|
||||
" stwcx. %4,0,%3\n"
|
||||
"2: isync"
|
||||
: "=&r" (oldval), "=&r" (tmp), "=m" (*once_control)
|
||||
: "r" (once_control), "r" (newval), "m" (*once_control)
|
||||
: "cr0");
|
||||
|
||||
/* 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. */
|
||||
__lll_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)
|
47
nptl/sysdeps/unix/sysv/linux/sem_post.c
Normal file
47
nptl/sysdeps/unix/sysv/linux/sem_post.c
Normal file
@ -0,0 +1,47 @@
|
||||
/* sem_post -- post to a POSIX semaphore. Generic futex-using version.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevellock.h>
|
||||
#include <internaltypes.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
#include <shlib-compat.h>
|
||||
|
||||
int
|
||||
__new_sem_post (sem_t *sem)
|
||||
{
|
||||
int *futex = (int *) sem;
|
||||
int err, nr;
|
||||
|
||||
__asm __volatile (__lll_rel_instr ::: "memory");
|
||||
nr = __lll_add (futex, 1);
|
||||
err = lll_futex_wake (futex, nr);
|
||||
if (err == 0)
|
||||
return 0;
|
||||
__set_errno (-err);
|
||||
return -1;
|
||||
}
|
||||
versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1);
|
||||
#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
|
||||
strong_alias (__new_sem_post, __old_sem_post)
|
||||
compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0);
|
||||
#endif
|
87
nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
Normal file
87
nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
Normal file
@ -0,0 +1,87 @@
|
||||
/* sem_timedwait -- wait on a semaphore. Generic futex-using version.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevellock.h>
|
||||
#include <internaltypes.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
#include <shlib-compat.h>
|
||||
|
||||
|
||||
int
|
||||
sem_timedwait (sem_t *sem, const struct timespec *abstime)
|
||||
{
|
||||
int *futex = (int *) sem;
|
||||
int val;
|
||||
int err;
|
||||
|
||||
if (*futex > 0)
|
||||
{
|
||||
val = __lll_dec_if_positive (futex);
|
||||
if (val > 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = -EINVAL;
|
||||
if (abstime->tv_nsec >= 1000000000)
|
||||
goto error_return;
|
||||
|
||||
do
|
||||
{
|
||||
struct timeval tv;
|
||||
struct timespec rt;
|
||||
int sec, nsec;
|
||||
|
||||
/* Get the current time. */
|
||||
__gettimeofday (&tv, NULL);
|
||||
|
||||
/* Compute relative timeout. */
|
||||
sec = abstime->tv_sec - tv.tv_sec;
|
||||
nsec = abstime->tv_nsec - tv.tv_usec * 1000;
|
||||
if (nsec < 0)
|
||||
{
|
||||
nsec += 1000000000;
|
||||
--sec;
|
||||
}
|
||||
|
||||
/* Already timed out? */
|
||||
err = -ETIMEDOUT;
|
||||
if (sec < 0)
|
||||
goto error_return;
|
||||
|
||||
/* Do wait. */
|
||||
rt.tv_sec = sec;
|
||||
rt.tv_nsec = nsec;
|
||||
err = lll_futex_timed_wait (futex, 0, &rt);
|
||||
if (err != 0 && err != -EWOULDBLOCK)
|
||||
goto error_return;
|
||||
|
||||
val = __lll_dec_if_positive (futex);
|
||||
}
|
||||
while (val <= 0);
|
||||
|
||||
return 0;
|
||||
|
||||
error_return:
|
||||
__set_errno (-err);
|
||||
return -1;
|
||||
}
|
50
nptl/sysdeps/unix/sysv/linux/sem_trywait.c
Normal file
50
nptl/sysdeps/unix/sysv/linux/sem_trywait.c
Normal file
@ -0,0 +1,50 @@
|
||||
/* sem_trywait -- wait on a semaphore. Generic futex-using version.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <sysdep.h>
|
||||
#include <lowlevellock.h>
|
||||
#include <internaltypes.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
#include <shlib-compat.h>
|
||||
|
||||
|
||||
int
|
||||
__new_sem_trywait (sem_t *sem)
|
||||
{
|
||||
int *futex = (int *) sem;
|
||||
int val;
|
||||
|
||||
if (*futex > 0)
|
||||
{
|
||||
val = __lll_dec_if_positive (futex);
|
||||
if (val > 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
__set_errno (EAGAIN);
|
||||
return -1;
|
||||
}
|
||||
versioned_symbol (libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1);
|
||||
#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
|
||||
strong_alias (__new_sem_trywait, __old_sem_trywait)
|
||||
compat_symbol (libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0);
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user