Skip to content

Commit 79f3307

Browse files
committed
Update comments, rearrange code
1 parent ac8c98d commit 79f3307

File tree

6 files changed

+131
-143
lines changed

6 files changed

+131
-143
lines changed

src/machine.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ pub struct Evaluator<'tcx> {
217217
pub(crate) time_anchor: Instant,
218218

219219
/// Cached `TyLayout`s for primitive data types that are commonly used inside Miri.
220+
/// FIXME: Search through the rest of the codebase for more layout_of() calls that
221+
/// could be cached here.
220222
primitive_layouts: PrimitiveLayouts<'tcx>,
221223
}
222224

src/shims/foreign_items/posix.rs

Lines changed: 38 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -233,113 +233,101 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
233233
this.write_null(dest)?;
234234
}
235235

236-
// Better error for attempts to create a thread
237-
"pthread_create" => {
238-
throw_unsup_format!("Miri does not support threading");
239-
}
240-
241-
// Miscellaneous
242-
"isatty" => {
243-
let _fd = this.read_scalar(args[0])?.to_i32()?;
244-
// "returns 1 if fd is an open file descriptor referring to a terminal; otherwise 0 is returned, and errno is set to indicate the error"
245-
// FIXME: we just say nothing is a terminal.
246-
let enotty = this.eval_libc("ENOTTY")?;
247-
this.set_last_error(enotty)?;
248-
this.write_null(dest)?;
249-
}
250-
"pthread_atfork" => {
251-
let _prepare = this.read_scalar(args[0])?.not_undef()?;
252-
let _parent = this.read_scalar(args[1])?.not_undef()?;
253-
let _child = this.read_scalar(args[1])?.not_undef()?;
254-
// We do not support forking, so there is nothing to do here.
255-
this.write_null(dest)?;
256-
}
257-
258-
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
259-
// These shims are enabled only when the caller is in the standard library.
260-
| "pthread_attr_init"
261-
| "pthread_attr_destroy"
262-
| "pthread_self"
263-
| "pthread_attr_setstacksize"
264-
| "pthread_condattr_init"
265-
| "pthread_condattr_setclock"
266-
| "pthread_cond_init"
267-
| "pthread_condattr_destroy"
268-
| "pthread_cond_destroy" if this.frame().instance.to_string().starts_with("std::sys::unix::")
269-
=> {
270-
this.write_null(dest)?;
271-
}
272-
236+
// Synchronization primitives
273237
"pthread_mutexattr_init" => {
274238
let result = this.pthread_mutexattr_init(args[0])?;
275239
this.write_scalar(Scalar::from_i32(result), dest)?;
276240
}
277-
278241
"pthread_mutexattr_settype" => {
279242
let result = this.pthread_mutexattr_settype(args[0], args[1])?;
280243
this.write_scalar(Scalar::from_i32(result), dest)?;
281244
}
282-
283245
"pthread_mutexattr_destroy" => {
284246
let result = this.pthread_mutexattr_destroy(args[0])?;
285247
this.write_scalar(Scalar::from_i32(result), dest)?;
286248
}
287-
288249
"pthread_mutex_init" => {
289250
let result = this.pthread_mutex_init(args[0], args[1])?;
290251
this.write_scalar(Scalar::from_i32(result), dest)?;
291252
}
292-
293253
"pthread_mutex_lock" => {
294254
let result = this.pthread_mutex_lock(args[0])?;
295255
this.write_scalar(Scalar::from_i32(result), dest)?;
296256
}
297-
298257
"pthread_mutex_trylock" => {
299258
let result = this.pthread_mutex_trylock(args[0])?;
300259
this.write_scalar(Scalar::from_i32(result), dest)?;
301260
}
302-
303261
"pthread_mutex_unlock" => {
304262
let result = this.pthread_mutex_unlock(args[0])?;
305263
this.write_scalar(Scalar::from_i32(result), dest)?;
306264
}
307-
308265
"pthread_mutex_destroy" => {
309266
let result = this.pthread_mutex_destroy(args[0])?;
310267
this.write_scalar(Scalar::from_i32(result), dest)?;
311268
}
312-
313269
"pthread_rwlock_rdlock" => {
314270
let result = this.pthread_rwlock_rdlock(args[0])?;
315271
this.write_scalar(Scalar::from_i32(result), dest)?;
316272
}
317-
318273
"pthread_rwlock_tryrdlock" => {
319274
let result = this.pthread_rwlock_tryrdlock(args[0])?;
320275
this.write_scalar(Scalar::from_i32(result), dest)?;
321276
}
322-
323277
"pthread_rwlock_wrlock" => {
324278
let result = this.pthread_rwlock_wrlock(args[0])?;
325279
this.write_scalar(Scalar::from_i32(result), dest)?;
326280
}
327-
328281
"pthread_rwlock_trywrlock" => {
329282
let result = this.pthread_rwlock_trywrlock(args[0])?;
330283
this.write_scalar(Scalar::from_i32(result), dest)?;
331284
}
332-
333285
"pthread_rwlock_unlock" => {
334286
let result = this.pthread_rwlock_unlock(args[0])?;
335287
this.write_scalar(Scalar::from_i32(result), dest)?;
336288
}
337-
338289
"pthread_rwlock_destroy" => {
339290
let result = this.pthread_rwlock_destroy(args[0])?;
340291
this.write_scalar(Scalar::from_i32(result), dest)?;
341292
}
342293

294+
// Better error for attempts to create a thread
295+
"pthread_create" => {
296+
throw_unsup_format!("Miri does not support threading");
297+
}
298+
299+
// Miscellaneous
300+
"isatty" => {
301+
let _fd = this.read_scalar(args[0])?.to_i32()?;
302+
// "returns 1 if fd is an open file descriptor referring to a terminal; otherwise 0 is returned, and errno is set to indicate the error"
303+
// FIXME: we just say nothing is a terminal.
304+
let enotty = this.eval_libc("ENOTTY")?;
305+
this.set_last_error(enotty)?;
306+
this.write_null(dest)?;
307+
}
308+
"pthread_atfork" => {
309+
let _prepare = this.read_scalar(args[0])?.not_undef()?;
310+
let _parent = this.read_scalar(args[1])?.not_undef()?;
311+
let _child = this.read_scalar(args[1])?.not_undef()?;
312+
// We do not support forking, so there is nothing to do here.
313+
this.write_null(dest)?;
314+
}
315+
316+
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
317+
// These shims are enabled only when the caller is in the standard library.
318+
| "pthread_attr_init"
319+
| "pthread_attr_destroy"
320+
| "pthread_self"
321+
| "pthread_attr_setstacksize"
322+
| "pthread_condattr_init"
323+
| "pthread_condattr_setclock"
324+
| "pthread_cond_init"
325+
| "pthread_condattr_destroy"
326+
| "pthread_cond_destroy" if this.frame().instance.to_string().starts_with("std::sys::unix::")
327+
=> {
328+
this.write_null(dest)?;
329+
}
330+
343331
| "signal"
344332
| "sigaction"
345333
| "sigaltstack"

src/shims/sync.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ fn assert_ptr_target_min_size<'mir, 'tcx: 'mir>(
2020

2121
// pthread_mutexattr_t is either 4 or 8 bytes, depending on the platform.
2222

23-
// Our chosen memory layout: store an i32 in the first four bytes equal to the
24-
// corresponding libc mutex kind constant (i.e. PTHREAD_MUTEX_NORMAL)
23+
// Our chosen memory layout for emulation (does not have to match the platform layout!):
24+
// store an i32 in the first four bytes equal to the corresponding libc mutex kind constant
25+
// (e.g. PTHREAD_MUTEX_NORMAL).
2526

2627
fn mutexattr_get_kind<'mir, 'tcx: 'mir>(
2728
ecx: &MiriEvalContext<'mir, 'tcx>,
@@ -48,7 +49,7 @@ fn mutexattr_set_kind<'mir, 'tcx: 'mir>(
4849

4950
// pthread_mutex_t is between 24 and 48 bytes, depending on the platform.
5051

51-
// Our chosen memory layout:
52+
// Our chosen memory layout for the emulated mutex (does not have to match the platform layout!):
5253
// bytes 0-3: reserved for signature on macOS
5354
// (need to avoid this because it is set by static initializer macros)
5455
// bytes 4-7: count of how many times this mutex has been locked, as a u32
@@ -117,7 +118,7 @@ fn mutex_set_kind<'mir, 'tcx: 'mir>(
117118

118119
// pthread_rwlock_t is between 32 and 56 bytes, depending on the platform.
119120

120-
// Our chosen memory layout:
121+
// Our chosen memory layout for the emulated rwlock (does not have to match the platform layout!):
121122
// bytes 0-3: reserved for signature on macOS
122123
// (need to avoid this because it is set by static initializer macros)
123124
// bytes 4-7: reader count, as a u32

tests/run-pass/libc.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,92 @@ fn test_posix_fadvise() {
4242
assert_eq!(result, 0);
4343
}
4444

45+
fn test_mutex_libc_init_recursive() {
46+
unsafe {
47+
let mut attr: libc::pthread_mutexattr_t = std::mem::zeroed();
48+
assert_eq!(libc::pthread_mutexattr_init(&mut attr as *mut _), 0);
49+
assert_eq!(libc::pthread_mutexattr_settype(&mut attr as *mut _, libc::PTHREAD_MUTEX_RECURSIVE), 0);
50+
let mut mutex: libc::pthread_mutex_t = std::mem::zeroed();
51+
assert_eq!(libc::pthread_mutex_init(&mut mutex as *mut _, &mut attr as *mut _), 0);
52+
assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
53+
assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), 0);
54+
assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
55+
assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
56+
assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), 0);
57+
assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
58+
assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
59+
assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
60+
assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), libc::EPERM);
61+
assert_eq!(libc::pthread_mutex_destroy(&mut mutex as *mut _), 0);
62+
assert_eq!(libc::pthread_mutexattr_destroy(&mut attr as *mut _), 0);
63+
}
64+
}
65+
66+
fn test_mutex_libc_init_normal() {
67+
unsafe {
68+
let mut mutexattr: libc::pthread_mutexattr_t = std::mem::zeroed();
69+
assert_eq!(libc::pthread_mutexattr_settype(&mut mutexattr as *mut _, libc::PTHREAD_MUTEX_NORMAL), 0);
70+
let mut mutex: libc::pthread_mutex_t = std::mem::zeroed();
71+
assert_eq!(libc::pthread_mutex_init(&mut mutex as *mut _, &mutexattr as *const _), 0);
72+
assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
73+
assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), libc::EBUSY);
74+
assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
75+
assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), 0);
76+
assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
77+
assert_eq!(libc::pthread_mutex_destroy(&mut mutex as *mut _), 0);
78+
}
79+
}
80+
81+
// Only linux provides PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
82+
// libc for macOS just has the default PTHREAD_MUTEX_INITIALIZER.
83+
#[cfg(target_os = "linux")]
84+
fn test_mutex_libc_static_initializer_recursive() {
85+
let mutex = std::cell::UnsafeCell::new(libc::PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
86+
unsafe {
87+
assert_eq!(libc::pthread_mutex_lock(mutex.get()), 0);
88+
assert_eq!(libc::pthread_mutex_trylock(mutex.get()), 0);
89+
assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0);
90+
assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0);
91+
assert_eq!(libc::pthread_mutex_trylock(mutex.get()), 0);
92+
assert_eq!(libc::pthread_mutex_lock(mutex.get()), 0);
93+
assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0);
94+
assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0);
95+
assert_eq!(libc::pthread_mutex_unlock(mutex.get()), libc::EPERM);
96+
assert_eq!(libc::pthread_mutex_destroy(mutex.get()), 0);
97+
}
98+
}
99+
100+
// Testing the behavior of std::sync::RwLock does not fully exercise the pthread rwlock shims, we
101+
// need to go a layer deeper and test the behavior of the libc functions, because
102+
// std::sys::unix::rwlock::RWLock itself keeps track of write_locked and num_readers.
103+
fn test_rwlock_libc_static_initializer() {
104+
let rw = std::cell::UnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER);
105+
unsafe {
106+
assert_eq!(libc::pthread_rwlock_rdlock(rw.get()), 0);
107+
assert_eq!(libc::pthread_rwlock_rdlock(rw.get()), 0);
108+
assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
109+
assert_eq!(libc::pthread_rwlock_tryrdlock(rw.get()), 0);
110+
assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
111+
assert_eq!(libc::pthread_rwlock_trywrlock(rw.get()), libc::EBUSY);
112+
assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
113+
114+
assert_eq!(libc::pthread_rwlock_wrlock(rw.get()), 0);
115+
assert_eq!(libc::pthread_rwlock_tryrdlock(rw.get()), libc::EBUSY);
116+
assert_eq!(libc::pthread_rwlock_trywrlock(rw.get()), libc::EBUSY);
117+
assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
118+
119+
assert_eq!(libc::pthread_rwlock_destroy(rw.get()), 0);
120+
}
121+
}
122+
45123
fn main() {
46124
#[cfg(not(target_os = "macos"))]
47125
test_posix_fadvise();
126+
127+
test_mutex_libc_init_recursive();
128+
test_mutex_libc_init_normal();
129+
test_rwlock_libc_static_initializer();
130+
131+
#[cfg(target_os = "linux")]
132+
test_mutex_libc_static_initializer_recursive();
48133
}

tests/run-pass/reentrant-println.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::fmt::{Display, Error, Formatter};
22

33
// This test case exercises std::sys_common::remutex::ReentrantMutex
4-
// by calling println!() from inside fmt
4+
// by calling println!() from inside fmt.
55

66
struct InterruptingCow;
77

0 commit comments

Comments
 (0)