1 use crate::rt::execution;
2 use crate::rt::object::Operation;
3 use crate::rt::vv::VersionVec;
4 
5 use std::{any::Any, collections::HashMap, fmt, ops};
6 pub(crate) struct Thread {
7     pub id: Id,
8 
9     /// If the thread is runnable, blocked, or terminated.
10     pub state: State,
11 
12     /// True if the thread is in a critical section
13     pub critical: bool,
14 
15     /// The operation the thread is about to take
16     pub(super) operation: Option<Operation>,
17 
18     /// Tracks observed causality
19     pub causality: VersionVec,
20 
21     /// Tracks DPOR relations
22     pub dpor_vv: VersionVec,
23 
24     /// Version at which the thread last yielded
25     pub last_yield: Option<u16>,
26 
27     /// Number of times the thread yielded
28     pub yield_count: usize,
29 
30     locals: LocalMap,
31 }
32 
33 #[derive(Debug)]
34 pub(crate) struct Set {
35     /// Unique execution identifier
36     execution_id: execution::Id,
37 
38     /// Set of threads
39     threads: Vec<Thread>,
40 
41     /// Currently scheduled thread.
42     ///
43     /// `None` signifies that no thread is runnable.
44     active: Option<usize>,
45 
46     /// Sequential consistency causality. All sequentially consistent operations
47     /// synchronize with this causality.
48     pub seq_cst_causality: VersionVec,
49 }
50 
51 #[derive(Eq, PartialEq, Hash, Copy, Clone)]
52 pub(crate) struct Id {
53     execution_id: execution::Id,
54     id: usize,
55 }
56 
57 impl Id {
58     /// Returns an integer ID unique to this current execution (for use in
59     /// [`thread::ThreadId`]'s `Debug` impl)
public_id(&self) -> usize60     pub(crate) fn public_id(&self) -> usize {
61         self.id
62     }
63 }
64 
65 #[derive(Debug, Clone, Copy)]
66 pub(crate) enum State {
67     Runnable,
68     Blocked,
69     Yield,
70     Terminated,
71 }
72 
73 type LocalMap = HashMap<LocalKeyId, LocalValue>;
74 
75 #[derive(Eq, PartialEq, Hash, Copy, Clone)]
76 struct LocalKeyId(usize);
77 
78 struct LocalValue(Option<Box<dyn Any>>);
79 
80 impl Thread {
new(id: Id) -> Thread81     fn new(id: Id) -> Thread {
82         Thread {
83             id,
84             state: State::Runnable,
85             critical: false,
86             operation: None,
87             causality: VersionVec::new(),
88             dpor_vv: VersionVec::new(),
89             last_yield: None,
90             yield_count: 0,
91             locals: HashMap::new(),
92         }
93     }
94 
is_runnable(&self) -> bool95     pub(crate) fn is_runnable(&self) -> bool {
96         match self.state {
97             State::Runnable => true,
98             _ => false,
99         }
100     }
101 
set_runnable(&mut self)102     pub(crate) fn set_runnable(&mut self) {
103         self.state = State::Runnable;
104     }
105 
set_blocked(&mut self)106     pub(crate) fn set_blocked(&mut self) {
107         self.state = State::Blocked;
108     }
109 
is_blocked(&self) -> bool110     pub(crate) fn is_blocked(&self) -> bool {
111         match self.state {
112             State::Blocked => true,
113             _ => false,
114         }
115     }
116 
is_yield(&self) -> bool117     pub(crate) fn is_yield(&self) -> bool {
118         match self.state {
119             State::Yield => true,
120             _ => false,
121         }
122     }
123 
set_yield(&mut self)124     pub(crate) fn set_yield(&mut self) {
125         self.state = State::Yield;
126         self.last_yield = Some(self.causality[self.id]);
127         self.yield_count += 1;
128     }
129 
is_terminated(&self) -> bool130     pub(crate) fn is_terminated(&self) -> bool {
131         match self.state {
132             State::Terminated => true,
133             _ => false,
134         }
135     }
136 
set_terminated(&mut self)137     pub(crate) fn set_terminated(&mut self) {
138         self.state = State::Terminated;
139     }
140 
drop_locals(&mut self) -> Box<dyn std::any::Any>141     pub(crate) fn drop_locals(&mut self) -> Box<dyn std::any::Any> {
142         let mut locals = Vec::with_capacity(self.locals.len());
143 
144         // run the Drop impls of any mock thread-locals created by this thread.
145         for (_, local) in &mut self.locals {
146             locals.push(local.0.take());
147         }
148 
149         Box::new(locals)
150     }
151 
unpark(&mut self, unparker: &Thread)152     pub(crate) fn unpark(&mut self, unparker: &Thread) {
153         self.causality.join(&unparker.causality);
154 
155         if self.is_blocked() || self.is_yield() {
156             self.set_runnable();
157         }
158     }
159 }
160 
161 impl fmt::Debug for Thread {
162     // Manual debug impl is necessary because thread locals are represented as
163     // `dyn Any`, which does not implement `Debug`.
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result164     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165         f.debug_struct("Thread")
166             .field("id", &self.id)
167             .field("state", &self.state)
168             .field("critical", &self.critical)
169             .field("operation", &self.operation)
170             .field("causality", &self.causality)
171             .field("dpor_vv", &self.dpor_vv)
172             .field("last_yield", &self.last_yield)
173             .field("yield_count", &self.yield_count)
174             .field("locals", &format_args!("[..locals..]"))
175             .finish()
176     }
177 }
178 
179 impl Set {
180     /// Create an empty thread set.
181     ///
182     /// The set may contain up to `max_threads` threads.
new(execution_id: execution::Id, max_threads: usize) -> Set183     pub(crate) fn new(execution_id: execution::Id, max_threads: usize) -> Set {
184         let mut threads = Vec::with_capacity(max_threads);
185 
186         // Push initial thread
187         threads.push(Thread::new(Id::new(execution_id, 0)));
188 
189         Set {
190             execution_id,
191             threads,
192             active: Some(0),
193             seq_cst_causality: VersionVec::new(),
194         }
195     }
196 
execution_id(&self) -> execution::Id197     pub(crate) fn execution_id(&self) -> execution::Id {
198         self.execution_id
199     }
200 
201     /// Create a new thread
new_thread(&mut self) -> Id202     pub(crate) fn new_thread(&mut self) -> Id {
203         assert!(self.threads.len() < self.max());
204 
205         // Get the identifier for the thread about to be created
206         let id = self.threads.len();
207 
208         // Push the thread onto the stack
209         self.threads
210             .push(Thread::new(Id::new(self.execution_id, id)));
211 
212         Id::new(self.execution_id, id)
213     }
214 
max(&self) -> usize215     pub(crate) fn max(&self) -> usize {
216         self.threads.capacity()
217     }
218 
is_active(&self) -> bool219     pub(crate) fn is_active(&self) -> bool {
220         self.active.is_some()
221     }
222 
active_id(&self) -> Id223     pub(crate) fn active_id(&self) -> Id {
224         Id::new(self.execution_id, self.active.unwrap())
225     }
226 
active(&self) -> &Thread227     pub(crate) fn active(&self) -> &Thread {
228         &self.threads[self.active.unwrap()]
229     }
230 
set_active(&mut self, id: Option<Id>)231     pub(crate) fn set_active(&mut self, id: Option<Id>) {
232         self.active = id.map(Id::as_usize);
233     }
234 
active_mut(&mut self) -> &mut Thread235     pub(crate) fn active_mut(&mut self) -> &mut Thread {
236         &mut self.threads[self.active.unwrap()]
237     }
238 
239     /// Get the active thread and second thread
active2_mut(&mut self, other: Id) -> (&mut Thread, &mut Thread)240     pub(crate) fn active2_mut(&mut self, other: Id) -> (&mut Thread, &mut Thread) {
241         let active = self.active.unwrap();
242         let other = other.id;
243 
244         if other >= active {
245             let (l, r) = self.threads.split_at_mut(other);
246 
247             (&mut l[active], &mut r[0])
248         } else {
249             let (l, r) = self.threads.split_at_mut(active);
250 
251             (&mut r[0], &mut l[other])
252         }
253     }
254 
active_causality_inc(&mut self)255     pub(crate) fn active_causality_inc(&mut self) {
256         let id = self.active_id();
257         self.active_mut().causality.inc(id);
258     }
259 
active_atomic_version(&self) -> u16260     pub(crate) fn active_atomic_version(&self) -> u16 {
261         let id = self.active_id();
262         self.active().causality[id]
263     }
264 
unpark(&mut self, id: Id)265     pub(crate) fn unpark(&mut self, id: Id) {
266         if id == self.active_id() {
267             return;
268         }
269 
270         // Synchronize memory
271         let (active, th) = self.active2_mut(id);
272         th.unpark(&active);
273     }
274 
275     /// Insert a point of sequential consistency
seq_cst(&mut self)276     pub(crate) fn seq_cst(&mut self) {
277         // The previous implementation of sequential consistency was incorrect.
278         // As a quick fix, just disable it. This may fail to model correct code,
279         // but will not silently allow bugs.
280     }
281 
clear(&mut self, execution_id: execution::Id)282     pub(crate) fn clear(&mut self, execution_id: execution::Id) {
283         self.threads.clear();
284         self.threads.push(Thread::new(Id::new(execution_id, 0)));
285 
286         self.execution_id = execution_id;
287         self.active = Some(0);
288         self.seq_cst_causality = VersionVec::new();
289     }
290 
iter<'a>(&'a self) -> impl ExactSizeIterator<Item = (Id, &'a Thread)> + 'a291     pub(crate) fn iter<'a>(&'a self) -> impl ExactSizeIterator<Item = (Id, &'a Thread)> + 'a {
292         let execution_id = self.execution_id;
293         self.threads
294             .iter()
295             .enumerate()
296             .map(move |(id, thread)| (Id::new(execution_id, id), thread))
297     }
298 
iter_mut<'a>( &'a mut self, ) -> impl ExactSizeIterator<Item = (Id, &'a mut Thread)>299     pub(crate) fn iter_mut<'a>(
300         &'a mut self,
301     ) -> impl ExactSizeIterator<Item = (Id, &'a mut Thread)> {
302         let execution_id = self.execution_id;
303         self.threads
304             .iter_mut()
305             .enumerate()
306             .map(move |(id, thread)| (Id::new(execution_id, id), thread))
307     }
308 
309     /// Split the set of threads into the active thread and an iterator of all
310     /// other threads.
split_active(&mut self) -> (&mut Thread, impl Iterator<Item = &mut Thread>)311     pub(crate) fn split_active(&mut self) -> (&mut Thread, impl Iterator<Item = &mut Thread>) {
312         let active = self.active.unwrap();
313         let (one, two) = self.threads.split_at_mut(active);
314         let (active, two) = two.split_at_mut(1);
315 
316         let iter = one.iter_mut().chain(two.iter_mut());
317 
318         (&mut active[0], iter)
319     }
320 
local<T: 'static>( &mut self, key: &'static crate::thread::LocalKey<T>, ) -> Option<Result<&T, AccessError>>321     pub(crate) fn local<T: 'static>(
322         &mut self,
323         key: &'static crate::thread::LocalKey<T>,
324     ) -> Option<Result<&T, AccessError>> {
325         self.active_mut()
326             .locals
327             .get(&LocalKeyId::new(key))
328             .map(|local_value| local_value.get())
329     }
330 
local_init<T: 'static>( &mut self, key: &'static crate::thread::LocalKey<T>, value: T, )331     pub(crate) fn local_init<T: 'static>(
332         &mut self,
333         key: &'static crate::thread::LocalKey<T>,
334         value: T,
335     ) {
336         assert!(self
337             .active_mut()
338             .locals
339             .insert(LocalKeyId::new(key), LocalValue::new(value))
340             .is_none())
341     }
342 }
343 
344 impl ops::Index<Id> for Set {
345     type Output = Thread;
346 
index(&self, index: Id) -> &Thread347     fn index(&self, index: Id) -> &Thread {
348         &self.threads[index.id]
349     }
350 }
351 
352 impl ops::IndexMut<Id> for Set {
index_mut(&mut self, index: Id) -> &mut Thread353     fn index_mut(&mut self, index: Id) -> &mut Thread {
354         &mut self.threads[index.id]
355     }
356 }
357 
358 impl Id {
new(execution_id: execution::Id, id: usize) -> Id359     pub(crate) fn new(execution_id: execution::Id, id: usize) -> Id {
360         Id { execution_id, id }
361     }
362 
as_usize(self) -> usize363     pub(crate) fn as_usize(self) -> usize {
364         self.id
365     }
366 }
367 
368 impl From<Id> for usize {
from(src: Id) -> usize369     fn from(src: Id) -> usize {
370         src.id
371     }
372 }
373 
374 impl fmt::Display for Id {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result375     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
376         self.id.fmt(fmt)
377     }
378 }
379 
380 impl fmt::Debug for Id {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result381     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
382         write!(fmt, "Id({})", self.id)
383     }
384 }
385 
386 impl LocalKeyId {
new<T>(key: &'static crate::thread::LocalKey<T>) -> Self387     fn new<T>(key: &'static crate::thread::LocalKey<T>) -> Self {
388         Self(key as *const _ as usize)
389     }
390 }
391 
392 impl LocalValue {
new<T: 'static>(value: T) -> Self393     fn new<T: 'static>(value: T) -> Self {
394         Self(Some(Box::new(value)))
395     }
396 
get<T: 'static>(&self) -> Result<&T, AccessError>397     fn get<T: 'static>(&self) -> Result<&T, AccessError> {
398         self.0
399             .as_ref()
400             .ok_or(AccessError { _private: () })
401             .map(|val| {
402                 val.downcast_ref::<T>()
403                     .expect("local value must downcast to expected type")
404             })
405     }
406 }
407 
408 /// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with).
409 pub struct AccessError {
410     _private: (),
411 }
412 
413 impl fmt::Debug for AccessError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result414     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
415         f.debug_struct("AccessError").finish()
416     }
417 }
418 
419 impl fmt::Display for AccessError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result420     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
421         fmt::Display::fmt("already destroyed", f)
422     }
423 }
424