summaryrefslogtreecommitdiff
path: root/libc/i386sys/signal.c
blob: dad338911c94892288540721afb0ab200c30789b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

#ifndef __MSDOS__
#ifdef __AS386_16__

#include <errno.h>
#include <signal.h>

typedef __sighandler_t Sig;

extern int __signal __P((int, __sighandler_t));
static Sig system_signal();

Sig __sigtable[_NSIG-1];

/*
 * Signal handler.
 *
 */

/*
 * KERNEL INTERFACE:
 *   It is assumed the kernel will never give us a signal we haven't
 *   _explicitly_ asked for!
 *
 * The Kernel need only save space for _one_ function pointer
 * (to system_signal) and must deal with SIG_DFL and SIG_IGN
 * in kernel space.
 *
 * When a signal is required the kernel must set all the registers as if
 * returning from a interrupt normally then push the number of the signal
 * to be generated, push the current pc value, then set the pc to the
 * address of the 'system_signal' function.
 */

Sig
signal(number, pointer)
int number;
Sig pointer;
{
   Sig old_sig;
   int rv;
   if( number < 1 || number >= _NSIG ) { errno=EINVAL; return SIG_ERR; }

   if( pointer == SIG_DFL || pointer == SIG_IGN )
      rv = __signal(number, pointer);
   else
      rv = __signal(number, (__sighandler_t) system_signal);

   if( rv < 0 ) return SIG_ERR;

   old_sig = __sigtable[number-1];
   __sigtable[number-1] = pointer;

   switch(rv)
   {
   case 0: return SIG_DFL;
   case 1: return SIG_IGN;
   return old_sig;
   }
}

#asm
  .text
_system_signal:		! When this is called by the kernel the stack contains
  pushf			! in order:
  push	ax		! 
  push	bx		!    The signal number,			(NOS)
  push	cx		!    The program counter,		(TOS)
  push	dx		!
  push	si		! It does NOT contain the CS register or the flags.
  push	di		! This means it cannot be unraveled by an iret.
  push	bp
  push	es		! Note also only ES segment register is saved.
  mov	bx,sp		! Unlike minix the rv from a system call is in AX.
  mov	bx,[bx+20]
#if __FIRST_ARG_IN_AX__
  mov	ax,bx
#else
  push	bx		! NB this is _unchecked_, do we want to ?
#endif
  add	bx,bx
  mov	bx,[bx+___sigtable-2]	! Offset by 2 cause no entry for signal 0
  call	bx		! Do we want to check BX for 0 or 1 ?
  inc	sp
  inc	sp
  pop	es
  pop	bp
  pop	di
  pop	si
  pop	dx
  pop	cx
  pop	bx
  pop	ax
  popf
  ret	#2		! Get rid of the signum too.
#endasm

#endif /* __AS386_16__ */
#endif /* __MSDOS__ */