1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-29 11:41:21 +03:00
This commit is contained in:
Jakub Jelinek
2007-07-12 18:26:36 +00:00
parent 7d58530341
commit 0ecb606cb6
6215 changed files with 494638 additions and 305010 deletions

View File

@ -0,0 +1,2 @@
# pull in __syscall_error routine
libpthread-routines += sysdep

View File

@ -1,5 +1,5 @@
/* Machine-specific pthread type layouts. SPARC version.
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
@ -58,11 +58,25 @@ typedef union
} pthread_attr_t;
#if __WORDSIZE == 64
typedef struct __pthread_internal_list
{
struct __pthread_internal_list *__prev;
struct __pthread_internal_list *__next;
} __pthread_list_t;
#else
typedef struct __pthread_internal_slist
{
struct __pthread_internal_slist *__next;
} __pthread_slist_t;
#endif
/* Data structures for mutex handling. The structure of the attribute
type is deliberately not exposed. */
typedef union
{
struct
struct __pthread_mutex_s
{
int __lock;
unsigned int __count;
@ -73,10 +87,18 @@ typedef union
/* KIND must stay at this position in the structure to maintain
binary compatibility. */
int __kind;
#if __WORDSIZE != 64
unsigned int __nusers;
#endif
#if __WORDSIZE == 64
int __spins;
__pthread_list_t __list;
# define __PTHREAD_MUTEX_HAVE_PREV 1
#else
unsigned int __nusers;
__extension__ union
{
int __spins;
__pthread_slist_t __list;
};
#endif
} __data;
char __size[__SIZEOF_PTHREAD_MUTEX_T];
long int __align;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
@ -30,6 +30,11 @@
#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)
#define FUTEX_LOCK_PI 6
#define FUTEX_UNLOCK_PI 7
#define FUTEX_TRYLOCK_PI 8
/* Initializer for compatibility lock. */
#define LLL_MUTEX_LOCK_INITIALIZER (0)
@ -76,15 +81,38 @@
INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
})
#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. */
#ifdef __sparc32_atomic_do_lock
#error SPARC < v9 does not support compare and swap which is essential for futex based locking
/* Avoid FUTEX_WAKE_OP if supporting pre-v9 CPUs. */
# define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) 1
#else
# 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); \
INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
})
#endif
static inline int
__attribute__ ((always_inline))
__lll_mutex_trylock (int *futex)
{
return atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0;
return atomic_compare_and_exchange_val_24_acq (futex, 1, 0) != 0;
}
#define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex))
@ -92,47 +120,71 @@ static inline int
__attribute__ ((always_inline))
__lll_mutex_cond_trylock (int *futex)
{
return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0;
return atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0;
}
#define lll_mutex_cond_trylock(futex) __lll_mutex_cond_trylock (&(futex))
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(futex, id) \
__lll_robust_mutex_trylock (&(futex), id)
extern void __lll_lock_wait (int *futex) attribute_hidden;
extern int __lll_robust_lock_wait (int *futex) attribute_hidden;
static inline void
__attribute__ ((always_inline))
__lll_mutex_lock (int *futex)
{
int val = atomic_compare_and_exchange_val_acq (futex, 1, 0);
int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0);
if (__builtin_expect (val != 0, 0))
__lll_lock_wait (futex);
}
#define lll_mutex_lock(futex) __lll_mutex_lock (&(futex))
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 (int *futex)
{
int val = atomic_compare_and_exchange_val_acq (futex, 2, 0);
int val = atomic_compare_and_exchange_val_24_acq (futex, 2, 0);
if (__builtin_expect (val != 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 (int *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 (int *futex, const struct timespec *abstime)
{
int val = atomic_compare_and_exchange_val_acq (futex, 1, 0);
int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0);
int result = 0;
if (__builtin_expect (val != 0, 0))
@ -142,18 +194,39 @@ __lll_mutex_timedlock (int *futex, const struct timespec *abstime)
#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)
#define lll_mutex_unlock(lock) \
((void) ({ \
int *__futex = &(lock); \
int __val = atomic_exchange_rel (__futex, 0); \
int __val = atomic_exchange_24_rel (__futex, 0); \
if (__builtin_expect (__val > 1, 0)) \
lll_futex_wake (__futex, 1); \
}))
#define lll_robust_mutex_unlock(lock) \
((void) ({ \
int *__futex = &(lock); \
int __val = atomic_exchange_rel (__futex, 0); \
if (__builtin_expect (__val & FUTEX_WAITERS, 0)) \
lll_futex_wake (__futex, 1); \
}))
#define lll_mutex_unlock_force(lock) \
((void) ({ \
int *__futex = &(lock); \
(void) atomic_exchange_rel (__futex, 0); \
(void) atomic_exchange_24_rel (__futex, 0); \
lll_futex_wake (__futex, 1); \
}))

View File

@ -1,2 +1,9 @@
#define RESET_PID
#include <sysdeps/unix/sysv/linux/sparc/sparc32/clone.S>
/* We want an #include_next, but we are the main source file.
So, #include ourselves and in that incarnation we can use #include_next. */
#ifndef INCLUDED_SELF
# define INCLUDED_SELF
# include <clone.S>
#else
# define RESET_PID
# include_next <clone.S>
#endif

View File

@ -0,0 +1,131 @@
/* low level locking for pthread library. SPARC version.
Copyright (C) 2003, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <sysdep.h>
#include <lowlevellock.h>
#include <sys/time.h>
void
__lll_lock_wait (int *futex)
{
do
{
int oldval = atomic_compare_and_exchange_val_24_acq (futex, 2, 1);
if (oldval != 0)
lll_futex_wait (futex, 2);
}
while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0);
}
int
__lll_timedlock_wait (int *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_24_acq (futex, 2, 1);
if (oldval != 0)
lll_futex_timed_wait (futex, 2, &rt);
}
while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0);
return 0;
}
/* These don't get included in libc.so */
#ifdef IS_IN_libpthread
int
lll_unlock_wake_cb (int *futex)
{
int val = atomic_exchange_24_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

@ -21,6 +21,7 @@
#include <tcb-offsets.h>
.text
.globl __syscall_error
ENTRY(__vfork)
ld [%g7 + PID], %o5
sub %g0, %o5, %o4
@ -28,15 +29,17 @@ ENTRY(__vfork)
LOADSYSCALL(vfork)
ta 0x10
bcs,a __syscall_error_handler
st %o5, [%g7 + PID]
SYSCALL_ERROR_HANDLER
sub %o1, 1, %o1
bcc 2f
mov %o7, %g1
st %o5, [%g7 + PID]
call __syscall_error
mov %g1, %o7
2: sub %o1, 1, %o1
andcc %o0, %o1, %o0
bne,a 1f
st %o5, [%g7 + PID]
1: retl
nop
END(__vfork)
PSEUDO_END (__vfork)
weak_alias (__vfork, vfork)

View File

@ -0,0 +1,62 @@
/* Copyright (C) 2002, 2006 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. */
#include <errno.h>
#include "pthreadP.h"
#include <lowlevellock.h>
struct sparc_pthread_barrier
{
struct pthread_barrier b;
unsigned char left_lock;
unsigned char pshared;
};
int
pthread_barrier_init (barrier, attr, count)
pthread_barrier_t *barrier;
const pthread_barrierattr_t *attr;
unsigned int count;
{
struct sparc_pthread_barrier *ibarrier;
if (__builtin_expect (count == 0, 0))
return EINVAL;
struct pthread_barrierattr *iattr = (struct pthread_barrierattr *) attr;
if (iattr != NULL)
{
if (iattr->pshared != PTHREAD_PROCESS_PRIVATE
&& __builtin_expect (iattr->pshared != PTHREAD_PROCESS_SHARED, 0))
/* Invalid attribute. */
return EINVAL;
}
ibarrier = (struct sparc_pthread_barrier *) barrier;
/* Initialize the individual fields. */
ibarrier->b.lock = LLL_LOCK_INITIALIZER;
ibarrier->b.left = count;
ibarrier->b.init_count = count;
ibarrier->b.curr_event = 0;
ibarrier->left_lock = 0;
ibarrier->pshared = (iattr && iattr->pshared == PTHREAD_PROCESS_SHARED);
return 0;
}

View File

@ -0,0 +1,100 @@
/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Martin Schwidefsky <schwidefsky@de.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 <pthreadP.h>
struct sparc_pthread_barrier
{
struct pthread_barrier b;
unsigned char left_lock;
unsigned char pshared;
};
/* Wait on barrier. */
int
pthread_barrier_wait (barrier)
pthread_barrier_t *barrier;
{
struct sparc_pthread_barrier *ibarrier
= (struct sparc_pthread_barrier *) barrier;
int result = 0;
/* Make sure we are alone. */
lll_lock (ibarrier->b.lock);
/* One more arrival. */
--ibarrier->b.left;
/* Are these all? */
if (ibarrier->b.left == 0)
{
/* Yes. Increment the event counter to avoid invalid wake-ups and
tell the current waiters that it is their turn. */
++ibarrier->b.curr_event;
/* Wake up everybody. */
lll_futex_wake (&ibarrier->b.curr_event, INT_MAX);
/* This is the thread which finished the serialization. */
result = PTHREAD_BARRIER_SERIAL_THREAD;
}
else
{
/* The number of the event we are waiting for. The barrier's event
number must be bumped before we continue. */
unsigned int event = ibarrier->b.curr_event;
/* Before suspending, make the barrier available to others. */
lll_unlock (ibarrier->b.lock);
/* Wait for the event counter of the barrier to change. */
do
lll_futex_wait (&ibarrier->b.curr_event, event);
while (event == ibarrier->b.curr_event);
}
/* Make sure the init_count is stored locally or in a register. */
unsigned int init_count = ibarrier->b.init_count;
/* If this was the last woken thread, unlock. */
if (__atomic_is_v9 || ibarrier->pshared == 0)
{
if (atomic_increment_val (&ibarrier->b.left) == init_count)
/* We are done. */
lll_unlock (ibarrier->b.lock);
}
else
{
unsigned int left;
/* Slightly more complicated. On pre-v9 CPUs, atomic_increment_val
is only atomic for threads within the same process, not for
multiple processes. */
__sparc32_atomic_do_lock24 (&ibarrier->left_lock);
left = ++ibarrier->b.left;
__sparc32_atomic_do_unlock24 (&ibarrier->left_lock);
if (left == init_count)
/* We are done. */
lll_unlock (ibarrier->b.lock);
}
return result;
}

View File

@ -0,0 +1,63 @@
/* Copyright (C) 2002, 2006 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. */
#include <errno.h>
#include <semaphore.h>
#include <lowlevellock.h>
#include <shlib-compat.h>
#include "semaphoreP.h"
struct sparc_sem
{
struct sem s;
unsigned char lock;
};
int
__new_sem_init (sem, pshared, value)
sem_t *sem;
int pshared;
unsigned int value;
{
/* Parameter sanity check. */
if (__builtin_expect (value > SEM_VALUE_MAX, 0))
{
__set_errno (EINVAL);
return -1;
}
/* Map to the internal type. */
struct sparc_sem *isem = (struct sparc_sem *) sem;
/* Use the value the user provided. */
isem->s.count = value;
isem->lock = 0;
/* We can completely ignore the PSHARED parameter since inter-process
use needs no special preparation. */
return 0;
}
versioned_symbol (libpthread, __new_sem_init, sem_init, GLIBC_2_1);
#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
strong_alias (__new_sem_init, __old_sem_init)
compat_symbol (libpthread, __old_sem_init, sem_init, GLIBC_2_0);
#endif

View File

@ -0,0 +1,54 @@
/* sem_post -- post to a POSIX semaphore. SPARC version.
Copyright (C) 2003, 2004, 2006 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 <errno.h>
#include <sysdep.h>
#include <lowlevellock.h>
#include <internaltypes.h>
#include <semaphore.h>
#include <shlib-compat.h>
int
__new_sem_post (sem_t *sem)
{
int *futex = (int *) sem, nr;
if (__atomic_is_v9)
nr = atomic_increment_val (futex);
else
{
__sparc32_atomic_do_lock24 (futex + 1);
nr = ++*futex;
__sparc32_atomic_do_unlock24 (futex + 1);
}
int err = lll_futex_wake (futex, nr);
if (__builtin_expect (err, 0) < 0)
{
__set_errno (-err);
return -1;
}
return 0;
}
versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1);
#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
strong_alias (__new_sem_post, __old_sem_post)
compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0);
#endif

View File

@ -0,0 +1,117 @@
/* sem_timedwait -- wait on a semaphore. SPARC version.
Copyright (C) 2003, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <sysdep.h>
#include <lowlevellock.h>
#include <internaltypes.h>
#include <semaphore.h>
#include <pthreadP.h>
#include <shlib-compat.h>
int
sem_timedwait (sem_t *sem, const struct timespec *abstime)
{
/* First check for cancellation. */
CANCELLATION_P (THREAD_SELF);
int *futex = (int *) sem;
int val;
int err;
if (*futex > 0)
{
if (__atomic_is_v9)
val = atomic_decrement_if_positive (futex);
else
{
__sparc32_atomic_do_lock24 (futex + 1);
val = *futex;
if (val > 0)
*futex = val - 1;
__sparc32_atomic_do_unlock24 (futex + 1);
}
if (val > 0)
return 0;
}
err = -EINVAL;
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
goto error_return;
do
{
struct timeval tv;
struct timespec rt;
int sec, nsec;
/* Get the current time. */
__gettimeofday (&tv, NULL);
/* Compute relative timeout. */
sec = abstime->tv_sec - tv.tv_sec;
nsec = abstime->tv_nsec - tv.tv_usec * 1000;
if (nsec < 0)
{
nsec += 1000000000;
--sec;
}
/* Already timed out? */
err = -ETIMEDOUT;
if (sec < 0)
goto error_return;
/* Do wait. */
rt.tv_sec = sec;
rt.tv_nsec = nsec;
/* Enable asynchronous cancellation. Required by the standard. */
int oldtype = __pthread_enable_asynccancel ();
err = lll_futex_timed_wait (futex, 0, &rt);
/* Disable asynchronous cancellation. */
__pthread_disable_asynccancel (oldtype);
if (err != 0 && err != -EWOULDBLOCK)
goto error_return;
if (__atomic_is_v9)
val = atomic_decrement_if_positive (futex);
else
{
__sparc32_atomic_do_lock24 (futex + 1);
val = *futex;
if (val > 0)
*futex = val - 1;
__sparc32_atomic_do_unlock24 (futex + 1);
}
}
while (val <= 0);
return 0;
error_return:
__set_errno (-err);
return -1;
}

View File

@ -0,0 +1,59 @@
/* sem_trywait -- wait on a semaphore. SPARC version.
Copyright (C) 2003, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <sysdep.h>
#include <lowlevellock.h>
#include <internaltypes.h>
#include <semaphore.h>
#include <shlib-compat.h>
int
__new_sem_trywait (sem_t *sem)
{
int *futex = (int *) sem;
int val;
if (*futex > 0)
{
if (__atomic_is_v9)
val = atomic_decrement_if_positive (futex);
else
{
__sparc32_atomic_do_lock24 (futex + 1);
val = *futex;
if (val > 0)
*futex = val - 1;
__sparc32_atomic_do_unlock24 (futex + 1);
}
if (val > 0)
return 0;
}
__set_errno (EAGAIN);
return -1;
}
versioned_symbol (libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1);
#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
strong_alias (__new_sem_trywait, __old_sem_trywait)
compat_symbol (libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0);
#endif

View File

@ -0,0 +1,74 @@
/* sem_wait -- wait on a semaphore. SPARC version.
Copyright (C) 2003, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <sysdep.h>
#include <lowlevellock.h>
#include <internaltypes.h>
#include <semaphore.h>
#include <pthreadP.h>
#include <shlib-compat.h>
int
__new_sem_wait (sem_t *sem)
{
/* First check for cancellation. */
CANCELLATION_P (THREAD_SELF);
int *futex = (int *) sem;
int err;
do
{
int val;
if (__atomic_is_v9)
val = atomic_decrement_if_positive (futex);
else
{
__sparc32_atomic_do_lock24 (futex + 1);
val = *futex;
if (val > 0)
*futex = val - 1;
__sparc32_atomic_do_unlock24 (futex + 1);
}
if (val > 0)
return 0;
/* Enable asynchronous cancellation. Required by the standard. */
int oldtype = __pthread_enable_asynccancel ();
err = lll_futex_wait (futex, 0);
/* Disable asynchronous cancellation. */
__pthread_disable_asynccancel (oldtype);
}
while (err == 0 || err == -EWOULDBLOCK);
__set_errno (-err);
return -1;
}
versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
strong_alias (__new_sem_wait, __old_sem_wait)
compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0);
#endif

View File

@ -0,0 +1 @@
#include "../../../../../../../pthread_barrier_init.c"

View File

@ -0,0 +1 @@
#include "../../../../../../pthread/pthread_barrier_wait.c"

View File

@ -0,0 +1 @@
#include "../../../../../../../sem_init.c"

View File

@ -0,0 +1 @@
#include "../../../sem_post.c"

View File

@ -0,0 +1 @@
#include "../../../sem_timedwait.c"

View File

@ -0,0 +1 @@
#include "../../../sem_trywait.c"

View File

@ -0,0 +1 @@
#include "../../../sem_wait.c"

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
@ -26,55 +26,48 @@
#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
# undef PSEUDO
# define PSEUDO(name, syscall_name, args) \
.text; \
ENTRY(name) \
ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1; \
cmp %g1, 0; \
bne 1f; \
.type __##syscall_name##_nocancel,@function; \
.globl __##syscall_name##_nocancel; \
__##syscall_name##_nocancel: \
mov SYS_ify(syscall_name), %g1; \
ta 0x10; \
bcs __syscall_error_handler; \
nop; \
.size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \
.subsection 2; \
cfi_startproc; \
1: save %sp, -96, %sp; \
cfi_def_cfa_register (%fp); \
cfi_window_save; \
cfi_register (%o7, %i7); \
CENABLE; \
nop; \
mov %o0, %l0; \
COPY_ARGS_##args \
mov SYS_ify(syscall_name), %g1; \
ta 0x10; \
bcs __syscall_error_handler2; \
mov %o0, %l1; \
CDISABLE; \
mov %l0, %o0; \
jmpl %i7 + 8, %g0; \
restore %g0, %l1, %o0; \
cfi_endproc; \
.previous; \
SYSCALL_ERROR_HANDLER \
SYSCALL_ERROR_HANDLER2
# define PSEUDO(name, syscall_name, args) \
.text; \
.globl __syscall_error; \
ENTRY(name) \
ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1;\
cmp %g1, 0; \
bne 1f; \
.type __##syscall_name##_nocancel,@function; \
.globl __##syscall_name##_nocancel; \
__##syscall_name##_nocancel: \
mov SYS_ify(syscall_name), %g1; \
ta 0x10; \
bcc 8f; \
mov %o7, %g1; \
call __syscall_error; \
mov %g1, %o7; \
8: jmpl %o7 + 8, %g0; \
nop; \
.size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;\
1: save %sp, -96, %sp; \
cfi_def_cfa_register(%fp); \
cfi_window_save; \
cfi_register(%o7, %i7); \
CENABLE; \
nop; \
mov %o0, %l0; \
COPY_ARGS_##args \
mov SYS_ify(syscall_name), %g1; \
ta 0x10; \
bcc 1f; \
mov %o0, %l1; \
CDISABLE; \
mov %l0, %o0; \
call __syscall_error; \
mov %l1, %o0; \
b 2f; \
mov -1, %l1; \
1: CDISABLE; \
mov %l0, %o0; \
2: jmpl %i7 + 8, %g0; \
restore %g0, %l1, %o0;
#define SYSCALL_ERROR_HANDLER2 \
SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2) \
.global __errno_location; \
.type __errno_location,@function; \
CDISABLE; \
mov %l0, %o0; \
call __errno_location; \
nop; \
st %l1, [%o0]; \
jmpl %i7 + 8, %g0; \
restore %g0, -1, %o0; \
.previous;
# ifdef IS_IN_libpthread
# define CENABLE call __pthread_enable_asynccancel
@ -111,3 +104,9 @@ SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2) \
# define NO_CANCELLATION 1
#endif
#ifndef __ASSEMBLER__
# define RTLD_SINGLE_THREAD_P \
__builtin_expect (THREAD_GETMEM (THREAD_SELF, \
header.multiple_threads) == 0, 1)
#endif

View File

@ -21,6 +21,7 @@
#include <tcb-offsets.h>
.text
.globl __syscall_error
ENTRY(__vfork)
ld [%g7 + PID], %o5
cmp %o5, 0
@ -31,16 +32,18 @@ ENTRY(__vfork)
LOADSYSCALL(vfork)
ta 0x10
bcs,a __syscall_error_handler
st %o5, [%g7 + PID]
SYSCALL_ERROR_HANDLER
sub %o1, 1, %o1
bcc 2f
mov %o7, %g1
st %o5, [%g7 + PID]
call __syscall_error
mov %g1, %o7
2: sub %o1, 1, %o1
andcc %o0, %o1, %o0
bne,a 1f
st %o5, [%g7 + PID]
1: retl
nop
END(__vfork)
PSEUDO_END (__vfork)
libc_hidden_def (__vfork)
weak_alias (__vfork, vfork)

View File

@ -0,0 +1,9 @@
/* We want an #include_next, but we are the main source file.
So, #include ourselves and in that incarnation we can use #include_next. */
#ifndef INCLUDED_SELF
# define INCLUDED_SELF
# include <clone.S>
#else
# define RESET_PID
# include_next <clone.S>
#endif

View File

@ -21,6 +21,7 @@
#include <tcb-offsets.h>
.text
.globl __syscall_error
ENTRY(__vfork)
ld [%g7 + PID], %o5
sub %g0, %o5, %o4
@ -28,15 +29,17 @@ ENTRY(__vfork)
LOADSYSCALL(vfork)
ta 0x6d
bcs,a,pn %xcc, __syscall_error_handler
st %o5, [%g7 + PID]
SYSCALL_ERROR_HANDLER
sub %o1, 1, %o1
bcc,pt %xcc, 2f
mov %o7, %g1
st %o5, [%g7 + PID]
call __syscall_error
mov %g1, %o7
2: sub %o1, 1, %o1
andcc %o0, %o1, %o0
bne,a,pt %icc, 1f
st %o5, [%g7 + PID]
1: retl
nop
END(__vfork)
PSEUDO_END (__vfork)
weak_alias (__vfork, vfork)

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
@ -26,49 +26,46 @@
#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
# undef PSEUDO
# define PSEUDO(name, syscall_name, args) \
.text; \
ENTRY(name) \
ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1; \
brnz,pn %g1, 1f; \
.type __##syscall_name##_nocancel,@function; \
.globl __##syscall_name##_nocancel; \
__##syscall_name##_nocancel: \
mov SYS_ify(syscall_name), %g1; \
ta 0x6d; \
bcs,pn %xcc, __syscall_error_handler; \
nop; \
.size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \
.subsection 2; \
1: save %sp, -192, %sp; \
CENABLE; \
nop; \
mov %o0, %l0; \
COPY_ARGS_##args \
mov SYS_ify(syscall_name), %g1; \
ta 0x6d; \
bcs,pn %xcc, __syscall_error_handler2; \
mov %o0, %l1; \
CDISABLE; \
mov %l0, %o0; \
jmpl %i7 + 8, %g0; \
restore %g0, %l1, %o0; \
.previous; \
SYSCALL_ERROR_HANDLER \
SYSCALL_ERROR_HANDLER2
#define SYSCALL_ERROR_HANDLER2 \
SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2) \
.global __errno_location; \
.type __errno_location,@function; \
CDISABLE; \
mov %l0, %o0; \
call __errno_location; \
nop; \
st %l1, [%o0]; \
jmpl %i7 + 8, %g0; \
restore %g0, -1, %o0; \
.previous;
# define PSEUDO(name, syscall_name, args) \
.text; \
.globl __syscall_error; \
ENTRY(name) \
ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1;\
brnz,pn %g1, 1f; \
.type __##syscall_name##_nocancel,@function; \
.globl __##syscall_name##_nocancel; \
__##syscall_name##_nocancel: \
mov SYS_ify(syscall_name), %g1; \
ta 0x6d; \
bcc,pt %xcc, 8f; \
mov %o7, %g1; \
call __syscall_error; \
mov %g1, %o7; \
8: jmpl %o7 + 8, %g0; \
nop; \
.size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;\
1: save %sp, -192, %sp; \
cfi_def_cfa_register(%fp); \
cfi_window_save; \
cfi_register(%o7, %i7); \
CENABLE; \
nop; \
mov %o0, %l0; \
COPY_ARGS_##args \
mov SYS_ify(syscall_name), %g1; \
ta 0x6d; \
bcc,pt %xcc, 1f; \
mov %o0, %l1; \
CDISABLE; \
mov %l0, %o0; \
call __syscall_error; \
mov %l1, %o0; \
ba,pt %xcc, 2f; \
mov -1, %l1; \
1: CDISABLE; \
mov %l0, %o0; \
2: jmpl %i7 + 8, %g0; \
restore %g0, %l1, %o0;
# ifdef IS_IN_libpthread
# define CENABLE call __pthread_enable_asynccancel
@ -105,3 +102,9 @@ SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2) \
# define NO_CANCELLATION 1
#endif
#ifndef __ASSEMBLER__
# define RTLD_SINGLE_THREAD_P \
__builtin_expect (THREAD_GETMEM (THREAD_SELF, \
header.multiple_threads) == 0, 1)
#endif

View File

@ -21,6 +21,7 @@
#include <tcb-offsets.h>
.text
.globl __syscall_error
ENTRY(__vfork)
ld [%g7 + PID], %o5
sethi %hi(0x80000000), %o3
@ -31,16 +32,18 @@ ENTRY(__vfork)
LOADSYSCALL(vfork)
ta 0x6d
bcs,a,pn %xcc, __syscall_error_handler
st %o5, [%g7 + PID]
SYSCALL_ERROR_HANDLER
sub %o1, 1, %o1
bcc,pt %xcc, 2f
mov %o7, %g1
st %o5, [%g7 + PID]
call __syscall_error
mov %g1, %o7
2: sub %o1, 1, %o1
andcc %o0, %o1, %o0
bne,a,pt %icc, 1f
st %o5, [%g7 + PID]
1: retl
nop
END(__vfork)
PSEUDO_END (__vfork)
libc_hidden_def (__vfork)
weak_alias (__vfork, vfork)