signal.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * Copyright (C) 2004 PathScale, Inc
  3. * Licensed under the GPL
  4. */
  5. #include <signal.h>
  6. #include <stdio.h>
  7. #include <unistd.h>
  8. #include <stdlib.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 "user.h"
  15. #include "signal_kern.h"
  16. #include "sysdep/sigcontext.h"
  17. #include "sysdep/signal.h"
  18. #include "sigcontext.h"
  19. #include "mode.h"
  20. #include "os.h"
  21. void sig_handler(ARCH_SIGHDLR_PARAM)
  22. {
  23. struct sigcontext *sc;
  24. ARCH_GET_SIGCONTEXT(sc, sig);
  25. CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
  26. sig, sc);
  27. }
  28. extern int timer_irq_inited;
  29. void alarm_handler(ARCH_SIGHDLR_PARAM)
  30. {
  31. struct sigcontext *sc;
  32. ARCH_GET_SIGCONTEXT(sc, sig);
  33. if(!timer_irq_inited) return;
  34. if(sig == SIGALRM)
  35. switch_timers(0);
  36. CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
  37. sig, sc);
  38. if(sig == SIGALRM)
  39. switch_timers(1);
  40. }
  41. extern void do_boot_timer_handler(struct sigcontext * sc);
  42. void boot_timer_handler(ARCH_SIGHDLR_PARAM)
  43. {
  44. struct sigcontext *sc;
  45. ARCH_GET_SIGCONTEXT(sc, sig);
  46. do_boot_timer_handler(sc);
  47. }
  48. void set_sigstack(void *sig_stack, int size)
  49. {
  50. stack_t stack = ((stack_t) { .ss_flags = 0,
  51. .ss_sp = (__ptr_t) sig_stack,
  52. .ss_size = size - sizeof(void *) });
  53. if(sigaltstack(&stack, NULL) != 0)
  54. panic("enabling signal stack failed, errno = %d\n", errno);
  55. }
  56. void remove_sigstack(void)
  57. {
  58. stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE,
  59. .ss_sp = NULL,
  60. .ss_size = 0 });
  61. if(sigaltstack(&stack, NULL) != 0)
  62. panic("disabling signal stack failed, errno = %d\n", errno);
  63. }
  64. void set_handler(int sig, void (*handler)(int), int flags, ...)
  65. {
  66. struct sigaction action;
  67. va_list ap;
  68. int mask;
  69. va_start(ap, flags);
  70. action.sa_handler = handler;
  71. sigemptyset(&action.sa_mask);
  72. while((mask = va_arg(ap, int)) != -1){
  73. sigaddset(&action.sa_mask, mask);
  74. }
  75. va_end(ap);
  76. action.sa_flags = flags;
  77. action.sa_restorer = NULL;
  78. if(sigaction(sig, &action, NULL) < 0)
  79. panic("sigaction failed");
  80. }
  81. int change_sig(int signal, int on)
  82. {
  83. sigset_t sigset, old;
  84. sigemptyset(&sigset);
  85. sigaddset(&sigset, signal);
  86. sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
  87. return(!sigismember(&old, signal));
  88. }
  89. /* Both here and in set/get_signal we don't touch SIGPROF, because we must not
  90. * disable profiling; it's safe because the profiling code does not interact
  91. * with the kernel code at all.*/
  92. static void change_signals(int type)
  93. {
  94. sigset_t mask;
  95. sigemptyset(&mask);
  96. sigaddset(&mask, SIGVTALRM);
  97. sigaddset(&mask, SIGALRM);
  98. sigaddset(&mask, SIGIO);
  99. if(sigprocmask(type, &mask, NULL) < 0)
  100. panic("Failed to change signal mask - errno = %d", errno);
  101. }
  102. void block_signals(void)
  103. {
  104. change_signals(SIG_BLOCK);
  105. }
  106. void unblock_signals(void)
  107. {
  108. change_signals(SIG_UNBLOCK);
  109. }
  110. /* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled
  111. * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to
  112. * be able to profile all of UML, not just the non-critical sections. If
  113. * profiling is not thread-safe, then that is not my problem. We can disable
  114. * profiling when SMP is enabled in that case.
  115. */
  116. #define SIGIO_BIT 0
  117. #define SIGVTALRM_BIT 1
  118. static int enable_mask(sigset_t *mask)
  119. {
  120. int sigs;
  121. sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT;
  122. sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT;
  123. sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT;
  124. return(sigs);
  125. }
  126. int get_signals(void)
  127. {
  128. sigset_t mask;
  129. if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0)
  130. panic("Failed to get signal mask");
  131. return(enable_mask(&mask));
  132. }
  133. int set_signals(int enable)
  134. {
  135. sigset_t mask;
  136. int ret;
  137. sigemptyset(&mask);
  138. if(enable & (1 << SIGIO_BIT))
  139. sigaddset(&mask, SIGIO);
  140. if(enable & (1 << SIGVTALRM_BIT)){
  141. sigaddset(&mask, SIGVTALRM);
  142. sigaddset(&mask, SIGALRM);
  143. }
  144. /* This is safe - sigprocmask is guaranteed to copy locally the
  145. * value of new_set, do his work and then, at the end, write to
  146. * old_set.
  147. */
  148. if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
  149. panic("Failed to enable signals");
  150. ret = enable_mask(&mask);
  151. sigemptyset(&mask);
  152. if((enable & (1 << SIGIO_BIT)) == 0)
  153. sigaddset(&mask, SIGIO);
  154. if((enable & (1 << SIGVTALRM_BIT)) == 0){
  155. sigaddset(&mask, SIGVTALRM);
  156. sigaddset(&mask, SIGALRM);
  157. }
  158. if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
  159. panic("Failed to block signals");
  160. return(ret);
  161. }