1 /* vi: set sw=4 ts=4: */
2 /*
3 * __rt_sigtimedwait() for uClibc
4 *
5 * Copyright (C) 2006 by Steven Hill <sjhill@realitydiluted.com>
6 * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
7 *
8 * GNU Library General Public License (LGPL) version 2 or later.
9 */
10
11 #include <sys/syscall.h>
12
13 #ifdef __NR_rt_sigtimedwait
14 # include <signal.h>
15 # include <cancel.h>
16 # ifdef __UCLIBC_HAS_THREADS_NATIVE__
17 # include <pthreadP.h> /* SIGCANCEL */
18 # endif
19 # ifdef SIGCANCEL
20 # define __need_NULL
21 # include <stddef.h>
22 # include <string.h>
23 # endif
24
__NC(sigtimedwait)25 int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info,
26 const struct timespec *timeout)
27 {
28 # ifdef SIGCANCEL
29 sigset_t tmpset;
30
31 if (set != NULL && (unlikely (__sigismember (set, SIGCANCEL))
32 # ifdef SIGSETXID
33 || unlikely (__sigismember (set, SIGSETXID))
34 # endif
35 ))
36 {
37 /* Create a temporary mask without the bit for SIGCANCEL set. */
38 // We are not copying more than we have to.
39 memcpy (&tmpset, set, _NSIG / 8);
40 __sigdelset (&tmpset, SIGCANCEL);
41 # ifdef SIGSETXID
42 __sigdelset (&tmpset, SIGSETXID);
43 # endif
44 set = &tmpset;
45 }
46 # endif
47
48 /* if this is enabled, enable the disabled section in sigwait.c */
49 # if defined SI_TKILL && defined SI_USER
50 /* XXX The size argument hopefully will have to be changed to the
51 real size of the user-level sigset_t. */
52 /* on uClibc we use the kernel sigset_t size */
53 int result = INLINE_SYSCALL(rt_sigtimedwait, 4, set, info,
54 timeout, __SYSCALL_SIGSET_T_SIZE);
55
56 /* The kernel generates a SI_TKILL code in si_code in case tkill is
57 used. tkill is transparently used in raise(). Since having
58 SI_TKILL as a code is useful in general we fold the results
59 here. */
60 if (result != -1 && info != NULL && info->si_code == SI_TKILL)
61 info->si_code = SI_USER;
62
63 return result;
64 # else
65 /* on uClibc we use the kernel sigset_t size */
66 return INLINE_SYSCALL(rt_sigtimedwait, 4, set, info,
67 timeout, __SYSCALL_SIGSET_T_SIZE);
68 # endif
69 }
70 CANCELLABLE_SYSCALL(int, sigtimedwait,
71 (const sigset_t *set, siginfo_t *info, const struct timespec *timeout),
72 (set, info, timeout))
73 lt_libc_hidden(sigtimedwait)
74 #endif
75