Subversion Repositories shark

Rev

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