Deleted Added
full compact
1/*
2 * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by John Birrell.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $FreeBSD: head/lib/libkse/thread/thr_sig.c 115080 2003-05-16 19:58:30Z deischen $
32 * $FreeBSD: head/lib/libkse/thread/thr_sig.c 115278 2003-05-24 02:29:25Z deischen $
33 */
34#include <sys/param.h>
35#include <sys/types.h>
36#include <sys/signalvar.h>
37#include <signal.h>
38#include <errno.h>
39#include <fcntl.h>
40#include <unistd.h>
41#include <string.h>
42#include <pthread.h>
43#include "thr_private.h"
44#include "pthread_md.h"
45
46/* Prototypes: */
47static void build_siginfo(siginfo_t *info, int signo);
48/* static void thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info); */
49static void thr_sig_check_state(struct pthread *pthread, int sig);
50static struct pthread *thr_sig_find(struct kse *curkse, int sig,
51 siginfo_t *info);
52static void handle_special_signals(struct kse *curkse, int sig);
53static void thr_sigframe_add(struct pthread *thread, int sig,
54 siginfo_t *info);
55static void thr_sigframe_restore(struct pthread *thread,
56 struct pthread_sigframe *psf);
57static void thr_sigframe_save(struct pthread *thread,
58 struct pthread_sigframe *psf);
59static void thr_sig_invoke_handler(struct pthread *, int sig,
60 siginfo_t *info, ucontext_t *ucp);
61
62/* #define DEBUG_SIGNAL */
63#ifdef DEBUG_SIGNAL
64#define DBG_MSG stdout_debug
65#else
66#define DBG_MSG(x...)
67#endif
68
69/*
70 * Signal setup and delivery.
71 *
72 * 1) Delivering signals to threads in the same KSE.
73 * These signals are sent by upcall events and are set in the
74 * km_sigscaught field of the KSE mailbox. Since these signals
75 * are received while operating on the KSE stack, they can be
76 * delivered either by using signalcontext() to add a stack frame
77 * to the target thread's stack, or by adding them in the thread's
78 * pending set and having the thread run them down after it
79 * 2) Delivering signals to threads in other KSEs/KSEGs.
80 * 3) Delivering signals to threads in critical regions.
81 * 4) Delivering signals to threads after they change their signal masks.
82 *
83 * Methods of delivering signals.
84 *
85 * 1) Add a signal frame to the thread's saved context.
86 * 2) Add the signal to the thread structure, mark the thread as
87 * having signals to handle, and let the thread run them down
88 * after it resumes from the KSE scheduler.
89 *
90 * Problem with 1). You can't do this to a running thread or a
91 * thread in a critical region.
92 *
93 * Problem with 2). You can't do this to a thread that doesn't
94 * yield in some way (explicitly enters the scheduler). A thread
95 * blocked in the kernel or a CPU hungry thread will not see the
96 * signal without entering the scheduler.
97 *
98 * The solution is to use both 1) and 2) to deliver signals:
99 *
100 * o Thread in critical region - use 2). When the thread
101 * leaves the critical region it will check to see if it
102 * has pending signals and run them down.
103 *
104 * o Thread enters scheduler explicitly - use 2). The thread
105 * can check for pending signals after it returns from the
106 * the scheduler.
107 *
108 * o Thread is running and not current thread - use 2). When the
109 * thread hits a condition specified by one of the other bullets,
110 * the signal will be delivered.
111 *
112 * o Thread is running and is current thread (e.g., the thread
113 * has just changed its signal mask and now sees that it has
114 * pending signals) - just run down the pending signals.
115 *
116 * o Thread is swapped out due to quantum expiration - use 1)
117 *
118 * o Thread is blocked in kernel - kse_thr_wakeup() and then
119 * use 1)
120 */
121
122/*
123 * Rules for selecting threads for signals received:
124 *
125 * 1) If the signal is a sychronous signal, it is delivered to
126 * the generating (current thread). If the thread has the
127 * signal masked, it is added to the threads pending signal
128 * set until the thread unmasks it.
129 *
130 * 2) A thread in sigwait() where the signal is in the thread's
131 * waitset.
132 *
133 * 3) A thread in sigsuspend() where the signal is not in the
134 * thread's suspended signal mask.
135 *
136 * 4) Any thread (first found/easiest to deliver) that has the
137 * signal unmasked.
138 */
139
140/*
141 * This signal handler only delivers asynchronous signals.
142 * This must be called with upcalls disabled and without
143 * holding any locks.
144 */
145void
146_thr_sig_dispatch(struct kse *curkse, int sig, siginfo_t *info)
147{
148 struct pthread *thread;
149
150 DBG_MSG(">>> _thr_sig_dispatch(%d)\n", sig);
151
152 /* Some signals need special handling: */
153 handle_special_signals(curkse, sig);
154
155 if ((thread = thr_sig_find(curkse, sig, info)) != NULL) {
154 stderr_debug("dispatch sig:%d\n", sig);
155 while ((thread = thr_sig_find(curkse, sig, info)) != NULL) {
156 /*
157 * Setup the target thread to receive the signal:
158 */
159 DBG_MSG("Got signal %d, selecting thread %p\n", sig, thread);
160 KSE_SCHED_LOCK(curkse, thread->kseg);
161 _thr_sig_add(thread, sig, info);
162 KSE_SCHED_UNLOCK(curkse, thread->kseg);
161 if ((thread->state == PS_DEAD) ||
162 (thread->state == PS_DEADLOCK) ||
163 THR_IS_EXITING(thread) || THR_IS_SUSPENDED(thread)) {
164 KSE_SCHED_UNLOCK(curkse, thread->kseg);
165 _thr_ref_delete(NULL, thread);
166 } else {
167 _thr_sig_add(thread, sig, info);
168 KSE_SCHED_UNLOCK(curkse, thread->kseg);
169 _thr_ref_delete(NULL, thread);
170 break;
171 }
172 }
173}
174
175void
176_thr_sig_handler(int sig, siginfo_t *info, ucontext_t *ucp)
177{
178 void (*sigfunc)(int, siginfo_t *, void *);
179 struct kse *curkse;
180
181 curkse = _get_curkse();
182 if ((curkse == NULL) || ((curkse->k_flags & KF_STARTED) == 0)) {
183 /* Upcalls are not yet started; just call the handler. */
184 sigfunc = _thread_sigact[sig - 1].sa_sigaction;
185 ucp->uc_sigmask = _thr_proc_sigmask;
186 if (((__sighandler_t *)sigfunc != SIG_DFL) &&
187 ((__sighandler_t *)sigfunc != SIG_IGN)) {
188 if (((_thread_sigact[sig - 1].sa_flags & SA_SIGINFO)
189 != 0) || (info == NULL))
190 (*(sigfunc))(sig, info, ucp);
191 else
192 (*(sigfunc))(sig, (siginfo_t *)info->si_code,
193 ucp);
194 }
195 }
196 else {
197 /* Nothing. */
198 DBG_MSG("Got signal %d\n", sig);
199 sigaddset(&curkse->k_mbx.km_sigscaught, sig);
200 ucp->uc_sigmask = _thr_proc_sigmask;
201 }
202}
203
204static void
205thr_sig_invoke_handler(struct pthread *curthread, int sig, siginfo_t *info,
206 ucontext_t *ucp)
207{
208 void (*sigfunc)(int, siginfo_t *, void *);
209 sigset_t saved_mask;
210 int saved_seqno;
211
212 /* Invoke the signal handler without going through the scheduler:
213 */
214 DBG_MSG("Got signal %d, calling handler for current thread %p\n",
215 sig, curthread);
216
217 /*
218 * Setup the threads signal mask.
219 *
220 * The mask is changed in the thread's active signal mask
221 * (in the context) and not in the base signal mask because
222 * a thread is allowed to change its signal mask within a
223 * signal handler. If it does, the signal mask restored
224 * after the handler should be the same as that set by the
225 * thread during the handler, not the original mask from
226 * before calling the handler. The thread could also
227 * modify the signal mask in the context and expect this
228 * mask to be used.
229 */
230 THR_SCHED_LOCK(curthread, curthread);
231 saved_mask = curthread->tmbx.tm_context.uc_sigmask;
232 saved_seqno = curthread->sigmask_seqno;
233 SIGSETOR(curthread->tmbx.tm_context.uc_sigmask,
234 _thread_sigact[sig - 1].sa_mask);
235 sigaddset(&curthread->tmbx.tm_context.uc_sigmask, sig);
236 THR_SCHED_UNLOCK(curthread, curthread);
237
238 /*
239 * Check that a custom handler is installed and if
240 * the signal is not blocked:
241 */
242 sigfunc = _thread_sigact[sig - 1].sa_sigaction;
243 ucp->uc_sigmask = _thr_proc_sigmask;
244 if (((__sighandler_t *)sigfunc != SIG_DFL) &&
245 ((__sighandler_t *)sigfunc != SIG_IGN)) {
246 if (((_thread_sigact[sig - 1].sa_flags & SA_SIGINFO) != 0) ||
247 (info == NULL))
248 (*(sigfunc))(sig, info, ucp);
249 else
250 (*(sigfunc))(sig, (siginfo_t *)info->si_code, ucp);
251 }
252
253 /*
254 * Restore the thread's signal mask.
255 */
256 if (saved_seqno == curthread->sigmask_seqno)
257 curthread->tmbx.tm_context.uc_sigmask = saved_mask;
258 else
259 curthread->tmbx.tm_context.uc_sigmask = curthread->sigmask;
260}
261
262/*
263 * Find a thread that can handle the signal. This must be called
264 * with upcalls disabled.
265 */
266struct pthread *
267thr_sig_find(struct kse *curkse, int sig, siginfo_t *info)
268{
269 int handler_installed;
270 struct pthread *pthread;
271 struct pthread *suspended_thread, *signaled_thread;
272
273 DBG_MSG("Looking for thread to handle signal %d\n", sig);
274
275 handler_installed = (_thread_sigact[sig - 1].sa_handler != SIG_IGN) &&
276 (_thread_sigact[sig - 1].sa_handler != SIG_DFL);
277
278 /* Check if the signal requires a dump of thread information: */
279 if (sig == SIGINFO) {
280 /* Dump thread information to file: */
281 _thread_dump_info();
282 }
283 /*
284 * Enter a loop to look for threads that have the signal
285 * unmasked. POSIX specifies that a thread in a sigwait
286 * will get the signal over any other threads. Second
287 * preference will be threads in in a sigsuspend. Third
288 * preference will be the current thread. If none of the
289 * above, then the signal is delivered to the first thread
290 * that is found. Note that if a custom handler is not
291 * installed, the signal only affects threads in sigwait.
292 */
293 suspended_thread = NULL;
294 signaled_thread = NULL;
295
296 KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock);
297 TAILQ_FOREACH(pthread, &_thread_list, tle) {
298 /* Take the scheduling lock. */
299 KSE_SCHED_LOCK(curkse, pthread->kseg);
300 if ((pthread->state == PS_SIGWAIT) &&
301 sigismember(pthread->data.sigwait, sig)) {
302 /*
303 * Return the signal number and make the
304 * thread runnable.
305 */
306 pthread->signo = sig;
307 _thr_setrunnable_unlocked(pthread);
308
309 KSE_SCHED_UNLOCK(curkse, pthread->kseg);
310
311 /*
312 * POSIX doesn't doesn't specify which thread
313 * will get the signal if there are multiple
314 * waiters, so we give it to the first thread
315 * we find.
316 *
317 * Do not attempt to deliver this signal
318 * to other threads and do not add the signal
319 * to the process pending set.
320 */
321 KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
322 DBG_MSG("Waking thread %p in sigwait with signal %d\n",
323 pthread, sig);
324 return (NULL);
325 }
326 else if ((pthread->state == PS_DEAD) ||
327 (pthread->state == PS_DEADLOCK) ||
328 THR_IS_EXITING(pthread) || THR_IS_SUSPENDED(pthread))
329 ; /* Skip this thread. */
330 else if ((handler_installed != 0) &&
331 !sigismember(&pthread->tmbx.tm_context.uc_sigmask, sig)) {
332 if (pthread->state == PS_SIGSUSPEND) {
324 if (suspended_thread == NULL)
333 if (suspended_thread == NULL) {
334 suspended_thread = pthread;
326 } else if (signaled_thread == NULL)
335 suspended_thread->refcount++;
336 }
337 } else if (signaled_thread == NULL) {
338 signaled_thread = pthread;
339 signaled_thread->refcount++;
340 }
341 }
342 KSE_SCHED_UNLOCK(curkse, pthread->kseg);
343 }
344 KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
345
346 /*
347 * Only perform wakeups and signal delivery if there is a
348 * custom handler installed:
349 */
350 if (handler_installed == 0) {
351 /*
352 * There is no handler installed; nothing to do here.
353 */
354 } else if (suspended_thread == NULL &&
355 signaled_thread == NULL) {
356 /*
357 * Add it to the set of signals pending
358 * on the process:
359 */
360 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
361 if (!sigismember(&_thr_proc_sigpending, sig)) {
362 sigaddset(&_thr_proc_sigpending, sig);
363 if (info == NULL)
364 build_siginfo(&_thr_proc_siginfo[sig], sig);
365 else
366 memcpy(&_thr_proc_siginfo[sig], info,
367 sizeof(*info));
368 }
369 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
370 } else {
371 /*
372 * We only deliver the signal to one thread;
373 * give preference to the suspended thread:
374 */
362 if (suspended_thread != NULL)
375 if (suspended_thread != NULL) {
376 pthread = suspended_thread;
364 else
377 _thr_ref_delete(NULL, signaled_thread);
378 } else
379 pthread = signaled_thread;
380 return (pthread);
381 }
382 return (NULL);
383}
384
385static void
386build_siginfo(siginfo_t *info, int signo)
387{
388 bzero(info, sizeof(*info));
389 info->si_signo = signo;
390 info->si_pid = _thr_pid;
391}
392
393/*
394 * This is called by a thread when it has pending signals to deliver.
395 * It should only be called from the context of the thread.
396 */
397void
398_thr_sig_rundown(struct pthread *curthread, ucontext_t *ucp,
399 struct pthread_sigframe *psf)
400{
401 struct pthread_sigframe psf_save;
402 sigset_t sigset;
403 int i;
404
405 THR_SCHED_LOCK(curthread, curthread);
406 memcpy(&sigset, &curthread->sigpend, sizeof(sigset));
407 sigemptyset(&curthread->sigpend);
408 if (psf != NULL) {
409 memcpy(&psf_save, psf, sizeof(*psf));
410 SIGSETOR(sigset, psf_save.psf_sigset);
411 sigemptyset(&psf->psf_sigset);
412 }
413 THR_SCHED_UNLOCK(curthread, curthread);
414
415 /* Check the threads previous state: */
416 if ((psf != NULL) && (psf_save.psf_state != PS_RUNNING)) {
417 /*
418 * Do a little cleanup handling for those threads in
419 * queues before calling the signal handler. Signals
420 * for these threads are temporarily blocked until
421 * after cleanup handling.
422 */
423 switch (psf_save.psf_state) {
424 case PS_COND_WAIT:
425 _cond_wait_backout(curthread);
426 psf_save.psf_state = PS_RUNNING;
427 break;
428
429 case PS_MUTEX_WAIT:
430 _mutex_lock_backout(curthread);
431 psf_save.psf_state = PS_RUNNING;
432 break;
433
434 default:
435 break;
436 }
437 }
438 /*
439 * Lower the priority before calling the handler in case
440 * it never returns (longjmps back):
441 */
442 curthread->active_priority &= ~THR_SIGNAL_PRIORITY;
443
444 for (i = 1; i < NSIG; i++) {
445 if (sigismember(&sigset, i) != 0) {
446 /* Call the handler: */
447 thr_sig_invoke_handler(curthread, i,
448 &curthread->siginfo[i], ucp);
449 }
450 }
451
452 THR_SCHED_LOCK(curthread, curthread);
453 if (psf != NULL)
454 thr_sigframe_restore(curthread, &psf_save);
455 /* Restore the signal mask. */
456 curthread->tmbx.tm_context.uc_sigmask = curthread->sigmask;
457 THR_SCHED_UNLOCK(curthread, curthread);
458 _thr_sig_check_pending(curthread);
459}
460
461/*
462 * This checks pending signals for the current thread. It should be
463 * called whenever a thread changes its signal mask. Note that this
464 * is called from a thread (using its stack).
465 *
466 * XXX - We might want to just check to see if there are pending
467 * signals for the thread here, but enter the UTS scheduler
468 * to actually install the signal handler(s).
469 */
470void
471_thr_sig_check_pending(struct pthread *curthread)
472{
473 sigset_t sigset;
474 sigset_t pending_process;
475 sigset_t pending_thread;
476 kse_critical_t crit;
477 int i;
478
479 curthread->check_pending = 0;
480
481 /*
482 * Check if there are pending signals for the running
483 * thread or process that aren't blocked:
484 */
485 crit = _kse_critical_enter();
486 KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock);
487 sigset = _thr_proc_sigpending;
488 KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock);
489 _kse_critical_leave(crit);
490
491 THR_SCHED_LOCK(curthread, curthread);
492 SIGSETOR(sigset, curthread->sigpend);
493 SIGSETNAND(sigset, curthread->tmbx.tm_context.uc_sigmask);
494 if (SIGNOTEMPTY(sigset)) {
495 ucontext_t uc;
496 volatile int once;
497
498 curthread->check_pending = 0;
499 THR_SCHED_UNLOCK(curthread, curthread);
500
501 /*
502 * Split the pending signals into those that were
503 * pending on the process and those that were pending
504 * on the thread.
505 */
506 sigfillset(&pending_process);
507 sigfillset(&pending_thread);
508 for (i = 1; i < NSIG; i++) {
509 if (sigismember(&sigset, i) != 0) {
510 if (sigismember(&curthread->sigpend, i) != 0) {
511 build_siginfo(&curthread->siginfo[i], i);
512 sigdelset(&pending_thread, i);
513 } else {
514 memcpy(&curthread->siginfo[i],
515 &_thr_proc_siginfo[i],
516 sizeof(siginfo_t));
517 sigdelset(&pending_process, i);
518 }
519 }
520 }
521 /*
522 * Remove any process pending signals that were scheduled
523 * to be delivered from process' pending set.
524 */
525 crit = _kse_critical_enter();
526 KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock);
527 SIGSETAND(_thr_proc_sigpending, pending_process);
528 KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock);
529 _kse_critical_leave(crit);
530
531 /*
532 * Remove any thread pending signals that were scheduled
533 * to be delivered from thread's pending set.
534 */
535 THR_SCHED_LOCK(curthread, curthread);
536 SIGSETAND(curthread->sigpend, pending_thread);
537 THR_SCHED_UNLOCK(curthread, curthread);
538
539 once = 0;
540 THR_GETCONTEXT(&uc);
541 if (once == 0) {
542 once = 1;
543 for (i = 1; i < NSIG; i++) {
544 if (sigismember(&sigset, i) != 0) {
545 /* Call the handler: */
546 thr_sig_invoke_handler(curthread, i,
547 &curthread->siginfo[i], &uc);
548 }
549 }
550 }
551 }
552 else
553 THR_SCHED_UNLOCK(curthread, curthread);
554}
555
556/*
557 * This must be called with upcalls disabled.
558 */
559static void
560handle_special_signals(struct kse *curkse, int sig)
561{
562 switch (sig) {
563 /*
564 * POSIX says that pending SIGCONT signals are
565 * discarded when one of these signals occurs.
566 */
567 case SIGTSTP:
568 case SIGTTIN:
569 case SIGTTOU:
570 KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock);
571 sigdelset(&_thr_proc_sigpending, SIGCONT);
572 KSE_LOCK_RELEASE(curkse, &_thread_signal_lock);
573 break;
574
575 default:
576 break;
577 }
578}
579
580/*
581 * Perform thread specific actions in response to a signal.
582 * This function is only called if there is a handler installed
583 * for the signal, and if the target thread has the signal
584 * unmasked.
585 *
586 * This must be called with the thread's scheduling lock held.
587 */
588void
589_thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
590{
591 int restart;
592 int suppress_handler = 0;
593
594 if (pthread->curframe == NULL) {
595 /*
596 * This thread is active. Just add it to the
597 * thread's pending set.
598 */
599 sigaddset(&pthread->sigpend, sig);
600 pthread->check_pending = 1;
601 if (info == NULL)
602 build_siginfo(&pthread->siginfo[sig], sig);
603 else if (info != &pthread->siginfo[sig])
604 memcpy(&pthread->siginfo[sig], info,
605 sizeof(*info));
606 if ((pthread->blocked != 0) && !THR_IN_CRITICAL(pthread))
607 kse_thr_interrupt(&pthread->tmbx /* XXX - restart?!?! */);
608 }
609 else {
610 restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART;
611
612 /* Make sure this signal isn't still in the pending set: */
613 sigdelset(&pthread->sigpend, sig);
614
615 /*
616 * Process according to thread state:
617 */
618 switch (pthread->state) {
619 /*
620 * States which do not change when a signal is trapped:
621 */
622 case PS_DEAD:
623 case PS_DEADLOCK:
624 case PS_LOCKWAIT:
625 case PS_SUSPENDED:
626 case PS_STATE_MAX:
627 /*
628 * You can't call a signal handler for threads in these
629 * states.
630 */
631 suppress_handler = 1;
632 break;
633
634 /*
635 * States which do not need any cleanup handling when signals
636 * occur:
637 */
638 case PS_RUNNING:
639 /*
640 * Remove the thread from the queue before changing its
641 * priority:
642 */
643 if ((pthread->flags & THR_FLAGS_IN_RUNQ) != 0)
644 THR_RUNQ_REMOVE(pthread);
645 break;
646
647 /*
648 * States which cannot be interrupted but still require the
649 * signal handler to run:
650 */
651 case PS_COND_WAIT:
652 case PS_MUTEX_WAIT:
653 /*
654 * Remove the thread from the wait queue. It will
655 * be added back to the wait queue once all signal
656 * handlers have been invoked.
657 */
658 KSE_WAITQ_REMOVE(pthread->kse, pthread);
659 break;
660
661 case PS_SLEEP_WAIT:
662 /*
663 * Unmasked signals always cause sleep to terminate
664 * early regardless of SA_RESTART:
665 */
666 pthread->interrupted = 1;
667 KSE_WAITQ_REMOVE(pthread->kse, pthread);
668 THR_SET_STATE(pthread, PS_RUNNING);
669 break;
670
671 case PS_JOIN:
672 case PS_SIGSUSPEND:
673 KSE_WAITQ_REMOVE(pthread->kse, pthread);
674 THR_SET_STATE(pthread, PS_RUNNING);
675 break;
676
677 case PS_SIGWAIT:
678 /*
679 * The signal handler is not called for threads in
680 * SIGWAIT.
681 */
682 suppress_handler = 1;
683 /* Wake up the thread if the signal is blocked. */
684 if (sigismember(pthread->data.sigwait, sig)) {
685 /* Return the signal number: */
686 pthread->signo = sig;
687
688 /* Make the thread runnable: */
689 _thr_setrunnable_unlocked(pthread);
690 } else
691 /* Increment the pending signal count. */
692 sigaddset(&pthread->sigpend, sig);
693 break;
694 }
695
696 if (suppress_handler == 0) {
697 /*
698 * Setup a signal frame and save the current threads
699 * state:
700 */
701 thr_sigframe_add(pthread, sig, info);
702
703 if (pthread->state != PS_RUNNING)
704 THR_SET_STATE(pthread, PS_RUNNING);
705
706 /*
707 * The thread should be removed from all scheduling
708 * queues at this point. Raise the priority and
709 * place the thread in the run queue. It is also
710 * possible for a signal to be sent to a suspended
711 * thread, mostly via pthread_kill(). If a thread
712 * is suspended, don't insert it into the priority
713 * queue; just set its state to suspended and it
714 * will run the signal handler when it is resumed.
715 */
716 pthread->active_priority |= THR_SIGNAL_PRIORITY;
717 if ((pthread->flags & THR_FLAGS_IN_RUNQ) == 0)
718 THR_RUNQ_INSERT_TAIL(pthread);
719 }
720 }
721}
722
723static void
724thr_sig_check_state(struct pthread *pthread, int sig)
725{
726 /*
727 * Process according to thread state:
728 */
729 switch (pthread->state) {
730 /*
731 * States which do not change when a signal is trapped:
732 */
733 case PS_RUNNING:
734 case PS_LOCKWAIT:
735 case PS_MUTEX_WAIT:
736 case PS_COND_WAIT:
737 case PS_JOIN:
738 case PS_SUSPENDED:
739 case PS_DEAD:
740 case PS_DEADLOCK:
741 case PS_STATE_MAX:
742 break;
743
744 case PS_SIGWAIT:
745 /* Wake up the thread if the signal is blocked. */
746 if (sigismember(pthread->data.sigwait, sig)) {
747 /* Return the signal number: */
748 pthread->signo = sig;
749
750 /* Change the state of the thread to run: */
751 _thr_setrunnable_unlocked(pthread);
752 } else
753 /* Increment the pending signal count. */
754 sigaddset(&pthread->sigpend, sig);
755 break;
756
757 case PS_SIGSUSPEND:
758 case PS_SLEEP_WAIT:
759 /*
760 * Remove the thread from the wait queue and make it
761 * runnable:
762 */
763 _thr_setrunnable_unlocked(pthread);
764
765 /* Flag the operation as interrupted: */
766 pthread->interrupted = 1;
767 break;
768 }
769}
770
771/*
772 * Send a signal to a specific thread (ala pthread_kill):
773 */
774void
775_thr_sig_send(struct pthread *pthread, int sig)
776{
777 struct pthread *curthread = _get_curthread();
778
779 /* Lock the scheduling queue of the target thread. */
780 THR_SCHED_LOCK(curthread, pthread);
781
782 /* Check for signals whose actions are SIG_DFL: */
783 if (_thread_sigact[sig - 1].sa_handler == SIG_DFL) {
784 /*
785 * Check to see if a temporary signal handler is
786 * installed for sigwaiters:
787 */
788 if (_thread_dfl_count[sig] == 0) {
789 /*
790 * Deliver the signal to the process if a handler
791 * is not installed:
792 */
793 THR_SCHED_UNLOCK(curthread, pthread);
794 kill(getpid(), sig);
795 THR_SCHED_LOCK(curthread, pthread);
796 }
797 /*
798 * Assuming we're still running after the above kill(),
799 * make any necessary state changes to the thread:
800 */
801 thr_sig_check_state(pthread, sig);
802 THR_SCHED_UNLOCK(curthread, pthread);
803 }
804 /*
805 * Check that the signal is not being ignored:
806 */
807 else if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
808 if (pthread->state == PS_SIGWAIT &&
809 sigismember(pthread->data.sigwait, sig)) {
810 /* Return the signal number: */
811 pthread->signo = sig;
812
813 /* Change the state of the thread to run: */
814 _thr_setrunnable_unlocked(pthread);
815 THR_SCHED_UNLOCK(curthread, pthread);
816 } else if (sigismember(&pthread->tmbx.tm_context.uc_sigmask, sig)) {
817 /* Add the signal to the pending set: */
818 sigaddset(&pthread->sigpend, sig);
819 THR_SCHED_UNLOCK(curthread, pthread);
820 } else if (pthread == curthread) {
821 ucontext_t uc;
822 siginfo_t info;
823 volatile int once;
824
825 THR_SCHED_UNLOCK(curthread, pthread);
826 build_siginfo(&info, sig);
827 once = 0;
828 THR_GETCONTEXT(&uc);
829 if (once == 0) {
830 once = 1;
831 /*
832 * Call the signal handler for the current
833 * thread:
834 */
835 thr_sig_invoke_handler(curthread, sig,
836 &info, &uc);
837 }
838 } else {
839 /*
840 * Perform any state changes due to signal
841 * arrival:
842 */
843 _thr_sig_add(pthread, sig, NULL);
844 THR_SCHED_UNLOCK(curthread, pthread);
845 }
846 }
847}
848
849static void
850thr_sigframe_add(struct pthread *thread, int sig, siginfo_t *info)
851{
852 if (thread->curframe == NULL)
853 PANIC("Thread doesn't have signal frame ");
854
855 if (thread->have_signals == 0) {
856 /*
857 * Multiple signals can be added to the same signal
858 * frame. Only save the thread's state the first time.
859 */
860 thr_sigframe_save(thread, thread->curframe);
861 thread->have_signals = 1;
862 thread->flags &= THR_FLAGS_PRIVATE;
863 }
864 sigaddset(&thread->curframe->psf_sigset, sig);
865 if (info == NULL)
866 build_siginfo(&thread->siginfo[sig], sig);
867 else if (info != &thread->siginfo[sig])
868 memcpy(&thread->siginfo[sig], info, sizeof(*info));
869
870 /* Setup the new signal mask. */
871 SIGSETOR(thread->tmbx.tm_context.uc_sigmask,
872 _thread_sigact[sig - 1].sa_mask);
873 sigaddset(&thread->tmbx.tm_context.uc_sigmask, sig);
874}
875
876void
877thr_sigframe_restore(struct pthread *thread, struct pthread_sigframe *psf)
878{
879 thread->flags = psf->psf_flags;
880 thread->interrupted = psf->psf_interrupted;
881 thread->signo = psf->psf_signo;
882 thread->state = psf->psf_state;
883 thread->data = psf->psf_wait_data;
884 thread->wakeup_time = psf->psf_wakeup_time;
885 if (thread->sigmask_seqno == psf->psf_seqno)
886 thread->tmbx.tm_context.uc_sigmask = psf->psf_sigmask;
887 else
888 thread->tmbx.tm_context.uc_sigmask = thread->sigmask;
889}
890
891static void
892thr_sigframe_save(struct pthread *thread, struct pthread_sigframe *psf)
893{
894 /* This has to initialize all members of the sigframe. */
895 psf->psf_flags = thread->flags & THR_FLAGS_PRIVATE;
896 psf->psf_interrupted = thread->interrupted;
897 psf->psf_signo = thread->signo;
898 psf->psf_state = thread->state;
899 psf->psf_wait_data = thread->data;
900 psf->psf_wakeup_time = thread->wakeup_time;
901 psf->psf_sigmask = thread->tmbx.tm_context.uc_sigmask;
902 psf->psf_seqno = thread->sigmask_seqno;
903 sigemptyset(&psf->psf_sigset);
904}