__rt_sigwaitinfo.c 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * __rt_sigwaitinfo() 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. #include <sys/syscall.h>
  11. #include <signal.h>
  12. #include <string.h>
  13. #ifdef __NR_rt_sigtimedwait
  14. # ifdef __UCLIBC_HAS_THREADS_NATIVE__
  15. # include <sysdep-cancel.h>
  16. static int do_sigwaitinfo(const sigset_t *set, siginfo_t *info)
  17. {
  18. # ifdef SIGCANCEL
  19. sigset_t tmpset;
  20. if (set != NULL && (__builtin_expect (__sigismember (set, SIGCANCEL), 0)
  21. # ifdef SIGSETXID
  22. || __builtin_expect (__sigismember (set, SIGSETXID), 0)
  23. # endif
  24. ))
  25. {
  26. /* Create a temporary mask without the bit for SIGCANCEL set. */
  27. // We are not copying more than we have to.
  28. memcpy (&tmpset, set, _NSIG / 8);
  29. __sigdelset (&tmpset, SIGCANCEL);
  30. # ifdef SIGSETXID
  31. __sigdelset (&tmpset, SIGSETXID);
  32. # endif
  33. set = &tmpset;
  34. }
  35. # endif
  36. /* XXX The size argument hopefully will have to be changed to the
  37. real size of the user-level sigset_t. */
  38. int result = INLINE_SYSCALL (rt_sigtimedwait, 4, set, info,
  39. NULL, _NSIG / 8);
  40. /* The kernel generates a SI_TKILL code in si_code in case tkill is
  41. used. tkill is transparently used in raise(). Since having
  42. SI_TKILL as a code is useful in general we fold the results
  43. here. */
  44. if (result != -1 && info != NULL && info->si_code == SI_TKILL)
  45. info->si_code = SI_USER;
  46. return result;
  47. }
  48. /* Return any pending signal or wait for one for the given time. */
  49. int __sigwaitinfo(const sigset_t *set, siginfo_t *info)
  50. {
  51. if(SINGLE_THREAD_P)
  52. return do_sigwaitinfo(set, info);
  53. int oldtype = LIBC_CANCEL_ASYNC();
  54. /* XXX The size argument hopefully will have to be changed to the
  55. real size of the user-level sigset_t. */
  56. int result = do_sigwaitinfo(set, info);
  57. LIBC_CANCEL_RESET(oldtype);
  58. return result;
  59. }
  60. # else
  61. # define __need_NULL
  62. # include <stddef.h>
  63. # define __NR___rt_sigwaitinfo __NR_rt_sigtimedwait
  64. static _syscall4(int, __rt_sigwaitinfo, const sigset_t *, set,
  65. siginfo_t *, info, const struct timespec *, timeout,
  66. size_t, setsize);
  67. int attribute_hidden __sigwaitinfo(const sigset_t * set, siginfo_t * info)
  68. {
  69. return __rt_sigwaitinfo(set, info, NULL, _NSIG / 8);
  70. }
  71. # endif
  72. libc_hidden_proto(sigwaitinfo)
  73. weak_alias (__sigwaitinfo, sigwaitinfo)
  74. libc_hidden_weak(sigwaitinfo)
  75. #endif