@@ -106,51 +106,75 @@ impl VmData {
106106 }
107107
108108 pub fn init ( & self ) -> anyhow:: Result < ( ) > {
109- let mut status_guard = self . machine . write ( ) ;
110- match core:: mem:: replace ( & mut * status_guard, VmMachineState :: Switching ) {
109+ let next;
110+ let res;
111+ let next_state;
112+
113+ match self . replace_status ( VmMachineState :: Switching ) {
111114 VmMachineState :: Uninit ( uninit) => {
112- let init = match uninit. init ( self . downgrade ( ) ) {
113- Ok ( inited) => inited,
115+ match uninit. init ( self . downgrade ( ) ) {
116+ Ok ( inited) => {
117+ next_state = Some ( VMStatus :: Inited ) ;
118+ res = Ok ( ( ) ) ;
119+ next = VmMachineState :: Inited ( inited) ;
120+ }
114121 Err ( e) => {
115122 self . set_err ( RunError :: ExitWithError ( anyhow ! ( "{e}" ) ) ) ;
116- * status_guard = VmMachineState :: Stopped ;
117- self . status . store ( VMStatus :: Stopped ) ;
118- return Err ( e) ;
123+ next_state = Some ( VMStatus :: Stopped ) ;
124+ next = VmMachineState :: Stopped ;
125+ res = Err ( e) ;
119126 }
120127 } ;
121- * status_guard = VmMachineState :: Inited ( init) ;
122- self . status . store ( VMStatus :: Inited ) ;
123- Ok ( ( ) )
124128 }
125129 other => {
126- * status_guard = other;
127- Err ( anyhow:: anyhow!( "VM is not in Uninit state" ) )
130+ next = other;
131+ next_state = None ;
132+ res = Err ( anyhow:: anyhow!( "VM is not in Uninit state" ) ) ;
128133 }
129134 }
135+ self . replace_status ( next) ;
136+ if let Some ( status) = next_state {
137+ self . status . store ( status) ;
138+ }
139+ res
140+ }
141+
142+ fn replace_status ( & self , new_status : VmMachineState ) -> VmMachineState {
143+ let mut status_guard = self . machine . write ( ) ;
144+ core:: mem:: replace ( & mut * status_guard, new_status)
130145 }
131146
132147 pub fn start ( & self ) -> anyhow:: Result < ( ) > {
133148 let data = self . downgrade ( ) ;
134- let mut status_guard = self . machine . write ( ) ;
135- match core:: mem:: replace ( & mut * status_guard, VmMachineState :: Switching ) {
149+ let next_state;
150+ let res;
151+ let next = match self . replace_status ( VmMachineState :: Switching ) {
136152 VmMachineState :: Inited ( init) => match init. start ( data) {
137153 Ok ( running) => {
138- * status_guard = VmMachineState :: Running ( running ) ;
139- self . status . store ( VMStatus :: Running ) ;
140- Ok ( ( ) )
154+ next_state = Some ( VMStatus :: Running ) ;
155+ res = Ok ( ( ) ) ;
156+ VmMachineState :: Running ( running )
141157 }
142158 Err ( e) => {
143159 self . set_err ( RunError :: ExitWithError ( anyhow ! ( "{e}" ) ) ) ;
144- * status_guard = VmMachineState :: Stopped ;
145- self . status . store ( VMStatus :: Stopped ) ;
146- Err ( e)
160+
161+ next_state = Some ( VMStatus :: Stopped ) ;
162+ res = Err ( e) ;
163+ VmMachineState :: Stopped
147164 }
148165 } ,
149166 other => {
150- * status_guard = other;
151- Err ( anyhow:: anyhow!( "VM is not in Init state" ) )
167+ next_state = None ;
168+
169+ res = Err ( anyhow:: anyhow!( "VM is not in Init state" ) ) ;
170+ other
152171 }
172+ } ;
173+ self . replace_status ( next) ;
174+ if let Some ( status) = next_state {
175+ self . status . store ( status) ;
153176 }
177+ res
154178 }
155179
156180 pub fn downgrade ( & self ) -> VmDataWeak {
@@ -163,32 +187,46 @@ impl VmData {
163187 where
164188 F : FnOnce ( & VmMachineRunning ) -> R ,
165189 {
166- let status = self . machine . read ( ) ;
167- let running = match & * status {
168- VmMachineState :: Running ( running) => running,
169- _ => {
170- return Err ( RunError :: ExitWithError ( anyhow ! (
171- "VM is not in Running state"
172- ) ) ) ;
173- }
174- } ;
175- Ok ( f ( running) )
190+ loop {
191+ let status = self . machine . read ( ) ;
192+ let running = match & * status {
193+ VmMachineState :: Running ( running) => running,
194+ VmMachineState :: Switching => {
195+ drop ( status) ;
196+ std:: thread:: yield_now ( ) ;
197+ continue ;
198+ }
199+ _ => {
200+ return Err ( RunError :: ExitWithError ( anyhow ! (
201+ "VM is not in Running state"
202+ ) ) ) ;
203+ }
204+ } ;
205+ return Ok ( f ( running) ) ;
206+ }
176207 }
177208
178209 pub ( crate ) fn with_machine_running_mut < F , R > ( & self , f : F ) -> Result < R , RunError >
179210 where
180211 F : FnOnce ( & mut VmMachineRunning ) -> R ,
181212 {
182- let mut status = self . machine . write ( ) ;
183- let running = match & mut * status {
184- VmMachineState :: Running ( running) => running,
185- _ => {
186- return Err ( RunError :: ExitWithError ( anyhow ! (
187- "VM is not in Running state"
188- ) ) ) ;
189- }
190- } ;
191- Ok ( f ( running) )
213+ loop {
214+ let mut status = self . machine . write ( ) ;
215+ let running = match & mut * status {
216+ VmMachineState :: Running ( running) => running,
217+ VmMachineState :: Switching => {
218+ drop ( status) ;
219+ std:: thread:: yield_now ( ) ;
220+ continue ;
221+ }
222+ _ => {
223+ return Err ( RunError :: ExitWithError ( anyhow ! (
224+ "VM is not in Running state"
225+ ) ) ) ;
226+ }
227+ } ;
228+ return Ok ( f ( running) ) ;
229+ }
192230 }
193231}
194232
0 commit comments