2006-04-19 Carlos O'Donell <carlos@systemhalted.org>

* sysdeps/hppa/linuxthreads/pspinlock.c: New file.
	* sysdeps/hppa/linuxthreads/pt-machine.h: Likewise.
	* sysdeps/hppa/linuxthreads/tls.h: Likewise.
	* sysdeps/unix/sysv/linux/hppa/linuxthreads/aio_cancel.c: Likewise.
	* sysdeps/unix/sysv/linux/hppa/linuxthreads/malloc-machine.h:
	Likewise.
	* sysdeps/unix/sysv/linux/hppa/linuxthreads/pt-initfini.c: Likewise.
	* sysdeps/unix/sysv/linux/hppa/linuxthreads/sysdep-cancel.h: Likewise.
	* sysdeps/unix/sysv/linux/hppa/linuxthreads/bits/initspin.h: Likewise.
	* sysdeps/unix/sysv/linux/hppa/linuxthreads/bits/pthreadtypes.h:
	Likewise.
This commit is contained in:
Carlos O'Donell 2006-04-19 05:35:34 +00:00
parent 44f4e76726
commit 5d3b4a7723
10 changed files with 1047 additions and 0 deletions

View file

@ -1,3 +1,17 @@
2006-04-19 Carlos O'Donell <carlos@systemhalted.org>
* sysdeps/hppa/linuxthreads/pspinlock.c: New file.
* sysdeps/hppa/linuxthreads/pt-machine.h: Likewise.
* sysdeps/hppa/linuxthreads/tls.h: Likewise.
* sysdeps/unix/sysv/linux/hppa/linuxthreads/aio_cancel.c: Likewise.
* sysdeps/unix/sysv/linux/hppa/linuxthreads/malloc-machine.h:
Likewise.
* sysdeps/unix/sysv/linux/hppa/linuxthreads/pt-initfini.c: Likewise.
* sysdeps/unix/sysv/linux/hppa/linuxthreads/sysdep-cancel.h: Likewise.
* sysdeps/unix/sysv/linux/hppa/linuxthreads/bits/initspin.h: Likewise.
* sysdeps/unix/sysv/linux/hppa/linuxthreads/bits/pthreadtypes.h:
Likewise.
2006-02-28 Roland McGrath <roland@redhat.com>
* sysdeps/hppa/shlib-versions: New file.

View file

@ -0,0 +1,82 @@
/* POSIX spinlock implementation. hppa version.
Copyright (C) 2000 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; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <pthread.h>
#include "internals.h"
int
__pthread_spin_lock (pthread_spinlock_t *lock)
{
volatile unsigned int *addr = __ldcw_align (lock);
while (__ldcw (addr) == 0)
while (*addr == 0) ;
return 0;
}
weak_alias (__pthread_spin_lock, pthread_spin_lock)
int
__pthread_spin_trylock (pthread_spinlock_t *lock)
{
volatile unsigned int *a = __ldcw_align (lock);
return __ldcw (a) ? 0 : EBUSY;
}
weak_alias (__pthread_spin_trylock, pthread_spin_trylock)
int
__pthread_spin_unlock (pthread_spinlock_t *lock)
{
volatile unsigned int *a = __ldcw_align (lock);
int tmp = 1;
/* This should be a memory barrier to newer compilers */
__asm__ __volatile__ ("stw,ma %1,0(%0)"
: : "r" (a), "r" (tmp) : "memory");
return 0;
}
weak_alias (__pthread_spin_unlock, pthread_spin_unlock)
int
__pthread_spin_init (pthread_spinlock_t *lock, int pshared)
{
/* We can ignore the `pshared' parameter. Since we are busy-waiting
all processes which can access the memory location `lock' points
to can use the spinlock. */
volatile unsigned int *a = __ldcw_align (lock);
int tmp = 1;
/* This should be a memory barrier to newer compilers */
__asm__ __volatile__ ("stw,ma %1,0(%0)"
: : "r" (a), "r" (tmp) : "memory");
return 0;
}
weak_alias (__pthread_spin_init, pthread_spin_init)
int
__pthread_spin_destroy (pthread_spinlock_t *lock)
{
/* Nothing to do. */
return 0;
}
weak_alias (__pthread_spin_destroy, pthread_spin_destroy)

View file

@ -0,0 +1,134 @@
/* Machine-dependent pthreads configuration and inline functions.
hppa version.
Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson <rth@tamu.edu>.
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; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _PT_MACHINE_H
#define _PT_MACHINE_H 1
#include <sys/types.h>
#include <bits/initspin.h>
#ifndef PT_EI
# define PT_EI extern inline __attribute__ ((always_inline))
#endif
extern inline long int testandset (__atomic_lock_t *spinlock);
extern inline int __compare_and_swap (long int *p, long int oldval, long int newval);
extern inline int lock_held (__atomic_lock_t *spinlock);
extern inline int __load_and_clear (__atomic_lock_t *spinlock);
/* Get some notion of the current stack. Need not be exactly the top
of the stack, just something somewhere in the current frame. */
#define CURRENT_STACK_FRAME stack_pointer
register char * stack_pointer __asm__ ("%r30");
/* Get/Set thread-specific pointer. We have to call into the kernel to
* modify it, but we can read it in user mode. */
#ifndef THREAD_SELF
#define THREAD_SELF __get_cr27()
#endif
#ifndef SET_THREAD_SELF
#define SET_THREAD_SELF(descr) __set_cr27(descr)
#endif
/* Use this to determine type */
struct _pthread_descr_struct *__thread_self;
static inline struct _pthread_descr_struct * __get_cr27(void)
{
long cr27;
asm ("mfctl %%cr27, %0" : "=r" (cr27) : );
return (struct _pthread_descr_struct *) cr27;
}
#ifndef INIT_THREAD_SELF
#define INIT_THREAD_SELF(descr, nr) __set_cr27(descr)
#endif
static inline void __set_cr27(struct _pthread_descr_struct * cr27)
{
asm ( "ble 0xe0(%%sr2, %%r0)\n\t"
"copy %0, %%r26"
: : "r" (cr27) : "r26" );
}
/* We want the OS to assign stack addresses. */
#define FLOATING_STACKS 1
#define ARCH_STACK_MAX_SIZE 8*1024*1024
/* The hppa only has one atomic read and modify memory operation,
load and clear, so hppa spinlocks must use zero to signify that
someone is holding the lock. The address used for the ldcw
semaphore must be 16-byte aligned. */
#define __ldcw(a) \
({ \
unsigned int __ret; \
__asm__ __volatile__("ldcw 0(%1),%0" \
: "=r" (__ret) : "r" (a) : "memory"); \
__ret; \
})
/* Strongly ordered lock reset */
#define __lock_reset(lock_addr, tmp) \
({ \
__asm__ __volatile__ ("stw,ma %1,0(%0)" \
: : "r" (lock_addr), "r" (tmp) : "memory"); \
})
/* Because malloc only guarantees 8-byte alignment for malloc'd data,
and GCC only guarantees 8-byte alignment for stack locals, we can't
be assured of 16-byte alignment for atomic lock data even if we
specify "__attribute ((aligned(16)))" in the type declaration. So,
we use a struct containing an array of four ints for the atomic lock
type and dynamically select the 16-byte aligned int from the array
for the semaphore. */
#define __PA_LDCW_ALIGNMENT 16
#define __ldcw_align(a) ({ \
volatile unsigned int __ret = (unsigned int) a; \
if ((__ret & ~(__PA_LDCW_ALIGNMENT - 1)) < (unsigned int) a) \
__ret = (__ret & ~(__PA_LDCW_ALIGNMENT - 1)) + __PA_LDCW_ALIGNMENT; \
(unsigned int *) __ret; \
})
/* Spinlock implementation; required. */
PT_EI int
__load_and_clear (__atomic_lock_t *spinlock)
{
volatile unsigned int *a = __ldcw_align (spinlock);
return __ldcw (a);
}
/* Emulate testandset */
PT_EI long int
testandset (__atomic_lock_t *spinlock)
{
return (__load_and_clear(spinlock) == 0);
}
PT_EI int
lock_held (__atomic_lock_t *spinlock)
{
volatile unsigned int *a = __ldcw_align (spinlock);
return *a == 0;
}
#endif /* pt-machine.h */

View file

@ -0,0 +1,163 @@
/* Definition for thread-local data handling. linuxthreads/hppa version.
Copyright (C) 2005 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
#ifndef __ASSEMBLER__
# include <pt-machine.h>
# include <stdbool.h>
# include <stddef.h>
/* Type for the dtv. */
typedef union dtv
{
size_t counter;
struct
{
void *val;
bool is_static;
} pointer;
} dtv_t;
#else /* __ASSEMBLER__ */
# include <tcb-offsets.h>
#endif /* __ASSEMBLER__ */
#if defined HAVE_TLS_SUPPORT
/* Signal that TLS support is available. */
# define USE_TLS 1
# ifndef __ASSEMBLER__
typedef struct
{
dtv_t *dtv;
void *private;
} tcbhead_t;
/* Include some syscall information for other headers */
# include <sysdep.h>
/* 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)
/* This is the size we need before TCB. */
# define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct)
/* Alignment requirements for the TCB. */
# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct)
/* The TLS blocks start right after the TCB. */
# define TLS_DTV_AT_TP 1
/* Return the thread descriptor for the current thread. */
# undef THREAD_SELF
# define THREAD_SELF \
({ struct _pthread_descr_struct *__self; \
__self = __get_cr27(); \
__self - 1; \
})
# undef INIT_THREAD_SELF
# define INIT_THREAD_SELF(descr, nr) \
({ struct _pthread_descr_struct *__self = (void *)descr; \
__set_cr27(__self + 1); \
0; \
})
/* Access to data in the thread descriptor is easy. */
#define THREAD_GETMEM(descr, member) \
((void) sizeof (descr), THREAD_SELF->member)
#define THREAD_GETMEM_NC(descr, member) \
((void) sizeof (descr), THREAD_SELF->member)
#define THREAD_SETMEM(descr, member, value) \
((void) sizeof (descr), THREAD_SELF->member = (value))
#define THREAD_SETMEM_NC(descr, member, value) \
((void) sizeof (descr), THREAD_SELF->member = (value))
/* 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) \
({ tcbhead_t *__tcbp = (tcbhead_t *)__get_cr27(); \
__tcbp->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) \
({ __set_cr27(tcbp); 0; })
/* Return the address of the dtv for the current thread. */
# define THREAD_DTV() \
({ tcbhead_t *__tcbp = (tcbhead_t *)__get_cr27(); \
__tcbp->dtv; \
})
# define TLS_MULTIPLE_THREADS_IN_TCB 1
/* Get the thread descriptor definition. This must be after the
the definition of THREAD_SELF for TLS. */
# include <linuxthreads/descr.h>
# endif /* __ASSEMBLER__ */
#else
# ifndef __ASSEMBLER__
typedef struct
{
void *tcb;
dtv_t *dtv;
void *self;
int multiple_threads;
} tcbhead_t;
/* Get the thread descriptor definition. */
# include <linuxthreads/descr.h>
# define NONTLS_INIT_TP \
do { \
static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 }; \
INIT_THREAD_SELF(&nontls_init_tp, 0); \
} while (0)
# endif /* __ASSEMBLER__ */
#endif /* HAVE_TLS_SUPPORT */
#endif /* tls.h */

View file

@ -0,0 +1,33 @@
#include <shlib-compat.h>
#define aio_cancel64 XXX
#include <aio.h>
#undef aio_cancel64
#include <errno.h>
extern __typeof (aio_cancel) __new_aio_cancel;
extern __typeof (aio_cancel) __old_aio_cancel;
#define aio_cancel __new_aio_cancel
#include <sysdeps/pthread/aio_cancel.c>
#undef aio_cancel
strong_alias (__new_aio_cancel, __new_aio_cancel64);
versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3);
versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3);
#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3)
#undef ECANCELED
#define aio_cancel __old_aio_cancel
#define ECANCELED 125
#include <sysdeps/pthread/aio_cancel.c>
#undef aio_cancel
strong_alias (__old_aio_cancel, __old_aio_cancel64);
compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1);
compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1);
#endif

View file

@ -0,0 +1,41 @@
/* PA-RISC specific definitions for spinlock initializers.
Copyright (C) 2000, 2001 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; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Initial value of a spinlock. PA-RISC only implements atomic load
and clear so this must be non-zero. */
#define __LT_SPINLOCK_INIT ((__atomic_lock_t) { { 1, 1, 1, 1 } })
/* Initialize global spinlocks without cast, generally macro wrapped */
#define __LT_SPINLOCK_ALT_INIT { { 1, 1, 1, 1 } }
/* Macros for lock initializers, not using the above definition.
The above definition is not used in the case that static initializers
use this value. */
#define __LOCK_ALT_INITIALIZER { __LT_SPINLOCK_ALT_INIT, 0 }
/* Used to initialize _pthread_fastlock's in non-static case */
#define __LOCK_INITIALIZER ((struct _pthread_fastlock){ __LT_SPINLOCK_INIT, 0 })
/* Used in pthread_atomic initialization */
#define __ATOMIC_INITIALIZER { 0, __LT_SPINLOCK_ALT_INIT }
/* Tell the rest of the code that the initializer is non-zero without
explaining it's internal structure */
#define __LT_INITIALIZER_NOT_ZERO

View file

@ -0,0 +1,160 @@
/* Linuxthreads - a simple clone()-based implementation of Posix */
/* threads for Linux. */
/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
/* */
/* This program is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU Library General Public License */
/* as published by the Free Software Foundation; either version 2 */
/* of the License, or (at your option) any later version. */
/* */
/* This program 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 Library General Public License for more details. */
#if !defined _BITS_TYPES_H && !defined _PTHREAD_H
# error "Never include <bits/pthreadtypes.h> directly; use <sys/types.h> instead."
#endif
#ifndef _BITS_PTHREADTYPES_H
#define _BITS_PTHREADTYPES_H 1
#define __need_schedparam
#include <bits/sched.h>
/* We need 128-bit alignment for the ldcw semaphore. At most, we are
assured of 64-bit alignment for stack locals and malloc'd data. Thus,
we use a struct with four ints for the atomic lock type. The locking
code will figure out which of the four to use for the ldcw semaphore. */
typedef volatile struct {
int lock[4];
} __attribute__ ((aligned(16))) __atomic_lock_t;
/* Fast locks (not abstract because mutexes and conditions aren't abstract). */
struct _pthread_fastlock
{
__atomic_lock_t __spinlock; /* Used by compare_and_swap emulation. Also,
adaptive SMP lock stores spin count here. */
long int __status; /* "Free" or "taken" or head of waiting list */
};
#ifndef _PTHREAD_DESCR_DEFINED
/* Thread descriptors */
typedef struct _pthread_descr_struct *_pthread_descr;
# define _PTHREAD_DESCR_DEFINED
#endif
/* Attributes for threads. */
typedef struct __pthread_attr_s
{
int __detachstate;
int __schedpolicy;
struct __sched_param __schedparam;
int __inheritsched;
int __scope;
size_t __guardsize;
int __stackaddr_set;
void *__stackaddr;
size_t __stacksize;
} pthread_attr_t;
/* Conditions (not abstract because of PTHREAD_COND_INITIALIZER */
#ifdef __GLIBC_HAVE_LONG_LONG
__extension__ typedef long long __pthread_cond_align_t;
#else
typedef long __pthread_cond_align_t;
#endif
typedef struct
{
struct _pthread_fastlock __c_lock; /* Protect against concurrent access */
_pthread_descr __c_waiting; /* Threads waiting on this condition */
char __padding[48 - sizeof (struct _pthread_fastlock)
- sizeof (_pthread_descr) - sizeof (__pthread_cond_align_t)];
__pthread_cond_align_t __align;
} pthread_cond_t;
/* Attribute for conditionally variables. */
typedef struct
{
int __dummy;
} pthread_condattr_t;
/* Keys for thread-specific data */
typedef unsigned int pthread_key_t;
/* Mutexes (not abstract because of PTHREAD_MUTEX_INITIALIZER). */
/* (The layout is unnatural to maintain binary compatibility
with earlier releases of LinuxThreads.) */
typedef struct
{
int __m_reserved; /* Reserved for future use */
int __m_count; /* Depth of recursive locking */
_pthread_descr __m_owner; /* Owner thread (if recursive or errcheck) */
int __m_kind; /* Mutex kind: fast, recursive or errcheck */
struct _pthread_fastlock __m_lock; /* Underlying fast lock */
} pthread_mutex_t;
/* Attribute for mutex. */
typedef struct
{
int __mutexkind;
} pthread_mutexattr_t;
/* Once-only execution */
typedef int pthread_once_t;
#ifdef __USE_UNIX98
/* Read-write locks. */
typedef struct _pthread_rwlock_t
{
struct _pthread_fastlock __rw_lock; /* Lock to guarantee mutual exclusion */
int __rw_readers; /* Number of readers */
_pthread_descr __rw_writer; /* Identity of writer, or NULL if none */
_pthread_descr __rw_read_waiting; /* Threads waiting for reading */
_pthread_descr __rw_write_waiting; /* Threads waiting for writing */
int __rw_kind; /* Reader/Writer preference selection */
int __rw_pshared; /* Shared between processes or not */
} pthread_rwlock_t;
/* Attribute for read-write locks. */
typedef struct
{
int __lockkind;
int __pshared;
} pthread_rwlockattr_t;
#endif
#ifdef __USE_XOPEN2K
/* POSIX spinlock data type. */
typedef __atomic_lock_t pthread_spinlock_t;
/* POSIX barrier. */
typedef struct {
struct _pthread_fastlock __ba_lock; /* Lock to guarantee mutual exclusion */
int __ba_required; /* Threads needed for completion */
int __ba_present; /* Threads waiting */
_pthread_descr __ba_waiting; /* Queue of waiting threads */
} pthread_barrier_t;
/* barrier attribute */
typedef struct {
int __pshared;
} pthread_barrierattr_t;
#endif
/* Thread identifiers */
typedef unsigned long int pthread_t;
#endif /* bits/pthreadtypes.h */

View file

@ -0,0 +1,73 @@
/* HP-PARISC macro definitions for mutexes, thread-specific data
and parameters for malloc.
Copyright (C) 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Carlos O'Donell <carlos@baldric.uwo.ca>, 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 _MALLOC_MACHINE_H
#define _MALLOC_MACHINE_H
#undef thread_atfork_static
#include <atomic.h>
#include <bits/libc-lock.h>
__libc_lock_define (typedef, mutex_t)
/* Since our lock structure does not tolerate being initialized to zero, we must
modify the standard function calls made by malloc */
# define mutex_init(m) \
__libc_maybe_call (__pthread_mutex_init, (m, NULL), \
(((m)->__m_lock.__spinlock = __LT_SPINLOCK_INIT),(*(int *)(m))) )
# define mutex_lock(m) \
__libc_maybe_call (__pthread_mutex_lock, (m), \
(__load_and_clear(&((m)->__m_lock.__spinlock)), 0))
# define mutex_trylock(m) \
__libc_maybe_call (__pthread_mutex_trylock, (m), \
(*(int *)(m) ? 1 : (__load_and_clear(&((m)->__m_lock.__spinlock)), 0)))
# define mutex_unlock(m) \
__libc_maybe_call (__pthread_mutex_unlock, (m), \
(((m)->__m_lock.__spinlock = __LT_SPINLOCK_INIT), (*(int *)(m))) )
/* This is defined by newer gcc version unique for each module. */
extern void *__dso_handle __attribute__ ((__weak__));
#include <fork.h>
#ifdef SHARED
# define thread_atfork(prepare, parent, child) \
__register_atfork (prepare, parent, child, __dso_handle)
#else
# define thread_atfork(prepare, parent, child) \
__register_atfork (prepare, parent, child, \
&__dso_handle == NULL ? NULL : __dso_handle)
#endif
/* thread specific data for glibc */
#include <bits/libc-tsd.h>
typedef int tsd_key_t[1]; /* no key data structure, libc magic does it */
__libc_tsd_define (static, MALLOC) /* declaration/common definition */
#define tsd_key_create(key, destr) ((void) (key))
#define tsd_setspecific(key, data) __libc_tsd_set (MALLOC, (data))
#define tsd_getspecific(key, vptr) ((vptr) = __libc_tsd_get (MALLOC))
#include <sysdeps/generic/malloc-machine.h>
#endif /* !defined(_MALLOC_MACHINE_H) */

View file

@ -0,0 +1,109 @@
/* Special .init and .fini section support for HPPA. Linuxthreads version.
Copyright (C) 2001, 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
The GNU C Library is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* This file is compiled into assembly code which is then munged by a sed
script into two files: crti.s and crtn.s.
* crti.s puts a function prologue at the beginning of the
.init and .fini sections and defines global symbols for
those addresses, so they can be called as functions.
* crtn.s puts the corresponding function epilogues
in the .init and .fini sections. */
/* If we use the standard C version, the linkage table pointer won't
be properly preserved due to the splitting up of function prologues
and epilogues. Therefore we write these in assembly to make sure
they do the right thing. */
__asm__ (
"#include \"defs.h\"\n"
"\n"
"/*@HEADER_ENDS*/\n"
"\n"
"/*@_init_PROLOG_BEGINS*/\n"
" .section .init\n"
" .align 4\n"
" .globl _init\n"
" .type _init,@function\n"
"_init:\n"
" stw %rp,-20(%sp)\n"
" stwm %r4,64(%sp)\n"
" stw %r19,-32(%sp)\n"
" bl __pthread_initialize_minimal,%rp\n"
" copy %r19,%r4 /* delay slot */\n"
" copy %r4,%r19\n"
"/*@_init_PROLOG_ENDS*/\n"
"\n"
"/*@_init_EPILOG_BEGINS*/\n"
"/* Here is the tail end of _init. */\n"
" .section .init\n"
" ldw -84(%sp),%rp\n"
" copy %r4,%r19\n"
" bv %r0(%rp)\n"
"_end_init:\n"
" ldwm -64(%sp),%r4\n"
"\n"
"/* Our very own unwind info, because the assembler can't handle\n"
" functions split into two or more pieces. */\n"
" .section .PARISC.unwind,\"a\",@progbits\n"
" .extern _init\n"
" .word _init, _end_init\n"
" .byte 0x08, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08\n"
"\n"
"/*@_init_EPILOG_ENDS*/\n"
"\n"
"/*@_fini_PROLOG_BEGINS*/\n"
" .section .fini\n"
" .align 4\n"
" .globl _fini\n"
" .type _fini,@function\n"
"_fini:\n"
" stw %rp,-20(%sp)\n"
" stwm %r4,64(%sp)\n"
" stw %r19,-32(%sp)\n"
" copy %r19,%r4\n"
"/*@_fini_PROLOG_ENDS*/\n"
"\n"
"/*@_fini_EPILOG_BEGINS*/\n"
" .section .fini\n"
" ldw -84(%sp),%rp\n"
" copy %r4,%r19\n"
" bv %r0(%rp)\n"
"_end_fini:\n"
" ldwm -64(%sp),%r4\n"
"\n"
" .section .PARISC.unwind,\"a\",@progbits\n"
" .extern _fini\n"
" .word _fini, _end_fini\n"
" .byte 0x08, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08\n"
"\n"
"/*@_fini_EPILOG_ENDS*/\n"
"\n"
"/*@TRAILER_BEGINS*/\n"
);

View file

@ -0,0 +1,238 @@
/* cancellable system calls for Linux/HPPA.
Copyright (C) 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Carlos O'Donell <carlos@baldric.uwo.ca>, 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 <linuxthreads/internals.h>
#endif
#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
# ifndef NO_ERROR
# define NO_ERROR -0x1000
# endif
/* The syscall cancellation mechanism requires userspace
assistance, the following code does roughly this:
do arguments (read arg5 and arg6 to registers)
setup frame
check if there are threads, yes jump to pseudo_cancel
unthreaded:
syscall
check syscall return (jump to pre_end)
set errno
set return to -1
(jump to pre_end)
pseudo_cancel:
cenable
syscall
cdisable
check syscall return (jump to pre_end)
set errno
set return to -1
pre_end
restore stack
It is expected that 'ret' and 'END' macros will
append an 'undo arguments' and 'return' to the
this PSEUDO macro. */
# undef PSEUDO
# define PSEUDO(name, syscall_name, args) \
ENTRY (name) \
DOARGS_##args ASM_LINE_SEP \
copy TREG, %r1 ASM_LINE_SEP \
copy %sp, TREG ASM_LINE_SEP \
stwm %r1, 64(%sp) ASM_LINE_SEP \
stw %rp, -20(%sp) ASM_LINE_SEP \
stw TREG, -4(%sp) ASM_LINE_SEP \
/* Done setting up frame, continue... */ ASM_LINE_SEP \
SINGLE_THREAD_P ASM_LINE_SEP \
cmpib,<>,n 0,%ret0,L(pseudo_cancel) ASM_LINE_SEP \
L(unthreaded): ASM_LINE_SEP \
/* Save r19 */ ASM_LINE_SEP \
SAVE_PIC(TREG) ASM_LINE_SEP \
/* Do syscall, delay loads # */ ASM_LINE_SEP \
ble 0x100(%sr2,%r0) ASM_LINE_SEP \
ldi SYS_ify (syscall_name), %r20 /* delay */ ASM_LINE_SEP \
ldi NO_ERROR,%r1 ASM_LINE_SEP \
cmpb,>>=,n %r1,%ret0,L(pre_end) ASM_LINE_SEP \
/* Restore r19 from TREG */ ASM_LINE_SEP \
LOAD_PIC(TREG) /* delay */ ASM_LINE_SEP \
SYSCALL_ERROR_HANDLER ASM_LINE_SEP \
/* Use TREG for temp storage */ ASM_LINE_SEP \
copy %ret0, TREG /* delay */ ASM_LINE_SEP \
/* OPTIMIZE: Don't reload r19 */ ASM_LINE_SEP \
/* do a -1*syscall_ret0 */ ASM_LINE_SEP \
sub %r0, TREG, TREG ASM_LINE_SEP \
/* Store into errno location */ ASM_LINE_SEP \
stw TREG, 0(%sr0,%ret0) ASM_LINE_SEP \
b L(pre_end) ASM_LINE_SEP \
/* return -1 as error */ ASM_LINE_SEP \
ldo -1(%r0), %ret0 /* delay */ ASM_LINE_SEP \
L(pseudo_cancel): ASM_LINE_SEP \
PUSHARGS_##args /* Save args */ ASM_LINE_SEP \
/* Save r19 into TREG */ ASM_LINE_SEP \
CENABLE /* FUNC CALL */ ASM_LINE_SEP \
SAVE_PIC(TREG) /* delay */ ASM_LINE_SEP \
/* restore syscall args */ ASM_LINE_SEP \
POPARGS_##args ASM_LINE_SEP \
/* save mask from cenable (use stub rp slot) */ ASM_LINE_SEP \
stw %ret0, -24(%sp) ASM_LINE_SEP \
/* ... SYSCALL ... */ ASM_LINE_SEP \
ble 0x100(%sr2,%r0) ASM_LINE_SEP \
ldi SYS_ify (syscall_name), %r20 /* delay */ ASM_LINE_SEP \
/* ............... */ ASM_LINE_SEP \
LOAD_PIC(TREG) ASM_LINE_SEP \
/* pass mask as arg0 to cdisable */ ASM_LINE_SEP \
ldw -24(%sp), %r26 ASM_LINE_SEP \
CDISABLE ASM_LINE_SEP \
stw %ret0, -24(%sp) /* delay */ ASM_LINE_SEP \
/* Restore syscall return */ ASM_LINE_SEP \
ldw -24(%sp), %ret0 ASM_LINE_SEP \
/* compare error */ ASM_LINE_SEP \
ldi NO_ERROR,%r1 ASM_LINE_SEP \
/* branch if no error */ ASM_LINE_SEP \
cmpb,>>=,n %r1,%ret0,L(pre_end) ASM_LINE_SEP \
LOAD_PIC(TREG) /* cond. nullify */ ASM_LINE_SEP \
copy %ret0, TREG /* save syscall return */ ASM_LINE_SEP \
SYSCALL_ERROR_HANDLER ASM_LINE_SEP \
/* make syscall res value positive */ ASM_LINE_SEP \
sub %r0, TREG, TREG /* delay */ ASM_LINE_SEP \
/* No need to LOAD_PIC */ ASM_LINE_SEP \
/* store into errno location */ ASM_LINE_SEP \
stw TREG, 0(%sr0,%ret0) ASM_LINE_SEP \
/* return -1 */ ASM_LINE_SEP \
ldo -1(%r0), %ret0 ASM_LINE_SEP \
L(pre_end): ASM_LINE_SEP \
/* Restore rp before exit */ ASM_LINE_SEP \
ldw -84(%sr0,%sp), %rp ASM_LINE_SEP \
/* Undo frame */ ASM_LINE_SEP \
ldwm -64(%sp),TREG ASM_LINE_SEP \
/* No need to LOAD_PIC */ ASM_LINE_SEP
/* Save arguments into our frame */
# define PUSHARGS_0 /* nothing to do */
# define PUSHARGS_1 PUSHARGS_0 stw %r26, -36(%sr0,%sp) ASM_LINE_SEP
# define PUSHARGS_2 PUSHARGS_1 stw %r25, -40(%sr0,%sp) ASM_LINE_SEP
# define PUSHARGS_3 PUSHARGS_2 stw %r24, -44(%sr0,%sp) ASM_LINE_SEP
# define PUSHARGS_4 PUSHARGS_3 stw %r23, -48(%sr0,%sp) ASM_LINE_SEP
# define PUSHARGS_5 PUSHARGS_4 stw %r22, -52(%sr0,%sp) ASM_LINE_SEP
# define PUSHARGS_6 PUSHARGS_5 stw %r21, -56(%sr0,%sp) ASM_LINE_SEP
/* Bring them back from the stack */
# define POPARGS_0 /* nothing to do */
# define POPARGS_1 POPARGS_0 ldw -36(%sr0,%sp), %r26 ASM_LINE_SEP
# define POPARGS_2 POPARGS_1 ldw -40(%sr0,%sp), %r25 ASM_LINE_SEP
# define POPARGS_3 POPARGS_2 ldw -44(%sr0,%sp), %r24 ASM_LINE_SEP
# define POPARGS_4 POPARGS_3 ldw -48(%sr0,%sp), %r23 ASM_LINE_SEP
# define POPARGS_5 POPARGS_4 ldw -52(%sr0,%sp), %r22 ASM_LINE_SEP
# define POPARGS_6 POPARGS_5 ldw -56(%sr0,%sp), %r21 ASM_LINE_SEP
# ifdef IS_IN_libpthread
# ifdef PIC
# define CENABLE .import __pthread_enable_asynccancel,code ASM_LINE_SEP \
bl __pthread_enable_asynccancel,%r2 ASM_LINE_SEP
# define CDISABLE .import __pthread_disable_asynccancel,code ASM_LINE_SEP \
bl __pthread_disable_asynccancel,%r2 ASM_LINE_SEP
# else
# define CENABLE .import __pthread_enable_asynccancel,code ASM_LINE_SEP \
bl __pthread_enable_asynccancel,%r2 ASM_LINE_SEP
# define CDISABLE .import __pthread_disable_asynccancel,code ASM_LINE_SEP \
bl __pthread_disable_asynccancel,%r2 ASM_LINE_SEP
# endif
# elif !defined NOT_IN_libc
# ifdef PIC
# define CENABLE .import __libc_enable_asynccancel,code ASM_LINE_SEP \
bl __libc_enable_asynccancel,%r2 ASM_LINE_SEP
# define CDISABLE .import __libc_disable_asynccancel,code ASM_LINE_SEP \
bl __libc_disable_asynccancel,%r2 ASM_LINE_SEP
# else
# define CENABLE .import __libc_enable_asynccancel,code ASM_LINE_SEP \
bl __libc_enable_asynccancel,%r2 ASM_LINE_SEP
# define CDISABLE .import __libc_disable_asynccancel,code ASM_LINE_SEP \
bl __libc_disable_asynccancel,%r2 ASM_LINE_SEP
# endif
# else
# ifdef PIC
# define CENABLE .import __librt_enable_asynccancel,code ASM_LINE_SEP \
bl __librt_enable_asynccancel,%r2 ASM_LINE_SEP
# define CDISABLE .import __librt_disable_asynccancel,code ASM_LINE_SEP \
bl __librt_disable_asynccancel,%r2 ASM_LINE_SEP
# else
# define CENABLE .import __librt_enable_asynccancel,code ASM_LINE_SEP \
bl __librt_enable_asynccancel,%r2 ASM_LINE_SEP
# define CDISABLE .import __librt_disable_asynccancel,code ASM_LINE_SEP \
bl __librt_disable_asynccancel,%r2 ASM_LINE_SEP
# endif
# endif
/* p_header.multiple_threads is +12 from the pthread_descr struct start,
We could have called __get_cr27() but we really want less overhead */
# define MULTIPLE_THREADS_OFFSET 0xC
/* cr27 has been initialized to 0x0 by kernel */
# define NO_THREAD_CR27 0x0
# ifdef IS_IN_libpthread
# define __local_multiple_threads __pthread_multiple_threads
# elif !defined NOT_IN_libc
# define __local_multiple_threads __libc_multiple_threads
# else
# define __local_multiple_threads __librt_multiple_threads
# endif
# ifndef __ASSEMBLER__
extern int __local_multiple_threads attribute_hidden;
# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
# else
/* This ALT version requires newer kernel support */
# define SINGLE_THREAD_P_MFCTL \
mfctl %cr27, %ret0 ASM_LINE_SEP \
cmpib,= NO_THREAD_CR27,%ret0,L(stp) ASM_LINE_SEP \
nop ASM_LINE_SEP \
ldw MULTIPLE_THREADS_OFFSET(%sr0,%ret0),%ret0 ASM_LINE_SEP \
L(stp): ASM_LINE_SEP
# ifdef PIC
/* Slower version uses GOT to get value of __local_multiple_threads */
# define SINGLE_THREAD_P \
addil LT%__local_multiple_threads, %r19 ASM_LINE_SEP \
ldw RT%__local_multiple_threads(%sr0,%r1), %ret0 ASM_LINE_SEP \
ldw 0(%sr0,%ret0), %ret0 ASM_LINE_SEP
# else
/* Slow non-pic version using DP */
# define SINGLE_THREAD_P \
addil LR%__local_multiple_threads-$global$,%r27 ASM_LINE_SEP \
ldw RR%__local_multiple_threads-$global$(%sr0,%r1),%ret0 ASM_LINE_SEP
# endif
# endif
#elif !defined __ASSEMBLER__
/* This code should never be used but we define it anyhow. */
# define SINGLE_THREAD_P (1)
#endif
/* !defined NOT_IN_libc || defined IS_IN_libpthread */