thr_sig.c revision 126000
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 126000 2004-02-19 13:51:52Z 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_BARRIER_WAIT:
134		/*
135		 * XXX - The thread has reached the barrier. We can't
136		 *	 "back it away" from the barrier.
137		 */
138		_thread_critical_enter(curthread);
139		break;
140	case PS_COND_WAIT:
141		/*
142		 * Cache the address, since it will not be available
143		 * after it has been backed out.
144		 */
145		up = &curthread->data.cond->c_lock;
146
147		UMTX_LOCK(up);
148		_thread_critical_enter(curthread);
149		_cond_wait_backout(curthread);
150		UMTX_UNLOCK(up);
151		break;
152	case PS_MUTEX_WAIT:
153		/*
154		 * Cache the address, since it will not be available
155		 * after it has been backed out.
156		 */
157		sp = &curthread->data.mutex->lock;
158
159		_SPINLOCK(sp);
160		_thread_critical_enter(curthread);
161		_mutex_lock_backout(curthread);
162		_SPINUNLOCK(sp);
163		break;
164	default:
165		/*
166		 * We need to lock the thread to read it's flags.
167		 */
168		_thread_critical_enter(curthread);
169		break;
170	}
171
172	/*
173	 * We save the flags now so that any modifications done as part
174	 * of the backout are reflected when the flags are restored.
175	 */
176	psd.psd_flags = curthread->flags;
177
178	PTHREAD_SET_STATE(curthread, PS_RUNNING);
179	_thread_critical_exit(curthread);
180	actp = proc_sigact_sigaction(sig);
181	handler = (__siginfohandler_t *)actp->sa_handler;
182	handler(sig, info, (ucontext_t *)context);
183
184        /* Restore the thread's flags, and make it runnable */
185	_thread_critical_enter(curthread);
186	curthread->flags = psd.psd_flags;
187	PTHREAD_SET_STATE(curthread, PS_RUNNING);
188	_thread_critical_exit(curthread);
189}
190