]> git.lizzy.rs Git - rust.git/blob - tests/run-pass/libc.rs
Move prctl test to the same file as other libc tests.
[rust.git] / tests / run-pass / libc.rs
1 // ignore-windows: No libc on Windows
2 // compile-flags: -Zmiri-disable-isolation
3
4 #![feature(rustc_private)]
5
6 extern crate libc;
7
8 #[cfg(target_os = "linux")]
9 fn tmp() -> std::path::PathBuf {
10     std::env::var("MIRI_TEMP").map(std::path::PathBuf::from).unwrap_or_else(|_| std::env::temp_dir())
11 }
12
13 #[cfg(target_os = "linux")]
14 fn test_posix_fadvise() {
15     use std::convert::TryInto;
16     use std::fs::{remove_file, File};
17     use std::io::Write;
18     use std::os::unix::io::AsRawFd;
19
20     let path = tmp().join("miri_test_libc.txt");
21     // Cleanup before test
22     remove_file(&path).ok();
23
24     // Set up an open file
25     let mut file = File::create(&path).unwrap();
26     let bytes = b"Hello, World!\n";
27     file.write(bytes).unwrap();
28
29     // Test calling posix_fadvise on a file.
30     let result = unsafe {
31         libc::posix_fadvise(
32             file.as_raw_fd(),
33             0,
34             bytes.len().try_into().unwrap(),
35             libc::POSIX_FADV_DONTNEED,
36         )
37     };
38     drop(file);
39     remove_file(&path).unwrap();
40     assert_eq!(result, 0);
41 }
42
43 fn test_mutex_libc_init_recursive() {
44     unsafe {
45         let mut attr: libc::pthread_mutexattr_t = std::mem::zeroed();
46         assert_eq!(libc::pthread_mutexattr_init(&mut attr as *mut _), 0);
47         assert_eq!(libc::pthread_mutexattr_settype(&mut attr as *mut _, libc::PTHREAD_MUTEX_RECURSIVE), 0);
48         let mut mutex: libc::pthread_mutex_t = std::mem::zeroed();
49         assert_eq!(libc::pthread_mutex_init(&mut mutex as *mut _, &mut attr as *mut _), 0);
50         assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
51         assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), 0);
52         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
53         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
54         assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), 0);
55         assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
56         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
57         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
58         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), libc::EPERM);
59         assert_eq!(libc::pthread_mutex_destroy(&mut mutex as *mut _), 0);
60         assert_eq!(libc::pthread_mutexattr_destroy(&mut attr as *mut _), 0);
61     }
62 }
63
64 fn test_mutex_libc_init_normal() {
65     unsafe {
66         let mut mutexattr: libc::pthread_mutexattr_t = std::mem::zeroed();
67         assert_eq!(libc::pthread_mutexattr_settype(&mut mutexattr as *mut _, 0x12345678), libc::EINVAL);
68         assert_eq!(libc::pthread_mutexattr_settype(&mut mutexattr as *mut _, libc::PTHREAD_MUTEX_NORMAL), 0);
69         let mut mutex: libc::pthread_mutex_t = std::mem::zeroed();
70         assert_eq!(libc::pthread_mutex_init(&mut mutex as *mut _, &mutexattr as *const _), 0);
71         assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
72         assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), libc::EBUSY);
73         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
74         assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), 0);
75         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
76         assert_eq!(libc::pthread_mutex_destroy(&mut mutex as *mut _), 0);
77     }
78 }
79
80 fn test_mutex_libc_init_errorcheck() {
81     unsafe {
82         let mut mutexattr: libc::pthread_mutexattr_t = std::mem::zeroed();
83         assert_eq!(libc::pthread_mutexattr_settype(&mut mutexattr as *mut _, libc::PTHREAD_MUTEX_ERRORCHECK), 0);
84         let mut mutex: libc::pthread_mutex_t = std::mem::zeroed();
85         assert_eq!(libc::pthread_mutex_init(&mut mutex as *mut _, &mutexattr as *const _), 0);
86         assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
87         assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), libc::EBUSY);
88         assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), libc::EDEADLK);
89         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
90         assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), 0);
91         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
92         assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), libc::EPERM);
93         assert_eq!(libc::pthread_mutex_destroy(&mut mutex as *mut _), 0);
94     }
95 }
96
97 // Only linux provides PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
98 // libc for macOS just has the default PTHREAD_MUTEX_INITIALIZER.
99 #[cfg(target_os = "linux")]
100 fn test_mutex_libc_static_initializer_recursive() {
101     let mutex = std::cell::UnsafeCell::new(libc::PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
102     unsafe {
103         assert_eq!(libc::pthread_mutex_lock(mutex.get()), 0);
104         assert_eq!(libc::pthread_mutex_trylock(mutex.get()), 0);
105         assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0);
106         assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0);
107         assert_eq!(libc::pthread_mutex_trylock(mutex.get()), 0);
108         assert_eq!(libc::pthread_mutex_lock(mutex.get()), 0);
109         assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0);
110         assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0);
111         assert_eq!(libc::pthread_mutex_unlock(mutex.get()), libc::EPERM);
112         assert_eq!(libc::pthread_mutex_destroy(mutex.get()), 0);
113     }
114 }
115
116 // Testing the behavior of std::sync::RwLock does not fully exercise the pthread rwlock shims, we
117 // need to go a layer deeper and test the behavior of the libc functions, because
118 // std::sys::unix::rwlock::RWLock itself keeps track of write_locked and num_readers.
119 fn test_rwlock_libc_static_initializer() {
120     let rw = std::cell::UnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER);
121     unsafe {
122         assert_eq!(libc::pthread_rwlock_rdlock(rw.get()), 0);
123         assert_eq!(libc::pthread_rwlock_rdlock(rw.get()), 0);
124         assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
125         assert_eq!(libc::pthread_rwlock_tryrdlock(rw.get()), 0);
126         assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
127         assert_eq!(libc::pthread_rwlock_trywrlock(rw.get()), libc::EBUSY);
128         assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
129
130         assert_eq!(libc::pthread_rwlock_wrlock(rw.get()), 0);
131         assert_eq!(libc::pthread_rwlock_tryrdlock(rw.get()), libc::EBUSY);
132         assert_eq!(libc::pthread_rwlock_trywrlock(rw.get()), libc::EBUSY);
133         assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
134
135         assert_eq!(libc::pthread_rwlock_trywrlock(rw.get()), 0);
136         assert_eq!(libc::pthread_rwlock_tryrdlock(rw.get()), libc::EBUSY);
137         assert_eq!(libc::pthread_rwlock_trywrlock(rw.get()), libc::EBUSY);
138         assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
139
140         assert_eq!(libc::pthread_rwlock_destroy(rw.get()), 0);
141     }
142 }
143
144 /// Test whether the `prctl` shim correctly sets the thread name.
145 ///
146 /// Note: `prctl` exists only on Linux.
147 fn test_prctl_thread_name() {
148     use std::ffi::CString;
149     unsafe {
150         let thread_name = CString::new("hello").expect("CString::new failed");
151         assert_eq!(libc::prctl(libc::PR_SET_NAME, thread_name.as_ptr() as libc::c_long, 0 as libc::c_long, 0 as libc::c_long, 0 as libc::c_long), 0);
152         let mut buf = [0; 6];
153         assert_eq!(libc::prctl(libc::PR_GET_NAME, buf.as_mut_ptr() as libc::c_long, 0 as libc::c_long, 0 as libc::c_long, 0 as libc::c_long), 0);
154         assert_eq!(thread_name.as_bytes_with_nul(), buf);
155     }
156 }
157
158 fn main() {
159     #[cfg(target_os = "linux")]
160     test_posix_fadvise();
161
162     test_mutex_libc_init_recursive();
163     test_mutex_libc_init_normal();
164     test_mutex_libc_init_errorcheck();
165     test_rwlock_libc_static_initializer();
166
167     #[cfg(target_os = "linux")]
168     test_mutex_libc_static_initializer_recursive();
169
170     #[cfg(target_os = "linux")]
171     test_prctl_thread_name();
172 }