Subversion Repositories shark

Rev

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