thr_sig.c revision 125999
1/*
2 * Copyright (c) 2003 Jeffrey Roberson <jeff@freebsd.org>
3 * Copyright (c) 2003 Jonathan Mini <mini@freebsd.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice unmodified, this list of conditions, and the following
11 *    disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 * $FreeBSD: head/lib/libthr/thread/thr_sig.c 125999 2004-02-19 13:47:12Z mtm $
28 */
29
30#include <sys/param.h>
31#include <sys/types.h>
32#include <sys/signalvar.h>
33#include <signal.h>
34#include <fcntl.h>
35#include <unistd.h>
36#include <setjmp.h>
37#include <errno.h>
38#include <pthread.h>
39#include <stdlib.h>
40
41#include "thr_private.h"
42
43/* #define DEBUG_SIGNAL */
44#ifdef DEBUG_SIGNAL
45#define DBG_MSG		stdout_debug
46#else
47#define DBG_MSG(x...)
48#endif
49
50__weak_reference(_sigprocmask, sigprocmask);
51
52int
53_sigprocmask(int how, const sigset_t *set, sigset_t *oset)
54{
55	sigset_t new;
56
57	/*
58	 * Make sure applications can't unblock our synchronization
59	 * signal. We always want to take this with sigwait().
60	 */
61	if (set != NULL) {
62		new = *set;
63		switch (how) {
64		case SIG_BLOCK:
65		case SIG_SETMASK:
66			SIGADDSET(new, SIGTHR);
67			break;
68		case SIG_UNBLOCK:
69			SIGDELSET(new, SIGTHR);
70			break;
71		default:
72			break;
73		}
74		set = &new;
75	}
76
77	return (__sys_sigprocmask(how, set, oset));
78}
79
80__weak_reference(_pthread_sigmask, pthread_sigmask);
81
82int
83_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
84{
85	int error;
86
87	/*
88	 * This always sets the mask on the current thread.
89	 */
90	error = sigprocmask(how, set, oset);
91
92	/*
93	 * pthread_sigmask returns errno or success while sigprocmask returns
94	 * -1 and sets errno.
95	 */
96	if (error == -1)
97		error = errno;
98
99	return (error);
100}
101
102
103__weak_reference(_pthread_kill, pthread_kill);
104
105int
106_pthread_kill(pthread_t pthread, int sig)
107{
108
109	if (_thread_initial == NULL)
110		_thread_init();
111	return (thr_kill(pthread->thr_id, sig));
112}
113
114/*
115 * User thread signal handler wrapper.
116 */
117void
118_thread_sig_wrapper(int sig, siginfo_t *info, void *context)
119{
120	struct pthread_state_data psd;
121	struct sigaction *actp;
122	__siginfohandler_t *handler;
123	struct umtx *up;
124	spinlock_t *sp;
125
126	/*
127	 * Do a little cleanup handling for those threads in
128	 * queues before calling the signal handler.  Signals
129	 * for these threads are temporarily blocked until
130	 * after cleanup handling.
131	 */
132	switch (curthread->state) {
133	case PS_COND_WAIT:
134		/*
135		 * Cache the address, since it will not be available
136		 * after it has been backed out.
137		 */
138		up = &curthread->data.cond->c_lock;
139
140		UMTX_LOCK(up);
141		_thread_critical_enter(curthread);
142		_cond_wait_backout(curthread);
143		UMTX_UNLOCK(up);
144		break;
145	case PS_MUTEX_WAIT:
146		/*
147		 * Cache the address, since it will not be available
148		 * after it has been backed out.
149		 */
150		sp = &curthread->data.mutex->lock;
151
152		_SPINLOCK(sp);
153		_thread_critical_enter(curthread);
154		_mutex_lock_backout(curthread);
155		_SPINUNLOCK(sp);
156		break;
157	default:
158		/*
159		 * We need to lock the thread to read it's flags.
160		 */
161		_thread_critical_enter(curthread);
162		break;
163	}
164
165	/*
166	 * We save the flags now so that any modifications done as part
167	 * of the backout are reflected when the flags are restored.
168	 */
169	psd.psd_flags = curthread->flags;
170
171	PTHREAD_SET_STATE(curthread, PS_RUNNING);
172	_thread_critical_exit(curthread);
173	actp = proc_sigact_sigaction(sig);
174	handler = (__siginfohandler_t *)actp->sa_handler;
175	handler(sig, info, (ucontext_t *)context);
176
177        /* Restore the thread's flags, and make it runnable */
178	_thread_critical_enter(curthread);
179	curthread->flags = psd.psd_flags;
180	PTHREAD_SET_STATE(curthread, PS_RUNNING);
181	_thread_critical_exit(curthread);
182}
183