Add ABI tagging to crates, adjust rustc output and runtime stack-frame setup so access to argv works.
This commit is contained in:
parent
01c2761769
commit
af4d6ae76b
@ -110,23 +110,33 @@ let indirect_args_elt_closure = 0;;
|
|||||||
(* Current worst case is by vec grow glue *)
|
(* Current worst case is by vec grow glue *)
|
||||||
let worst_case_glue_call_args = 8;;
|
let worst_case_glue_call_args = 8;;
|
||||||
|
|
||||||
|
(*
|
||||||
|
* ABI tags used to inform the runtime which sort of frame to set up for new
|
||||||
|
* spawned functions. FIXME: There is almost certainly a better abstraction to
|
||||||
|
* use.
|
||||||
|
*)
|
||||||
|
let abi_x86_rustboot_cdecl = 1;;
|
||||||
|
let abi_x86_rustc_fastcall = 2;;
|
||||||
|
|
||||||
type abi =
|
type abi =
|
||||||
{
|
{
|
||||||
abi_word_sz: int64;
|
abi_word_sz: int64;
|
||||||
abi_word_bits: Il.bits;
|
abi_word_bits: Il.bits;
|
||||||
abi_word_ty: Common.ty_mach;
|
abi_word_ty: Common.ty_mach;
|
||||||
|
|
||||||
abi_has_pcrel_data: bool;
|
abi_tag: int;
|
||||||
abi_has_pcrel_code: bool;
|
|
||||||
|
|
||||||
abi_n_hardregs: int;
|
abi_has_pcrel_data: bool;
|
||||||
abi_str_of_hardreg: (int -> string);
|
abi_has_pcrel_code: bool;
|
||||||
|
|
||||||
abi_emit_target_specific: (Il.emitter -> Il.quad -> unit);
|
abi_n_hardregs: int;
|
||||||
abi_constrain_vregs: (Il.quad -> (Il.vreg,Bits.t) Hashtbl.t -> unit);
|
abi_str_of_hardreg: (int -> string);
|
||||||
|
|
||||||
abi_emit_fn_prologue: (Il.emitter
|
abi_emit_target_specific: (Il.emitter -> Il.quad -> unit);
|
||||||
-> Common.size (* framesz *)
|
abi_constrain_vregs: (Il.quad -> (Il.vreg,Bits.t) Hashtbl.t -> unit);
|
||||||
|
|
||||||
|
abi_emit_fn_prologue: (Il.emitter
|
||||||
|
-> Common.size (* framesz *)
|
||||||
-> Common.size (* callsz *)
|
-> Common.size (* callsz *)
|
||||||
-> Common.nabi
|
-> Common.nabi
|
||||||
-> Common.fixup (* grow_task *)
|
-> Common.fixup (* grow_task *)
|
||||||
|
@ -1851,6 +1851,8 @@ let (abi:Abi.abi) =
|
|||||||
Abi.abi_word_bits = word_bits;
|
Abi.abi_word_bits = word_bits;
|
||||||
Abi.abi_word_ty = word_ty;
|
Abi.abi_word_ty = word_ty;
|
||||||
|
|
||||||
|
Abi.abi_tag = Abi.abi_x86_rustboot_cdecl;
|
||||||
|
|
||||||
Abi.abi_has_pcrel_data = false;
|
Abi.abi_has_pcrel_data = false;
|
||||||
Abi.abi_has_pcrel_code = true;
|
Abi.abi_has_pcrel_code = true;
|
||||||
|
|
||||||
|
@ -2727,6 +2727,7 @@ let trans_visitor
|
|||||||
[|
|
[|
|
||||||
Il.Cell new_task;
|
Il.Cell new_task;
|
||||||
exit_task_glue_fptr;
|
exit_task_glue_fptr;
|
||||||
|
(imm (Int64.of_int abi.Abi.abi_tag));
|
||||||
fptr_operand;
|
fptr_operand;
|
||||||
callsz
|
callsz
|
||||||
|];
|
|];
|
||||||
@ -2739,6 +2740,7 @@ let trans_visitor
|
|||||||
[|
|
[|
|
||||||
Il.Cell new_task;
|
Il.Cell new_task;
|
||||||
exit_task_glue_fptr;
|
exit_task_glue_fptr;
|
||||||
|
(imm (Int64.of_int abi.Abi.abi_tag));
|
||||||
fptr_operand;
|
fptr_operand;
|
||||||
callsz
|
callsz
|
||||||
|];
|
|];
|
||||||
@ -6183,6 +6185,8 @@ let trans_visitor
|
|||||||
tab_sz cx.ctxt_required_rust_sym_num;
|
tab_sz cx.ctxt_required_rust_sym_num;
|
||||||
tab_sz cx.ctxt_required_c_sym_num;
|
tab_sz cx.ctxt_required_c_sym_num;
|
||||||
tab_sz cx.ctxt_required_lib_num;
|
tab_sz cx.ctxt_required_lib_num;
|
||||||
|
|
||||||
|
Asm.WORD (word_ty_mach, Asm.IMM (Int64.of_int abi.Abi.abi_tag));
|
||||||
|]))
|
|]))
|
||||||
in
|
in
|
||||||
|
|
||||||
|
@ -60,6 +60,9 @@ const int worst_case_glue_call_args = 7;
|
|||||||
|
|
||||||
const int n_upcall_glues = 7;
|
const int n_upcall_glues = 7;
|
||||||
|
|
||||||
|
const int abi_x86_rustboot_cdecl = 1;
|
||||||
|
const int abi_x86_rustc_fastcall = 2;
|
||||||
|
|
||||||
fn memcpy_glue_name() -> str {
|
fn memcpy_glue_name() -> str {
|
||||||
ret "rust_memcpy_glue";
|
ret "rust_memcpy_glue";
|
||||||
}
|
}
|
||||||
|
@ -98,12 +98,12 @@ fn rust_activate_glue() -> vec[str] {
|
|||||||
* | esi |
|
* | esi |
|
||||||
* | ebx | <-- current task->rust_sp == current esp
|
* | ebx | <-- current task->rust_sp == current esp
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* This is a problem. If we return to "esp <- task->rust_sp" it
|
* This is a problem. If we return to "esp <- task->rust_sp" it
|
||||||
* will push esp back down by 5 words. This manifests as a rust
|
* will push esp back down by 5 words. This manifests as a rust
|
||||||
* stack that grows by 5 words on each yield/reactivate. Not
|
* stack that grows by 5 words on each yield/reactivate. Not
|
||||||
* good.
|
* good.
|
||||||
*
|
*
|
||||||
* So what we do here is just adjust task->rust_sp up 5 words as
|
* So what we do here is just adjust task->rust_sp up 5 words as
|
||||||
* well, to mirror the movement in esp we're about to
|
* well, to mirror the movement in esp we're about to
|
||||||
* perform. That way the "esp <- task->rust_sp" we 'ret' to below
|
* perform. That way the "esp <- task->rust_sp" we 'ret' to below
|
||||||
|
@ -345,7 +345,8 @@ fn T_crate(type_names tn) -> TypeRef {
|
|||||||
T_int(), // size_t main_exit_task_glue_off
|
T_int(), // size_t main_exit_task_glue_off
|
||||||
T_int(), // int n_rust_syms
|
T_int(), // int n_rust_syms
|
||||||
T_int(), // int n_c_syms
|
T_int(), // int n_c_syms
|
||||||
T_int() // int n_libs
|
T_int(), // int n_libs
|
||||||
|
T_int() // uintptr_t abi_tag
|
||||||
));
|
));
|
||||||
tn.associate(s, t);
|
tn.associate(s, t);
|
||||||
ret t;
|
ret t;
|
||||||
@ -4545,7 +4546,7 @@ fn trans_exit_task_glue(@crate_ctxt cx) {
|
|||||||
let vec[ValueRef] V_args = vec();
|
let vec[ValueRef] V_args = vec();
|
||||||
|
|
||||||
auto llfn = cx.glues.exit_task_glue;
|
auto llfn = cx.glues.exit_task_glue;
|
||||||
let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 0u);
|
let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 3u);
|
||||||
auto fcx = @rec(llfn=llfn,
|
auto fcx = @rec(llfn=llfn,
|
||||||
lltaskptr=lltaskptr,
|
lltaskptr=lltaskptr,
|
||||||
llenv=C_null(T_opaque_closure_ptr(cx.tn)),
|
llenv=C_null(T_opaque_closure_ptr(cx.tn)),
|
||||||
@ -4596,7 +4597,8 @@ fn create_crate_constant(@crate_ctxt cx) {
|
|||||||
exit_task_glue_off, // size_t main_exit_task_glue_off
|
exit_task_glue_off, // size_t main_exit_task_glue_off
|
||||||
C_null(T_int()), // int n_rust_syms
|
C_null(T_int()), // int n_rust_syms
|
||||||
C_null(T_int()), // int n_c_syms
|
C_null(T_int()), // int n_c_syms
|
||||||
C_null(T_int()) // int n_libs
|
C_null(T_int()), // int n_libs
|
||||||
|
C_int(abi.abi_x86_rustc_fastcall) // uintptr_t abi_tag
|
||||||
));
|
));
|
||||||
|
|
||||||
llvm.LLVMSetInitializer(cx.crate_ptr, crate_val);
|
llvm.LLVMSetInitializer(cx.crate_ptr, crate_val);
|
||||||
@ -4810,7 +4812,10 @@ fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns {
|
|||||||
* this is the signature required to retrieve it.
|
* this is the signature required to retrieve it.
|
||||||
*/
|
*/
|
||||||
exit_task_glue = decl_cdecl_fn(llmod, abi.exit_task_glue_name(),
|
exit_task_glue = decl_cdecl_fn(llmod, abi.exit_task_glue_name(),
|
||||||
T_fn(vec(T_taskptr(tn)),
|
T_fn(vec(T_int(),
|
||||||
|
T_int(),
|
||||||
|
T_int(),
|
||||||
|
T_taskptr(tn)),
|
||||||
T_void())),
|
T_void())),
|
||||||
|
|
||||||
upcall_glues =
|
upcall_glues =
|
||||||
|
@ -78,7 +78,7 @@ command_line_args : public dom_owned<command_line_args>
|
|||||||
|
|
||||||
extern "C" CDECL int
|
extern "C" CDECL int
|
||||||
rust_start(uintptr_t main_fn, rust_crate const *crate, int argc,
|
rust_start(uintptr_t main_fn, rust_crate const *crate, int argc,
|
||||||
char **argv) {
|
char **argv) {
|
||||||
|
|
||||||
rust_srv *srv = new rust_srv();
|
rust_srv *srv = new rust_srv();
|
||||||
rust_kernel *kernel = new rust_kernel(srv);
|
rust_kernel *kernel = new rust_kernel(srv);
|
||||||
@ -87,7 +87,8 @@ rust_start(uintptr_t main_fn, rust_crate const *crate, int argc,
|
|||||||
rust_dom *dom = handle->referent();
|
rust_dom *dom = handle->referent();
|
||||||
command_line_args *args = new (dom) command_line_args(dom, argc, argv);
|
command_line_args *args = new (dom) command_line_args(dom, argc, argv);
|
||||||
|
|
||||||
dom->log(rust_log::DOM, "startup: %d args", args->argc);
|
dom->log(rust_log::DOM, "startup: %d args in 0x%" PRIxPTR,
|
||||||
|
args->argc, (uintptr_t)args->args);
|
||||||
for (int i = 0; i < args->argc; i++) {
|
for (int i = 0; i < args->argc; i++) {
|
||||||
dom->log(rust_log::DOM,
|
dom->log(rust_log::DOM,
|
||||||
"startup: arg[%d] = '%s'", i, args->argv[i]);
|
"startup: arg[%d] = '%s'", i, args->argv[i]);
|
||||||
@ -99,7 +100,8 @@ rust_start(uintptr_t main_fn, rust_crate const *crate, int argc,
|
|||||||
|
|
||||||
uintptr_t main_args[4] = {0, 0, 0, (uintptr_t)args->args};
|
uintptr_t main_args[4] = {0, 0, 0, (uintptr_t)args->args};
|
||||||
dom->root_task->start(crate->get_exit_task_glue(),
|
dom->root_task->start(crate->get_exit_task_glue(),
|
||||||
main_fn, (uintptr_t)&main_args, sizeof(main_args));
|
crate->abi_tag, main_fn,
|
||||||
|
(uintptr_t)&main_args, sizeof(main_args));
|
||||||
int ret = dom->start_main_loop();
|
int ret = dom->start_main_loop();
|
||||||
delete args;
|
delete args;
|
||||||
kernel->destroy_domain(dom);
|
kernel->destroy_domain(dom);
|
||||||
|
@ -88,6 +88,10 @@ static size_t const TIME_SLICE_IN_MS = 10;
|
|||||||
|
|
||||||
static intptr_t const CONST_REFCOUNT = 0x7badface;
|
static intptr_t const CONST_REFCOUNT = 0x7badface;
|
||||||
|
|
||||||
|
// ABI tags for rust_start, rust_task::start and friends.
|
||||||
|
static uintptr_t const ABI_X86_RUSTBOOT_CDECL = 1;
|
||||||
|
static uintptr_t const ABI_X86_RUSTC_FASTCALL = 2;
|
||||||
|
|
||||||
// This accounts for logging buffers.
|
// This accounts for logging buffers.
|
||||||
|
|
||||||
static size_t const BUF_BYTES = 2048;
|
static size_t const BUF_BYTES = 2048;
|
||||||
@ -241,6 +245,8 @@ public:
|
|||||||
size_t n_c_syms;
|
size_t n_c_syms;
|
||||||
size_t n_libs;
|
size_t n_libs;
|
||||||
|
|
||||||
|
uintptr_t abi_tag;
|
||||||
|
|
||||||
// Crates are immutable, constructed by the compiler.
|
// Crates are immutable, constructed by the compiler.
|
||||||
|
|
||||||
uintptr_t get_image_base() const;
|
uintptr_t get_image_base() const;
|
||||||
|
@ -123,6 +123,7 @@ rust_task::~rust_task()
|
|||||||
|
|
||||||
void
|
void
|
||||||
rust_task::start(uintptr_t exit_task_glue,
|
rust_task::start(uintptr_t exit_task_glue,
|
||||||
|
uintptr_t spawnee_abi,
|
||||||
uintptr_t spawnee_fn,
|
uintptr_t spawnee_fn,
|
||||||
uintptr_t args,
|
uintptr_t args,
|
||||||
size_t callsz)
|
size_t callsz)
|
||||||
@ -147,39 +148,46 @@ rust_task::start(uintptr_t exit_task_glue,
|
|||||||
// The exit_task_glue frame we synthesize above the frame we activate:
|
// The exit_task_glue frame we synthesize above the frame we activate:
|
||||||
*spp-- = (uintptr_t) 0; // closure-or-obj
|
*spp-- = (uintptr_t) 0; // closure-or-obj
|
||||||
*spp-- = (uintptr_t) this; // task
|
*spp-- = (uintptr_t) this; // task
|
||||||
*spp-- = (uintptr_t) 0; // output
|
*spp-- = (uintptr_t) 0x0; // output
|
||||||
*spp-- = (uintptr_t) 0; // retpc
|
*spp-- = (uintptr_t) 0x0; // retpc
|
||||||
|
|
||||||
uintptr_t exit_task_frame_base;
|
uintptr_t exit_task_frame_base;
|
||||||
|
|
||||||
for (size_t j = 0; j < n_callee_saves; ++j) {
|
if (spawnee_abi == ABI_X86_RUSTBOOT_CDECL) {
|
||||||
|
for (size_t j = 0; j < n_callee_saves; ++j) {
|
||||||
|
|
||||||
// We want 'frame_base' to point to the old fp in this (exit-task)
|
// We want 'frame_base' to point to the old fp in this (exit-task)
|
||||||
// frame, because we're going to inject this frame-pointer into the
|
// frame, because we're going to inject this frame-pointer into
|
||||||
// callee-save frame pointer value in the *next* (spawnee) frame. A
|
// the callee-save frame pointer value in the *next* (spawnee)
|
||||||
// cheap trick, but this means the spawnee frame will restore the
|
// frame. A cheap trick, but this means the spawnee frame will
|
||||||
// proper frame pointer of the glue frame as it runs its epilogue.
|
// restore the proper frame pointer of the glue frame as it runs
|
||||||
if (j == callee_save_fp)
|
// its epilogue.
|
||||||
exit_task_frame_base = (uintptr_t)spp;
|
if (j == callee_save_fp)
|
||||||
|
exit_task_frame_base = (uintptr_t)spp;
|
||||||
|
|
||||||
*spp-- = 0;
|
*spp-- = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*spp-- = (uintptr_t) dom->root_crate; // crate ptr
|
||||||
|
*spp-- = (uintptr_t) 0; // frame_glue_fns
|
||||||
}
|
}
|
||||||
|
|
||||||
*spp-- = (uintptr_t) dom->root_crate; // crate ptr
|
|
||||||
*spp-- = (uintptr_t) 0; // frame_glue_fns
|
|
||||||
|
|
||||||
// Copy args from spawner to spawnee.
|
// Copy args from spawner to spawnee.
|
||||||
if (args) {
|
if (args) {
|
||||||
uintptr_t *src = (uintptr_t *)args;
|
uintptr_t *src = (uintptr_t *)args;
|
||||||
src += 1; // spawn-call output slot
|
src += 1; // spawn-call output slot
|
||||||
src += 1; // spawn-call task slot
|
src += 1; // spawn-call task slot
|
||||||
src += 1; // spawn-call closure-or-obj slot
|
src += 1; // spawn-call closure-or-obj slot
|
||||||
|
|
||||||
|
// Undo previous sp-- so we're pointing at the last word pushed.
|
||||||
|
++spp;
|
||||||
|
|
||||||
// Memcpy all but the task, output and env pointers
|
// Memcpy all but the task, output and env pointers
|
||||||
callsz -= (3 * sizeof(uintptr_t));
|
callsz -= (3 * sizeof(uintptr_t));
|
||||||
spp = (uintptr_t*) (((uintptr_t)spp) - callsz);
|
spp = (uintptr_t*) (((uintptr_t)spp) - callsz);
|
||||||
memcpy(spp, src, callsz);
|
memcpy(spp, src, callsz);
|
||||||
|
|
||||||
// Move sp down to point to task cell.
|
// Move sp down to point to last implicit-arg cell (env).
|
||||||
spp--;
|
spp--;
|
||||||
} else {
|
} else {
|
||||||
// We're at root, starting up.
|
// We're at root, starting up.
|
||||||
@ -188,10 +196,18 @@ rust_task::start(uintptr_t exit_task_glue,
|
|||||||
|
|
||||||
// The *implicit* incoming args to the spawnee frame we're
|
// The *implicit* incoming args to the spawnee frame we're
|
||||||
// activating:
|
// activating:
|
||||||
|
*spp-- = (uintptr_t) 0x0; // closure-or-obj
|
||||||
|
|
||||||
|
if (spawnee_abi == ABI_X86_RUSTBOOT_CDECL) {
|
||||||
|
// in CDECL mode we write the task + outptr to the spawnee stack.
|
||||||
|
*spp-- = (uintptr_t) this; // task
|
||||||
|
*spp-- = (uintptr_t) 0; // output addr
|
||||||
|
} else {
|
||||||
|
// in FASTCALL mode we don't, the outptr will be in ecx and the task
|
||||||
|
// in edx, and the activate_glue will make sure to set that up.
|
||||||
|
I(dom, spawnee_abi == ABI_X86_RUSTC_FASTCALL);
|
||||||
|
}
|
||||||
|
|
||||||
*spp-- = (uintptr_t) 0; // closure-or-obj
|
|
||||||
*spp-- = (uintptr_t) this; // task
|
|
||||||
*spp-- = (uintptr_t) 0; // output addr
|
|
||||||
*spp-- = (uintptr_t) exit_task_glue; // retpc
|
*spp-- = (uintptr_t) exit_task_glue; // retpc
|
||||||
|
|
||||||
// The context the activate_glue needs to switch stack.
|
// The context the activate_glue needs to switch stack.
|
||||||
|
@ -56,6 +56,7 @@ rust_task : public maybe_proxy<rust_task>,
|
|||||||
~rust_task();
|
~rust_task();
|
||||||
|
|
||||||
void start(uintptr_t exit_task_glue,
|
void start(uintptr_t exit_task_glue,
|
||||||
|
uintptr_t spawnee_abi,
|
||||||
uintptr_t spawnee_fn,
|
uintptr_t spawnee_fn,
|
||||||
uintptr_t args,
|
uintptr_t args,
|
||||||
size_t callsz);
|
size_t callsz);
|
||||||
|
@ -559,6 +559,7 @@ extern "C" CDECL rust_task *
|
|||||||
upcall_start_task(rust_task *spawner,
|
upcall_start_task(rust_task *spawner,
|
||||||
rust_task *task,
|
rust_task *task,
|
||||||
uintptr_t exit_task_glue,
|
uintptr_t exit_task_glue,
|
||||||
|
uintptr_t spawnee_abi,
|
||||||
uintptr_t spawnee_fn,
|
uintptr_t spawnee_fn,
|
||||||
size_t callsz) {
|
size_t callsz) {
|
||||||
LOG_UPCALL_ENTRY(spawner);
|
LOG_UPCALL_ENTRY(spawner);
|
||||||
@ -570,7 +571,8 @@ upcall_start_task(rust_task *spawner,
|
|||||||
", spawnee 0x%" PRIxPTR
|
", spawnee 0x%" PRIxPTR
|
||||||
", callsz %" PRIdPTR ")", task->name, task, exit_task_glue,
|
", callsz %" PRIdPTR ")", task->name, task, exit_task_glue,
|
||||||
spawnee_fn, callsz);
|
spawnee_fn, callsz);
|
||||||
task->start(exit_task_glue, spawnee_fn, spawner->rust_sp, callsz);
|
task->start(exit_task_glue, spawnee_abi, spawnee_fn,
|
||||||
|
spawner->rust_sp, callsz);
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,6 +625,7 @@ extern "C" CDECL maybe_proxy<rust_task> *
|
|||||||
upcall_start_thread(rust_task *task,
|
upcall_start_thread(rust_task *task,
|
||||||
rust_proxy<rust_task> *child_task_proxy,
|
rust_proxy<rust_task> *child_task_proxy,
|
||||||
uintptr_t exit_task_glue,
|
uintptr_t exit_task_glue,
|
||||||
|
uintptr_t spawnee_abi,
|
||||||
uintptr_t spawnee_fn,
|
uintptr_t spawnee_fn,
|
||||||
size_t callsz) {
|
size_t callsz) {
|
||||||
LOG_UPCALL_ENTRY(task);
|
LOG_UPCALL_ENTRY(task);
|
||||||
@ -630,9 +633,11 @@ upcall_start_thread(rust_task *task,
|
|||||||
rust_handle<rust_task> *child_task_handle = child_task_proxy->handle();
|
rust_handle<rust_task> *child_task_handle = child_task_proxy->handle();
|
||||||
task->log(rust_log::UPCALL | rust_log::MEM | rust_log::TASK,
|
task->log(rust_log::UPCALL | rust_log::MEM | rust_log::TASK,
|
||||||
"exit_task_glue: " PTR ", spawnee_fn " PTR
|
"exit_task_glue: " PTR ", spawnee_fn " PTR
|
||||||
", callsz %" PRIdPTR ")", exit_task_glue, spawnee_fn, callsz);
|
", callsz %" PRIdPTR ")",
|
||||||
|
exit_task_glue, spawnee_fn, callsz);
|
||||||
rust_task *child_task = child_task_handle->referent();
|
rust_task *child_task = child_task_handle->referent();
|
||||||
child_task->start(exit_task_glue, spawnee_fn, task->rust_sp, callsz);
|
child_task->start(exit_task_glue, spawnee_abi, spawnee_fn,
|
||||||
|
task->rust_sp, callsz);
|
||||||
#if defined(__WIN32__)
|
#if defined(__WIN32__)
|
||||||
HANDLE thread;
|
HANDLE thread;
|
||||||
thread = CreateThread(NULL, 0, rust_thread_start, child_task->dom, 0,
|
thread = CreateThread(NULL, 0, rust_thread_start, child_task->dom, 0,
|
||||||
|
@ -54,6 +54,7 @@ rust_task_test::worker::run() {
|
|||||||
kernel->create_domain(crate, "test");
|
kernel->create_domain(crate, "test");
|
||||||
rust_dom *domain = handle->referent();
|
rust_dom *domain = handle->referent();
|
||||||
domain->root_task->start(crate->get_exit_task_glue(),
|
domain->root_task->start(crate->get_exit_task_glue(),
|
||||||
|
ABI_X86_RUSTBOOT_CDECL,
|
||||||
(uintptr_t)&task_entry, (uintptr_t)NULL, 0);
|
(uintptr_t)&task_entry, (uintptr_t)NULL, 0);
|
||||||
domain->start_main_loop();
|
domain->start_main_loop();
|
||||||
kernel->destroy_domain(domain);
|
kernel->destroy_domain(domain);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user