/*
* signal.c
*
* Description:
* Thread-aware signal functions.
*
* --------------------------------------------------------------------------
*
* Pthreads-win32 - POSIX Threads Library for Win32
* Copyright(C) 1998 John E. Bossom
* Copyright(C) 1999,2005 Pthreads-win32 contributors
*
* Contact Email: [email protected]
*
* The current list of contributors is contained
* in the file CONTRIBUTORS included with the source
* code distribution. The list can also be seen at the
* following World Wide Web location:
* http://sources.redhat.com/pthreads-win32/contributors.html
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library in the file COPYING.LIB;
* if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
/*
* Possible future strategy for implementing pthread_kill()
* ========================================================
*
* Win32 does not implement signals.
* Signals are simply software interrupts.
* pthread_kill() asks the system to deliver a specified
* signal (interrupt) to a specified thread in the same
* process.
* Signals are always asynchronous (no deferred signals).
* Pthread-win32 has an async cancelation mechanism.
* A similar system can be written to deliver signals
* within the same process (on ix86 processors at least).
*
* Each thread maintains information about which
* signals it will respond to. Handler routines
* are set on a per-process basis - not per-thread.
* When signalled, a thread will check it's sigmask
* and, if the signal is not being ignored, call the
* handler routine associated with the signal. The
* thread must then (except for some signals) return to
* the point where it was interrupted.
*
* Ideally the system itself would check the target thread's
* mask before possibly needlessly bothering the thread
* itself. This could be done by pthread_kill(), that is,
* in the signaling thread since it has access to
* all pthread_t structures. It could also retrieve
* the handler routine address to minimise the target
* threads response overhead. This may also simplify
* serialisation of the access to the per-thread signal
* structures.
*
* pthread_kill() eventually calls a routine similar to
* ptw32_cancel_thread() which manipulates the target
* threads processor context to cause the thread to
* run the handler launcher routine. pthread_kill() must
* save the target threads current context so that the
* handler launcher routine can restore the context after
* the signal handler has returned. Some handlers will not
* return, eg. the default SIGKILL handler may simply
* call pthread_exit().
*
* The current context is saved in the target threads
* pthread_t structure.
*/
#include "pthread.h"
#include "implement.h"
#if defined(HAVE_SIGSET_T)
static void
ptw32_signal_thread ()
{
}
static void
ptw32_signal_callhandler ()
{
}
int
pthread_sigmask (int how, sigset_t const *set, sigset_t * oset)
{
pthread_t thread = pthread_self ();
if (thread.p == NULL)
{
return ENOENT;
}
/* Validate the `how' argument. */
if (set != NULL)
{
switch (how)
{
case SIG_BLOCK:
break;
case SIG_UNBLOCK:
break;
case SIG_SETMASK:
break;
default:
/* Invalid `how' argument. */
return EINVAL;
}
}
/* Copy the old mask before modifying it. */
if (oset != NULL)
{
memcpy (oset, &(thread.p->sigmask), sizeof (sigset_t));
}
if (set != NULL)
{
unsigned int i;
/* FIXME: this code assumes that sigmask is an even multiple of
the size of a long integer. */
unsigned long *src = (unsigned long const *) set;
unsigned long *dest = (unsigned long *) &(thread.p->sigmask);
switch (how)
{
case SIG_BLOCK:
for (i = 0; i < (sizeof (sigset_t) / sizeof (unsigned long)); i++)
{
/* OR the bit field longword-wise. */
*dest++ |= *src++;
}
break;
case SIG_UNBLOCK:
for (i = 0; i < (sizeof (sigset_t) / sizeof (unsigned long)); i++)
{
/* XOR the bitfield longword-wise. */
*dest++ ^= *src++;
}
case SIG_SETMASK:
/* Replace the whole sigmask. */
memcpy (&(thread.p->sigmask), set, sizeof (sigset_t));
break;
}
}
return 0;
}
int
sigwait (const sigset_t * set, int *sig)
{
/* This routine is a cancellation point */
pthread_test_cancel();
}
int
sigaction (int signum, const struct sigaction *act, struct sigaction *oldact)
{
}
#endif /* HAVE_SIGSET_T */