mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
2.5-18.1
This commit is contained in:
2
nptl/sysdeps/unix/sysv/linux/sparc/Makefile
Normal file
2
nptl/sysdeps/unix/sysv/linux/sparc/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
# pull in __syscall_error routine
|
||||
libpthread-routines += sysdep
|
@ -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;
|
||||
|
@ -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); \
|
||||
}))
|
||||
|
||||
|
@ -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
|
||||
|
131
nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c
Normal file
131
nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c
Normal 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
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
63
nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c
Normal file
63
nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c
Normal 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
|
54
nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c
Normal file
54
nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c
Normal 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
|
117
nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c
Normal file
117
nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c
Normal 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;
|
||||
}
|
59
nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c
Normal file
59
nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c
Normal 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
|
74
nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c
Normal file
74
nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c
Normal 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
|
@ -0,0 +1 @@
|
||||
#include "../../../../../../../pthread_barrier_init.c"
|
@ -0,0 +1 @@
|
||||
#include "../../../../../../pthread/pthread_barrier_wait.c"
|
@ -0,0 +1 @@
|
||||
#include "../../../../../../../sem_init.c"
|
@ -0,0 +1 @@
|
||||
#include "../../../sem_post.c"
|
@ -0,0 +1 @@
|
||||
#include "../../../sem_timedwait.c"
|
@ -0,0 +1 @@
|
||||
#include "../../../sem_trywait.c"
|
@ -0,0 +1 @@
|
||||
#include "../../../sem_wait.c"
|
@ -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
|
||||
|
@ -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)
|
||||
|
9
nptl/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S
Normal file
9
nptl/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S
Normal 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
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user