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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [runtime/] [go-signal.c] - Blame information for rev 801

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
/* go-signal.c -- signal handling for Go.
2
 
3
   Copyright 2009 The Go Authors. All rights reserved.
4
   Use of this source code is governed by a BSD-style
5
   license that can be found in the LICENSE file.  */
6
 
7
#include <signal.h>
8
#include <stdlib.h>
9
#include <unistd.h>
10
#include <sys/time.h>
11
 
12
#include "runtime.h"
13
#include "go-assert.h"
14
#include "go-panic.h"
15
 
16
#ifndef SA_RESTART
17
  #define SA_RESTART 0
18
#endif
19
 
20
#ifdef USING_SPLIT_STACK
21
 
22
extern void __splitstack_getcontext(void *context[10]);
23
 
24
extern void __splitstack_setcontext(void *context[10]);
25
 
26
#endif
27
 
28
#define C SigCatch
29
#define I SigIgnore
30
#define R SigRestart
31
#define Q SigQueue
32
#define P SigPanic
33
 
34
/* Signal actions.  This collects the sigtab tables for several
35
   different targets from the master library.  SIGKILL, SIGCONT, and
36
   SIGSTOP are not listed, as we don't want to set signal handlers for
37
   them.  */
38
 
39
SigTab runtime_sigtab[] = {
40
#ifdef SIGHUP
41
  { SIGHUP,     Q + R },
42
#endif
43
#ifdef SIGINT
44
  { SIGINT,     Q + R },
45
#endif
46
#ifdef SIGQUIT
47
  { SIGQUIT,    C },
48
#endif
49
#ifdef SIGILL
50
  { SIGILL,     C },
51
#endif
52
#ifdef SIGTRAP
53
  { SIGTRAP,    C },
54
#endif
55
#ifdef SIGABRT
56
  { SIGABRT,    C },
57
#endif
58
#ifdef SIGBUS
59
  { SIGBUS,     C + P },
60
#endif
61
#ifdef SIGFPE
62
  { SIGFPE,     C + P },
63
#endif
64
#ifdef SIGUSR1
65
  { SIGUSR1,    Q + I + R },
66
#endif
67
#ifdef SIGSEGV
68
  { SIGSEGV,    C + P },
69
#endif
70
#ifdef SIGUSR2
71
  { SIGUSR2,    Q + I + R },
72
#endif
73
#ifdef SIGPIPE
74
  { SIGPIPE,    I },
75
#endif
76
#ifdef SIGALRM
77
  { SIGALRM,    Q + I + R },
78
#endif
79
#ifdef SIGTERM
80
  { SIGTERM,    Q + R },
81
#endif
82
#ifdef SIGSTKFLT
83
  { SIGSTKFLT,  C },
84
#endif
85
#ifdef SIGCHLD
86
  { SIGCHLD,    Q + I + R },
87
#endif
88
#ifdef SIGTSTP
89
  { SIGTSTP,    Q + I + R },
90
#endif
91
#ifdef SIGTTIN
92
  { SIGTTIN,    Q + I + R },
93
#endif
94
#ifdef SIGTTOU
95
  { SIGTTOU,    Q + I + R },
96
#endif
97
#ifdef SIGURG
98
  { SIGURG,     Q + I + R },
99
#endif
100
#ifdef SIGXCPU
101
  { SIGXCPU,    Q + I + R },
102
#endif
103
#ifdef SIGXFSZ
104
  { SIGXFSZ,    Q + I + R },
105
#endif
106
#ifdef SIGVTALRM
107
  { SIGVTALRM,  Q + I + R },
108
#endif
109
#ifdef SIGPROF
110
  { SIGPROF,    Q + I + R },
111
#endif
112
#ifdef SIGWINCH
113
  { SIGWINCH,   Q + I + R },
114
#endif
115
#ifdef SIGIO
116
  { SIGIO,      Q + I + R },
117
#endif
118
#ifdef SIGPWR
119
  { SIGPWR,     Q + I + R },
120
#endif
121
#ifdef SIGSYS
122
  { SIGSYS,     C },
123
#endif
124
#ifdef SIGEMT
125
  { SIGEMT,     C },
126
#endif
127
#ifdef SIGINFO
128
  { SIGINFO,    Q + I + R },
129
#endif
130
#ifdef SIGTHR
131
  { SIGTHR,     Q + I + R },
132
#endif
133
  { -1,         0 }
134
};
135
#undef C
136
#undef I
137
#undef R
138
#undef Q
139
#undef P
140
 
141
/* Handle a signal, for cases where we don't panic.  We can split the
142
   stack here.  */
143
 
144
static void
145
sig_handler (int sig)
146
{
147
  int i;
148
 
149
#ifdef SIGPROF
150
  if (sig == SIGPROF)
151
    {
152
      /* FIXME.  */
153
      runtime_sigprof (0, 0, nil, nil);
154
      return;
155
    }
156
#endif
157
 
158
  for (i = 0; runtime_sigtab[i].sig != -1; ++i)
159
    {
160
      struct sigaction sa;
161
 
162
      if (runtime_sigtab[i].sig != sig)
163
        continue;
164
 
165
      if ((runtime_sigtab[i].flags & SigQueue) != 0)
166
        {
167
          if (__go_sigsend (sig)
168
              || (runtime_sigtab[sig].flags & SigIgnore) != 0)
169
            return;
170
          runtime_exit (2);             // SIGINT, SIGTERM, etc
171
        }
172
 
173
      if (runtime_panicking)
174
        runtime_exit (2);
175
      runtime_panicking = 1;
176
 
177
      /* We should do a stack backtrace here.  Until we can do that,
178
         we reraise the signal in order to get a slightly better
179
         report from the shell.  */
180
 
181
      memset (&sa, 0, sizeof sa);
182
 
183
      sa.sa_handler = SIG_DFL;
184
 
185
      i = sigemptyset (&sa.sa_mask);
186
      __go_assert (i == 0);
187
 
188
      if (sigaction (sig, &sa, NULL) != 0)
189
        abort ();
190
 
191
      raise (sig);
192
 
193
      runtime_exit (2);
194
    }
195
 
196
  __builtin_unreachable ();
197
}
198
 
199
/* The start of handling a signal which panics.  */
200
 
201
static void
202
sig_panic_leadin (int sig)
203
{
204
  int i;
205
  sigset_t clear;
206
 
207
  if (runtime_m ()->mallocing)
208
    {
209
      runtime_printf ("caught signal while mallocing: %d\n", sig);
210
      runtime_throw ("caught signal while mallocing");
211
    }
212
 
213
  /* The signal handler blocked signals; unblock them.  */
214
  i = sigfillset (&clear);
215
  __go_assert (i == 0);
216
  i = sigprocmask (SIG_UNBLOCK, &clear, NULL);
217
  __go_assert (i == 0);
218
}
219
 
220
#ifdef SA_SIGINFO
221
 
222
/* Signal dispatch for signals which panic, on systems which support
223
   SA_SIGINFO.  This is called on the thread stack, and as such it is
224
   permitted to split the stack.  */
225
 
226
static void
227
sig_panic_info_handler (int sig, siginfo_t *info,
228
                        void *context __attribute__ ((unused)))
229
{
230
  if (runtime_g () == NULL)
231
    {
232
      sig_handler (sig);
233
      return;
234
    }
235
 
236
  sig_panic_leadin (sig);
237
 
238
  switch (sig)
239
    {
240
#ifdef SIGBUS
241
    case SIGBUS:
242
      if (info->si_code == BUS_ADRERR && (uintptr_t) info->si_addr < 0x1000)
243
        runtime_panicstring ("invalid memory address or "
244
                             "nil pointer dereference");
245
      runtime_printf ("unexpected fault address %p\n", info->si_addr);
246
      runtime_throw ("fault");
247
#endif
248
 
249
#ifdef SIGSEGV
250
    case SIGSEGV:
251
      if ((info->si_code == 0
252
           || info->si_code == SEGV_MAPERR
253
           || info->si_code == SEGV_ACCERR)
254
          && (uintptr_t) info->si_addr < 0x1000)
255
        runtime_panicstring ("invalid memory address or "
256
                             "nil pointer dereference");
257
      runtime_printf ("unexpected fault address %p\n", info->si_addr);
258
      runtime_throw ("fault");
259
#endif
260
 
261
#ifdef SIGFPE
262
    case SIGFPE:
263
      switch (info->si_code)
264
        {
265
        case FPE_INTDIV:
266
          runtime_panicstring ("integer divide by zero");
267
        case FPE_INTOVF:
268
          runtime_panicstring ("integer overflow");
269
        }
270
      runtime_panicstring ("floating point error");
271
#endif
272
    }
273
 
274
  /* All signals with SigPanic should be in cases above, and this
275
     handler should only be invoked for those signals.  */
276
  __builtin_unreachable ();
277
}
278
 
279
#else /* !defined (SA_SIGINFO) */
280
 
281
static void
282
sig_panic_handler (int sig)
283
{
284
  if (runtime_g () == NULL)
285
    {
286
      sig_handler (sig);
287
      return;
288
    }
289
 
290
  sig_panic_leadin (sig);
291
 
292
  switch (sig)
293
    {
294
#ifdef SIGBUS
295
    case SIGBUS:
296
      runtime_panicstring ("invalid memory address or "
297
                           "nil pointer dereference");
298
#endif
299
 
300
#ifdef SIGSEGV
301
    case SIGSEGV:
302
      runtime_panicstring ("invalid memory address or "
303
                           "nil pointer dereference");
304
#endif
305
 
306
#ifdef SIGFPE
307
    case SIGFPE:
308
      runtime_panicstring ("integer divide by zero or floating point error");
309
#endif
310
    }
311
 
312
  /* All signals with SigPanic should be in cases above, and this
313
     handler should only be invoked for those signals.  */
314
  __builtin_unreachable ();
315
}
316
 
317
#endif /* !defined (SA_SIGINFO) */
318
 
319
/* Ignore a signal.  This is called on the alternate signal stack so
320
   it may not split the stack.  */
321
 
322
static void sig_ignore (int) __attribute__ ((no_split_stack));
323
 
324
static void
325
sig_ignore (int sig __attribute__ ((unused)))
326
{
327
}
328
 
329
/* A signal handler used for signals which are not going to panic.
330
   This is called on the alternate signal stack so it may not split
331
   the stack.  */
332
 
333
static void
334
sig_tramp (int) __attribute__ ((no_split_stack));
335
 
336
static void
337
sig_tramp (int sig)
338
{
339
  G *gp;
340
  M *mp;
341
 
342
  /* We are now running on the stack registered via sigaltstack.
343
     (Actually there is a small span of time between runtime_siginit
344
     and sigaltstack when the program starts.)  */
345
  gp = runtime_g ();
346
  mp = runtime_m ();
347
 
348
  if (gp != NULL)
349
    {
350
#ifdef USING_SPLIT_STACK
351
      __splitstack_getcontext (&gp->stack_context[0]);
352
#endif
353
    }
354
 
355
  if (gp != NULL && mp->gsignal != NULL)
356
    {
357
      /* We are running on the signal stack.  Set the split stack
358
         context so that the stack guards are checked correctly.  */
359
#ifdef USING_SPLIT_STACK
360
      __splitstack_setcontext (&mp->gsignal->stack_context[0]);
361
#endif
362
    }
363
 
364
  sig_handler (sig);
365
 
366
  /* We are going to return back to the signal trampoline and then to
367
     whatever we were doing before we got the signal.  Restore the
368
     split stack context so that stack guards are checked
369
     correctly.  */
370
 
371
  if (gp != NULL)
372
    {
373
#ifdef USING_SPLIT_STACK
374
      __splitstack_setcontext (&gp->stack_context[0]);
375
#endif
376
    }
377
}
378
 
379
/* Initialize signal handling for Go.  This is called when the program
380
   starts.  */
381
 
382
void
383
runtime_initsig (int32 queue)
384
{
385
  struct sigaction sa;
386
  int i;
387
 
388
  siginit ();
389
 
390
  memset (&sa, 0, sizeof sa);
391
 
392
  i = sigfillset (&sa.sa_mask);
393
  __go_assert (i == 0);
394
 
395
  for (i = 0; runtime_sigtab[i].sig != -1; ++i)
396
    {
397
      if (runtime_sigtab[i].flags == 0)
398
        continue;
399
      if ((runtime_sigtab[i].flags & SigQueue) != queue)
400
        continue;
401
 
402
      if ((runtime_sigtab[i].flags & (SigCatch | SigQueue)) != 0)
403
        {
404
          if ((runtime_sigtab[i].flags & SigPanic) == 0)
405
            {
406
              sa.sa_flags = SA_ONSTACK;
407
              sa.sa_handler = sig_tramp;
408
            }
409
          else
410
            {
411
#ifdef SA_SIGINFO
412
              sa.sa_flags = SA_SIGINFO;
413
              sa.sa_sigaction = sig_panic_info_handler;
414
#else
415
              sa.sa_flags = 0;
416
              sa.sa_handler = sig_panic_handler;
417
#endif
418
            }
419
        }
420
      else
421
        {
422
          sa.sa_flags = SA_ONSTACK;
423
          sa.sa_handler = sig_ignore;
424
        }
425
 
426
      if ((runtime_sigtab[i].flags & SigRestart) != 0)
427
        sa.sa_flags |= SA_RESTART;
428
 
429
      if (sigaction (runtime_sigtab[i].sig, &sa, NULL) != 0)
430
        __go_assert (0);
431
    }
432
}
433
 
434
void
435
runtime_resetcpuprofiler(int32 hz)
436
{
437
#ifdef SIGPROF
438
  struct itimerval it;
439
  struct sigaction sa;
440
  int i;
441
 
442
  memset (&it, 0, sizeof it);
443
 
444
  memset (&sa, 0, sizeof sa);
445
  i = sigfillset (&sa.sa_mask);
446
  __go_assert (i == 0);
447
 
448
  if (hz == 0)
449
    {
450
      i = setitimer (ITIMER_PROF, &it, NULL);
451
      __go_assert (i == 0);
452
 
453
      sa.sa_handler = SIG_IGN;
454
      i = sigaction (SIGPROF, &sa, NULL);
455
      __go_assert (i == 0);
456
    }
457
  else
458
    {
459
      sa.sa_handler = sig_handler;
460
      sa.sa_flags = SA_RESTART;
461
      i = sigaction (SIGPROF, &sa, NULL);
462
      __go_assert (i == 0);
463
 
464
      it.it_interval.tv_sec = 0;
465
      it.it_interval.tv_usec = 1000000 / hz;
466
      it.it_value = it.it_interval;
467
      i = setitimer (ITIMER_PROF, &it, NULL);
468
      __go_assert (i == 0);
469
    }
470
#endif
471
 
472
  runtime_m()->profilehz = hz;
473
}
474
 
475
/* Used by the os package to raise SIGPIPE.  */
476
 
477
void os_sigpipe (void) __asm__ ("libgo_os.os.sigpipe");
478
 
479
void
480
os_sigpipe (void)
481
{
482
  struct sigaction sa;
483
  int i;
484
 
485
  memset (&sa, 0, sizeof sa);
486
 
487
  sa.sa_handler = SIG_DFL;
488
 
489
  i = sigemptyset (&sa.sa_mask);
490
  __go_assert (i == 0);
491
 
492
  if (sigaction (SIGPIPE, &sa, NULL) != 0)
493
    abort ();
494
 
495
  raise (SIGPIPE);
496
}

powered by: WebSVN 2.1.0

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