17
17
* along with Aero. If not, see <https://www.gnu.org/licenses/>.
18
18
*/
19
19
20
+ use aero_syscall:: signal:: { SigProcMask , SignalFlags } ;
21
+ use aero_syscall:: AeroSyscallError ;
22
+
20
23
use crate :: userland;
21
24
use crate :: userland:: scheduler;
22
25
use crate :: utils:: StackHelper ;
@@ -42,6 +45,23 @@ impl SignalFrame {
42
45
sigmask,
43
46
}
44
47
}
48
+
49
+ fn from_syscall (
50
+ restart : bool ,
51
+ syscall_result : u64 ,
52
+ frame : & mut InterruptStack ,
53
+ sigmask : u64 ,
54
+ ) -> SignalFrame {
55
+ SignalFrame {
56
+ restart_syscall : if restart {
57
+ frame. scratch . rax // syscall number
58
+ } else {
59
+ syscall_result
60
+ } ,
61
+ frame : * frame,
62
+ sigmask,
63
+ }
64
+ }
45
65
}
46
66
47
67
pub fn interrupt_check_signals ( stack : & mut InterruptStack ) {
@@ -59,12 +79,7 @@ pub fn interrupt_check_signals(stack: &mut InterruptStack) {
59
79
let old_mask = signals. blocked_mask ( ) ;
60
80
61
81
let signal_frame = SignalFrame :: from_interrupt ( stack, old_mask) ;
62
-
63
- signals. set_mask (
64
- aero_syscall:: signal:: SigProcMask :: Block ,
65
- 1u64 << signal,
66
- None ,
67
- ) ;
82
+ signals. set_mask ( SigProcMask :: Block , 1u64 << signal, None ) ;
68
83
69
84
// We cannot straight away update the stack pointer from the stack
70
85
// helper, since it will created a reference to a packed field which
@@ -92,10 +107,47 @@ pub fn interrupt_check_signals(stack: &mut InterruptStack) {
92
107
}
93
108
}
94
109
95
- pub fn syscall_check_signals ( _syscall_result : isize , _stack : & mut InterruptStack ) {
96
- if let Some ( ( _signal, entry) ) = userland:: signals:: check_for_signals ( ) {
97
- if let aero_syscall:: signal:: SignalHandler :: Handle ( _) = entry. handler ( ) {
98
- todo ! ( )
110
+ pub fn syscall_check_signals ( syscall_result : isize , stack : & mut InterruptStack ) {
111
+ if let Some ( ( signal, entry) ) = userland:: signals:: check_for_signals ( ) {
112
+ if let aero_syscall:: signal:: SignalHandler :: Handle ( func) = entry. handler ( ) {
113
+ let task = scheduler:: get_scheduler ( ) . current_task ( ) ;
114
+
115
+ let signals = task. signals ( ) ;
116
+ let old_mask = signals. blocked_mask ( ) ;
117
+
118
+ let syscall_rresult = aero_syscall:: isize_as_syscall_result ( syscall_result) ;
119
+ let restart_syscall = syscall_rresult == Err ( AeroSyscallError :: EINTR )
120
+ && entry. flags ( ) . contains ( SignalFlags :: SA_RESTART ) ;
121
+
122
+ #[ cfg( feature = "syslog" ) ]
123
+ log:: warn!( "syscall routine signaled: (restart={restart_syscall})" ) ;
124
+
125
+ let signal_frame =
126
+ SignalFrame :: from_syscall ( restart_syscall, syscall_result as _ , stack, old_mask) ;
127
+ signals. set_mask ( SigProcMask :: Block , 1u64 << signal, None ) ;
128
+
129
+ // We cannot straight away update the stack pointer from the stack
130
+ // helper, since it will created a reference to a packed field which
131
+ // is undefined behavior. So we create a copy of the current rsp and
132
+ // update the actual rsp with the updated rsp.
133
+ let mut ptr = stack. iret . rsp ;
134
+ let mut writer = StackHelper :: new ( & mut ptr) ;
135
+
136
+ // Signal handlers are executed on the same stack, but 128 bytes
137
+ // known as the red zone is subtracted from the stack before
138
+ // anything is pushed to the stack. This allows small leaf
139
+ // functions to use 128 bytes of stack space without reserving
140
+ // stack space by subtracting from the stack pointer.
141
+ writer. skip_by ( REDZONE_SIZE ) ;
142
+
143
+ unsafe {
144
+ writer. write ( signal_frame) ;
145
+ writer. write ( entry. sigreturn ( ) ) ;
146
+ }
147
+
148
+ stack. iret . rsp = ptr;
149
+ stack. iret . rip = func as u64 ;
150
+ stack. scratch . rdi = signal as u64 ;
99
151
}
100
152
}
101
153
}
@@ -118,6 +170,12 @@ pub fn sigreturn(stack: &mut InterruptStack) -> usize {
118
170
* stack = signal_frame. frame ;
119
171
120
172
if signal_frame. restart_syscall != u64:: MAX {
173
+ #[ cfg( feature = "syslog" ) ]
174
+ log:: debug!(
175
+ "sigreturn: restarting {} syscall" ,
176
+ aero_syscall:: syscall_as_str( signal_frame. restart_syscall as _)
177
+ ) ;
178
+
121
179
stack. iret . rip -= SYSCALL_INSTRUCTION_SIZE ;
122
180
}
123
181
0 commit comments