|
| 1 | +use crate::job::JobRef; |
1 | 2 | use crate::job::StackJob;
|
2 | 3 | use crate::latch::SpinLatch;
|
3 |
| -use crate::registry::{self, WorkerThread}; |
4 |
| -use crate::tlv::{self, Tlv}; |
| 4 | +use crate::registry; |
| 5 | +use crate::tlv; |
5 | 6 | use crate::unwind;
|
6 |
| -use std::any::Any; |
| 7 | +use std::sync::atomic::{AtomicBool, Ordering}; |
7 | 8 |
|
8 | 9 | use crate::FnContext;
|
9 | 10 |
|
@@ -135,68 +136,41 @@ where
|
135 | 136 | // Create virtual wrapper for task b; this all has to be
|
136 | 137 | // done here so that the stack frame can keep it all live
|
137 | 138 | // long enough.
|
138 |
| - let job_b = StackJob::new(tlv, call_b(oper_b), SpinLatch::new(worker_thread)); |
| 139 | + let job_b_started = AtomicBool::new(false); |
| 140 | + let job_b = StackJob::new( |
| 141 | + tlv, |
| 142 | + |migrated| { |
| 143 | + job_b_started.store(true, Ordering::Relaxed); |
| 144 | + call_b(oper_b)(migrated) |
| 145 | + }, |
| 146 | + SpinLatch::new(worker_thread), |
| 147 | + ); |
139 | 148 | let job_b_ref = job_b.as_job_ref();
|
140 | 149 | let job_b_id = job_b_ref.id();
|
141 | 150 | worker_thread.push(job_b_ref);
|
142 | 151 |
|
143 | 152 | // Execute task a; hopefully b gets stolen in the meantime.
|
144 | 153 | let status_a = unwind::halt_unwinding(call_a(oper_a, injected));
|
145 |
| - let result_a = match status_a { |
146 |
| - Ok(v) => v, |
147 |
| - Err(err) => join_recover_from_panic(worker_thread, &job_b.latch, err, tlv), |
148 |
| - }; |
149 |
| - |
150 |
| - // Now that task A has finished, try to pop job B from the |
151 |
| - // local stack. It may already have been popped by job A; it |
152 |
| - // may also have been stolen. There may also be some tasks |
153 |
| - // pushed on top of it in the stack, and we will have to pop |
154 |
| - // those off to get to it. |
155 |
| - while !job_b.latch.probe() { |
156 |
| - if let Some(job) = worker_thread.take_local_job() { |
157 |
| - if job_b_id == job.id() { |
158 |
| - // Found it! Let's run it. |
159 |
| - // |
160 |
| - // Note that this could panic, but it's ok if we unwind here. |
161 | 154 |
|
162 |
| - // Restore the TLV since we might have run some jobs overwriting it when waiting for job b. |
163 |
| - tlv::set(tlv); |
164 |
| - |
165 |
| - let result_b = job_b.run_inline(injected); |
166 |
| - return (result_a, result_b); |
167 |
| - } else { |
168 |
| - worker_thread.execute(job); |
169 |
| - } |
170 |
| - } else { |
171 |
| - // Local deque is empty. Time to steal from other |
172 |
| - // threads. |
173 |
| - worker_thread.wait_until(&job_b.latch); |
174 |
| - debug_assert!(job_b.latch.probe()); |
175 |
| - break; |
176 |
| - } |
177 |
| - } |
| 155 | + // Wait for job B or execute it if it's in the local queue. |
| 156 | + worker_thread.wait_for_jobs::<_, false>( |
| 157 | + &job_b.latch, |
| 158 | + || job_b_started.load(Ordering::Relaxed), |
| 159 | + |job| job.id() == job_b_id, |
| 160 | + |job: JobRef| { |
| 161 | + debug_assert_eq!(job.id(), job_b_id); |
| 162 | + job_b.run_inline(injected); |
| 163 | + }, |
| 164 | + ); |
178 | 165 |
|
179 | 166 | // Restore the TLV since we might have run some jobs overwriting it when waiting for job b.
|
180 | 167 | tlv::set(tlv);
|
181 | 168 |
|
| 169 | + let result_a = match status_a { |
| 170 | + Ok(v) => v, |
| 171 | + Err(err) => unwind::resume_unwinding(err), |
| 172 | + }; |
| 173 | + |
182 | 174 | (result_a, job_b.into_result())
|
183 | 175 | })
|
184 | 176 | }
|
185 |
| - |
186 |
| -/// If job A panics, we still cannot return until we are sure that job |
187 |
| -/// B is complete. This is because it may contain references into the |
188 |
| -/// enclosing stack frame(s). |
189 |
| -#[cold] // cold path |
190 |
| -unsafe fn join_recover_from_panic( |
191 |
| - worker_thread: &WorkerThread, |
192 |
| - job_b_latch: &SpinLatch<'_>, |
193 |
| - err: Box<dyn Any + Send>, |
194 |
| - tlv: Tlv, |
195 |
| -) -> ! { |
196 |
| - worker_thread.wait_until(job_b_latch); |
197 |
| - |
198 |
| - // Restore the TLV since we might have run some jobs overwriting it when waiting for job b. |
199 |
| - tlv::set(tlv); |
200 |
| - |
201 |
| - unwind::resume_unwinding(err) |
202 |
| -} |
0 commit comments