2006-07-13 Carlos O'Donell <carlos@systemhalted.org>

* sysdeps/unix/sysv/linux/hppa/xstat.c: New file.
	* sysdeps/unix/sysv/linux/hppa/lxstat.c: Likewise.
	* sysdeps/unix/sysv/linux/hppa/fxstat.c: Likewise.
	* sysdeps/unix/sysv/linux/hppa/fxstatat.c: Likewise.

2006-07-13  Carlos O'Donell  <carlos@systemhalted.org>

	* sysdeps/hppa/nptl/Makefile: New file
	* sysdeps/hppa/nptl/jmpbuf-unwind.h: Likewise
	* sysdeps/hppa/nptl/pthread_spin_lock.c: Likewise
	* sysdeps/hppa/nptl/pthread_spin_trylock.c: Likewise
	* sysdeps/hppa/nptl/pthread_spin_unlock.c: Likewise
	* sysdeps/hppa/nptl/pthreaddef.h: Likewise
	* sysdeps/hppa/nptl/tcb-offsets.sym: Likewise
	* sysdeps/hppa/nptl/tls.h: Likewise
	* sysdeps/unix/sysv/linux/hppa/nptl/bits: Likewise
	* sysdeps/unix/sysv/linux/hppa/nptl/createthread.c: Likewise
	* sysdeps/unix/sysv/linux/hppa/nptl/fork.c: Likewise
	* sysdeps/unix/sysv/linux/hppa/nptl/internaltypes.h: Likewise
	* sysdeps/unix/sysv/linux/hppa/nptl/libc-lowlevellock.c: Likewise
	* sysdeps/unix/sysv/linux/hppa/nptl/lowlevellock.c: Likewise
	* sysdeps/unix/sysv/linux/hppa/nptl/lowlevellock.h: Likewise
	* sysdeps/unix/sysv/linux/hppa/nptl/pt-initfini.c: Likewise
	* sysdeps/unix/sysv/linux/hppa/nptl/pt-vfork.S: Likewise
	* sysdeps/unix/sysv/linux/hppa/nptl/pthread_once.c: Likewise
	* sysdeps/unix/sysv/linux/hppa/nptl/sysdep-cancel.h: Likewise
	* sysdeps/unix/sysv/linux/hppa/nptl/unwind-forcedunwind.c: Likewise
	* sysdeps/unix/sysv/linux/hppa/nptl/unwind-resume.c: Likewise
This commit is contained in:
Carlos O'Donell 2006-07-14 13:51:24 +00:00
parent b725f54b9a
commit da1ea0f056
27 changed files with 1884 additions and 0 deletions

View File

@ -1,5 +1,36 @@
2006-07-13 Carlos O'Donell <carlos@systemhalted.org> 2006-07-13 Carlos O'Donell <carlos@systemhalted.org>
* sysdeps/unix/sysv/linux/hppa/xstat.c: New file.
* sysdeps/unix/sysv/linux/hppa/lxstat.c: Likewise.
* sysdeps/unix/sysv/linux/hppa/fxstat.c: Likewise.
* sysdeps/unix/sysv/linux/hppa/fxstatat.c: Likewise.
2006-07-13 Carlos O'Donell <carlos@systemhalted.org>
* sysdeps/hppa/nptl/Makefile: New file
* sysdeps/hppa/nptl/jmpbuf-unwind.h: Likewise
* sysdeps/hppa/nptl/pthread_spin_lock.c: Likewise
* sysdeps/hppa/nptl/pthread_spin_trylock.c: Likewise
* sysdeps/hppa/nptl/pthread_spin_unlock.c: Likewise
* sysdeps/hppa/nptl/pthreaddef.h: Likewise
* sysdeps/hppa/nptl/tcb-offsets.sym: Likewise
* sysdeps/hppa/nptl/tls.h: Likewise
* sysdeps/unix/sysv/linux/hppa/nptl/bits: Likewise
* sysdeps/unix/sysv/linux/hppa/nptl/createthread.c: Likewise
* sysdeps/unix/sysv/linux/hppa/nptl/fork.c: Likewise
* sysdeps/unix/sysv/linux/hppa/nptl/internaltypes.h: Likewise
* sysdeps/unix/sysv/linux/hppa/nptl/libc-lowlevellock.c: Likewise
* sysdeps/unix/sysv/linux/hppa/nptl/lowlevellock.c: Likewise
* sysdeps/unix/sysv/linux/hppa/nptl/lowlevellock.h: Likewise
* sysdeps/unix/sysv/linux/hppa/nptl/pt-initfini.c: Likewise
* sysdeps/unix/sysv/linux/hppa/nptl/pt-vfork.S: Likewise
* sysdeps/unix/sysv/linux/hppa/nptl/pthread_once.c: Likewise
* sysdeps/unix/sysv/linux/hppa/nptl/sysdep-cancel.h: Likewise
* sysdeps/unix/sysv/linux/hppa/nptl/unwind-forcedunwind.c: Likewise
* sysdeps/unix/sysv/linux/hppa/nptl/unwind-resume.c: Likewise
2006-06-08 Carlos O'Donell <carlos@systemhalted.org>
* sysdeps/unix/sysv/linux/hppa/Versions: new errlist compat entry * sysdeps/unix/sysv/linux/hppa/Versions: new errlist compat entry
for up to 256 errnos for up to 256 errnos

View File

@ -0,0 +1,21 @@
# 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.
ifeq ($(subdir),csu)
gen-as-const-headers += tcb-offsets.sym
endif

View File

@ -0,0 +1,31 @@
/* Copyright (C) 2003, 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. */
#include <setjmp.h>
#include <jmpbuf-offsets.h>
#include <stdint.h>
#include <unwind.h>
#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
_JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
((uintptr_t) (_address) - (_adj) > (uintptr_t)(((unsigned long *) _jmpbuf)[JB_SP]) - (_adj))
/* We use the normal longjmp for unwinding. */
#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val)

View File

@ -0,0 +1,38 @@
/* 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. */
#include <atomic.h>
#include "pthreadP.h"
int
pthread_spin_lock (pthread_spinlock_t *lock)
{
#if 0
volatile unsigned int *addr = __ldcw_align (lock);
while (__ldcw (addr) == 0)
while (*addr == 0) ;
return 0;
#endif
while (atomic_compare_and_exchange_val_acq(lock, 0, 1) == 1)
while (*lock == 1);
return 0;
}

View File

@ -0,0 +1,34 @@
/* 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. */
#include <errno.h>
#include <atomic.h>
#include "pthreadP.h"
int
pthread_spin_trylock (pthread_spinlock_t *lock)
{
#if 0
volatile unsigned int *a = __ldcw_align (lock);
return __ldcw (a) ? 0 : EBUSY;
#endif
return atomic_compare_and_exchange_val_acq(lock, 0, 1) ? EBUSY : 0;
}

View File

@ -0,0 +1,36 @@
/* 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. */
/* Ugly hack to avoid the declaration of pthread_spin_init. */
#define pthread_spin_init pthread_spin_init_XXX
#include "pthreadP.h"
#undef pthread_spin_init
int
pthread_spin_unlock (pthread_spinlock_t *lock)
{
#if 0
volatile unsigned int *a = __ldcw_align (lock);
#endif
int tmp = 0;
/* This should be a memory barrier to newer compilers */
__asm__ __volatile__ ("stw,ma %1,0(%0)"
: : "r" (lock), "r" (tmp) : "memory");
return 0;
}
strong_alias (pthread_spin_unlock, pthread_spin_init)

View File

@ -0,0 +1,40 @@
/* Copyright (C) 2002, 2003, 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. */
/* Default stack size. */
#define ARCH_STACK_DEFAULT_SIZE (8 * 1024 * 1024)
/* Required stack pointer alignment at beginning. */
#define STACK_ALIGN 64
/* Minimal stack size after allocating thread descriptor and guard size. */
#define MINIMAL_REST_STACK 2048
/* Alignment requirement for TCB, note that this must be larger than STACK_ALIGN */
#define TCB_ALIGNMENT STACK_ALIGN
/* Location of current stack frame. */
#define CURRENT_STACK_FRAME stack_pointer
register char * stack_pointer __asm__ ("%r30");
/* XXX Until we have a better place keep the definitions here. */
#define __exit_thread_inline(val) \
INLINE_SYSCALL (exit, 1, (val))

View File

@ -0,0 +1,18 @@
#include <sysdep.h>
#include <tls.h>
RESULT offsetof (struct pthread, result)
TID offsetof (struct pthread, tid)
PID offsetof (struct pthread, pid)
CANCELHANDLING offsetof (struct pthread, cancelhandling)
CLEANUP_JMP_BUF offsetof (struct pthread, cleanup_jmp_buf)
MULTIPLE_THREADS_OFFSET offsetof (struct pthread, header.multiple_threads)
TLS_PRE_TCB_SIZE sizeof (struct pthread)
MUTEX_FUTEX offsetof (pthread_mutex_t, __data.__lock)
-- Use a thread_offset when working with asm to make things simpler
-- This way we get the offset of a member in the struct pthread that
-- preceeds the thread pointer (which points to the dtv).
#define thread_offsetof(mem) (unsigned int)(offsetof(struct pthread, mem) - sizeof(struct pthread))
PID_THREAD_OFFSET thread_offsetof (pid)
MULTIPLE_THREADS_THREAD_OFFSET thread_offsetof (header.multiple_threads)

151
sysdeps/hppa/nptl/tls.h Normal file
View File

@ -0,0 +1,151 @@
/* Definition for thread-local data handling. NPTL/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 1
#include <dl-sysdep.h>
#ifndef __ASSEMBLER__
# include <stdbool.h>
# include <stddef.h>
# include <stdint.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__ */
/* We require TLS support in the tools. */
#ifndef HAVE_TLS_SUPPORT
# error "TLS support is required."
#endif
/* Signal that TLS support is available. */
#define USE_TLS 1
#ifndef __ASSEMBLER__
/* Get system call information. */
# include <sysdep.h>
/* The TP points to the start of the thread blocks. */
# define TLS_DTV_AT_TP 1
/* Get the thread descriptor definition. */
# include <nptl/descr.h>
typedef struct
{
dtv_t *dtv;
void *private;
} 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__ (struct pthread)
/* This is the size we need before TCB */
# define TLS_PRE_TCB_SIZE sizeof (struct pthread)
/* 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; \
})
/* Return the thread descriptor for the current thread. */
# define THREAD_SELF \
({ struct pthread *__self; \
__self = __get_cr27(); \
__self - 1; \
})
/* FIXME */
/* Magic for libthread_db to know how to do THREAD_SELF. */
# define DB_THREAD_SELF \
REGISTER (32, 32, 32 * 4, -sizeof (struct pthread))
/* Access to data in the thread descriptor is easy. */
# define THREAD_GETMEM(descr, member) \
descr->member
# define THREAD_GETMEM_NC(descr, member, idx) \
descr->member[idx]
# define THREAD_SETMEM(descr, member, value) \
descr->member = (value)
# define THREAD_SETMEM_NC(descr, member, idx, value) \
descr->member[idx] = (value)
static inline struct pthread *__get_cr27(void)
{
long cr27;
asm ("mfctl %%cr27, %0" : "=r" (cr27) : );
return (struct pthread *) cr27;
}
static inline void __set_cr27(struct pthread *cr27)
{
asm ( "ble 0xe0(%%sr2, %%r0)\n\t"
"copy %0, %%r26"
: : "r" (cr27) : "r26" );
}
#endif /* __ASSEMBLER__ */
#endif /* tls.h */

View File

@ -0,0 +1 @@
#include <sysdeps/unix/sysv/linux/i386/fxstat.c>

View File

@ -0,0 +1 @@
#include <sysdeps/unix/sysv/linux/i386/fxstatat.c>

View File

@ -0,0 +1 @@
#include <sysdeps/unix/sysv/linux/i386/lxstat.c>

View File

@ -0,0 +1,192 @@
/* Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _BITS_PTHREADTYPES_H
#define _BITS_PTHREADTYPES_H 1
/* Linuxthread type sizes:
sizeof(pthread_attr_t) = 0x24 (36)
sizeof(pthread_mutex_t) = 0x30 (48)
sizeof(pthread_mutexattr_t) = 0x4 (4)
sizeof(pthread_cond_t) = 0x30 (48)
No pthread_cond_compat_t ...
sizeof(pthread_condattr_t) = 0x4 (4)
sizeof(pthread_rwlock_t) = 0x40 (64)
sizeof(pthread_rwlockattr_t) = 0x8 (8)
sizeof(pthread_barrier_t) = 0x30 (48)
sizeof(pthread_barrierattr_t) = 0x4 (4) */
#define __SIZEOF_PTHREAD_ATTR_T 36
#define __SIZEOF_PTHREAD_MUTEX_T 48
#define __SIZEOF_PTHREAD_MUTEXATTR_T 4
#define __SIZEOF_PTHREAD_COND_T 48
#define __SIZEOF_PTHREAD_COND_COMPAT_T 12
#define __SIZEOF_PTHREAD_CONDATTR_T 4
#define __SIZEOF_PTHREAD_RWLOCK_T 64
#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
#define __SIZEOF_PTHREAD_BARRIER_T 48
#define __SIZEOF_PTHREAD_BARRIERATTR_T 4
#define __PAD_ATOMIC_LOCK_T 12
/* Thread identifiers. The structure of the attribute type is not
exposed on purpose. */
typedef unsigned long int pthread_t;
/* Our old basic lock type, listed here for posterity.
We needed self-aligning locks for linuxthreads LDCW
implementation. For NPTL we use LWS Compare and
Exchange to implement primitives. */
#if 0
typedef struct {
int lock[4];
} __atomic_lock_t;
#endif
typedef union
{
char __size[__SIZEOF_PTHREAD_ATTR_T];
long int __align;
} pthread_attr_t;
typedef struct __pthread_internal_slist
{
struct __pthread_internal_slist *__next;
} __pthread_slist_t;
/* Data structures for mutex handling. The structure of the attribute
type is not exposed on purpose. */
typedef union
{
struct __pthread_mutex_s
{
int __lock;
char __size[__PAD_ATOMIC_LOCK_T];
unsigned int __count;
int __owner;
/* KIND must stay at this position in the structure to maintain
binary compatibility. */
int __kind;
unsigned int __nusers;
__extension__ union
{
int __spins;
__pthread_slist_t __list;
};
} __data;
char __size[__SIZEOF_PTHREAD_MUTEX_T];
long int __align;
} pthread_mutex_t;
typedef union
{
char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
long int __align;
} pthread_mutexattr_t;
/* Data structure for conditional variable handling. The structure of
the attribute type is not exposed on purpose. */
typedef union
{
struct
{
int __lock;
char __size[__PAD_ATOMIC_LOCK_T];
unsigned int __futex;
__extension__ unsigned long long int __total_seq;
__extension__ unsigned long long int __wakeup_seq;
__extension__ unsigned long long int __woken_seq;
void *__mutex;
unsigned int __nwaiters;
unsigned int __broadcast_seq;
} __data;
char __size[__SIZEOF_PTHREAD_COND_T];
__extension__ long 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;
#if defined __USE_UNIX98 || defined __USE_XOPEN2K
/* Data structure for read-write lock variable handling. The
structure of the attribute type is not exposed on purpose. */
typedef union
{
struct
{
int __lock;
char __size[__PAD_ATOMIC_LOCK_T];
unsigned int __nr_readers;
unsigned int __readers_wakeup;
unsigned int __writer_wakeup;
unsigned int __nr_readers_queued;
unsigned int __nr_writers_queued;
/* FLAGS must stay at this position in the structure to maintain
binary compatibility. */
unsigned int __flags;
int __writer;
} __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 */

View File

@ -0,0 +1,39 @@
/* Copyright (C) 2002, 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 _SEMAPHORE_H
# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead."
#endif
#define __SIZEOF_SEM_T 16
/* 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;

View File

@ -0,0 +1,23 @@
/* 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. */
/* Value passed to 'clone' for initialization of the thread register. */
#define TLS_VALUE (pd + 1)
/* Get the real implementation. */
#include <nptl/sysdeps/pthread/createthread.c>

View File

@ -0,0 +1,34 @@
/* 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. */
#include <sched.h>
#include <signal.h>
#include <sysdep.h>
#include <tls.h>
/* Argument 1 - Clone flags.
2 - Child stack pointer.
3 - Parent tid pointer.
4 - New TLS area pointer.
5 - Child tid pointer. */
#define ARCH_FORK() \
INLINE_SYSCALL (clone, 5, \
CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, \
NULL, NULL, NULL, &THREAD_SELF->tid)
#include <nptl/sysdeps/unix/sysv/linux/fork.c>

View File

@ -0,0 +1,153 @@
/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _INTERNALTYPES_H
#define _INTERNALTYPES_H 1
#include <stdint.h>
struct pthread_attr
{
/* Scheduler parameters and priority. */
struct sched_param schedparam;
int schedpolicy;
/* Various flags like detachstate, scope, etc. */
int flags;
/* Size of guard area. */
size_t guardsize;
/* Stack handling. */
void *stackaddr;
size_t stacksize;
/* Affinity map. */
cpu_set_t *cpuset;
size_t cpusetsize;
};
#define ATTR_FLAG_DETACHSTATE 0x0001
#define ATTR_FLAG_NOTINHERITSCHED 0x0002
#define ATTR_FLAG_SCOPEPROCESS 0x0004
#define ATTR_FLAG_STACKADDR 0x0008
#define ATTR_FLAG_OLDATTR 0x0010
#define ATTR_FLAG_SCHED_SET 0x0020
#define ATTR_FLAG_POLICY_SET 0x0040
/* Mutex attribute data structure. */
struct pthread_mutexattr
{
/* Identifier for the kind of mutex.
Bit 31 is set if the mutex is to be shared between processes.
Bit 0 to 30 contain one of the PTHREAD_MUTEX_ values to identify
the type of the mutex. */
int mutexkind;
};
/* Conditional variable attribute data structure. */
struct pthread_condattr
{
/* Combination of values:
Bit 0 : flag whether coditional variable will be shareable between
processes.
Bit 1-7: clock ID. */
int value;
};
/* The __NWAITERS field is used as a counter and to house the number
of bits which represent the clock. COND_CLOCK_BITS is the number
of bits reserved for the clock. */
#define COND_CLOCK_BITS 1
/* Read-write lock variable attribute data structure. */
struct pthread_rwlockattr
{
int lockkind;
int pshared;
};
/* Barrier data structure. */
struct pthread_barrier
{
unsigned int curr_event;
int lock;
unsigned int left;
unsigned int init_count;
};
/* Barrier variable attribute data structure. */
struct pthread_barrierattr
{
int pshared;
};
/* Thread-local data handling. */
struct pthread_key_struct
{
/* Sequence numbers. Even numbers indicated vacant entries. Note
that zero is even. We use uintptr_t to not require padding on
32- and 64-bit machines. On 64-bit machines it helps to avoid
wrapping, too. */
uintptr_t seq;
/* Destructor for the data. */
void (*destr) (void *);
};
/* Check whether an entry is unused. */
#define KEY_UNUSED(p) (((p) & 1) == 0)
/* Check whether a key is usable. We cannot reuse an allocated key if
the sequence counter would overflow after the next destroy call.
This would mean that we potentially free memory for a key with the
same sequence. This is *very* unlikely to happen, A program would
have to create and destroy a key 2^31 times (on 32-bit platforms,
on 64-bit platforms that would be 2^63). If it should happen we
simply don't use this specific key anymore. */
#define KEY_USABLE(p) (((uintptr_t) (p)) < ((uintptr_t) ((p) + 2)))
/* Handling of read-write lock data. */
// XXX For now there is only one flag. Maybe more in future.
#define RWLOCK_RECURSIVE(rwlock) ((rwlock)->__data.__flags != 0)
/* Semaphore variable structure. */
struct sem
{
unsigned int count;
};
/* Compatibility type for old conditional variable interfaces. */
typedef struct
{
pthread_cond_t *cond;
} pthread_cond_2_0_t;
#endif /* internaltypes.h */

View File

@ -0,0 +1,21 @@
/* 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 "lowlevellock.c"

View File

@ -0,0 +1,130 @@
/* 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 (lll_lock_t *futex)
{
do
{
int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
if (oldval != 0)
lll_futex_wait (futex, 2);
}
while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
}
int
__lll_timedlock_wait (lll_lock_t *futex, const struct timespec *abstime)
{
/* Reject invalid timeouts. */
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
return EINVAL;
do
{
struct timeval tv;
struct timespec rt;
/* Get the current time. */
(void) __gettimeofday (&tv, NULL);
/* Compute relative timeout. */
rt.tv_sec = abstime->tv_sec - tv.tv_sec;
rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
if (rt.tv_nsec < 0)
{
rt.tv_nsec += 1000000000;
--rt.tv_sec;
}
/* Already timed out? */
if (rt.tv_sec < 0)
return ETIMEDOUT;
/* Wait. */
int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
if (oldval != 0)
lll_futex_timed_wait (futex, 2, &rt);
}
while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
return 0;
}
/* These don't get included in libc.so */
#ifdef IS_IN_libpthread
int
lll_unlock_wake_cb (lll_lock_t *futex)
{
int val = atomic_exchange_rel (futex, 0);
if (__builtin_expect (val > 1, 0))
lll_futex_wake (futex, 1);
return 0;
}
int
__lll_timedwait_tid (int *tidp, const struct timespec *abstime)
{
int tid;
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
return EINVAL;
/* Repeat until thread terminated. */
while ((tid = *tidp) != 0)
{
struct timeval tv;
struct timespec rt;
/* Get the current time. */
(void) __gettimeofday (&tv, NULL);
/* Compute relative timeout. */
rt.tv_sec = abstime->tv_sec - tv.tv_sec;
rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
if (rt.tv_nsec < 0)
{
rt.tv_nsec += 1000000000;
--rt.tv_sec;
}
/* Already timed out? */
if (rt.tv_sec < 0)
return ETIMEDOUT;
/* Wait until thread terminates. */
if (lll_futex_timed_wait (tidp, tid, &rt) == -ETIMEDOUT)
return ETIMEDOUT;
}
return 0;
}
#endif

View File

@ -0,0 +1,336 @@
/* Copyright (C) 2003, 2004, 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 _LOWLEVELLOCK_H
#define _LOWLEVELLOCK_H 1
#include <time.h>
#include <sys/param.h>
#include <bits/pthreadtypes.h>
#include <sysdep.h>
#include <atomic.h>
#if 0
/* 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; \
})
/* 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; \
})
#endif
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
#define FUTEX_REQUEUE 3
#define FUTEX_CMP_REQUEUE 4
#define FUTEX_WAKE_OP 5
#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1)
/* Initializer for compatibility lock. */
#if 0
#define LLL_INITIALIZER_NOT_ZERO
#define LLL_MUTEX_LOCK_INITIALIZER ((__atomic_lock_t){ { 1, 1, 1, 1 } })
#endif
#define LLL_MUTEX_LOCK_INITIALIZER (0)
/* Type for lock object. */
typedef int lll_lock_t;
#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 : __ret; \
})
#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 : __ret; \
})
#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 : __ret; \
})
#define lll_robust_mutex_dead(futexv) \
do \
{ \
int *__futexp = &(futexv); \
atomic_or (__futexp, FUTEX_OWNER_DIED); \
lll_futex_wake (__futexp, 1); \
} \
while (0)
/* Returns non-zero if error happened, zero if success. */
#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \
({ \
INTERNAL_SYSCALL_DECL (__err); \
long int __ret; \
__ret = INTERNAL_SYSCALL (futex, __err, 6, \
(futexp), FUTEX_CMP_REQUEUE, (nr_wake), \
(nr_move), (mutex), (val)); \
INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
})
/* Returns non-zero if error happened, zero if success. */
#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) \
({ \
INTERNAL_SYSCALL_DECL (__err); \
long int __ret; \
__ret = INTERNAL_SYSCALL (futex, __err, 6, \
(futexp), FUTEX_WAKE_OP, (nr_wake), \
(nr_wake2), (futexp2), \
FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \
__ret; \
})
static inline int __attribute__((always_inline))
__lll_mutex_trylock(lll_lock_t *futex)
{
return atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0;
}
#define lll_mutex_trylock(lock) __lll_mutex_trylock (&(lock))
static inline int __attribute__((always_inline))
__lll_robust_mutex_trylock(int *futex, int id)
{
return atomic_compare_and_exchange_val_acq (futex, id, 0) != 0;
}
#define lll_robust_mutex_trylock(lock, id) \
__lll_robust_mutex_trylock (&(lock), id)
static inline int __attribute__((always_inline))
__lll_mutex_cond_trylock(lll_lock_t *futex)
{
return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0;
}
#define lll_mutex_cond_trylock(lock) __lll_mutex_cond_trylock (&(lock))
extern void __lll_lock_wait (lll_lock_t *futex) attribute_hidden;
static inline void __attribute__((always_inline))
__lll_mutex_lock(lll_lock_t *futex)
{
if (atomic_compare_and_exchange_bool_acq (futex, 1, 0) != 0)
__lll_lock_wait (futex);
}
#define lll_mutex_lock(futex) __lll_mutex_lock (&(futex))
extern int __lll_robust_lock_wait (int *futex) attribute_hidden;
static inline int __attribute__ ((always_inline))
__lll_robust_mutex_lock (int *futex, int id)
{
int result = 0;
if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0)
result = __lll_robust_lock_wait (futex);
return result;
}
#define lll_robust_mutex_lock(futex, id) \
__lll_robust_mutex_lock (&(futex), id)
static inline void __attribute__ ((always_inline))
__lll_mutex_cond_lock (lll_lock_t *futex)
{
if (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0)
__lll_lock_wait (futex);
}
#define lll_mutex_cond_lock(futex) __lll_mutex_cond_lock (&(futex))
#define lll_robust_mutex_cond_lock(futex, id) \
__lll_robust_mutex_lock (&(futex), (id) | FUTEX_WAITERS)
extern int __lll_timedlock_wait (lll_lock_t *futex, const struct timespec *)
attribute_hidden;
extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *)
attribute_hidden;
static inline int __attribute__ ((always_inline))
__lll_mutex_timedlock (lll_lock_t *futex, const struct timespec *abstime)
{
int result = 0;
if (atomic_compare_and_exchange_bool_acq (futex, 1, 0) != 0)
result = __lll_timedlock_wait (futex, abstime);
return result;
}
#define lll_mutex_timedlock(futex, abstime) \
__lll_mutex_timedlock (&(futex), abstime)
static inline int __attribute__ ((always_inline))
__lll_robust_mutex_timedlock (int *futex, const struct timespec *abstime,
int id)
{
int result = 0;
if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0)
result = __lll_robust_timedlock_wait (futex, abstime);
return result;
}
#define lll_robust_mutex_timedlock(futex, abstime, id) \
__lll_robust_mutex_timedlock (&(futex), abstime, id)
static inline void __attribute__ ((always_inline))
__lll_mutex_unlock (lll_lock_t *futex)
{
int val = atomic_exchange_rel (futex, 0);
if (__builtin_expect (val > 1, 0))
lll_futex_wake (futex, 1);
}
#define lll_mutex_unlock(futex) __lll_mutex_unlock(&(futex))
static inline void __attribute__ ((always_inline))
__lll_robust_mutex_unlock (int *futex, int mask)
{
int val = atomic_exchange_rel (futex, 0);
if (__builtin_expect (val & mask, 0))
lll_futex_wake (futex, 1);
}
#define lll_robust_mutex_unlock(futex) \
__lll_robust_mutex_unlock(&(futex), FUTEX_WAITERS)
static inline void __attribute__ ((always_inline))
__lll_mutex_unlock_force (lll_lock_t *futex)
{
(void) atomic_exchange_rel (futex, 0);
lll_futex_wake (futex, 1);
}
#define lll_mutex_unlock_force(futex) __lll_mutex_unlock_force(&(futex))
static inline int __attribute__ ((always_inline))
__lll_mutex_islocked (lll_lock_t *futex)
{
return (*futex != 0);
}
#define lll_mutex_islocked(futex) __lll_mutex_islocked(&(futex))
/* Our internal lock implementation is identical to the binary-compatible
mutex implementation. */
/* Initializers for lock. */
#if 0
#define LLL_LOCK_INITIALIZER ((__atomic_lock_t){ { 1, 1, 1, 1 } })
#define LLL_LOCK_INITIALIZER_CONST { { 1, 1, 1, 1 } }
#define LLL_LOCK_INITIALIZER_LOCKED ((__atomic_lock_t){ { 0, 0, 0, 0 } })
#endif
#define LLL_LOCK_INITIALIZER (0)
#define LLL_LOCK_INITIALIZER_CONST (0)
#define LLL_LOCK_INITIALIZER_LOCKED (1)
#define THREAD_INIT_LOCK(PD, LOCK) \
(PD)->LOCK = LLL_LOCK_INITIALIZER
extern int lll_unlock_wake_cb (lll_lock_t *__futex) attribute_hidden;
/* The states of a lock are:
0 - untaken
1 - taken by one user
>1 - taken by more users */
#define lll_trylock(lock) lll_mutex_trylock (lock)
#define lll_lock(lock) lll_mutex_lock (lock)
#define lll_unlock(lock) lll_mutex_unlock (lock)
#define lll_islocked(lock) lll_mutex_islocked (lock)
/* The kernel notifies a process which uses CLONE_CLEARTID via futex
wakeup when the clone terminates. The memory location contains the
thread ID while the clone is running and is reset to zero
afterwards. */
#define lll_wait_tid(tid) \
do { \
__typeof (tid) __tid; \
while ((__tid = (tid)) != 0) \
lll_futex_wait (&(tid), __tid); \
} while (0)
extern int __lll_timedwait_tid (int *, const struct timespec *)
attribute_hidden;
#define lll_timedwait_tid(tid, abstime) \
({ \
int __res = 0; \
if ((tid) != 0) \
__res = __lll_timedwait_tid (&(tid), (abstime)); \
__res; \
})
/* Conditional variable handling. */
extern void __lll_cond_wait (pthread_cond_t *cond)
attribute_hidden;
extern int __lll_cond_timedwait (pthread_cond_t *cond,
const struct timespec *abstime)
attribute_hidden;
extern void __lll_cond_wake (pthread_cond_t *cond)
attribute_hidden;
extern void __lll_cond_broadcast (pthread_cond_t *cond)
attribute_hidden;
#define lll_cond_wait(cond) \
__lll_cond_wait (cond)
#define lll_cond_timedwait(cond, abstime) \
__lll_cond_timedwait (cond, abstime)
#define lll_cond_wake(cond) \
__lll_cond_wake (cond)
#define lll_cond_broadcast(cond) \
__lll_cond_broadcast (cond)
#endif /* lowlevellock.h */

View File

@ -0,0 +1,109 @@
/* Special .init and .fini section support for HPPA. NPTL 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.
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_internal,%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,90 @@
/* 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. */
#include <sysdep.h>
#define _ERRNO_H 1
#include <bits/errno.h>
#include <tcb-offsets.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. */
/* Load the thread register.
Load the saved PID value.
Negate the value.
Store the temporary PID. */
#define SAVE_PID \
mfctl %cr27, %r26 ASM_LINE_SEP \
ldw PID_THREAD_OFFSET(%r26),%r1 ASM_LINE_SEP \
sub %r0,%r1,%r1 ASM_LINE_SEP \
stw %r1,PID_THREAD_OFFSET(%r26) ASM_LINE_SEP
/* If we are the parent...
Get the thread pointer.
Load the saved PID.
Negate the value (got back original)
Restore the PID. */
#define RESTORE_PID \
cmpb,=,n %r0,%ret0,.Lthread_start ASM_LINE_SEP \
mfctl %cr27, %r26 ASM_LINE_SEP \
ldw PID_THREAD_OFFSET(%r26),%r1 ASM_LINE_SEP \
sub %r0,%r1,%r1 ASM_LINE_SEP \
stw %r1,PID_THREAD_OFFSET(%r26) ASM_LINE_SEP \
.Lthread_start: ASM_LINE_SEP
/* r26, r25, r24, r23 are free since vfork has no arguments */
ENTRY(__vfork)
/* Save the PIC register. */
#ifdef PIC
copy %r19, %r25 /* parent */
#endif
/* Save the process PID */
SAVE_PID
/* Syscall saves and restores all register states */
ble 0x100(%sr2,%r0)
ldi __NR_vfork,%r20
/* Conditionally restore the PID */
RESTORE_PID
/* Check for error */
ldi -4096,%r1
comclr,>>= %r1,%ret0,%r0 /* Note: unsigned compare. */
b,n .Lerror
/* Return, no need to restore the PIC register. */
bv,n %r0(%rp)
.Lerror:
SYSCALL_ERROR_HANDLER
/* Restore the PIC register (in delay slot) on error */
#ifdef PIC
copy %r25, %r19 /* parent */
#else
nop
#endif
sub %r0,%ret0,%arg0
/* Return error */
PSEUDO_END (__vfork)
libc_hidden_def (__vfork)
weak_alias (__vfork, vfork)

View File

@ -0,0 +1,94 @@
/* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.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 (once_control, init_routine)
pthread_once_t *once_control;
void (*init_routine) (void);
{
while (1)
{
int oldval, val, newval;
val = *once_control;
do
{
/* Check if the initialized has already been done. */
if ((val & 2) != 0)
return 0;
oldval = val;
newval = (oldval & 3) | __fork_generation | 1;
val = atomic_compare_and_exchange_val_acq (once_control, newval,
oldval);
}
while (__builtin_expect (val != oldval, 0));
/* Check if another thread already runs the initializer. */
if ((oldval & 1) != 0)
{
/* Check whether the initializer execution was interrupted
by a fork. */
if (((oldval ^ newval) & -4) == 0)
{
/* Same generation, some other thread was faster. Wait. */
lll_futex_wait (once_control, newval);
continue;
}
}
/* This thread is the first here. Do the initialization.
Register a cleanup handler so that in case the thread gets
interrupted the initialization can be restarted. */
pthread_cleanup_push (clear_once_control, once_control);
init_routine ();
pthread_cleanup_pop (0);
/* Add one to *once_control. */
atomic_increment (once_control);
/* Wake up all other threads. */
lll_futex_wake (once_control, INT_MAX);
break;
}
return 0;
}
weak_alias (__pthread_once, pthread_once)
strong_alias (__pthread_once, __pthread_once_internal)

View File

@ -0,0 +1,217 @@
/* 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. */
#include <sysdep.h>
#include <sysdeps/generic/sysdep.h>
#include <tls.h>
#ifndef __ASSEMBLER__
# include <nptl/pthreadP.h>
#endif
#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
# 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
# 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__
# define SINGLE_THREAD_P \
__builtin_expect (THREAD_GETMEM (THREAD_SELF, \
header.multiple_threads) == 0, 1)
# else
/* Read the value of header.multiple_threads from the thread pointer */
# define SINGLE_THREAD_P \
mfctl %cr27, %ret0 ASM_LINE_SEP \
ldw MULTIPLE_THREADS_THREAD_OFFSET(%sr0,%ret0),%ret0 ASM_LINE_SEP
# endif
#elif !defined __ASSEMBLER__
/* This code should never be used but we define it anyhow. */
# define SINGLE_THREAD_P (1)
# define NO_CANCELLATION 1
#endif
/* !defined NOT_IN_libc || defined IS_IN_libpthread */

View File

@ -0,0 +1,21 @@
/* 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; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define LIBGCC_S_SO "libgcc_s.so.2"
#include <sysdeps/pthread/unwind-forcedunwind.c>

View File

@ -0,0 +1,21 @@
/* 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; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define LIBGCC_S_SO "libgcc_s.so.2"
#include <sysdeps/pthread/unwind-resume.c>

View File

@ -0,0 +1 @@
#include <sysdeps/unix/sysv/linux/i386/xstat.c>