1/*
2 * signal.c
3 *
4 * Description:
5 * Thread-aware signal functions.
6 *
7 * --------------------------------------------------------------------------
8 *
9 *      Pthreads-win32 - POSIX Threads Library for Win32
10 *      Copyright(C) 1998 John E. Bossom
11 *      Copyright(C) 1999,2005 Pthreads-win32 contributors
12 *
13 *      Contact Email: rpj@callisto.canberra.edu.au
14 *
15 *      The current list of contributors is contained
16 *      in the file CONTRIBUTORS included with the source
17 *      code distribution. The list can also be seen at the
18 *      following World Wide Web location:
19 *      http://sources.redhat.com/pthreads-win32/contributors.html
20 *
21 *      This library is free software; you can redistribute it and/or
22 *      modify it under the terms of the GNU Lesser General Public
23 *      License as published by the Free Software Foundation; either
24 *      version 2 of the License, or (at your option) any later version.
25 *
26 *      This library is distributed in the hope that it will be useful,
27 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
28 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
29 *      Lesser General Public License for more details.
30 *
31 *      You should have received a copy of the GNU Lesser General Public
32 *      License along with this library in the file COPYING.LIB;
33 *      if not, write to the Free Software Foundation, Inc.,
34 *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
35 */
36
37/*
38 * Possible future strategy for implementing pthread_kill()
39 * ========================================================
40 *
41 * Win32 does not implement signals.
42 * Signals are simply software interrupts.
43 * pthread_kill() asks the system to deliver a specified
44 * signal (interrupt) to a specified thread in the same
45 * process.
46 * Signals are always asynchronous (no deferred signals).
47 * Pthread-win32 has an async cancelation mechanism.
48 * A similar system can be written to deliver signals
49 * within the same process (on ix86 processors at least).
50 *
51 * Each thread maintains information about which
52 * signals it will respond to. Handler routines
53 * are set on a per-process basis - not per-thread.
54 * When signalled, a thread will check it's sigmask
55 * and, if the signal is not being ignored, call the
56 * handler routine associated with the signal. The
57 * thread must then (except for some signals) return to
58 * the point where it was interrupted.
59 *
60 * Ideally the system itself would check the target thread's
61 * mask before possibly needlessly bothering the thread
62 * itself. This could be done by pthread_kill(), that is,
63 * in the signaling thread since it has access to
64 * all pthread_t structures. It could also retrieve
65 * the handler routine address to minimise the target
66 * threads response overhead. This may also simplify
67 * serialisation of the access to the per-thread signal
68 * structures.
69 *
70 * pthread_kill() eventually calls a routine similar to
71 * ptw32_cancel_thread() which manipulates the target
72 * threads processor context to cause the thread to
73 * run the handler launcher routine. pthread_kill() must
74 * save the target threads current context so that the
75 * handler launcher routine can restore the context after
76 * the signal handler has returned. Some handlers will not
77 * return, eg. the default SIGKILL handler may simply
78 * call pthread_exit().
79 *
80 * The current context is saved in the target threads
81 * pthread_t structure.
82 */
83
84#include "pthread.h"
85#include "implement.h"
86
87#if defined(HAVE_SIGSET_T)
88
89static void
90ptw32_signal_thread ()
91{
92}
93
94static void
95ptw32_signal_callhandler ()
96{
97}
98
99int
100pthread_sigmask (int how, sigset_t const *set, sigset_t * oset)
101{
102  pthread_t thread = pthread_self ();
103
104  if (thread.p == NULL)
105    {
106      return ENOENT;
107    }
108
109  /* Validate the `how' argument. */
110  if (set != NULL)
111    {
112      switch (how)
113	{
114	case SIG_BLOCK:
115	  break;
116	case SIG_UNBLOCK:
117	  break;
118	case SIG_SETMASK:
119	  break;
120	default:
121	  /* Invalid `how' argument. */
122	  return EINVAL;
123	}
124    }
125
126  /* Copy the old mask before modifying it. */
127  if (oset != NULL)
128    {
129      memcpy (oset, &(thread.p->sigmask), sizeof (sigset_t));
130    }
131
132  if (set != NULL)
133    {
134      unsigned int i;
135
136      /* FIXME: this code assumes that sigmask is an even multiple of
137         the size of a long integer. */
138
139      unsigned long *src = (unsigned long const *) set;
140      unsigned long *dest = (unsigned long *) &(thread.p->sigmask);
141
142      switch (how)
143	{
144	case SIG_BLOCK:
145	  for (i = 0; i < (sizeof (sigset_t) / sizeof (unsigned long)); i++)
146	    {
147	      /* OR the bit field longword-wise. */
148	      *dest++ |= *src++;
149	    }
150	  break;
151	case SIG_UNBLOCK:
152	  for (i = 0; i < (sizeof (sigset_t) / sizeof (unsigned long)); i++)
153	    {
154	      /* XOR the bitfield longword-wise. */
155	      *dest++ ^= *src++;
156	    }
157	case SIG_SETMASK:
158	  /* Replace the whole sigmask. */
159	  memcpy (&(thread.p->sigmask), set, sizeof (sigset_t));
160	  break;
161	}
162    }
163
164  return 0;
165}
166
167int
168sigwait (const sigset_t * set, int *sig)
169{
170  /* This routine is a cancellation point */
171  pthread_test_cancel();
172}
173
174int
175sigaction (int signum, const struct sigaction *act, struct sigaction *oldact)
176{
177}
178
179#endif /* HAVE_SIGSET_T */
180