__rt_sigtimedwait.c 2.8 KB

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