diff options
Diffstat (limited to 'libc')
| -rw-r--r-- | libc/signal/sigpause.c | 19 | ||||
| -rw-r--r-- | libc/signal/sigwait.c | 76 | 
2 files changed, 94 insertions, 1 deletions
diff --git a/libc/signal/sigpause.c b/libc/signal/sigpause.c index 8c99af0a1..ffb3595fb 100644 --- a/libc/signal/sigpause.c +++ b/libc/signal/sigpause.c @@ -23,6 +23,9 @@  #define __FAVOR_BSD  #include <signal.h>  #include <stddef.h>		/* For NULL.  */ +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include <sysdep-cancel.h> +#endif  libc_hidden_proto(sigprocmask)  libc_hidden_proto(sigdelset) @@ -48,6 +51,9 @@ int __sigpause (int sig_or_mask, int is_sig)    else if (sigset_set_old_mask (&set, sig_or_mask) < 0)      return -1; +  /* Note the sigpause() is a cancellation point.  But since we call +     sigsuspend() which itself is a cancellation point we do not have +     to do anything here.  */    return sigsuspend (&set);  }  libc_hidden_def(__sigpause) @@ -60,6 +66,19 @@ libc_hidden_def(__sigpause)  libc_hidden_proto(sigpause)  int sigpause (int mask)  { +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +  if (SINGLE_THREAD_P) +    return __sigpause (mask, 0); + +  int oldtype = LIBC_CANCEL_ASYNC (); + +  int result = __sigpause (mask, 0); + +  LIBC_CANCEL_RESET (oldtype); + +  return result; +#else    return __sigpause (mask, 0); +#endif  }  libc_hidden_def(sigpause) diff --git a/libc/signal/sigwait.c b/libc/signal/sigwait.c index 8ff2541a0..f15208863 100644 --- a/libc/signal/sigwait.c +++ b/libc/signal/sigwait.c @@ -1,7 +1,8 @@  /* vi: set sw=4 ts=4: */  /* sigwait   * - * Copyright (C) 2003 by Erik Andersen <andersen@uclibc.org> + * Copyright (C) 2006 by Steven J. Hill <sjhill@realitydiluted.com> + * Copyright (C) 2003-2005 by Erik Andersen <andersen@uclibc.org>   *   * This program is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -24,6 +25,78 @@  libc_hidden_proto(sigwaitinfo) +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +# include <sysdep-cancel.h> + +# ifdef __NR_rt_sigtimedwait + +/* Return any pending signal or wait for one for the given time.  */ +static int do_sigwait(const sigset_t *set, int *sig) +{ +	int ret; + +#  ifdef SIGCANCEL +	sigset_t tmpset; +	if (set != NULL +		&& (__builtin_expect (__sigismember (set, SIGCANCEL), 0) +#   ifdef SIGSETXID +		|| __builtin_expect (__sigismember (set, SIGSETXID), 0) +#   endif +		)) +	{ +		/* Create a temporary mask without the bit for SIGCANCEL set.  */ +		// We are not copying more than we have to. +		memcpy(&tmpset, set, _NSIG / 8); +		__sigdelset(&tmpset, SIGCANCEL); +#   ifdef SIGSETXID +		__sigdelset(&tmpset, SIGSETXID); +#   endif +		set = &tmpset; +	} +#  endif + +	/* XXX The size argument hopefully will have to be changed to the +	   real size of the user-level sigset_t.  */ +#  ifdef INTERNAL_SYSCALL +	INTERNAL_SYSCALL_DECL(err); +	do +		ret = INTERNAL_SYSCALL (rt_sigtimedwait, err, 4, set, NULL, +			NULL, _NSIG / 8); +	while (INTERNAL_SYSCALL_ERROR_P (ret, err) +		&& INTERNAL_SYSCALL_ERRNO (ret, err) == EINTR); +	if (! INTERNAL_SYSCALL_ERROR_P (ret, err)) +	{ +		*sig = ret; +		ret = 0; +	} +else +	ret = INTERNAL_SYSCALL_ERRNO (ret, err); +#  else +#   error INTERNAL_SYSCALL must be defined!!! +#  endif + +	return ret; +} + +int __sigwait (const sigset_t *set, int *sig) attribute_hidden; +int __sigwait (const sigset_t *set, int *sig) +{ +	if(SINGLE_THREAD_P) +		return do_sigwait(set, sig); + +	int oldtype = LIBC_CANCEL_ASYNC(); + +	int result = do_sigwait(set, sig); + +	LIBC_CANCEL_RESET(oldtype); + +	return result; +} +# else +#  error We must have rt_sigtimedwait defined!!! +# endif +#else +# undef sigwait  int __sigwait (const sigset_t *set, int *sig) attribute_hidden;  int __sigwait (const sigset_t *set, int *sig)  { @@ -34,6 +107,7 @@ int __sigwait (const sigset_t *set, int *sig)  	}  	return 1;  } +#endif  libc_hidden_proto(sigwait)  weak_alias(__sigwait,sigwait)  libc_hidden_def(sigwait)  | 
