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