signal.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /*
  2. * Copyright (C) 2004 PathScale, Inc
  3. * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  4. * Licensed under the GPL
  5. */
  6. #include <stdlib.h>
  7. #include <stdarg.h>
  8. #include <errno.h>
  9. #include <signal.h>
  10. #include <strings.h>
  11. #include "os.h"
  12. #include "sysdep/barrier.h"
  13. #include "sysdep/sigcontext.h"
  14. #include "user.h"
  15. /*
  16. * These are the asynchronous signals. SIGVTALRM and SIGARLM are handled
  17. * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to
  18. * be able to profile all of UML, not just the non-critical sections. If
  19. * profiling is not thread-safe, then that is not my problem. We can disable
  20. * profiling when SMP is enabled in that case.
  21. */
  22. #define SIGIO_BIT 0
  23. #define SIGIO_MASK (1 << SIGIO_BIT)
  24. #define SIGVTALRM_BIT 1
  25. #define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)
  26. #define SIGALRM_BIT 2
  27. #define SIGALRM_MASK (1 << SIGALRM_BIT)
  28. /*
  29. * These are used by both the signal handlers and
  30. * block/unblock_signals. I don't want modifications cached in a
  31. * register - they must go straight to memory.
  32. */
  33. static volatile int signals_enabled = 1;
  34. static volatile int pending = 0;
  35. void sig_handler(int sig, struct sigcontext *sc)
  36. {
  37. int enabled;
  38. enabled = signals_enabled;
  39. if (!enabled && (sig == SIGIO)) {
  40. pending |= SIGIO_MASK;
  41. return;
  42. }
  43. block_signals();
  44. sig_handler_common_skas(sig, sc);
  45. set_signals(enabled);
  46. }
  47. static void real_alarm_handler(int sig, struct sigcontext *sc)
  48. {
  49. struct uml_pt_regs regs;
  50. if (sig == SIGALRM)
  51. switch_timers(0);
  52. if (sc != NULL)
  53. copy_sc(&regs, sc);
  54. regs.is_user = 0;
  55. unblock_signals();
  56. timer_handler(sig, &regs);
  57. if (sig == SIGALRM)
  58. switch_timers(1);
  59. }
  60. void alarm_handler(int sig, struct sigcontext *sc)
  61. {
  62. int enabled;
  63. enabled = signals_enabled;
  64. if (!signals_enabled) {
  65. if (sig == SIGVTALRM)
  66. pending |= SIGVTALRM_MASK;
  67. else pending |= SIGALRM_MASK;
  68. return;
  69. }
  70. block_signals();
  71. real_alarm_handler(sig, sc);
  72. set_signals(enabled);
  73. }
  74. void set_sigstack(void *sig_stack, int size)
  75. {
  76. stack_t stack = ((stack_t) { .ss_flags = 0,
  77. .ss_sp = (__ptr_t) sig_stack,
  78. .ss_size = size - sizeof(void *) });
  79. if (sigaltstack(&stack, NULL) != 0)
  80. panic("enabling signal stack failed, errno = %d\n", errno);
  81. }
  82. void remove_sigstack(void)
  83. {
  84. stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE,
  85. .ss_sp = NULL,
  86. .ss_size = 0 });
  87. if (sigaltstack(&stack, NULL) != 0)
  88. panic("disabling signal stack failed, errno = %d\n", errno);
  89. }
  90. void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
  91. void handle_signal(int sig, struct sigcontext *sc)
  92. {
  93. unsigned long pending = 1UL << sig;
  94. do {
  95. int nested, bail;
  96. /*
  97. * pending comes back with one bit set for each
  98. * interrupt that arrived while setting up the stack,
  99. * plus a bit for this interrupt, plus the zero bit is
  100. * set if this is a nested interrupt.
  101. * If bail is true, then we interrupted another
  102. * handler setting up the stack. In this case, we
  103. * have to return, and the upper handler will deal
  104. * with this interrupt.
  105. */
  106. bail = to_irq_stack(&pending);
  107. if (bail)
  108. return;
  109. nested = pending & 1;
  110. pending &= ~1;
  111. while ((sig = ffs(pending)) != 0){
  112. sig--;
  113. pending &= ~(1 << sig);
  114. (*handlers[sig])(sig, sc);
  115. }
  116. /*
  117. * Again, pending comes back with a mask of signals
  118. * that arrived while tearing down the stack. If this
  119. * is non-zero, we just go back, set up the stack
  120. * again, and handle the new interrupts.
  121. */
  122. if (!nested)
  123. pending = from_irq_stack(nested);
  124. } while (pending);
  125. }
  126. extern void hard_handler(int sig);
  127. void set_handler(int sig, void (*handler)(int), int flags, ...)
  128. {
  129. struct sigaction action;
  130. va_list ap;
  131. sigset_t sig_mask;
  132. int mask;
  133. handlers[sig] = (void (*)(int, struct sigcontext *)) handler;
  134. action.sa_handler = hard_handler;
  135. sigemptyset(&action.sa_mask);
  136. va_start(ap, flags);
  137. while ((mask = va_arg(ap, int)) != -1)
  138. sigaddset(&action.sa_mask, mask);
  139. va_end(ap);
  140. action.sa_flags = flags;
  141. action.sa_restorer = NULL;
  142. if (sigaction(sig, &action, NULL) < 0)
  143. panic("sigaction failed - errno = %d\n", errno);
  144. sigemptyset(&sig_mask);
  145. sigaddset(&sig_mask, sig);
  146. if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
  147. panic("sigprocmask failed - errno = %d\n", errno);
  148. }
  149. int change_sig(int signal, int on)
  150. {
  151. sigset_t sigset, old;
  152. sigemptyset(&sigset);
  153. sigaddset(&sigset, signal);
  154. sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
  155. return !sigismember(&old, signal);
  156. }
  157. void block_signals(void)
  158. {
  159. signals_enabled = 0;
  160. /*
  161. * This must return with signals disabled, so this barrier
  162. * ensures that writes are flushed out before the return.
  163. * This might matter if gcc figures out how to inline this and
  164. * decides to shuffle this code into the caller.
  165. */
  166. mb();
  167. }
  168. void unblock_signals(void)
  169. {
  170. int save_pending;
  171. if (signals_enabled == 1)
  172. return;
  173. /*
  174. * We loop because the IRQ handler returns with interrupts off. So,
  175. * interrupts may have arrived and we need to re-enable them and
  176. * recheck pending.
  177. */
  178. while(1) {
  179. /*
  180. * Save and reset save_pending after enabling signals. This
  181. * way, pending won't be changed while we're reading it.
  182. */
  183. signals_enabled = 1;
  184. /*
  185. * Setting signals_enabled and reading pending must
  186. * happen in this order.
  187. */
  188. mb();
  189. save_pending = pending;
  190. if (save_pending == 0) {
  191. /*
  192. * This must return with signals enabled, so
  193. * this barrier ensures that writes are
  194. * flushed out before the return. This might
  195. * matter if gcc figures out how to inline
  196. * this (unlikely, given its size) and decides
  197. * to shuffle this code into the caller.
  198. */
  199. mb();
  200. return;
  201. }
  202. pending = 0;
  203. /*
  204. * We have pending interrupts, so disable signals, as the
  205. * handlers expect them off when they are called. They will
  206. * be enabled again above.
  207. */
  208. signals_enabled = 0;
  209. /*
  210. * Deal with SIGIO first because the alarm handler might
  211. * schedule, leaving the pending SIGIO stranded until we come
  212. * back here.
  213. */
  214. if (save_pending & SIGIO_MASK)
  215. sig_handler_common_skas(SIGIO, NULL);
  216. if (save_pending & SIGALRM_MASK)
  217. real_alarm_handler(SIGALRM, NULL);
  218. if (save_pending & SIGVTALRM_MASK)
  219. real_alarm_handler(SIGVTALRM, NULL);
  220. }
  221. }
  222. int get_signals(void)
  223. {
  224. return signals_enabled;
  225. }
  226. int set_signals(int enable)
  227. {
  228. int ret;
  229. if (signals_enabled == enable)
  230. return enable;
  231. ret = signals_enabled;
  232. if (enable)
  233. unblock_signals();
  234. else block_signals();
  235. return ret;
  236. }