-
Notifications
You must be signed in to change notification settings - Fork 0
/
interrupt_trampoline.S
216 lines (170 loc) · 5.46 KB
/
interrupt_trampoline.S
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
.file "interrupt_trampoline.S"
.text
.globl gomp_interrupt_trampoline
.type gomp_interrupt_trampoline, @function
gomp_interrupt_trampoline:
# save RAX
pushq %rax
# save FLAGS
lahf
seto %al
pushq %rax
# save RBX
pushq %rbx
# new stack-frame creation
# above the old stack-pointer
movq 32(%rsp), %rax
subq $32, %rax
# copy content of the alternate-
# stack into the new stack-frame
movq (%rsp), %rbx
movq %rbx, (%rax)
movq 8(%rsp), %rbx
movq %rbx, 8(%rax)
movq 16(%rsp), %rbx
movq %rbx, 16(%rax)
movq 24(%rsp), %rbx
movq %rbx, 24(%rax)
# stack-switch occurs here
movq %rax, %rsp
# %rax <-- &gomp_global_sfo
leaq gomp_global_sfo(%rip), %rax
# %rbx <-- &gomp_tls_data
movq %fs:0, %rbx
addq gomp_tls_ptr@gottpoff(%rip), %rbx
movq (%rbx), %rbx
# save RCX
pushq %rcx
# %rcx <- (&gomp_global_sfo)->in_thread_team_offset
movq (%rax), %rcx
# %rcx <- (&gomp_tls_data)->ts.team (it's a pointer)
movq (%rbx, %rcx, 1), %rcx
# ((&gomp_tls_data)->ts.team == NULL) ?
testq %rcx, %rcx
je .L5
# %rcx <- (&gomp_global_sfo)->in_thread_preemptable_offset
movq 8(%rax), %rcx
# %rcx <- (&gomp_tls_data)->non_preemptable
movq (%rbx, %rcx, 1), %rcx
# ((&gomp_tls_data)->non_preemptable > 0) ?
testq %rcx, %rcx
jne .L5
# %rcx <- (&gomp_global_sfo)->in_thread_task_offset
movq 16(%rax), %rcx
# %rcx <- (&gomp_tls_data)->task (it's a pointer)
movq (%rbx, %rcx, 1), %rcx
# ((&gomp_tls_data)->task == NULL) ?
testq %rcx, %rcx
je .L5
# save RSI
pushq %rsi
# %rsi <- (&gomp_global_sfo)->in_task_kind_offset
movq 24(%rax), %rsi
# %esi <- (&gomp_tls_data)->task->kind
movl (%rcx, %rsi, 1), %esi
# (&gomp_tls_data)->task->kind == GOMP_TASK_IMPLICIT ?
testl %esi, %esi
je .L4
# save RDI
pushq %rdi
# %rdi <- (&gomp_global_sfo)->in_task_state_offset
movq 32(%rax), %rdi
# %rsi <- (&gomp_tls_data)->task->state (it's a pointer)
movq (%rcx, %rdi, 1), %rsi
# ((&gomp_tls_data)->task->state == NULL) ?
testq %rsi, %rsi
je .L3
# %rdi <- (&gomp_global_sfo)->in_state_context_offset
movq 40(%rax), %rdi
# %rdi <- (&gomp_tls_data)->task->state->context
leaq (%rsi, %rdi, 1), %rdi
call _set_jmp
# _set_jmp return 0: we have just saved current context for the first time,
# so we give control to the scheduler in order to check
# whether higher priority tasks are available.
testl %eax, %eax
je .L1
# _set_jmp return 1: this context is resumed by a possible different thread
# in a second time, and we need therefore to perform some
# activities that depend on the task state at the time it
# has been suspended.
cmpl $0x1, %eax
je .L2
# _set_jmp return 6887: all tasks related to the scheduling activities have
# been performed, and we can safetly leave this routine.
jmp .L3
.L1:
call gomp_interrupt_task_scheduling_pre
# Thid branch is executed if and only if "gomp_interrupt_task_scheduling_pre"
# function invokation does ot lead to context-switch current task for another.
# In this case we don't need to execute "gomp_interrupt_task_scheduling_post"
# cause this context has not been resumed by anyone, and we can safetely
# resume the interrupted flow.
# %rax <-- &gomp_global_sfo
leaq gomp_global_sfo(%rip), %rax
# %rbx <-- &gomp_tls_data
movq %fs:0, %rbx
addq gomp_tls_ptr@gottpoff(%rip), %rbx
movq (%rbx), %rbx
# %rdi <- (&gomp_global_sfo)->in_thread_task_offset
movq 16(%rax), %rdi
# %rsi <- (&gomp_tls_data)->task (it's a pointer)
movq (%rbx, %rdi, 1), %rsi
# %rdi <- (&gomp_global_sfo)->in_task_state_offset
movq 32(%rax), %rdi
# %rsi <- (&gomp_tls_data)->task->state (it's a pointer)
movq (%rsi, %rdi, 1), %rsi
# %rdi <- (&gomp_global_sfo)->in_state_context_offset
movq 40(%rax), %rdi
# %rdi <- (&gomp_tls_data)->task->state->context
leaq (%rsi, %rdi, 1), %rdi
# %rsi <-- 6887
movq $0x1ae7, %rsi
call _long_jmp
.L2:
call gomp_interrupt_task_scheduling_post
# Thid branch is executed when "gomp_interrupt_task_scheduling_pre" function
# invokation has previously context-switched off this task, while it is
# currently resumed along the execution path of the same thread or another
# one, and we need to perform some finalization operations before resuming
# the interrupted flow.
# %rax <-- &gomp_global_sfo
leaq gomp_global_sfo(%rip), %rax
# %rbx <-- &gomp_tls_data
movq %fs:0, %rbx
addq gomp_tls_ptr@gottpoff(%rip), %rbx
movq (%rbx), %rbx
# %rdi <- (&gomp_global_sfo)->in_thread_task_offset
movq 16(%rax), %rdi
# %rsi <- (&gomp_tls_data)->task (it's a pointer)
movq (%rbx, %rdi, 1), %rsi
# %rdi <- (&gomp_global_sfo)->in_task_state_offset
movq 32(%rax), %rdi
# %rsi <- (&gomp_tls_data)->task->state (it's a pointer)
movq (%rsi, %rdi, 1), %rsi
# %rdi <- (&gomp_global_sfo)->in_state_context_offset
movq 40(%rax), %rdi
# %rdi <- (&gomp_tls_data)->task->state->context
leaq (%rsi, %rdi, 1), %rdi
# %rsi <-- 6887
movq $0x1ae7, %rsi
call _long_jmp
.L3:
# restore RDI
popq %rdi
.L4:
# restore RSI
popq %rsi
.L5:
# restore RCX
popq %rcx
# restore RBX
popq %rbx
# restore FLAGS
popq %rax
addb $0x7f, %al
sahf
# restore RAX
popq %rax
retq
.size gomp_interrupt_trampoline, .-gomp_interrupt_trampoline