1 /* $OpenBSD: uthread_kill.c,v 1.11 2003/04/30 17:54:17 marc Exp $ */
2 /* PUBLIC_DOMAIN <marc@snafu.org> */
3 
4 #include <errno.h>
5 #include <signal.h>
6 #include <string.h>
7 #include <unistd.h>
8 #ifdef _THREAD_SAFE
9 #include <pthread.h>
10 
11 #include "pthread_private.h"
12 
13 /*
14  * Fake up a minimal siginfo_t for the given signal unless one is already
15  * pending. The signal number is assumed to be valid.
16  */
17 void
_thread_kill_siginfo(int sig)18 _thread_kill_siginfo(int sig)
19 {
20 	struct sigstatus *ss = &_thread_sigq[sig - 1];
21 
22 	_SPINLOCK(&ss->lock);
23 	if (ss->pending == 0) {
24 		ss->pending = 1;
25 		memset(&ss->siginfo, 0, sizeof ss->siginfo);
26 		ss->siginfo.si_signo = sig;
27 		ss->siginfo.si_code = SI_USER;
28 		ss->siginfo.si_errno = errno;
29 		ss->siginfo.si_pid = getpid();
30 	}
31 	_SPINUNLOCK(&ss->lock);
32 }
33 
34 /*
35  * Validate the signal number and thread.  If valid process the signal.
36  */
37 int
pthread_kill(pthread_t pthread,int sig)38 pthread_kill(pthread_t pthread, int sig)
39 {
40 	int ret;
41 
42 	if (sig >= 0 && sig < NSIG) {
43 		ret = _find_thread(pthread);
44 		if (sig != 0) {
45 			if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) {
46 				_thread_kern_sig_defer();
47 				if (pthread->state == PS_SIGWAIT &&
48 				    sigismember(pthread->data.sigwait, sig)) {
49 					PTHREAD_NEW_STATE(pthread,PS_RUNNING);
50 					pthread->signo = sig;
51 				} else {
52 					_thread_kill_siginfo(sig);
53 					_thread_signal(pthread,sig);
54 				}
55 				_thread_kern_sig_undefer();
56 			}
57 		}
58 	} else
59 		ret = EINVAL;
60 
61 	return ret;
62 }
63 #endif
64