__rt_sigtimedwait.c 2.8 KB

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