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
pub trait Mode: Copy + private::ModePriv {}
#[derive(Clone, Copy)]
pub struct Sync;
impl Mode for Sync {}
cfg_if::cfg_if! {
if #[cfg(feature = "async")] {
use crate::memory::stack_page::Slot;
#[derive(Clone, Copy)]
pub struct Async<'frame>{
top: &'frame Slot
}
impl<'frame> Async<'frame> {
pub(crate) unsafe fn new(top: &'frame Slot) -> Self {
Async { top }
}
pub(crate) unsafe fn top(&self) -> &Slot {
self.top
}
}
impl<'frame> Mode for Async<'frame> {
}
}
}
pub(crate) mod private {
use crate::memory::stack_page::Slot;
use crate::{memory::mode::Sync, private::Private};
use std::ptr::{null_mut, NonNull};
pub trait ModePriv {
unsafe fn push_frame(&self, raw_frame: &[Slot], _: Private);
unsafe fn pop_frame(&self, raw_frame: &[Slot], _: Private);
}
cfg_if::cfg_if! {
if #[cfg(all(feature = "lts", not(feature = "all-features-override")))] {
impl ModePriv for Sync {
unsafe fn push_frame(&self, raw_frame: &[Slot], _: Private) {
let rtls = NonNull::new_unchecked(jl_sys::jl_get_ptls_states()).as_mut();
raw_frame[0].set(null_mut());
raw_frame[1].set(rtls.pgcstack.cast());
rtls.pgcstack = raw_frame[..].as_ptr() as *const _ as *mut _;
}
unsafe fn pop_frame(&self, _raw_frame: &[Slot], _: Private) {
let rtls = NonNull::new_unchecked(jl_sys::jl_get_ptls_states()).as_mut();
rtls.pgcstack = NonNull::new_unchecked(rtls.pgcstack).as_ref().prev;
}
}
} else {
use jl_sys::{jl_get_current_task, jl_task_t};
impl ModePriv for Sync {
unsafe fn push_frame(&self, raw_frame: &[Slot], _: Private) {
let task = NonNull::new_unchecked(jl_get_current_task().cast::<jl_task_t>()).as_mut();
raw_frame[0].set(null_mut());
raw_frame[1].set(task.gcstack.cast());
task.gcstack = raw_frame[..].as_ptr() as *const _ as *mut _;
}
unsafe fn pop_frame(&self, _raw_frame: &[Slot], _: Private) {
let task = NonNull::new_unchecked(jl_get_current_task().cast::<jl_task_t>()).as_mut();
task.gcstack = NonNull::new_unchecked(task.gcstack).as_ref().prev;
}
}
}
}
cfg_if::cfg_if! {
if #[cfg(feature = "async")] {
use super::Async;
impl<'frame> ModePriv for Async<'frame> {
unsafe fn push_frame(&self, raw_frame: &[Slot], _: Private) {
raw_frame[0].set(null_mut());
raw_frame[1].set(self.top().get());
self.top().set(raw_frame.as_ptr() as *const _ as *mut _);
}
unsafe fn pop_frame(&self, raw_frame: &[Slot], _: Private) {
self.top().set(raw_frame[1].get());
}
}
}
}
}