sigqueue.goc 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // This file implements runtime support for signal handling.
  5. //
  6. // Most synchronization primitives are not available from
  7. // the signal handler (it cannot block, allocate memory, or use locks)
  8. // so the handler communicates with a processing goroutine
  9. // via struct sig, below.
  10. //
  11. // sigsend() is called by the signal handler to queue a new signal.
  12. // signal_recv() is called by the Go program to receive a newly queued signal.
  13. // Synchronization between sigsend() and signal_recv() is based on the sig.state
  14. // variable. It can be in 3 states: 0, HASWAITER and HASSIGNAL.
  15. // HASWAITER means that signal_recv() is blocked on sig.Note and there are no
  16. // new pending signals.
  17. // HASSIGNAL means that sig.mask *may* contain new pending signals,
  18. // signal_recv() can't be blocked in this state.
  19. // 0 means that there are no new pending signals and signal_recv() is not blocked.
  20. // Transitions between states are done atomically with CAS.
  21. // When signal_recv() is unblocked, it resets sig.Note and rechecks sig.mask.
  22. // If several sigsend()'s and signal_recv() execute concurrently, it can lead to
  23. // unnecessary rechecks of sig.mask, but must not lead to missed signals
  24. // nor deadlocks.
  25. package signal
  26. #include "config.h"
  27. #include "runtime.h"
  28. #include "arch.h"
  29. #include "malloc.h"
  30. #include "defs.h"
  31. static struct {
  32. Note;
  33. uint32 mask[(NSIG+31)/32];
  34. uint32 wanted[(NSIG+31)/32];
  35. uint32 state;
  36. bool inuse;
  37. } sig;
  38. enum {
  39. HASWAITER = 1,
  40. HASSIGNAL = 2,
  41. };
  42. // Called from sighandler to send a signal back out of the signal handling thread.
  43. bool
  44. __go_sigsend(int32 s)
  45. {
  46. uint32 bit, mask, old, new;
  47. if(!sig.inuse || s < 0 || (size_t)s >= 32*nelem(sig.wanted) || !(sig.wanted[s/32]&(1U<<(s&31))))
  48. return false;
  49. bit = 1 << (s&31);
  50. for(;;) {
  51. mask = sig.mask[s/32];
  52. if(mask & bit)
  53. break; // signal already in queue
  54. if(runtime_cas(&sig.mask[s/32], mask, mask|bit)) {
  55. // Added to queue.
  56. // Only send a wakeup if the receiver needs a kick.
  57. for(;;) {
  58. old = runtime_atomicload(&sig.state);
  59. if(old == HASSIGNAL)
  60. break;
  61. if(old == HASWAITER)
  62. new = 0;
  63. else // if(old == 0)
  64. new = HASSIGNAL;
  65. if(runtime_cas(&sig.state, old, new)) {
  66. if (old == HASWAITER)
  67. runtime_notewakeup(&sig);
  68. break;
  69. }
  70. }
  71. break;
  72. }
  73. }
  74. return true;
  75. }
  76. // Called to receive the next queued signal.
  77. // Must only be called from a single goroutine at a time.
  78. func signal_recv() (m uint32) {
  79. static uint32 recv[nelem(sig.mask)];
  80. uint32 i, old, new;
  81. for(;;) {
  82. // Serve from local copy if there are bits left.
  83. for(i=0; i<NSIG; i++) {
  84. if(recv[i/32]&(1U<<(i&31))) {
  85. recv[i/32] ^= 1U<<(i&31);
  86. m = i;
  87. goto done;
  88. }
  89. }
  90. // Check and update sig.state.
  91. for(;;) {
  92. old = runtime_atomicload(&sig.state);
  93. if(old == HASWAITER)
  94. runtime_throw("inconsistent state in signal_recv");
  95. if(old == HASSIGNAL)
  96. new = 0;
  97. else // if(old == 0)
  98. new = HASWAITER;
  99. if(runtime_cas(&sig.state, old, new)) {
  100. if (new == HASWAITER) {
  101. runtime_notetsleepg(&sig, -1);
  102. runtime_noteclear(&sig);
  103. }
  104. break;
  105. }
  106. }
  107. // Get a new local copy.
  108. for(i=0; (size_t)i<nelem(sig.mask); i++) {
  109. for(;;) {
  110. m = sig.mask[i];
  111. if(runtime_cas(&sig.mask[i], m, 0))
  112. break;
  113. }
  114. recv[i] = m;
  115. }
  116. }
  117. done:;
  118. // goc requires that we fall off the end of functions
  119. // that return values instead of using our own return
  120. // statements.
  121. }
  122. // Must only be called from a single goroutine at a time.
  123. func signal_enable(s uint32) {
  124. if(!sig.inuse) {
  125. // The first call to signal_enable is for us
  126. // to use for initialization. It does not pass
  127. // signal information in m.
  128. sig.inuse = true; // enable reception of signals; cannot disable
  129. runtime_noteclear(&sig);
  130. return;
  131. }
  132. if(s >= nelem(sig.wanted)*32)
  133. return;
  134. sig.wanted[s/32] |= 1U<<(s&31);
  135. runtime_sigenable(s);
  136. }
  137. // Must only be called from a single goroutine at a time.
  138. func signal_disable(s uint32) {
  139. if(s >= nelem(sig.wanted)*32)
  140. return;
  141. sig.wanted[s/32] &= ~(1U<<(s&31));
  142. runtime_sigdisable(s);
  143. }
  144. // This runs on a foreign stack, without an m or a g. No stack split.
  145. void
  146. runtime_badsignal(int sig)
  147. {
  148. __go_sigsend(sig);
  149. }