Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Misc. cosmetic changes.
[simgrid.git] / src / kernel / context / ContextRaw.cpp
1 /* Copyright (c) 2009-2021. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include "ContextRaw.hpp"
7 #include "mc/mc.h"
8 #include "simgrid/Exception.hpp"
9
10 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
11
12 // Raw context routines
13
14 using rawctx_entry_point_t = void (*)(simgrid::kernel::context::SwappedContext*);
15
16 using raw_stack_t = void*;
17 extern "C" raw_stack_t raw_makecontext(void* malloced_stack, int stack_size, rawctx_entry_point_t entry_point,
18                                        simgrid::kernel::context::SwappedContext* arg);
19 extern "C" void raw_swapcontext(raw_stack_t* old, raw_stack_t new_context);
20
21 // TODO, we should handle FP, MMX and the x87 control-word (for x86 and x86_64)
22
23 #if SIMGRID_PROCESSOR_x86_64
24 __asm__ (
25 #if defined(__APPLE__)
26    ".text\n"
27    ".globl _raw_makecontext\n"
28    "_raw_makecontext:\n"
29 #elif defined(_WIN32)
30    ".text\n"
31    ".globl raw_makecontext\n"
32    "raw_makecontext:\n"
33 #else
34    ".text\n"
35    ".globl raw_makecontext\n"
36    ".type raw_makecontext,@function\n"
37    "raw_makecontext:\n"/* Calling convention sets the arguments in rdi, rsi, rdx and rcx, respectively */
38 #endif
39    "   mov %rdi,%rax\n"      /* stack */
40    "   add %rsi,%rax\n"      /* size  */
41    "   andq $-16, %rax\n"    /* align stack */
42    "   movq $0,   -8(%rax)\n" /* @return for func */
43    "   mov %rdx,-16(%rax)\n" /* func */
44    "   mov %rcx,-24(%rax)\n" /* arg/rdi */
45    "   movq $0,  -32(%rax)\n" /* rsi */
46    "   movq $0,  -40(%rax)\n" /* rdx */
47    "   movq $0,  -48(%rax)\n" /* rcx */
48    "   movq $0,  -56(%rax)\n" /* r8  */
49    "   movq $0,  -64(%rax)\n" /* r9  */
50    "   movq $0,  -72(%rax)\n" /* rbp */
51    "   movq $0,  -80(%rax)\n" /* rbx */
52    "   movq $0,  -88(%rax)\n" /* r12 */
53    "   movq $0,  -96(%rax)\n" /* r13 */
54    "   movq $0, -104(%rax)\n" /* r14 */
55    "   movq $0, -112(%rax)\n" /* r15 */
56    "   sub $112,%rax\n"
57    "   ret\n"
58 );
59
60 __asm__ (
61 #if defined(__APPLE__)
62    ".text\n"
63    ".globl _raw_swapcontext\n"
64    "_raw_swapcontext:\n"
65 #elif defined(_WIN32)
66    ".text\n"
67    ".globl raw_swapcontext\n"
68    "raw_swapcontext:\n"
69 #else
70    ".text\n"
71    ".globl raw_swapcontext\n"
72    ".type raw_swapcontext,@function\n"
73    "raw_swapcontext:\n" /* Calling convention sets the arguments in rdi and rsi, respectively */
74 #endif
75    "   push %rdi\n"
76    "   push %rsi\n"
77    "   push %rdx\n"
78    "   push %rcx\n"
79    "   push %r8\n"
80    "   push %r9\n"
81    "   push %rbp\n"
82    "   push %rbx\n"
83    "   push %r12\n"
84    "   push %r13\n"
85    "   push %r14\n"
86    "   push %r15\n"
87    "   mov %rsp,(%rdi)\n" /* old */
88    "   mov %rsi,%rsp\n" /* new */
89    "   pop %r15\n"
90    "   pop %r14\n"
91    "   pop %r13\n"
92    "   pop %r12\n"
93    "   pop %rbx\n"
94    "   pop %rbp\n"
95    "   pop %r9\n"
96    "   pop %r8\n"
97    "   pop %rcx\n"
98    "   pop %rdx\n"
99    "   pop %rsi\n"
100    "   pop %rdi\n"
101    "   ret\n"
102 );
103 #elif SIMGRID_PROCESSOR_i686
104 __asm__ (
105 #if defined(__APPLE__) || defined(_WIN32)
106    ".text\n"
107    ".globl _raw_makecontext\n"
108    "_raw_makecontext:\n"
109 #else
110    ".text\n"
111    ".globl raw_makecontext\n"
112    ".type raw_makecontext,@function\n"
113    "raw_makecontext:\n"
114 #endif
115    "   movl 4(%esp),%eax\n"   /* stack */
116    "   addl 8(%esp),%eax\n"   /* size  */
117    "   andl $-16, %eax\n"     /* align stack */
118    "   movl 12(%esp),%ecx\n"  /* func  */
119    "   movl 16(%esp),%edx\n"  /* arg   */
120    "   movl %edx, -4(%eax)\n"
121    "   movl $0,   -8(%eax)\n" /* @return for func */
122    "   movl %ecx,-12(%eax)\n"
123    "   movl $0,  -16(%eax)\n" /* ebp */
124    "   movl $0,  -20(%eax)\n" /* ebx */
125    "   movl $0,  -24(%eax)\n" /* esi */
126    "   movl $0,  -28(%eax)\n" /* edi */
127    "   subl $28,%eax\n"
128    "   retl\n"
129 );
130
131 __asm__ (
132 #if defined(__APPLE__) || defined(_WIN32)
133    ".text\n"
134    ".globl _raw_swapcontext\n"
135    "_raw_swapcontext:\n"
136 #else
137    ".text\n"
138    ".globl raw_swapcontext\n"
139    ".type raw_swapcontext,@function\n"
140    "raw_swapcontext:\n"
141 #endif
142    // Fetch the parameters:
143    "   movl 4(%esp),%eax\n" /* old (raw_stack_t*) */
144    "   movl 8(%esp),%edx\n" /* new (raw_stack_t)  */
145    // Save registers of the current context on the stack:
146    "   pushl %ebp\n"
147    "   pushl %ebx\n"
148    "   pushl %esi\n"
149    "   pushl %edi\n"
150    // Save the current context (stack pointer) in *old:
151    "   movl %esp,(%eax)\n"
152    // Switch to the stack of the new context:
153    "   movl %edx,%esp\n"
154    // Pop the values of the new context:
155    "   popl %edi\n"
156    "   popl %esi\n"
157    "   popl %ebx\n"
158    "   popl %ebp\n"
159    // Return using the return address of the new context:
160    "   retl\n"
161 );
162 #else
163
164
165 /* If you implement raw contexts for other processors, don't forget to
166    update the definition of HAVE_RAW_CONTEXTS in tools/cmake/CompleteInFiles.cmake */
167
168 raw_stack_t raw_makecontext(void* malloced_stack, int stack_size, rawctx_entry_point_t entry_point,
169                             simgrid::kernel::context::SwappedContext* arg)
170 {
171   THROW_UNIMPLEMENTED;
172 }
173
174 void raw_swapcontext(raw_stack_t* old, raw_stack_t new_context)
175 {
176   THROW_UNIMPLEMENTED;
177 }
178
179 #endif
180
181 // ***** Method definitions
182
183 namespace simgrid {
184 namespace kernel {
185 namespace context {
186
187 // RawContextFactory
188
189 RawContext* RawContextFactory::create_context(std::function<void()>&& code, actor::ActorImpl* actor)
190 {
191   return this->new_context<RawContext>(std::move(code), actor, this);
192 }
193
194 // RawContext
195
196 RawContext::RawContext(std::function<void()>&& code, actor::ActorImpl* actor, SwappedContextFactory* factory)
197     : SwappedContext(std::move(code), actor, factory)
198 {
199   XBT_VERB("Creating a context of stack %uMb", actor->get_stacksize() / 1024 / 1024);
200   if (has_code()) {
201     this->stack_top_ = raw_makecontext(get_stack(), actor->get_stacksize(), smx_ctx_wrapper, this);
202   } else {
203     if (MC_is_active())
204       MC_ignore_heap(&stack_top_, sizeof stack_top_);
205   }
206 }
207
208 void RawContext::swap_into_for_real(SwappedContext* to_)
209 {
210   const RawContext* to = static_cast<RawContext*>(to_);
211   raw_swapcontext(&this->stack_top_, to->stack_top_);
212 }
213
214 ContextFactory* raw_factory()
215 {
216   XBT_VERB("Using raw contexts. Because the glibc is just not good enough for us.");
217   return new RawContextFactory();
218 }
219 } // namespace context
220 } // namespace kernel
221 } // namespace simgrid