1 //@ignore-target-windows: No libc on Windows
4 test_mutex_libc_init_recursive();
5 test_mutex_libc_init_normal();
6 test_mutex_libc_init_errorcheck();
7 test_rwlock_libc_static_initializer();
9 #[cfg(any(target_os = "linux"))]
10 test_mutex_libc_static_initializer_recursive();
13 fn test_mutex_libc_init_recursive() {
15 let mut attr: libc::pthread_mutexattr_t = std::mem::zeroed();
16 assert_eq!(libc::pthread_mutexattr_init(&mut attr as *mut _), 0);
18 libc::pthread_mutexattr_settype(&mut attr as *mut _, libc::PTHREAD_MUTEX_RECURSIVE),
21 let mut mutex: libc::pthread_mutex_t = std::mem::zeroed();
22 assert_eq!(libc::pthread_mutex_init(&mut mutex as *mut _, &mut attr as *mut _), 0);
23 assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
24 assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), 0);
25 assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
26 assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
27 assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), 0);
28 assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
29 assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
30 assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
31 assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), libc::EPERM);
32 assert_eq!(libc::pthread_mutex_destroy(&mut mutex as *mut _), 0);
33 assert_eq!(libc::pthread_mutexattr_destroy(&mut attr as *mut _), 0);
37 fn test_mutex_libc_init_normal() {
39 let mut mutexattr: libc::pthread_mutexattr_t = std::mem::zeroed();
41 libc::pthread_mutexattr_settype(&mut mutexattr as *mut _, 0x12345678),
45 libc::pthread_mutexattr_settype(&mut mutexattr as *mut _, libc::PTHREAD_MUTEX_NORMAL),
48 let mut mutex: libc::pthread_mutex_t = std::mem::zeroed();
49 assert_eq!(libc::pthread_mutex_init(&mut mutex as *mut _, &mutexattr as *const _), 0);
50 assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
51 assert_eq!(libc::pthread_mutex_trylock(&mut mutex as *mut _), libc::EBUSY);
52 assert_eq!(libc::pthread_mutex_unlock(&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_destroy(&mut mutex as *mut _), 0);
59 fn test_mutex_libc_init_errorcheck() {
61 let mut mutexattr: libc::pthread_mutexattr_t = std::mem::zeroed();
63 libc::pthread_mutexattr_settype(
64 &mut mutexattr as *mut _,
65 libc::PTHREAD_MUTEX_ERRORCHECK,
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_lock(&mut mutex as *mut _), libc::EDEADLK);
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_unlock(&mut mutex as *mut _), libc::EPERM);
78 assert_eq!(libc::pthread_mutex_destroy(&mut mutex as *mut _), 0);
82 // Only linux provides PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
83 // libc for macOS just has the default PTHREAD_MUTEX_INITIALIZER.
84 #[cfg(target_os = "linux")]
85 fn test_mutex_libc_static_initializer_recursive() {
86 let mutex = std::cell::UnsafeCell::new(libc::PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
88 assert_eq!(libc::pthread_mutex_lock(mutex.get()), 0);
89 assert_eq!(libc::pthread_mutex_trylock(mutex.get()), 0);
90 assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0);
91 assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0);
92 assert_eq!(libc::pthread_mutex_trylock(mutex.get()), 0);
93 assert_eq!(libc::pthread_mutex_lock(mutex.get()), 0);
94 assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0);
95 assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0);
96 assert_eq!(libc::pthread_mutex_unlock(mutex.get()), libc::EPERM);
97 assert_eq!(libc::pthread_mutex_destroy(mutex.get()), 0);
101 // Testing the behavior of std::sync::RwLock does not fully exercise the pthread rwlock shims, we
102 // need to go a layer deeper and test the behavior of the libc functions, because
103 // std::sys::unix::rwlock::RWLock itself keeps track of write_locked and num_readers.
104 fn test_rwlock_libc_static_initializer() {
105 let rw = std::cell::UnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER);
107 assert_eq!(libc::pthread_rwlock_rdlock(rw.get()), 0);
108 assert_eq!(libc::pthread_rwlock_rdlock(rw.get()), 0);
109 assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
110 assert_eq!(libc::pthread_rwlock_tryrdlock(rw.get()), 0);
111 assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
112 assert_eq!(libc::pthread_rwlock_trywrlock(rw.get()), libc::EBUSY);
113 assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
115 assert_eq!(libc::pthread_rwlock_wrlock(rw.get()), 0);
116 assert_eq!(libc::pthread_rwlock_tryrdlock(rw.get()), libc::EBUSY);
117 assert_eq!(libc::pthread_rwlock_trywrlock(rw.get()), libc::EBUSY);
118 assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
120 assert_eq!(libc::pthread_rwlock_trywrlock(rw.get()), 0);
121 assert_eq!(libc::pthread_rwlock_tryrdlock(rw.get()), libc::EBUSY);
122 assert_eq!(libc::pthread_rwlock_trywrlock(rw.get()), libc::EBUSY);
123 assert_eq!(libc::pthread_rwlock_unlock(rw.get()), 0);
125 assert_eq!(libc::pthread_rwlock_destroy(rw.get()), 0);