__rt_sigwaitinfo.c 2.6 KB

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