66// http://opensource.org/licenses/MIT>, at your option. This file may not be
77// copied, modified, or distributed except according to those terms.
88
9+ use core:: ptr:: NonNull ;
10+
11+ // #[cfg_attr(target_arch = "x86", path = "x86.rs")]
12+ //#[cfg_attr(target_arch = "x86_64", path = "x86_64.rs")]
13+ // #[cfg_attr(target_arch = "aarch64", path = "aarch64.rs")]
14+ // #[cfg_attr(target_arch = "or1k", path = "or1k.rs")]
15+ //mod imp;
16+
17+ // TEMP FOR RUST-ANALYZER
18+ mod x86_64;
19+ use x86_64 as imp;
20+
921pub use self :: imp:: * ;
1022
11- #[ cfg_attr( target_arch = "x86" , path = "x86.rs" ) ]
12- #[ cfg_attr( target_arch = "x86_64" , path = "x86_64.rs" ) ]
13- #[ cfg_attr( target_arch = "aarch64" , path = "aarch64.rs" ) ]
14- #[ cfg_attr( target_arch = "or1k" , path = "or1k.rs" ) ]
15- mod imp;
23+ #[ derive( Debug , Clone , Copy ) ]
24+ #[ repr( transparent) ]
25+ pub struct StackPointer ( NonNull < usize > ) ;
26+
27+ impl StackPointer {
28+ #[ inline( always) ]
29+ pub unsafe fn push ( & mut self , val : usize ) {
30+ self . 0 = NonNull :: new_unchecked ( self . 0 . as_ptr ( ) . offset ( -1 ) ) ;
31+ self . 0 . as_ptr ( ) . write ( val) ;
32+ }
33+
34+ #[ inline( always) ]
35+ pub const unsafe fn new < T > ( sp : * mut T ) -> StackPointer {
36+ StackPointer ( NonNull :: new_unchecked ( sp as * mut usize ) )
37+ }
38+
39+ #[ inline( always) ]
40+ pub unsafe fn offset ( & self , count : isize ) -> * mut usize {
41+ self . 0 . as_ptr ( ) . offset ( count)
42+ }
43+ }
44+
45+ impl From < NonNull < usize > > for StackPointer {
46+ #[ inline( always) ]
47+ fn from ( val : NonNull < usize > ) -> Self {
48+ Self ( val)
49+ }
50+ }
1651
1752#[ cfg( test) ]
1853mod tests {
1954 extern crate test;
2055
2156 use crate :: {
2257 arch:: { self , StackPointer } ,
23- OsStack ,
58+ OsStack , Stack ,
2459 } ;
2560
2661 #[ test]
2762 fn context ( ) {
28- unsafe extern "C" fn adder ( arg : usize , stack_ptr : StackPointer ) -> ! {
63+ unsafe fn adder ( arg : usize , stack_ptr : StackPointer ) {
2964 println ! ( "it's alive! arg: {}" , arg) ;
30- let ( arg, stack_ptr) = arch:: swap ( arg + 1 , stack_ptr, None ) ;
65+ let ( arg, stack_ptr) = arch:: swap ( arg + 1 , stack_ptr) ;
3166 println ! ( "still alive! arg: {}" , arg) ;
32- arch:: swap ( arg + 1 , stack_ptr, None ) ;
67+ arch:: swap ( arg + 1 , stack_ptr) ;
3368 panic ! ( "i should be dead" ) ;
3469 }
3570
3671 unsafe {
3772 let stack = OsStack :: new ( 4 << 20 ) . unwrap ( ) ;
38- let stack_ptr = arch:: init ( & stack, adder) ;
73+ let stack_ptr = arch:: init ( stack. base ( ) , adder) ;
3974
40- let ( ret, stack_ptr) = arch:: swap ( 10 , stack_ptr, Some ( & stack) ) ;
75+ let ( ret, stack_ptr) = arch:: swap_link ( 10 , stack_ptr, stack. base ( ) ) ;
4176 assert_eq ! ( ret, 11 ) ;
42- let ( ret, _) = arch:: swap ( 50 , stack_ptr, Some ( & stack) ) ;
77+ let ( ret, _) = arch:: swap_link ( 50 , stack_ptr. unwrap ( ) , stack. base ( ) ) ;
4378 assert_eq ! ( ret, 51 ) ;
4479 }
4580 }
4681
47- #[ test]
48- fn context_simd ( ) {
49- unsafe extern "C" fn permuter ( arg : usize , stack_ptr : StackPointer ) -> ! {
50- // This will crash if the stack is not aligned properly.
51- let x = packed_simd:: i32x4:: splat ( arg as i32 ) ;
52- let y = x * x;
53- println ! ( "simd result: {:?}" , y) ;
54- let ( _, stack_ptr) = arch:: swap ( 0 , stack_ptr, None ) ;
55- // And try again after a context switch.
56- let x = packed_simd:: i32x4:: splat ( arg as i32 ) ;
57- let y = x * x;
58- println ! ( "simd result: {:?}" , y) ;
59- arch:: swap ( 0 , stack_ptr, None ) ;
60- panic ! ( "i should be dead" ) ;
61- }
62-
63- unsafe {
64- let stack = OsStack :: new ( 4 << 20 ) . unwrap ( ) ;
65- let stack_ptr = arch:: init ( & stack, permuter) ;
66-
67- let ( _, stack_ptr) = arch:: swap ( 10 , stack_ptr, Some ( & stack) ) ;
68- arch:: swap ( 20 , stack_ptr, Some ( & stack) ) ;
69- }
70- }
71-
72- unsafe extern "C" fn do_panic ( arg : usize , stack_ptr : StackPointer ) -> ! {
82+ // #[test]
83+ // fn context_simd() {
84+ // unsafe fn permuter(arg: usize, stack_ptr: StackPointer) {
85+ // // This will crash if the stack is not aligned properly.
86+ // let x = packed_simd::i32x4::splat(arg as i32);
87+ // let y = x * x;
88+ // println!("simd result: {:?}", y);
89+ // let (_, stack_ptr) = arch::swap(0, stack_ptr);
90+ // // And try again after a context switch.
91+ // let x = packed_simd::i32x4::splat(arg as i32);
92+ // let y = x * x;
93+ // println!("simd result: {:?}", y);
94+ // arch::swap(0, stack_ptr);
95+ // panic!("i should be dead");
96+ // }
97+
98+ // unsafe {
99+ // let stack = OsStack::new(4 << 20).unwrap();
100+ // let stack_ptr = arch::init(stack.base() , permuter);
101+
102+ // let (_, stack_ptr) = arch::swap_link (10, stack_ptr, stack.base( ));
103+ // arch::swap_link (20, stack_ptr.unwrap(), stack.base( ));
104+ // }
105+ // }
106+
107+ unsafe fn do_panic ( arg : usize , stack_ptr : StackPointer ) {
73108 match arg {
74109 0 => panic ! ( "arg=0" ) ,
75110 1 => {
76- arch:: swap ( 0 , stack_ptr, None ) ;
111+ arch:: swap ( 0 , stack_ptr) ;
77112 panic ! ( "arg=1" ) ;
78113 }
79114 _ => unreachable ! ( ) ,
@@ -85,9 +120,9 @@ mod tests {
85120 fn panic_after_start ( ) {
86121 unsafe {
87122 let stack = OsStack :: new ( 4 << 20 ) . unwrap ( ) ;
88- let stack_ptr = arch:: init ( & stack, do_panic) ;
123+ let stack_ptr = arch:: init ( stack. base ( ) , do_panic) ;
89124
90- arch:: swap ( 0 , stack_ptr, Some ( & stack) ) ;
125+ arch:: swap_link ( 0 , stack_ptr, stack. base ( ) ) ;
91126 }
92127 }
93128
@@ -96,32 +131,45 @@ mod tests {
96131 fn panic_after_swap ( ) {
97132 unsafe {
98133 let stack = OsStack :: new ( 4 << 20 ) . unwrap ( ) ;
99- let stack_ptr = arch:: init ( & stack, do_panic) ;
134+ let stack_ptr = arch:: init ( stack. base ( ) , do_panic) ;
135+
136+ let ( _, stack_ptr) = arch:: swap_link ( 1 , stack_ptr, stack. base ( ) ) ;
137+ arch:: swap_link ( 0 , stack_ptr. unwrap ( ) , stack. base ( ) ) ;
138+ }
139+ }
140+
141+ #[ test]
142+ fn ret ( ) {
143+ unsafe fn ret2 ( _: usize , _: StackPointer ) { }
144+
145+ unsafe {
146+ let stack = OsStack :: new ( 4 << 20 ) . unwrap ( ) ;
147+ let stack_ptr = arch:: init ( stack. base ( ) , ret2) ;
100148
101- let ( _, stack_ptr) = arch:: swap ( 1 , stack_ptr, Some ( & stack) ) ;
102- arch :: swap ( 0 , stack_ptr, Some ( & stack ) ) ;
149+ let ( _, stack_ptr) = arch:: swap_link ( 0 , stack_ptr, stack. base ( ) ) ;
150+ assert ! ( stack_ptr. is_none ( ) ) ;
103151 }
104152 }
105153
106154 #[ bench]
107155 fn swap ( b : & mut test:: Bencher ) {
108- unsafe extern "C" fn loopback ( mut arg : usize , mut stack_ptr : StackPointer ) -> ! {
156+ unsafe fn loopback ( mut arg : usize , mut stack_ptr : StackPointer ) {
109157 // This deliberately does not ignore arg, to measure the time it takes
110158 // to move the return value between registers.
111159 loop {
112- let data = arch:: swap ( arg, stack_ptr, None ) ;
160+ let data = arch:: swap ( arg, stack_ptr) ;
113161 arg = data. 0 ;
114162 stack_ptr = data. 1 ;
115163 }
116164 }
117165
118166 unsafe {
119167 let stack = OsStack :: new ( 4 << 20 ) . unwrap ( ) ;
120- let mut stack_ptr = arch:: init ( & stack, loopback) ;
168+ let mut stack_ptr = arch:: init ( stack. base ( ) , loopback) ;
121169
122170 b. iter ( || {
123171 for _ in 0 ..10 {
124- stack_ptr = arch:: swap ( 0 , stack_ptr, Some ( & stack) ) . 1 ;
172+ stack_ptr = arch:: swap_link ( 0 , stack_ptr, stack. base ( ) ) . 1 . unwrap ( ) ;
125173 }
126174 } ) ;
127175 }
0 commit comments