1 /* Set a thread's signal state.  Hurd on Mach version.
2    Copyright (C) 2002-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library;  if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <pthread.h>
20 #include <assert.h>
21 #include <signal.h>
22 #include <hurd/signal.h>
23 #include <hurd/msg.h>
24 
25 #include <pt-internal.h>
26 
27 error_t
__pthread_sigstate(struct __pthread * thread,int how,const sigset_t * set,sigset_t * oset,int clear_pending)28 __pthread_sigstate (struct __pthread *thread, int how,
29 		    const sigset_t *set, sigset_t *oset, int clear_pending)
30 {
31   error_t err = 0;
32   struct hurd_sigstate *ss;
33   sigset_t old, new;
34   sigset_t pending;
35 
36   if (set != NULL)
37     new = *set;
38 
39   ss = _hurd_thread_sigstate (thread->kernel_thread);
40   assert (ss);
41 
42   _hurd_sigstate_lock (ss);
43 
44   old = ss->blocked;
45 
46   if (set != NULL)
47     {
48       switch (how)
49 	{
50 	case SIG_BLOCK:
51 	  ss->blocked |= new;
52 	  break;
53 
54 	case SIG_SETMASK:
55 	  ss->blocked = new;
56 	  break;
57 
58 	case SIG_UNBLOCK:
59 	  ss->blocked &= ~new;
60 	  break;
61 
62 	default:
63 	  err = EINVAL;
64 	  break;
65 	}
66       ss->blocked &= ~_SIG_CANT_MASK;
67     }
68 
69   if (!err && clear_pending)
70     __sigemptyset (&ss->pending);
71 
72   pending = _hurd_sigstate_pending (ss) & ~ss->blocked;
73   _hurd_sigstate_unlock (ss);
74 
75   if (!err && oset != NULL)
76     *oset = old;
77 
78   if (!err && pending)
79     /* Send a message to the signal thread so it
80        will wake up and check for pending signals.  */
81     __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ());
82 
83   return err;
84 }
85