Subversion Repositories shark

Rev

Rev 29 | Rev 318 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/*
2
 * Project: S.Ha.R.K.
3
 *
4
 * Coordinators:
5
 *   Giorgio Buttazzo    <giorgio@sssup.it>
6
 *   Paolo Gai           <pj@gandalf.sssup.it>
7
 *
8
 * Authors     :
9
 *   Paolo Gai           <pj@gandalf.sssup.it>
10
 *   (see the web pages for full authors list)
11
 *
12
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
13
 *
14
 * http://www.sssup.it
15
 * http://retis.sssup.it
16
 * http://shark.sssup.it
17
 */
18
 
19
/**
20
 ------------
38 pj 21
 CVS :        $Id: signal.c,v 1.3 2003-01-07 17:07:49 pj Exp $
2 pj 22
 
23
 File:        $File$
38 pj 24
 Revision:    $Revision: 1.3 $
25
 Last update: $Date: 2003-01-07 17:07:49 $
2 pj 26
 ------------
27
 
28
 This file contains:
29
 
30
 Signal Handling
31
 
32
 - Data structures
33
 - sigset_t handling functions
34
 
35
**/
36
 
37
/*
38
 * Copyright (C) 2000 Paolo Gai
39
 *
40
 * This program is free software; you can redistribute it and/or modify
41
 * it under the terms of the GNU General Public License as published by
42
 * the Free Software Foundation; either version 2 of the License, or
43
 * (at your option) any later version.
44
 *
45
 * This program is distributed in the hope that it will be useful,
46
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
47
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
48
 * GNU General Public License for more details.
49
 *
50
 * You should have received a copy of the GNU General Public License
51
 * along with this program; if not, write to the Free Software
52
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
53
 *
54
 */
55
 
56
/*
57
 * some functions are inspired on the implementation of OsKit..
58
 *
59
 * Copyright (c) 1997, 1998, 1999 University of Utah and the Flux Group.
60
 * All rights reserved.
61
 *
62
 * [...] The OSKit is free software, also known
63
 * as "open source;" you can redistribute it and/or modify it under the terms
64
 * of the GNU General Public License (GPL), version 2, as published by the Free
65
 * Software Foundation (FSF).  To explore alternate licensing terms, contact
66
 * the University of Utah at csl-dist@cs.utah.edu or +1-801-585-3271.
67
 *
68
 * The OSKit is distributed in the hope that it will be useful, but WITHOUT ANY
69
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
70
 * FOR A PARTICULAR PURPOSE.  See the GPL for more details.  You should have
71
 * received a copy of the GPL along with the OSKit; see the file COPYING.  If
72
 * not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA.
73
 */
74
 
75
 
76
 
77
#include <ll/ll.h>
78
#include <ll/stdlib.h>
79
#include <ll/stdio.h>
80
#include <ll/i386/pic.h>
81
#include <signal.h>
82
#include <errno.h>
83
#include <kernel/descr.h>
84
#include <kernel/var.h>
85
#include <kernel/func.h>
86
#include <kernel/trace.h>
87
 
88
/* look at nanoslp.c */
89
int nanosleep_interrupted_by_signal(PID i);
90
 
91
 
92
/*---------------------------------------------------------------------*/
93
/* Data structures                                                     */
94
/*---------------------------------------------------------------------*/
95
 
96
/*+ A flag, see kern_raise +*/
97
static int active_exc = 0;
98
 
99
/*+ The signal table... +*/
100
static struct sigaction    sigactions[SIG_MAX];
101
 
102
/*+ There is a global (or "process") set of pending signals.
103
    kill() and sigqueue() affect the process pending set.
104
+*/
105
static sigset_t            procsigpending;
106
 
107
/*
108
 * A queue of all threads waiting in sigwait.
109
 * It is not static because it is used into the task_kill...ð
110
 */
29 pj 111
static  IQUEUE               sigwaiters;
2 pj 112
 
113
 
114
/*+ An array of queues of pending signals posted with sigqueue(). +*/
115
static SIGQ                sigqueued[SIG_MAX];
116
 
117
/*+ We avoid malloc in interrupt handlers by preallocating the queue
118
    entries for sig_queued above.
119
    it is used also in kernel/time.c +*/
120
SIGQ                sigqueue_free;
121
 
122
/*+ this is the signal queue... +*/
123
sig_queue_entry     sig_queue[SIGQUEUE_MAX];
124
 
125
/*+ alarm stuffs +*/
126
static struct timespec alarm_time;
127
static int alarm_timer;
128
 
129
 
130
/* returns the first non-zero bit... */
131
static int ffs(int value)
132
{
133
  int x;
134
 
135
  for (x=0; value; x++, value = value>>1)
136
    if (value & 1)
137
      return x;
138
  return 0;
139
}
140
 
141
/*---------------------------------------------------------------------*/
142
/* interruptable function registration...                              */
143
/*---------------------------------------------------------------------*/
144
 
145
 
146
/*+ this structure contains the functions to be called to test if a
147
    task is blocked on a cancellation point +*/
148
static struct {
149
  int (*test)(PID p, void *arg);
150
  void *arg;
151
} interruptable_table[MAX_SIGINTPOINTS];
152
 
153
static int interruptable_points = 0;
154
 
155
 
156
/*+ This function register a cancellation point into the system.
157
    Be careful!!! no check are performed... +*/
158
void register_interruptable_point(int (*func)(PID p, void *arg), void *arg)
159
{
160
  interruptable_table[interruptable_points].test = func;
161
  interruptable_table[interruptable_points].arg = arg;
162
  interruptable_points++;
163
}
164
 
165
static void test_interruptable_points(PID i)
166
{
167
  int j;
168
 
169
  /* check if the task is blocked on a cancellation point */
170
  for (j=0; j<interruptable_points; j++)
171
     if (interruptable_table[j].test(i,interruptable_table[j].arg))
172
       break;
173
}
174
 
175
 
176
/*---------------------------------------------------------------------*/
177
/* sigset_t handling functions                                         */
178
/*---------------------------------------------------------------------*/
179
 
180
/* These functions will become soon macros... */
181
int sigemptyset(sigset_t *set)
182
{
183
  *set = 0;
184
 
185
  return 0;
186
}
187
 
188
int sigfillset(sigset_t *set)
189
{
190
  *set=0xFFFFFFFFUL;
191
 
192
  return 0;
193
}
194
 
195
int sigaddset(sigset_t *set, int signo)
196
{
197
  if (signo < 0 || signo >= SIG_MAX)
198
  {
199
    errno = EINVAL;
200
    return -1;
201
  }
202
 
203
  *set |= 1 << signo;
204
  return 0;
205
}
206
 
207
 
208
int sigdelset(sigset_t *set, int signo)
209
{
210
  if (signo < 0 || signo >= SIG_MAX)
211
  {
212
    errno = EINVAL;
213
    return -1;
214
  }
215
 
216
  *set &= ~(1 << signo);
217
  return 0;
218
}
219
 
220
int sigismember(const sigset_t *set, int signo)
221
{
222
  if (signo < 0 || signo >= SIG_MAX)
223
  {
224
    errno = EINVAL;
225
    return -1;
226
  }
227
 
228
  return *set & (1 << signo );
229
}
230
 
231
 
232
/*---------------------------------------------------------------------*/
233
/* Finally, the public functions                                       */
234
/*---------------------------------------------------------------------*/
235
 
236
/*
237
 * Prototypes.
238
 */
239
void    really_deliver_signal(int sig, siginfo_t *code);
240
void    kern_deliver_async_signal(int sig);
241
void    kern_deliver_process_signal(int sig);
242
 
243
int task_sigmask(int how, const sigset_t *set, sigset_t *oset)
244
{
245
        proc_des *task;    /* current executing task... */
246
        int      err = 0;
247
 
248
        kern_cli();
249
 
250
        task = &proc_table[exec_shadow];
251
 
252
        if (oset)
253
                *oset = task->sigmask;
254
 
255
        if (set) {
256
                switch (how) {
257
                case SIG_BLOCK:
258
                        task->sigmask |= *set;
259
                        break;
260
                case SIG_UNBLOCK:
261
                        task->sigmask &= ~*set;
262
                        break;
263
                case SIG_SETMASK:
264
                        task->sigmask = *set;
265
                        break;
266
                default:
267
                        err = EINVAL;
268
                }
269
        }
270
 
271
        /*
272
         * Look for process pending signals that are unblocked, and deliver.
273
         */
274
        while (procsigpending & ~task->sigmask) {
275
                int sig = ffs(procsigpending & ~task->sigmask);
276
                kern_deliver_process_signal(sig);
277
        }
278
 
279
        /*
280
         * Look for task pending signals that are unblocked, and deliver.
281
         */
282
        while (task->sigpending & ~task->sigmask) {
283
                int sig = ffs(task->sigpending & ~task->sigmask);
284
                kern_deliver_async_signal(sig);
285
        }
286
 
287
        kern_sti();
288
        return err;
289
}
290
 
291
/*
292
 * This can be called out of an interrupt handler, say from an alarm
293
 * expiration.
294
 */
295
int
296
task_signal(PID p, int signo)
297
{
298
//      int       enabled;
299
 
300
        /* Error check? Sure! */
301
        if (!signo)
302
                return 0;
303
 
304
        if (signo < 0 || signo >= SIG_MAX)
305
                return EINVAL;
306
 
307
        if (proc_table[p].status == FREE)
308
                return EINVAL;
309
 
310
        kern_cli();
311
 
312
        /*
313
         * Look at the process sigactions. If the "process" is ignoring
314
         * the signal, then the signal is not placed in the pending list.
315
         */
316
        if (!(sigactions[signo].sa_flags & SA_SIGINFO) &&
317
            sigactions[signo].sa_handler == SIG_IGN) {
318
                kern_sti();
319
                return 0;
320
        }
321
 
322
        /*
323
         * Add the signal to list of pending signals for the target task.
324
         */
325
        sigaddset(&proc_table[p].sigpending, signo);
326
 
327
        /* check for an interruptable function!!! */
328
        test_interruptable_points(p);
329
 
330
        if (proc_table[p].status == WAIT_SIGSUSPEND) {
331
            LEVEL l;
332
 
333
            /* Reactivate the task... */
29 pj 334
            iq_extract(p, &sigwaiters);
2 pj 335
 
336
            l = proc_table[p].task_level;
38 pj 337
            level_table[l]->public_unblock(l,p);
2 pj 338
 
339
        }
340
 
341
 
342
        /*
343
         * If not in an interrupt, use this opportunity to deliver
344
         * pending unblocked signals to the current thread.
345
         */
346
        if (!ll_ActiveInt()) {
347
                kern_deliver_pending_signals();
348
        }
349
 
350
        kern_sti();
351
        return 0;
352
}
353
 
354
/*
355
 * sigaction
356
 */
357
int
358
sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
359
{
360
        int sos; /* used to empty the sigqueue... */
361
        SYS_FLAGS f;
362
 
363
 
364
        if (sig < 0 || sig >= SIG_MAX)
365
                return errno = EINVAL, -1;
366
 
367
        f = kern_fsave();
368
 
369
        if (oact)
370
                *oact = sigactions[sig];
371
        if (act)
372
                sigactions[sig] = *act;
373
 
374
        /*
375
         * If the action for this signal is being set to SIG_IGN or SIG_DFL,
376
         * and that signal is process pending, then clear it.
377
         */
378
        if (act && !(act->sa_flags & SA_SIGINFO) &&
379
            (act->sa_handler == SIG_IGN || act->sa_handler == SIG_DFL)) {
380
                sos = sigqueued[sig];
381
                while (sos != -1) {
382
                        /* Remove the first entry and put it to the free
383
                           queue */
384
                        sos = sig_queue[sigqueued[sig]].next;
385
 
386
                        if (sig_queue[sigqueued[sig]].flags & USED_FOR_TIMER)
387
                          sig_queue[sigqueued[sig]].flags &= ~SIGNAL_POSTED;
388
                        else {
389
                          sig_queue[sigqueued[sig]].next = sigqueue_free;
390
                          sigqueue_free = sigqueued[sig];
391
                        }
392
                }
393
                sigqueued[sig] = -1;
394
                sigdelset(&procsigpending, sig);
395
        }
396
 
397
        kern_frestore(f);
398
        return 0;
399
}
400
 
401
/*
402
 * sigprocmask. this is just task_sigmask
403
 */
404
int
405
sigprocmask(int how, const sigset_t *set, sigset_t *oset)
406
{
407
        return task_sigmask(how, set, oset);
408
}
409
 
410
/*
411
 * raise. this is just task_signal on itself.
412
 */
413
int
414
raise(int sig)
415
{
416
        return task_signal(exec_shadow, sig);
417
}
418
 
419
/*
420
 * kill. What does it mean to kill() in a multithreaded program? The POSIX
421
 * spec says that a signal sent to a "process" shall be delivered to only
422
 * one task. If no task has that signal unblocked, then the first
423
 * task to unblock the signal is the lucky winner. Well, that means we
424
 * need to have a global procsigpending to record process pending signals.
425
 */
426
int
427
kill(pid_t pid, int signo)
428
{
429
        PID                     task;
430
        PID                     i;
431
        SYS_FLAGS               f;
432
        struct sigaction        act;
433
 
434
        /* Error check? Sure! */
435
        if (!signo)
436
                return 0;
437
 
438
        if (signo < 0 || signo >= SIG_MAX)
439
                return EINVAL;
440
 
441
 
442
        f = kern_fsave();
443
 
444
        act = sigactions[signo];
445
 
446
        if (!(act.sa_flags & SA_SIGINFO) && act.sa_handler == SIG_IGN) {
447
                kern_frestore(f);
448
                return 0;
449
        }
450
 
451
        /*
452
         * Kill does not queue. If the signal is already pending, this
453
         * one is tossed.
454
         */
455
        if (sigismember(&procsigpending, signo)) {
456
                kern_frestore(f);
457
                return 0;
458
        }
459
 
460
        /*
461
         * Make the signal process pending.
462
         */
463
        sigaddset(&procsigpending, signo);
464
 
465
        /*
466
         * Look through the threads in sigwait to see if any of them
467
         * is waiting for the signal. This is done as a separate pass
468
         * since the value of the pthread sigmask is ignored (threads
469
         * in sigwait will have blocked the signals being waited for).
470
         */
471
 
29 pj 472
        for (task = iq_query_first(&sigwaiters);
2 pj 473
             task != NIL;
29 pj 474
             task = iq_query_next(task, &sigwaiters)) {
2 pj 475
          if (sigismember(&proc_table[task].sigwaiting, signo)) {
476
            LEVEL l;
477
 
478
            if (proc_table[task].status == WAIT_SIGSUSPEND)
479
               sigaddset(&proc_table[task].sigpending, signo);
480
 
481
            /* Reactivate the task... */
29 pj 482
            iq_extract(task, &sigwaiters);
2 pj 483
            l = proc_table[task].task_level;
38 pj 484
            level_table[l]->public_unblock(l,task);
2 pj 485
 
486
            if (proc_table[task].delay_timer != -1) {
38 pj 487
              kern_event_delete(proc_table[task].delay_timer);
2 pj 488
              proc_table[task].delay_timer = -1;
489
            }
490
 
491
            kern_frestore(f);
492
            return 0;
493
          }
494
        }
495
 
496
        /*
497
         * No threads in sigwait. Too bad. Must find another thread to
498
         * deliver it to.
499
         */
500
        for (i = 1; i < MAX_PROC; i++) {
501
                if (proc_table[i].status != FREE) {
502
                        if (! sigismember(&proc_table[i].sigmask, signo)) {
503
                                /* Add the signal to list of pending
504
                                   signals for the target task. */
505
                                sigaddset(&proc_table[i].sigpending, signo);
506
 
507
                                /* check for an interruptable function!!! */
508
                                test_interruptable_points(i);
509
                                break;
510
                        }
511
                }
512
        }
513
 
514
        /*
515
         * If not in an interrupt, use this opportunity to deliver
516
         * pending unblocked signals to the current thread.
517
         */
518
        if (! ll_ActiveInt()) {
519
                kern_deliver_pending_signals();
520
        }
521
 
522
        kern_frestore(f);
523
        return 0;
524
}
525
 
526
/*
527
 * sigqueue internal: accept also the SI_XXX value
528
 */
529
int
530
sigqueue_internal(pid_t pid, int signo, const union sigval value, int si_code)
531
{
532
        PID                     task;
533
        SYS_FLAGS               f;
534
        int                     i;
535
 
536
        int                     thingie; /* an element of the signal queue */
537
        int                     sos;     /* used when inserting thinghie in
538
                                            the signal queue */
539
        struct sigaction        act;
540
 
541
        /* Error check? Sure! */
542
        if (!signo)
543
                return 0;
544
 
545
        if (signo < 0 || signo >= SIG_MAX)
546
                return EINVAL;
547
 
548
 
549
        f = kern_fsave();
550
        /*
551
         * Look at the process sigactions. If the "process" is ignoring
552
         * the signal, then the signal is not placed in the pending list.
553
         */
554
        act = sigactions[signo];
555
 
556
        if (!(act.sa_flags & SA_SIGINFO) && act.sa_handler == SIG_IGN) {
557
                kern_frestore(f);
558
                return 0;
559
        }
560
 
561
 
562
        /*
563
         * If the flags does not include SA_SIGINFO, and there is already
564
         * a signal pending, this new one is dropped.
565
         */
566
        if ((! (act.sa_flags & SA_SIGINFO)) &&
567
            sigismember(&procsigpending, signo)) {
568
                kern_frestore(f);
569
                return 0;
570
        }
571
 
572
        /*
573
         * Gotta have space for the new signal.
574
         */
575
        if (sigqueue_free == -1) {
576
                kern_frestore(f);
577
                return EAGAIN;
578
        }
579
 
580
        /*
581
         * Create a queue entry.
582
         */
583
        thingie = sigqueue_free;
584
        sigqueue_free = sig_queue[sigqueue_free].next;
585
 
586
        sig_queue[thingie].info.si_signo = signo;
587
        sig_queue[thingie].info.si_code  = si_code;
588
        sig_queue[thingie].info.si_value = value;
589
        sig_queue[thingie].info.si_task  = exec_shadow;
590
        sig_queue[thingie].next          = -1;
591
 
592
        /*
593
         * Queue the signal on the process.
594
         */
595
 
596
        /* we insert the signal at the queue's tail */
597
        if (sigqueued[signo] == -1)
598
                sigqueued[signo] = thingie;
599
        else {
600
                sos = sigqueued[signo];
601
                while (sig_queue[sos].next != -1) sos = sig_queue[sos].next;
602
                sig_queue[sos].next = thingie;
603
        }
604
        sigaddset(&procsigpending, signo);
605
 
606
        /*
607
         * Look through the threads in sigwait to see if any of them
608
         * is waiting for the signal. This is done as a separate pass
609
         * since the value of the pthread sigmask is ignored (threads
610
         * in sigwait will have blocked the signals being waited for).
611
         * If we find one, wakeup that thread. Note that POSIX says that
612
         * if multiple threads are sigwaiting for the same signal number,
613
         * exactly one thread is woken up. The problem is how to maintain
614
         * the FIFO order, and how to prevent lost signals in the case that
615
         * a thread calls sigwait before the woken thread runs and gets it.
616
         */
29 pj 617
        for (task = iq_query_first(&sigwaiters);
2 pj 618
             task != NIL;
29 pj 619
             task = iq_query_next(task, &sigwaiters)) {
2 pj 620
          if (sigismember(&proc_table[task].sigwaiting, signo)) {
621
            LEVEL l;
622
 
623
            if (proc_table[task].status == WAIT_SIGSUSPEND)
624
               sigaddset(&proc_table[task].sigpending, signo);
625
 
626
            /* Reactivate the task... */
29 pj 627
            iq_extract(task, &sigwaiters);
2 pj 628
 
629
            l = proc_table[task].task_level;
38 pj 630
            level_table[l]->public_unblock(l,task);
2 pj 631
 
632
            if (proc_table[task].delay_timer != -1) {
38 pj 633
              kern_event_delete(proc_table[task].delay_timer);
2 pj 634
              proc_table[task].delay_timer = -1;
635
            }
636
 
637
            kern_frestore(f);
638
            return 0;
639
 
640
          }
641
        }
642
 
643
        /*
644
         * Need to find a thread to deliver the signal to. Look for the
645
         * first thread that is not blocking the signal, and send it the
646
         * signal. It is my opinion that any program that is using sigwait,
647
         * and has not blocked signals in all of its threads, is bogus. The
648
         * same is true if the program is not using sigwait, and has the
649
         * signal unblocked in more than one thread.
650
         * Why? You might wake up a thread, but not have an actual queue
651
         * entry left by the time it runs again and looks, since another
652
         * thread could call sigwait and get that queue entry, or if there
653
         * are multiple threads that can take the signal, one thread could
654
         * get all the entries. This could result in an interrupted thread,
655
         * but with no signal to deliver. Well, not much to do about it.
656
         * Lets just queue the signal for the process, and let the chips
657
         * fall where they may.
658
         */
659
        for (i = 1; i < MAX_PROC; i++) {
660
                if (proc_table[i].status != FREE) {
661
                        if (! sigismember(&proc_table[i].sigmask, signo)) {
662
                                /* Add the signal to list of pending
663
                                   signals for the target task. */
664
                                sigaddset(&proc_table[i].sigpending, signo);
665
 
666
                                /* check for an interruptable function!!! */
667
                                test_interruptable_points(i);
668
 
669
                                break;
670
                        }
671
                }
672
        }
673
 
674
        /*
675
         * If not in an interrupt, use this opportunity to deliver
676
         * pending unblocked signals to the current thread.
677
         * (NB: a discussion on the flag active_exc is near the function
678
         * kern_raise() )
679
         */
680
        if (! ll_ActiveInt() && active_exc == 0) {
681
                kern_deliver_pending_signals();
682
        }
683
 
684
        kern_frestore(f);
685
        return 0;
686
}
687
 
688
static void sigwait_timer(void *arg)
689
{
690
  PID p = (PID)arg;
691
  LEVEL l;
692
 
693
  /* reset the event timer */
694
  proc_table[p].delay_timer = -1;
695
 
696
  /* set the timeout flag */
697
  proc_table[p].control |= SIGTIMEOUT_EXPIRED;
698
 
699
  /* insert the task into the ready queue and extract it from the waiters */
29 pj 700
  iq_extract(p, &sigwaiters);
2 pj 701
 
702
  l = proc_table[p].task_level;
38 pj 703
  level_table[l]->public_unblock(l,p);
2 pj 704
 
705
  event_need_reschedule();
706
}
707
 
708
/*
709
 * Sigwait. Sigwait overrides the state of the pthread sigmask and the global
710
 * sigactions. The caller *must* block the set of signals in "set", before
711
 * calling sigwait, otherwise the behaviour is undefined (which means that
712
 * the caller will take an async signal anyway, and sigwait will return EINTR.
713
 */
714
int
715
kern_sigwait_internal(const sigset_t *set,
716
                      siginfo_t *info, const struct timespec *timeout)
717
{
718
        proc_des *pthread = &proc_table[exec_shadow];
719
        int                     thissig;
720
 
721
        LEVEL l;
722
 
723
        task_testcancel();
724
 
725
        /* siglock and pthread siglock are taken from an interrupt handler */
726
        kern_cli();
727
 
728
        /*
729
         * First check for process pending signals. Must take and hold
730
         * the global siglock to prevent races with kill() and sigqueue().
731
         */
732
        if (procsigpending & *set) {
733
                int sos;
734
 
735
                thissig = ffs(procsigpending & *set);
736
 
737
                /*
738
                 * Sent with kill(). Using sigwait and kill is Bogus!
739
                 */
740
                if (sigqueued[thissig] == -1) {
741
                        info->si_signo           = thissig;
742
                        info->si_code            = SI_USER;
743
                        info->si_value.sival_int = 0;
744
 
745
                        sigdelset(&pthread->sigpending, thissig);
746
                        sigdelset(&procsigpending, thissig);
747
                        kern_sti();
748
                        return 0;
749
                }
750
 
751
                /*
752
                 * Grab the first queue entry.
753
                 */
754
                sos = sigqueued[thissig];
29 pj 755
                sigqueued[thissig] = sig_queue[sos].next;
2 pj 756
 
757
                /*
758
                 * If that was the last one, reset the process procsigpending.
759
                 */
760
                if (sigqueued[thissig] == -1)
761
                        sigdelset(&procsigpending, thissig);
762
                sigdelset(&pthread->sigpending, thissig);
763
 
764
                /*
765
                 * Copy the information and free the queue entry.
766
                 */
767
                info->si_signo           = sig_queue[sos].info.si_signo;
768
                info->si_code            = sig_queue[sos].info.si_code;
769
                info->si_value.sival_int = sig_queue[sos].info.si_value.sival_int;
770
 
771
                if (sig_queue[sos].flags & USED_FOR_TIMER)
772
                  sig_queue[sos].flags &= ~SIGNAL_POSTED;
773
                else {
774
                  sig_queue[sos].next = sigqueue_free;
775
                  sigqueue_free = sos;
776
                }
777
                kern_sti();
778
                return 0;
779
        }
780
 
781
        /*
782
         * Now check for pthread pending signals.
783
         */
784
        if (pthread->sigpending & *set) {
785
                thissig = ffs(pthread->sigpending & *set);
786
                info->si_signo           = thissig;
787
                info->si_code            = SI_USER;
788
                info->si_value.sival_int = 0;
789
                sigdelset(&pthread->sigpending, thissig);
790
                kern_sti();
791
                return 0;
792
        }
793
 
794
        /*
795
         * For timed wait, if nothing is available and the timeout value
796
         * is zero, its an error.
797
         */
798
        if (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0) {
799
                kern_sti();
800
                return EAGAIN;
801
        }
802
 
803
        /*
804
         * Grab the wait lock and set the sigwaiting mask. Once that is done,
805
         * release the thread siglock; Another thread can try and wake this
806
         * thread up as a result of seeing it in sigwait, but the actual
807
         * wakeup will be delayed until the waitlock is released in the switch
808
         * code.
809
         */
810
        pthread->sigwaiting = *set;
811
 
812
        /* now, we really block the task... */
813
        proc_table[exec_shadow].context = kern_context_save();
814
 
38 pj 815
        kern_epilogue_macro();
816
 
2 pj 817
        l = proc_table[exec_shadow].task_level;
38 pj 818
        level_table[l]->public_block(l,exec_shadow);
2 pj 819
 
820
        /*
821
         * Add this thread to the list of threads in sigwait. Once that is
822
         * done, it is safe to release the global siglock, which will allow
823
         * another thread to scan the sigwaiters list. As above, it might
824
         * find a thread in sigwait, but it will not be able to wake it up
825
         * until the waitlock is released in the switch code.
826
         */
29 pj 827
        iq_insertfirst(exec_shadow, &sigwaiters);
2 pj 828
        proc_table[exec_shadow].status = WAIT_SIG;
829
 
830
        if (timeout) {
831
          /* we can use the delaytimer because if we are here we are not in a
832
             task_delay */
833
          struct timespec t, abstime;
38 pj 834
          kern_gettime(&t);
2 pj 835
          ADDTIMESPEC(&t, timeout, &abstime);
836
 
837
          proc_table[exec_shadow].delay_timer =
838
            kern_event_post(&abstime,sigwait_timer,(void *)exec_shadow);
839
        }
840
 
841
        /* and finally we reschedule */
842
        exec = exec_shadow = -1;
843
        scheduler();
844
        ll_context_to(proc_table[exec_shadow].context);
845
 
846
        task_testcancel();
847
 
848
        pthread->sigwaiting = 0;
849
 
850
        /*
851
         * Look for timeout.
852
         */
853
        if (proc_table[exec_shadow].control & SIGTIMEOUT_EXPIRED) {
854
                kern_sti();
855
                return EAGAIN;
856
        }
857
 
858
        /*
859
         * Look for a wakeup to deliver a queued signal. This would come
860
         * either from kill() or from sigqueue().
861
         */
862
        if (procsigpending & *set) {
863
                int sos;
864
 
865
                thissig = ffs(procsigpending & *set);
866
 
867
                /*
868
                 * Sent with kill(). Using sigwait and kill is Bogus!
869
                 */
870
                if (sigqueued[thissig] == -1) {
871
                        info->si_signo           = thissig;
872
                        info->si_code            = SI_USER;
873
                        info->si_value.sival_int = 0;
874
 
875
                        sigdelset(&procsigpending, thissig);
876
                        kern_sti();
877
                        return 0;
878
                }
879
 
880
                /*
881
                 * Grab the first queue entry.
882
                 */
29 pj 883
                sos = sigqueued[thissig];
884
                sigqueued[thissig] = sig_queue[sos].next;
2 pj 885
 
886
                /*
887
                 * If that was the last one, reset the process procsigpending.
888
                 */
889
                if (sigqueued[thissig] == -1)
890
                        sigdelset(&procsigpending, thissig);
891
 
892
                /*
893
                 * Copy the information and free the queue entry.
894
                 */
895
                info->si_signo           = sig_queue[sos].info.si_signo;
896
                info->si_code            = sig_queue[sos].info.si_code;
897
                info->si_value.sival_int = sig_queue[sos].info.si_value.sival_int;
898
 
899
                if (sig_queue[sos].flags & USED_FOR_TIMER)
900
                  sig_queue[sos].flags &= ~SIGNAL_POSTED;
901
                else {
902
                  sig_queue[sos].next = sigqueue_free;
903
                  sigqueue_free = sos;
904
                }
905
 
906
                kern_sti();
907
                return 0;
908
        }
909
 
910
        /*
911
         * Well, at the moment I am going to assume that if this thread
912
         * wakes up, and there is no signal pending in the waitset, the
913
         * thread wait was interrupted for some other reason. Return EINTR.
914
         */
915
        if (! (pthread->sigpending & *set)) {
916
                kern_sti();
917
                return EINTR;
918
        }
919
 
920
        /*
921
         * Otherwise, get the first signal and return it.
922
         */
923
        thissig = ffs(pthread->sigpending & *set);
924
        info->si_signo           = thissig;
925
        info->si_code            = SI_USER;
926
        info->si_value.sival_int = 0;
927
        sigdelset(&pthread->sigpending, thissig);
928
        kern_sti();
929
        return 0;
930
}
931
 
932
/*
933
 * Sigwait.
934
 */
935
int
936
sigwait(const sigset_t *set, int *sig)
937
{
938
        siginfo_t       info;
939
        int             rc;
940
 
941
        memset(&info, 0, sizeof(info));
942
 
943
        rc = kern_sigwait_internal(set, &info, 0);
944
 
945
        if (rc)
946
                return rc;
947
 
948
        *sig = info.si_signo;
949
        return 0;
950
}
951
 
952
/*
953
 * Sigwaitinfo.
954
 */
955
int
956
sigwaitinfo(const sigset_t *set, siginfo_t *info)
957
{
958
        return kern_sigwait_internal(set, info, 0);
959
}
960
 
961
/*
962
 * Sigtimedwait.
963
 */
964
int
965
sigtimedwait(const sigset_t *set,
966
             siginfo_t *info, const struct timespec *timeout)
967
{
968
        if (! timeout)
969
                return EINVAL;
970
 
971
        return kern_sigwait_internal(set, info, timeout);
972
}
973
 
974
/*
975
 * Signal
976
 */
977
void (*signal(int signum, void (*handler)(int)))(int)
978
{
979
  struct sigaction act, oact;
980
  int olderrno;
981
  void (*retvalue)(int);
982
 
983
  act.sa_handler = handler;
984
  sigemptyset(&act.sa_mask);
985
  act.sa_flags = 0;
986
 
987
  olderrno = errno;
988
  if (sigaction(signum, &act, &oact))
989
    retvalue = SIG_ERR;
990
  else
991
    if (oact.sa_flags & SA_SIGINFO)
992
      retvalue = SIG_ERR;
993
    else
994
      retvalue = oact.sa_handler;
995
 
996
  errno = olderrno;
997
 
998
  return retvalue;
999
 
1000
}
1001
 
1002
 
1003
/*
1004
 * sigpending
1005
 */
1006
int sigpending(sigset_t *set)
1007
{
1008
  *set = procsigpending | proc_table[exec_shadow].sigpending;
1009
  return 0;
1010
}
1011
 
1012
 
1013
/*
1014
 * sigsuspend
1015
 */
1016
int sigsuspend(const sigset_t *set)
1017
{
1018
        proc_des *pthread = &proc_table[exec_shadow];
1019
 
1020
        LEVEL l;
1021
 
1022
        task_testcancel();
1023
 
1024
        kern_cli();
1025
 
1026
        /*
1027
         * Now check for pthread pending signals.
1028
         */
1029
        if (pthread->sigpending & *set) {
1030
          kern_deliver_pending_signals();
1031
          kern_sti();
1032
          return 0;
1033
        }
1034
 
1035
        /*
1036
         * Grab the wait lock and set the sigwaiting mask. Once that is done,
1037
         * release the thread siglock; Another thread can try and wake this
1038
         * thread up as a result of seeing it in sigwait, but the actual
1039
         * wakeup will be delayed until the waitlock is released in the switch
1040
         * code.
1041
         */
1042
        pthread->sigwaiting = *set;
1043
 
1044
        /* now, we really block the task... */
1045
        proc_table[exec_shadow].context = kern_context_save();
1046
 
38 pj 1047
        kern_epilogue_macro();
2 pj 1048
        l = proc_table[exec_shadow].task_level;
38 pj 1049
        level_table[l]->public_block(l,exec_shadow);
2 pj 1050
 
29 pj 1051
        iq_insertfirst(exec_shadow, &sigwaiters);
2 pj 1052
        proc_table[exec_shadow].status = WAIT_SIGSUSPEND;
1053
 
1054
        /* and finally we reschedule */
1055
        exec = exec_shadow = -1;
1056
        scheduler();
1057
        ll_context_to(proc_table[exec_shadow].context);
1058
 
1059
        task_testcancel();
1060
 
1061
        /*
1062
         * Well, at the moment I am going to assume that if this thread
1063
         * wakes up, and there is no signal pending in the waitset, the
1064
         * thread wait was interrupted for some other reason. Return EINTR.
1065
         */
1066
        if (! (pthread->sigpending & *set)) {
1067
                kern_sti();
1068
                return EINTR;
1069
        }
1070
 
1071
        /*
1072
         * Otherwise, deliver the signals.
1073
         */
1074
        kern_deliver_pending_signals();
1075
        kern_sti();
1076
        return 0;
1077
}
1078
 
1079
 
1080
void timer_alarmfire(void *arg)
1081
{
1082
  alarm_timer = -1;
1083
 
1084
  kill(0, SIGALRM);
1085
 
1086
  event_need_reschedule();
1087
}
1088
 
1089
/*
1090
 * alarm
1091
 */
1092
unsigned int alarm(unsigned int seconds)
1093
{
1094
  struct timespec returnvalue, temp;
1095
 
1096
  kern_cli();
1097
 
38 pj 1098
  kern_gettime(&temp);
2 pj 1099
 
1100
  if (alarm_timer == -1)
1101
    returnvalue.tv_sec = 0;
1102
  else {
1103
    SUBTIMESPEC(&alarm_time, &temp, &returnvalue);
1104
 
38 pj 1105
    kern_event_delete(alarm_timer);
2 pj 1106
  }
1107
 
1108
  if (seconds) {
1109
    temp.tv_sec += seconds;
1110
    TIMESPEC_ASSIGN(&alarm_time, &temp);
1111
    alarm_timer = kern_event_post(&temp, timer_alarmfire, NULL);
1112
  }
1113
  else
1114
    alarm_timer = -1;
1115
 
1116
  kern_sti();
1117
 
1118
  return returnvalue.tv_sec;
1119
}
1120
 
1121
int pause(void)
1122
{
1123
  sigset_t set;
1124
 
1125
  sigfillset(&set);
1126
  return sigsuspend(&set);
1127
}
1128
 
1129
/*
1130
 * Internal stuff.
1131
 */
1132
 
1133
/*
1134
 * Deliver an asynchronous signal. This must be called with interrupts
1135
 * blocked and the pthread siglock held.
1136
 */
1137
void
1138
kern_deliver_async_signal(int sig)
1139
{
1140
        siginfo_t               siginfo;
1141
 
1142
        siginfo.si_signo           = sig;
1143
        siginfo.si_code            = SI_USER;
1144
        siginfo.si_value.sival_int = 0;
1145
        siginfo.si_task            = exec_shadow;
1146
 
1147
        really_deliver_signal(sig, &siginfo);
1148
}
1149
 
1150
/*
1151
 * Deliver a process signals. This must be called with interrupts
1152
 * blocked and the siglock and pthread siglock held.
1153
 */
1154
void
1155
kern_deliver_process_signal(int sig)
1156
{
1157
        siginfo_t               siginfo;
1158
        int                     thingie;
1159
 
1160
        /*
1161
         * Sent with kill(). Using sigwait and kill is Bogus!
1162
         */
1163
        if (sigqueued[sig] == -1) {
1164
                siginfo.si_signo           = sig;
1165
                siginfo.si_code            = SI_USER;
1166
                siginfo.si_value.sival_int = 0;
1167
                siginfo.si_task            = exec_shadow;
1168
 
1169
                sigdelset(&procsigpending, sig);
1170
                goto deliver;
1171
        }
1172
 
1173
        /*
1174
         * Grab the first queue entry.
1175
         */
1176
        thingie = sigqueued[sig];
1177
        sigqueued[sig] = sig_queue[sigqueued[sig]].next;
1178
 
1179
        /*
1180
         * If that was the last one, reset the process sigpending.
1181
         */
1182
        if (sigqueued[sig] == -1)
1183
                sigdelset(&procsigpending, sig);
1184
 
1185
        /*
1186
         * Copy the information and free the queue entry.
1187
         */
1188
        siginfo.si_signo           = sig_queue[thingie].info.si_signo;
1189
        siginfo.si_code            = sig_queue[thingie].info.si_code;
1190
        siginfo.si_value.sival_int = sig_queue[thingie].info.si_value.sival_int;
1191
        siginfo.si_task            = sig_queue[thingie].info.si_task;
1192
 
1193
        if (sig_queue[thingie].flags & USED_FOR_TIMER)
1194
          sig_queue[thingie].flags &= ~SIGNAL_POSTED;
1195
        else {
1196
          sig_queue[thingie].next = sigqueue_free;
1197
          sigqueue_free = thingie;
1198
        }
1199
 
1200
 deliver:
1201
        really_deliver_signal(sig, &siginfo);
1202
 
1203
}
1204
 
1205
/*
1206
 * Deliver any pending signals. Called out of the context switch code
1207
 * when a task switches in, and there are pending signals.
1208
 *
1209
 * Interrupts are blocked...
1210
 */
1211
void
1212
kern_deliver_pending_signals(void)
1213
{
1214
        proc_des *task;    /* current executing task... */
1215
 
1216
        task = &proc_table[exec_shadow];
1217
 
1218
        /* we have to check if the task was descheduled while serving
1219
           signals... if so, it is useless the call to this function...
1220
           because the task is already in it!!! (NB: the task can be
1221
           descheduled because the signal handlers are executed with
1222
           interrupts enabled...) */
1223
        if (task->control & TASK_DOING_SIGNALS)
1224
          return;
1225
 
1226
        task->control |= TASK_DOING_SIGNALS;
1227
 
1228
        /*
1229
         * Look for process pending signals that are unblocked, and deliver.
1230
         */
1231
        while (procsigpending & ~task->sigmask) {
1232
                /* NB: the while test should be indipendent from any local
1233
                   variable... because when we process signals there can be
1234
                   some context_change before we return from the
1235
                   kern_deliver-signals...
1236
                */
1237
                int sig = ffs(procsigpending & ~task->sigmask);
1238
 
1239
                /* Call with siglock and thread siglock locked */
1240
                kern_deliver_process_signal(sig);
1241
        }
1242
 
1243
        /*
1244
         * Now deliver any pthread pending signals that are left.
1245
         * NB: the pthread pending signals are NOT sent via sigqueue!!!
1246
         */
1247
        while (task->sigpending & ~task->sigmask) {
1248
                int sig = ffs(task->sigpending & ~task->sigmask);
1249
 
1250
                /* Call at splhigh and thread locked */
1251
                kern_deliver_async_signal(sig);
1252
        }
1253
        task->control &= ~TASK_DOING_SIGNALS;
1254
}
1255
 
1256
/*
1257
 * Actually deliver the signal to the task. At this point the signal
1258
 * is going to be delivered, so it no longer matters if it is blocked.
1259
 */
1260
void
1261
really_deliver_signal(int sig, siginfo_t *info)
1262
{
1263
        proc_des *task;    /* current executing task... */
1264
 
1265
        sigset_t                sigmask, oldmask;
1266
        struct sigaction        act;
1267
        SYS_FLAGS               f;
1268
 
1269
        f = kern_fsave();
1270
 
1271
        task = &proc_table[exec_shadow];
1272
 
1273
        act = sigactions[sig];
1274
 
1275
        //kern_printf("Ci sono!!!flags=%d hand=%d sigaction=%d mask=%d",act.sa_flags,
1276
        //          (int)act.sa_handler, (int)act.sa_sigaction, (int)act.sa_mask);
1277
 
1278
        /*
1279
         * Ignored?
1280
         */
1281
        if (!(act.sa_flags & SA_SIGINFO) && (act.sa_handler == SIG_IGN ||
1282
                                             act.sa_handler == SIG_ERR)  )
1283
            return;
1284
 
1285
        if (!(act.sa_flags & SA_SIGINFO) && act.sa_handler == SIG_DFL) {
1286
                /* Default action for all signals is termination */
1287
                kern_printf("\nSignal number %d...\n",sig);
1288
                if (act.sa_flags & SA_SIGINFO)
1289
                  kern_printf("with value : %d\n",info->si_value.sival_int);
1290
                sys_abort(ASIG_DEFAULT_ACTION);
1291
        }
1292
 
1293
        /*
1294
         * Set the signal mask for calling the handler.
1295
         */
1296
        oldmask = sigmask = task->sigmask;
1297
        sigaddset(&sigmask, sig);
1298
        sigmask |= act.sa_mask;
1299
        sigdelset(&task->sigpending, sig);
1300
        task->sigmask = sigmask;
1301
        kern_sti();
1302
 
1303
        /*
1304
         * and call the handler ...
1305
         */
1306
        if (act.sa_flags & SA_SIGINFO)
1307
                act.sa_sigaction(sig, info, NULL);
1308
        else
1309
                ((void (*)(int, int, void *))act.sa_handler)
1310
                        (sig, info->si_value.sival_int, NULL);
1311
 
1312
        /* NB: when we pass the kern_cli(), there can be the case that
1313
           an irq (and/or a timer...) fired... and do a context change.
1314
           so, we return here after an indefinite time... */
1315
        kern_cli();
1316
        task->sigmask = oldmask;
1317
 
1318
        kern_frestore(f);
1319
}
1320
 
1321
 
1322
/*---------------------------------------------------------------------*/
1323
/* S.HA.R.K. exceptions handling                                       */
1324
/*---------------------------------------------------------------------*/
1325
 
1326
void kern_raise(int n, PID p)
1327
{
1328
  union sigval v;
1329
  PID sos;         /* temp. PID */
1330
 
1331
  v.sival_int = n;
1332
//  kern_printf("RAISE");
1333
 
1334
  /* sigqueue set the p field to exec_shadow... so whe change it for a
1335
     little... because sigqueue fill descriptor with exec_shadow... */
1336
  kern_cli();
1337
  sos = exec_shadow;
1338
  exec_shadow = p;
1339
 
1340
  active_exc = 1;  // see (*)
1341
  sigqueue(0, SIGHEXC, v);
1342
  active_exc = 0;
1343
 
1344
  exec_shadow = sos;
1345
  kern_sti();
1346
 
1347
  /* (*)
1348
     when we are in an exception, we don't have to call the
1349
     really_deliver signal.
1350
     For example, when the capacity of a task is exausted, an event is
1351
     called. this event simply call scheduler, that call the task_epilogue.
1352
 
1353
     the task_epilogue checks the capacity and raise an exception, BUT
1354
     we don't have to deliver this exception immediately.
1355
 
1356
     Why? because the task pointed by exec_shadow was extracted from the
1357
     ready queue (as sigqueue do normally...) and the exception does not have
1358
     to be delivered to that task. It must be delivered
1359
     only after we exit from the kern_raise (because the signal handler
1360
     in SIGHEXC may be long and another timer interrupt can fire...), to
1361
     another task...
1362
  */
1363
 
1364
}
1365
 
1366
 
1367
/*---------------------------------------------------------------------*/
1368
/* S.Ha.R.K. interrupts handling                                       */
1369
/*---------------------------------------------------------------------*/
1370
 
1371
/*----------------------------------------------------------------------*/
1372
/* Interrupt table management. The following function install the fast  */
1373
/* handler and the sporadic task linked to the interrupt no.            */
1374
/* If the fast parameter is NULL, no handler is called.                 */
1375
/* If the pi parameter is NIL no task is installed                      */
1376
/*----------------------------------------------------------------------*/
1377
 
1378
/* Interrupt handling table */
1379
static struct int_des {
1380
    void (*fast)(int n);
1381
    PID proc_index;
1382
    BYTE isUsed;
1383
} int_table[16];
1384
 
1385
/* Warning the interrupt can cause a preemption!                */
1386
/* The fast handler is a standard piece of code which runs with */
1387
/* interrupts enabled to allow interrupt nesting                */
1388
 
1389
void irq_fasthandler(void *n)
1390
{
1391
  int no = *(int *)n;
1392
  PID p;
1393
 
1394
  /* tracer stuff */
1395
  trc_logevent(TRC_INTR,&no);
1396
 
1397
  if (int_table[no].fast != NULL) {
1398
    kern_sti();
1399
    (int_table[no].fast)(no);
1400
    kern_cli();
1401
  }
1402
 
1403
  /* If a sporadic process is linked,activate it */
1404
  p = int_table[no].proc_index;
1405
  task_activate(p); // no problem if p == nil
1406
}
1407
 
1408
/*----------------------------------------------------------------------*/
1409
/* Interrupt table management. The following function install the fast  */
1410
/* handler and the sporadic task linked to the interrupt no.            */
1411
/* If the fast parameter is NULL, no handler is called.                 */
1412
/* If the pi parameter is NIL no task is installed                      */
1413
/*----------------------------------------------------------------------*/
1414
int handler_set(int no, void (*fast)(int n), PID pi)
1415
{
1416
    SYS_FLAGS f;
1417
 
1418
    if ((no < 1) || (no > 15)) {
1419
                        errno = EWRONG_INT_NO;
1420
                        return -1;
1421
    }
1422
 
1423
    f = kern_fsave();
1424
    //kern_printf("handler_set: no %d pid %d\n",no, pi);
1425
    if (int_table[no].isUsed == TRUE) {
1426
                        kern_frestore(f);
1427
                        errno = EUSED_INT_NO;
1428
                        return -1;
1429
    }
1430
    int_table[no].fast = fast;
1431
    int_table[no].proc_index = pi;
1432
    int_table[no].isUsed = TRUE;
1433
 
1434
    irq_bind(no, irq_fasthandler, INT_FORCE);
1435
    irq_unmask(no);
1436
    kern_frestore(f);
1437
 
1438
    return 1;
1439
}
1440
 
1441
int handler_remove(int no)
1442
{
1443
    SYS_FLAGS f;
1444
    return 0;
1445
 
1446
    if (no < 1 || no > 15) {
1447
                        errno = EWRONG_INT_NO;
1448
                        return -1;
1449
    }
1450
 
1451
    f = kern_fsave();
1452
    if (int_table[no].isUsed == FALSE) {
1453
                        kern_frestore(f);
1454
                        errno = EUNUSED_INT_NO;
1455
                        return -1;
1456
    }
1457
 
1458
    int_table[no].fast = NULL;
1459
    int_table[no].proc_index = NIL;
1460
    int_table[no].isUsed = FALSE;
1461
 
1462
    irq_bind(no,NULL, INT_PREEMPTABLE);
1463
    irq_mask(no);
1464
    kern_frestore(f);
1465
 
1466
    return 1;
1467
 
1468
}
1469
 
1470
/* this is the test that is done when a task is being killed
1471
   and it is waiting on a sigwait */
1472
static int signal_cancellation_point(PID i, void *arg)
1473
{
1474
    LEVEL l;
1475
 
1476
    if (proc_table[i].status == WAIT_SIG) {
1477
 
1478
      if (proc_table[i].delay_timer != -1) {
38 pj 1479
        kern_event_delete(proc_table[i].delay_timer);
2 pj 1480
        proc_table[i].delay_timer = -1;
1481
      }
1482
 
29 pj 1483
      iq_extract(i, &sigwaiters);
2 pj 1484
 
1485
      l = proc_table[i].task_level;
38 pj 1486
      level_table[l]->public_unblock(l,i);
2 pj 1487
 
1488
      return 1;
1489
    }
1490
    else if (proc_table[i].status == WAIT_SIGSUSPEND) {
1491
 
1492
      l = proc_table[i].task_level;
38 pj 1493
      level_table[l]->public_unblock(l,i);
2 pj 1494
 
1495
      return 1;
1496
    }
1497
 
1498
 
1499
    return 0;
1500
}
1501
 
1502
void signals_init()
1503
{
1504
        int i;
1505
 
1506
        /* Initialize the default signal actions and the signal
1507
           queue headers. */
1508
        for (i = 0; i < SIG_MAX; i++) {
1509
          sigactions[i].sa_handler = SIG_DFL;
1510
          sigactions[i].sa_flags = 0;
1511
          sigactions[i].sa_mask = 0;
1512
          sigactions[i].sa_sigaction = 0;
1513
          sigqueued[i] = -1;
1514
        }
1515
 
1516
        /* Initialize the signal queue */
1517
        for (i=0; i < SIGQUEUE_MAX-1; i++) {
1518
           sig_queue[i].next = i+1;
1519
           sig_queue[i].flags = 0;
1520
        }
1521
        sig_queue[SIGQUEUE_MAX-1].next = NIL;
1522
        sig_queue[SIGQUEUE_MAX-1].flags = 0;
1523
        sigqueue_free = 0;
1524
 
1525
        procsigpending = 0;
1526
 
29 pj 1527
        iq_init(&sigwaiters, &freedesc, 0);
2 pj 1528
        alarm_timer = -1;
1529
 
1530
        /* Interrupt handling init */
1531
        for (i=0; i<16; i++) {
1532
          int_table[i].fast = NULL;
1533
          int_table[i].proc_index = NIL;
1534
          int_table[i].isUsed = FALSE;
1535
        }
1536
 
1537
        register_cancellation_point(signal_cancellation_point, NULL);
1538
}
1539
 
1540