OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-newlib/] [newlib-1.17.0/] [newlib/] [libc/] [sys/] [linux/] [linuxthreads/] [signals.c] - Blame information for rev 9

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 9 jlechner
/* Linuxthreads - a simple clone()-based implementation of Posix        */
2
/* threads for Linux.                                                   */
3
/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
4
/*                                                                      */
5
/* This program is free software; you can redistribute it and/or        */
6
/* modify it under the terms of the GNU Library General Public License  */
7
/* as published by the Free Software Foundation; either version 2       */
8
/* of the License, or (at your option) any later version.               */
9
/*                                                                      */
10
/* This program 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        */
13
/* GNU Library General Public License for more details.                 */
14
 
15
/* Handling of signals */
16
 
17
#include <errno.h>
18
#include <signal.h>
19
#include "pthread.h"
20
#include "internals.h"
21
#include "spinlock.h"
22
#include <ucontext.h>
23
#include <sigcontextinfo.h>
24
 
25
int pthread_sigmask(int how, const sigset_t * newmask, sigset_t * oldmask)
26
{
27
  sigset_t mask;
28
 
29
  if (newmask != NULL) {
30
    mask = *newmask;
31
    /* Don't allow __pthread_sig_restart to be unmasked.
32
       Don't allow __pthread_sig_cancel to be masked. */
33
    switch(how) {
34
    case SIG_SETMASK:
35
      sigaddset(&mask, __pthread_sig_restart);
36
      sigdelset(&mask, __pthread_sig_cancel);
37
      break;
38
    case SIG_BLOCK:
39
      sigdelset(&mask, __pthread_sig_cancel);
40
      break;
41
    case SIG_UNBLOCK:
42
      sigdelset(&mask, __pthread_sig_restart);
43
      break;
44
    }
45
    newmask = &mask;
46
  }
47
  if (sigprocmask(how, newmask, oldmask) == -1)
48
    return errno;
49
  else
50
    return 0;
51
}
52
 
53
int pthread_kill(pthread_t thread, int signo)
54
{
55
  pthread_handle handle = thread_handle(thread);
56
  int pid;
57
 
58
  __pthread_lock(&handle->h_lock, NULL);
59
  if (invalid_handle(handle, thread)) {
60
    __pthread_unlock(&handle->h_lock);
61
    return ESRCH;
62
  }
63
  pid = handle->h_descr->p_pid;
64
  __pthread_unlock(&handle->h_lock);
65
  if (kill(pid, signo) == -1)
66
    return errno;
67
  else
68
    return 0;
69
}
70
 
71
/* User-provided signal handlers */
72
typedef void (*arch_sighandler_t) (int, SIGCONTEXT);
73
static union
74
{
75
  arch_sighandler_t old;
76
  void (*rt) (int, struct siginfo *, struct ucontext *);
77
} sighandler[NSIG] = { [1 ... NSIG - 1] = { (arch_sighandler_t) SIG_ERR } };
78
 
79
/* The wrapper around user-provided signal handlers */
80
static void pthread_sighandler(int signo, SIGCONTEXT ctx)
81
{
82
  pthread_descr self;
83
  char * in_sighandler;
84
  self = thread_self();
85
  /* If we're in a sigwait operation, just record the signal received
86
     and return without calling the user's handler */
87
  if (THREAD_GETMEM(self, p_sigwaiting)) {
88
    THREAD_SETMEM(self, p_sigwaiting, 0);
89
    THREAD_SETMEM(self, p_signal, signo);
90
    return;
91
  }
92
  /* Record that we're in a signal handler and call the user's
93
     handler function */
94
  in_sighandler = THREAD_GETMEM(self, p_in_sighandler);
95
  if (in_sighandler == NULL)
96
    THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME);
97
  CALL_SIGHANDLER(sighandler[signo].old, signo, ctx);
98
  if (in_sighandler == NULL)
99
    THREAD_SETMEM(self, p_in_sighandler, NULL);
100
}
101
 
102
/* The same, this time for real-time signals.  */
103
static void pthread_sighandler_rt(int signo, struct siginfo *si,
104
                                  struct ucontext *uc)
105
{
106
  pthread_descr self;
107
  char * in_sighandler;
108
  self =  thread_self();
109
  /* If we're in a sigwait operation, just record the signal received
110
     and return without calling the user's handler */
111
  if (THREAD_GETMEM(self, p_sigwaiting)) {
112
    THREAD_SETMEM(self, p_sigwaiting, 0);
113
    THREAD_SETMEM(self, p_signal, signo);
114
    return;
115
  }
116
  /* Record that we're in a signal handler and call the user's
117
     handler function */
118
  in_sighandler = THREAD_GETMEM(self, p_in_sighandler);
119
  if (in_sighandler == NULL)
120
    THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME);
121
  sighandler[signo].rt(signo, si, uc);
122
  if (in_sighandler == NULL)
123
    THREAD_SETMEM(self, p_in_sighandler, NULL);
124
}
125
 
126
/* The wrapper around sigaction.  Install our own signal handler
127
   around the signal. */
128
int __sigaction(int sig, const struct sigaction * act,
129
              struct sigaction * oact)
130
{
131
  struct sigaction newact;
132
  struct sigaction *newactp;
133
 
134
  if (sig == __pthread_sig_restart ||
135
      sig == __pthread_sig_cancel ||
136
      (sig == __pthread_sig_debug && __pthread_sig_debug > 0))
137
    {
138
      __set_errno (EINVAL);
139
      return -1;
140
    }
141
  if (act)
142
    {
143
      newact = *act;
144
      if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL
145
          && sig > 0 && sig < NSIG)
146
        {
147
          if (act->sa_flags & SA_SIGINFO)
148
            newact.sa_handler = (__sighandler_t) pthread_sighandler_rt;
149
          else
150
            newact.sa_handler = (__sighandler_t) pthread_sighandler;
151
        }
152
      newactp = &newact;
153
    }
154
  else
155
    newactp = NULL;
156
  if (__libc_sigaction(sig, newactp, oact) == -1)
157
    return -1;
158
  if (sig > 0 && sig < NSIG)
159
    {
160
      if (oact != NULL
161
          /* We may have inherited SIG_IGN from the parent, so return the
162
             kernel's idea of the signal handler the first time
163
             through.  */
164
          && (__sighandler_t) sighandler[sig].old != SIG_ERR)
165
        oact->sa_handler = (__sighandler_t) sighandler[sig].old;
166
      if (act)
167
        /* For the assignment it does not matter whether it's a normal
168
           or real-time signal.  */
169
        sighandler[sig].old = (arch_sighandler_t) act->sa_handler;
170
    }
171
  return 0;
172
}
173
strong_alias(__sigaction, sigaction)
174
 
175
/* A signal handler that does nothing */
176
static void pthread_null_sighandler(int sig) { }
177
 
178
/* sigwait -- synchronously wait for a signal */
179
int sigwait(const sigset_t * set, int * sig)
180
{
181
  volatile pthread_descr self = thread_self();
182
  sigset_t mask;
183
  int s;
184
  sigjmp_buf jmpbuf;
185
  struct sigaction sa;
186
 
187
  /* Get ready to block all signals except those in set
188
     and the cancellation signal.
189
     Also check that handlers are installed on all signals in set,
190
     and if not, install our dummy handler.  This is conformant to
191
     POSIX: "The effect of sigwait() on the signal actions for the
192
     signals in set is unspecified." */
193
  sigfillset(&mask);
194
  sigdelset(&mask, __pthread_sig_cancel);
195
  for (s = 1; s < NSIG; s++) {
196
    if (sigismember(set, s) &&
197
        s != __pthread_sig_restart &&
198
        s != __pthread_sig_cancel &&
199
        s != __pthread_sig_debug) {
200
      sigdelset(&mask, s);
201
      if (sighandler[s].old == (arch_sighandler_t) SIG_ERR ||
202
          sighandler[s].old == (arch_sighandler_t) SIG_DFL ||
203
          sighandler[s].old == (arch_sighandler_t) SIG_IGN) {
204
        sa.sa_handler = pthread_null_sighandler;
205
        sigfillset(&sa.sa_mask);
206
        sa.sa_flags = 0;
207
        sigaction(s, &sa, NULL);
208
      }
209
    }
210
  }
211
  /* Test for cancellation */
212
  if (sigsetjmp(jmpbuf, 1) == 0) {
213
    THREAD_SETMEM(self, p_cancel_jmp, &jmpbuf);
214
    if (! (THREAD_GETMEM(self, p_canceled)
215
           && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) {
216
      /* Reset the signal count */
217
      THREAD_SETMEM(self, p_signal, 0);
218
      /* Say we're in sigwait */
219
      THREAD_SETMEM(self, p_sigwaiting, 1);
220
      /* Unblock the signals and wait for them */
221
      sigsuspend(&mask);
222
    }
223
  }
224
  THREAD_SETMEM(self, p_cancel_jmp, NULL);
225
  /* The signals are now reblocked.  Check for cancellation */
226
  pthread_testcancel();
227
  /* We should have self->p_signal != 0 and equal to the signal received */
228
  *sig = THREAD_GETMEM(self, p_signal);
229
  return 0;
230
}
231
 
232
/* Redefine raise() to send signal to calling thread only,
233
   as per POSIX 1003.1c */
234
int raise (int sig)
235
{
236
  int retcode = pthread_kill(pthread_self(), sig);
237
  if (retcode == 0)
238
    return 0;
239
  else {
240
    errno = retcode;
241
    return -1;
242
  }
243
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.