signal_user.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
  3. * Licensed under the GPL
  4. */
  5. #include <stdio.h>
  6. #include <unistd.h>
  7. #include <stdlib.h>
  8. #include <signal.h>
  9. #include <errno.h>
  10. #include <stdarg.h>
  11. #include <string.h>
  12. #include <sys/mman.h>
  13. #include "user_util.h"
  14. #include "kern_util.h"
  15. #include "user.h"
  16. #include "signal_user.h"
  17. #include "signal_kern.h"
  18. #include "sysdep/sigcontext.h"
  19. #include "sigcontext.h"
  20. void set_sigstack(void *sig_stack, int size)
  21. {
  22. stack_t stack = ((stack_t) { .ss_flags = 0,
  23. .ss_sp = (__ptr_t) sig_stack,
  24. .ss_size = size - sizeof(void *) });
  25. if(sigaltstack(&stack, NULL) != 0)
  26. panic("enabling signal stack failed, errno = %d\n", errno);
  27. }
  28. void set_handler(int sig, void (*handler)(int), int flags, ...)
  29. {
  30. struct sigaction action;
  31. va_list ap;
  32. int mask;
  33. va_start(ap, flags);
  34. action.sa_handler = handler;
  35. sigemptyset(&action.sa_mask);
  36. while((mask = va_arg(ap, int)) != -1){
  37. sigaddset(&action.sa_mask, mask);
  38. }
  39. va_end(ap);
  40. action.sa_flags = flags;
  41. action.sa_restorer = NULL;
  42. if(sigaction(sig, &action, NULL) < 0)
  43. panic("sigaction failed");
  44. }
  45. int change_sig(int signal, int on)
  46. {
  47. sigset_t sigset, old;
  48. sigemptyset(&sigset);
  49. sigaddset(&sigset, signal);
  50. sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
  51. return(!sigismember(&old, signal));
  52. }
  53. /* Both here and in set/get_signal we don't touch SIGPROF, because we must not
  54. * disable profiling; it's safe because the profiling code does not interact
  55. * with the kernel code at all.*/
  56. static void change_signals(int type)
  57. {
  58. sigset_t mask;
  59. sigemptyset(&mask);
  60. sigaddset(&mask, SIGVTALRM);
  61. sigaddset(&mask, SIGALRM);
  62. sigaddset(&mask, SIGIO);
  63. if(sigprocmask(type, &mask, NULL) < 0)
  64. panic("Failed to change signal mask - errno = %d", errno);
  65. }
  66. void block_signals(void)
  67. {
  68. change_signals(SIG_BLOCK);
  69. }
  70. void unblock_signals(void)
  71. {
  72. change_signals(SIG_UNBLOCK);
  73. }
  74. /* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled
  75. * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to
  76. * be able to profile all of UML, not just the non-critical sections. If
  77. * profiling is not thread-safe, then that is not my problem. We can disable
  78. * profiling when SMP is enabled in that case.
  79. */
  80. #define SIGIO_BIT 0
  81. #define SIGVTALRM_BIT 1
  82. static int enable_mask(sigset_t *mask)
  83. {
  84. int sigs;
  85. sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT;
  86. sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT;
  87. sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT;
  88. return(sigs);
  89. }
  90. int get_signals(void)
  91. {
  92. sigset_t mask;
  93. if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0)
  94. panic("Failed to get signal mask");
  95. return(enable_mask(&mask));
  96. }
  97. int set_signals(int enable)
  98. {
  99. sigset_t mask;
  100. int ret;
  101. sigemptyset(&mask);
  102. if(enable & (1 << SIGIO_BIT))
  103. sigaddset(&mask, SIGIO);
  104. if(enable & (1 << SIGVTALRM_BIT)){
  105. sigaddset(&mask, SIGVTALRM);
  106. sigaddset(&mask, SIGALRM);
  107. }
  108. /* This is safe - sigprocmask is guaranteed to copy locally the
  109. * value of new_set, do his work and then, at the end, write to
  110. * old_set.
  111. */
  112. if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
  113. panic("Failed to enable signals");
  114. ret = enable_mask(&mask);
  115. sigemptyset(&mask);
  116. if((enable & (1 << SIGIO_BIT)) == 0)
  117. sigaddset(&mask, SIGIO);
  118. if((enable & (1 << SIGVTALRM_BIT)) == 0){
  119. sigaddset(&mask, SIGVTALRM);
  120. sigaddset(&mask, SIGALRM);
  121. }
  122. if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
  123. panic("Failed to block signals");
  124. return(ret);
  125. }
  126. /*
  127. * Overrides for Emacs so that we follow Linus's tabbing style.
  128. * Emacs will notice this stuff at the end of the file and automatically
  129. * adjust the settings for this buffer only. This must remain at the end
  130. * of the file.
  131. * ---------------------------------------------------------------------------
  132. * Local variables:
  133. * c-file-style: "linux"
  134. * End:
  135. */