xref: /freebsd/lib/libthr/thread/thr_sig.c (revision 0ad70ba98ee085920278919358d55d7c4f365280)
1bb535300SJeff Roberson /*
2bb535300SJeff Roberson  * Copyright (c) 2003 Jeffrey Roberson <jeff@freebsd.org>
3bb535300SJeff Roberson  * Copyright (c) 2003 Jonathan Mini <mini@freebsd.org>
4bb535300SJeff Roberson  * All rights reserved.
5bb535300SJeff Roberson  *
6bb535300SJeff Roberson  * Redistribution and use in source and binary forms, with or without
7bb535300SJeff Roberson  * modification, are permitted provided that the following conditions
8bb535300SJeff Roberson  * are met:
9bb535300SJeff Roberson  * 1. Redistributions of source code must retain the above copyright
10bb535300SJeff Roberson  *    notice unmodified, this list of conditions, and the following
11bb535300SJeff Roberson  *    disclaimer.
12bb535300SJeff Roberson  * 2. Redistributions in binary form must reproduce the above copyright
13bb535300SJeff Roberson  *    notice, this list of conditions and the following disclaimer in the
14bb535300SJeff Roberson  *    documentation and/or other materials provided with the distribution.
15bb535300SJeff Roberson  *
16bb535300SJeff Roberson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17bb535300SJeff Roberson  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18bb535300SJeff Roberson  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19bb535300SJeff Roberson  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20bb535300SJeff Roberson  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21bb535300SJeff Roberson  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22bb535300SJeff Roberson  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23bb535300SJeff Roberson  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24bb535300SJeff Roberson  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25bb535300SJeff Roberson  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26bb535300SJeff Roberson  *
27bb535300SJeff Roberson  * $FreeBSD$
28bb535300SJeff Roberson  */
29bb535300SJeff Roberson 
30bb535300SJeff Roberson #include <sys/param.h>
31bb535300SJeff Roberson #include <sys/types.h>
32bb535300SJeff Roberson #include <sys/signalvar.h>
33bb535300SJeff Roberson #include <signal.h>
34bb535300SJeff Roberson #include <fcntl.h>
35bb535300SJeff Roberson #include <unistd.h>
36bb535300SJeff Roberson #include <setjmp.h>
37bb535300SJeff Roberson #include <errno.h>
38bb535300SJeff Roberson #include <pthread.h>
3989552201SMike Makonnen #include <stdlib.h>
4089552201SMike Makonnen 
41bb535300SJeff Roberson #include "thr_private.h"
42bb535300SJeff Roberson 
43bb535300SJeff Roberson /* #define DEBUG_SIGNAL */
44bb535300SJeff Roberson #ifdef DEBUG_SIGNAL
45bb535300SJeff Roberson #define DBG_MSG		stdout_debug
46bb535300SJeff Roberson #else
47bb535300SJeff Roberson #define DBG_MSG(x...)
48bb535300SJeff Roberson #endif
49bb535300SJeff Roberson 
50bb535300SJeff Roberson __weak_reference(_pthread_sigmask, pthread_sigmask);
51bb535300SJeff Roberson 
52bb535300SJeff Roberson int
53bb535300SJeff Roberson _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
54bb535300SJeff Roberson {
55bb535300SJeff Roberson 	int error;
56bb535300SJeff Roberson 
57bb535300SJeff Roberson 	/*
58bb535300SJeff Roberson 	 * This always sets the mask on the current thread.
59bb535300SJeff Roberson 	 */
60bb535300SJeff Roberson 	error = sigprocmask(how, set, oset);
61bb535300SJeff Roberson 
62bb535300SJeff Roberson 	/*
63bb535300SJeff Roberson 	 * pthread_sigmask returns errno or success while sigprocmask returns
64bb535300SJeff Roberson 	 * -1 and sets errno.
65bb535300SJeff Roberson 	 */
66bb535300SJeff Roberson 	if (error == -1)
67bb535300SJeff Roberson 		error = errno;
68bb535300SJeff Roberson 
69bb535300SJeff Roberson 	return (error);
70bb535300SJeff Roberson }
71bb535300SJeff Roberson 
72bb535300SJeff Roberson 
73bb535300SJeff Roberson __weak_reference(_pthread_kill, pthread_kill);
74bb535300SJeff Roberson 
75bb535300SJeff Roberson int
76bb535300SJeff Roberson _pthread_kill(pthread_t pthread, int sig)
77bb535300SJeff Roberson {
780ad70ba9SMike Makonnen 	int error;
79bb535300SJeff Roberson 
800ad70ba9SMike Makonnen 	if (sig < 0 || sig > NSIG)
810ad70ba9SMike Makonnen 		return (EINVAL);
82bb535300SJeff Roberson 	if (_thread_initial == NULL)
83bb535300SJeff Roberson 		_thread_init();
840ad70ba9SMike Makonnen 	error = _find_thread(pthread);
850ad70ba9SMike Makonnen 	if (error != 0)
860ad70ba9SMike Makonnen 		return (error);
870ad70ba9SMike Makonnen 
880ad70ba9SMike Makonnen 	/*
890ad70ba9SMike Makonnen 	 * A 0 signal means do error-checking but don't send signal.
900ad70ba9SMike Makonnen 	 */
910ad70ba9SMike Makonnen 	if (sig == 0)
920ad70ba9SMike Makonnen 		return (0);
930ad70ba9SMike Makonnen 
94bb535300SJeff Roberson 	return (thr_kill(pthread->thr_id, sig));
95bb535300SJeff Roberson }
96bb535300SJeff Roberson 
97bb535300SJeff Roberson /*
98bb535300SJeff Roberson  * User thread signal handler wrapper.
99bb535300SJeff Roberson  */
100bb535300SJeff Roberson void
1017d9d7ca2SMike Makonnen _thread_sig_wrapper(int sig, siginfo_t *info, void *context)
102bb535300SJeff Roberson {
103bb535300SJeff Roberson 	struct pthread_state_data psd;
10489552201SMike Makonnen 	struct sigaction *actp;
105bb535300SJeff Roberson 	__siginfohandler_t *handler;
10689552201SMike Makonnen 	struct umtx *up;
10789552201SMike Makonnen 	spinlock_t *sp;
108bb535300SJeff Roberson 
109bb535300SJeff Roberson 	/*
110bb535300SJeff Roberson 	 * Do a little cleanup handling for those threads in
111bb535300SJeff Roberson 	 * queues before calling the signal handler.  Signals
112bb535300SJeff Roberson 	 * for these threads are temporarily blocked until
113bb535300SJeff Roberson 	 * after cleanup handling.
114bb535300SJeff Roberson 	 */
11589552201SMike Makonnen 	switch (curthread->state) {
116d4d7df5cSMike Makonnen 	case PS_BARRIER_WAIT:
117d4d7df5cSMike Makonnen 		/*
118d4d7df5cSMike Makonnen 		 * XXX - The thread has reached the barrier. We can't
119d4d7df5cSMike Makonnen 		 *	 "back it away" from the barrier.
120d4d7df5cSMike Makonnen 		 */
121d4d7df5cSMike Makonnen 		_thread_critical_enter(curthread);
122d4d7df5cSMike Makonnen 		break;
123bb535300SJeff Roberson 	case PS_COND_WAIT:
12489552201SMike Makonnen 		/*
12589552201SMike Makonnen 		 * Cache the address, since it will not be available
12689552201SMike Makonnen 		 * after it has been backed out.
12789552201SMike Makonnen 		 */
12889552201SMike Makonnen 		up = &curthread->data.cond->c_lock;
12989552201SMike Makonnen 
13089552201SMike Makonnen 		UMTX_LOCK(up);
13189552201SMike Makonnen 		_thread_critical_enter(curthread);
132bb535300SJeff Roberson 		_cond_wait_backout(curthread);
13389552201SMike Makonnen 		UMTX_UNLOCK(up);
134bb535300SJeff Roberson 		break;
135bb535300SJeff Roberson 	case PS_MUTEX_WAIT:
13689552201SMike Makonnen 		/*
13789552201SMike Makonnen 		 * Cache the address, since it will not be available
13889552201SMike Makonnen 		 * after it has been backed out.
13989552201SMike Makonnen 		 */
14089552201SMike Makonnen 		sp = &curthread->data.mutex->lock;
14189552201SMike Makonnen 
14289552201SMike Makonnen 		_SPINLOCK(sp);
14389552201SMike Makonnen 		_thread_critical_enter(curthread);
144479778b0SMike Makonnen 		_mutex_lock_backout(curthread);
14589552201SMike Makonnen 		_SPINUNLOCK(sp);
146bb535300SJeff Roberson 		break;
147bb535300SJeff Roberson 	default:
14889552201SMike Makonnen 		/*
14989552201SMike Makonnen 		 * We need to lock the thread to read it's flags.
15089552201SMike Makonnen 		 */
15189552201SMike Makonnen 		_thread_critical_enter(curthread);
152bb535300SJeff Roberson 		break;
153bb535300SJeff Roberson 	}
154bb535300SJeff Roberson 
15589552201SMike Makonnen 	/*
15689552201SMike Makonnen 	 * We save the flags now so that any modifications done as part
15789552201SMike Makonnen 	 * of the backout are reflected when the flags are restored.
15889552201SMike Makonnen 	 */
15989552201SMike Makonnen 	psd.psd_flags = curthread->flags;
160bb535300SJeff Roberson 
16189552201SMike Makonnen 	PTHREAD_SET_STATE(curthread, PS_RUNNING);
16289552201SMike Makonnen 	_thread_critical_exit(curthread);
16389552201SMike Makonnen 	actp = proc_sigact_sigaction(sig);
16489552201SMike Makonnen 	handler = (__siginfohandler_t *)actp->sa_handler;
16589552201SMike Makonnen 	handler(sig, info, (ucontext_t *)context);
16689552201SMike Makonnen 
16789552201SMike Makonnen         /* Restore the thread's flags, and make it runnable */
16889552201SMike Makonnen 	_thread_critical_enter(curthread);
16989552201SMike Makonnen 	curthread->flags = psd.psd_flags;
1708c18819aSMike Makonnen 	PTHREAD_SET_STATE(curthread, PS_RUNNING);
17189552201SMike Makonnen 	_thread_critical_exit(curthread);
172bb535300SJeff Roberson }
173