88// option. This file may not be copied, modified, or distributed 
99// except according to those terms. 
1010
11+ use  option:: * ; 
1112use  super :: stack:: StackSegment ; 
1213use  libc:: c_void; 
1314use  cast:: { transmute,  transmute_mut_unsafe, 
@@ -16,17 +17,30 @@ use cast::{transmute, transmute_mut_unsafe,
1617// XXX: Registers is boxed so that it is 16-byte aligned, for storing 
1718// SSE regs.  It would be marginally better not to do this. In C++ we 
1819// use an attribute on a struct. 
19- pub  struct  Context ( ~Registers ) ; 
20+ // XXX: It would be nice to define regs as `~Option<Registers>` since 
21+ // the registers are sometimes empty, but the discriminant would 
22+ // then misalign the regs again. 
23+ pub  struct  Context  { 
24+     /// The context entry point, saved here for later destruction 
25+ start :  Option < ~~fn ( ) > , 
26+     /// Hold the registers while the task or scheduler is suspended 
27+ regs :  ~Registers 
28+ } 
2029
2130pub  impl  Context  { 
2231    fn  empty ( )  -> Context  { 
23-         Context ( new_regs ( ) ) 
32+         Context  { 
33+             start :  None , 
34+             regs :  new_regs ( ) 
35+         } 
2436    } 
2537
2638    /// Create a new context that will resume execution by running ~fn() 
27- /// # Safety Note 
28- /// The `start` closure must remain valid for the life of the Task 
29- fn  new ( start :  & ~fn ( ) ,  stack :  & mut  StackSegment )  -> Context  { 
39+ fn  new ( start :  ~fn ( ) ,  stack :  & mut  StackSegment )  -> Context  { 
40+         // XXX: Putting main into a ~ so it's a thin pointer and can 
41+         // be passed to the spawn function.  Another unfortunate 
42+         // allocation 
43+         let  start = ~start; 
3044
3145        // The C-ABI function that is the task entry point 
3246        extern  fn  task_start_wrapper ( f :  & ~fn ( ) )  {  ( * f) ( )  } 
@@ -40,21 +54,29 @@ pub impl Context {
4054        // which we will then modify to call the given function when restored 
4155        let  mut  regs = new_regs ( ) ; 
4256        unsafe  { 
43-             swap_registers ( transmute_mut_region ( & mut  * regs) , 
44-                            transmute_region ( & * regs) ) 
57+             swap_registers ( transmute_mut_region ( & mut  * regs) ,  transmute_region ( & * regs) ) 
4558        } ; 
4659
4760        initialize_call_frame ( & mut  * regs,  fp,  argp,  sp) ; 
4861
49-         return  Context ( regs) ; 
62+         return  Context  { 
63+             start :  Some ( start) , 
64+             regs :  regs
65+         } 
5066    } 
5167
68+     /* Switch contexts 
69+ 
70+     Suspend the current execution context and resume another by 
71+     saving the registers values of the executing thread to a Context 
72+     then loading the registers from a previously saved Context. 
73+     */ 
5274    fn  swap ( out_context :  & mut  Context ,  in_context :  & Context )  { 
5375        let  out_regs:  & mut  Registers  = match  out_context { 
54-             & Context ( ~ref  mut  r)  => r
76+             & Context   {   regs :   ~ref  mut  r,  _  }  => r
5577        } ; 
5678        let  in_regs:  & Registers  = match  in_context { 
57-             & Context ( ~ref  r)  => r
79+             & Context   {   regs :   ~ref  r,  _  }  => r
5880        } ; 
5981
6082        unsafe  {  swap_registers ( out_regs,  in_regs)  } ; 
@@ -84,11 +106,10 @@ fn new_regs() -> ~Registers {
84106} 
85107
86108#[ cfg( target_arch = "x86" ) ]  
87- fn  initialize_call_frame ( regs :  & mut  Registers , 
88-                          fptr :  * c_void ,  arg :  * c_void ,  sp :  * mut  uint )  { 
109+ fn  initialize_call_frame ( regs :  & mut  Registers ,  fptr :  * c_void ,  arg :  * c_void ,  sp :  * mut  uint )  { 
89110
90111    let  sp = align_down ( sp) ; 
91-     let  sp = mut_offset ( sp,  -4 ) ;   // XXX: -4 words? Needs this be done at all? 
112+     let  sp = mut_offset ( sp,  -4 ) ; 
92113
93114    unsafe  {  * sp = arg as  uint ;  } 
94115    let  sp = mut_offset ( sp,  -1 ) ; 
@@ -108,8 +129,7 @@ type Registers = [uint * 22];
108129fn  new_regs ( )  -> ~Registers  {  ~[ 0 ,  .. 22 ]  } 
109130
110131#[ cfg( target_arch = "x86_64" ) ]  
111- fn  initialize_call_frame ( regs :  & mut  Registers , 
112-                          fptr :  * c_void ,  arg :  * c_void ,  sp :  * mut  uint )  { 
132+ fn  initialize_call_frame ( regs :  & mut  Registers ,  fptr :  * c_void ,  arg :  * c_void ,  sp :  * mut  uint )  { 
113133
114134    // Redefinitions from regs.h 
115135    static  RUSTRT_ARG0 :  uint  = 3 ; 
@@ -143,8 +163,7 @@ type Registers = [uint * 32];
143163fn  new_regs ( )  -> ~Registers  {  ~[ 0 ,  .. 32 ]  } 
144164
145165#[ cfg( target_arch = "arm" ) ]  
146- fn  initialize_call_frame ( regs :  & mut  Registers , 
147-                          fptr :  * c_void ,  arg :  * c_void ,  sp :  * mut  uint )  { 
166+ fn  initialize_call_frame ( regs :  & mut  Registers ,  fptr :  * c_void ,  arg :  * c_void ,  sp :  * mut  uint )  { 
148167    let  sp = mut_offset ( sp,  -1 ) ; 
149168
150169    // The final return address. 0 indicates the bottom of the stack 
@@ -162,8 +181,7 @@ type Registers = [uint * 32];
162181fn  new_regs ( )  -> ~Registers  {  ~[ 0 ,  .. 32 ]  } 
163182
164183#[ cfg( target_arch = "mips" ) ]  
165- fn  initialize_call_frame ( regs :  & mut  Registers , 
166-                          fptr :  * c_void ,  arg :  * c_void ,  sp :  * mut  uint )  { 
184+ fn  initialize_call_frame ( regs :  & mut  Registers ,  fptr :  * c_void ,  arg :  * c_void ,  sp :  * mut  uint )  { 
167185    let  sp = mut_offset ( sp,  -1 ) ; 
168186
169187    // The final return address. 0 indicates the bottom of the stack 
0 commit comments