+54
-18
src/header/pthread/cond.rs
+54
-18
src/header/pthread/cond.rs
···
1
+
// Used design from https://www.remlab.net/op/futex-condvar.shtml
2
+
1
3
use super::*;
4
+
5
+
use core::sync::atomic::{AtomicI32 as AtomicInt, Ordering};
2
6
3
7
// PTHREAD_COND_INITIALIZER
4
8
···
10
14
11
15
#[repr(C)]
12
16
pub struct Cond {
17
+
cur: AtomicInt,
18
+
prev: AtomicInt,
13
19
}
14
20
15
-
// #[no_mangle]
16
-
pub extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int {
17
-
todo!()
21
+
#[no_mangle]
22
+
pub unsafe extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int {
23
+
wake(cond, i32::MAX)
18
24
}
19
25
20
-
// #[no_mangle]
21
-
pub extern "C" fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> c_int {
22
-
todo!()
26
+
unsafe fn wake(cond: *mut pthread_cond_t, n: i32) -> c_int {
27
+
let cond: &pthread_cond_t = &*cond;
28
+
29
+
// This is formally correct as long as we don't have more than u32::MAX threads.
30
+
let prev = cond.prev.load(Ordering::SeqCst);
31
+
cond.cur.store(prev.wrapping_add(1), Ordering::SeqCst);
32
+
33
+
crate::sync::futex_wake(&cond.cur, n);
34
+
35
+
0
23
36
}
24
37
25
-
// #[no_mangle]
26
-
pub extern "C" fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) -> c_int {
27
-
todo!()
38
+
#[no_mangle]
39
+
pub unsafe extern "C" fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> c_int {
40
+
let _cond: &pthread_cond_t = &*cond;
41
+
0
28
42
}
29
43
30
-
// #[no_mangle]
31
-
pub extern "C" fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int {
32
-
todo!()
44
+
#[no_mangle]
45
+
pub unsafe extern "C" fn pthread_cond_init(cond: *mut pthread_cond_t, _attr: *const pthread_condattr_t) -> c_int {
46
+
cond.write(Cond {
47
+
cur: AtomicInt::new(0),
48
+
prev: AtomicInt::new(0),
49
+
});
50
+
0
33
51
}
34
52
35
-
// #[no_mangle]
36
-
pub extern "C" fn pthread_cond_timedwait(cond: *mut pthread_cond_t, mutex: *const pthread_mutex_t, timeout: *const timespec) -> c_int {
37
-
todo!()
53
+
#[no_mangle]
54
+
pub unsafe extern "C" fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int {
55
+
wake(cond, 1)
38
56
}
39
57
40
-
// #[no_mangle]
41
-
pub extern "C" fn pthread_cond_wait(cond: *mut pthread_cond_t, mutex: *const pthread_mutex_t) -> c_int {
42
-
todo!()
58
+
#[no_mangle]
59
+
pub unsafe extern "C" fn pthread_cond_timedwait(cond: *mut pthread_cond_t, mutex_ptr: *const pthread_mutex_t, timeout: *const timespec) -> c_int {
60
+
// TODO: Error checking for certain types (i.e. robust and errorcheck) of mutexes, e.g. if the
61
+
// mutex is not locked.
62
+
let cond: &pthread_cond_t = &*cond;
63
+
let mutex: &pthread_mutex_t = &*mutex_ptr;
64
+
let timeout: Option<×pec> = timeout.as_ref();
65
+
66
+
let current = cond.cur.load(Ordering::Relaxed);
67
+
cond.prev.store(current, Ordering::SeqCst);
68
+
69
+
mutex.inner.manual_unlock();
70
+
crate::sync::futex_wait(&cond.cur, current, timeout);
71
+
mutex.inner.manual_lock();
72
+
73
+
0
74
+
}
75
+
76
+
#[no_mangle]
77
+
pub unsafe extern "C" fn pthread_cond_wait(cond: *mut pthread_cond_t, mutex: *const pthread_mutex_t) -> c_int {
78
+
pthread_cond_timedwait(cond, mutex, core::ptr::null())
43
79
}
44
80
45
81
#[no_mangle]
+10
-24
src/header/pthread/mod.rs
+10
-24
src/header/pthread/mod.rs
···
9
9
pub const PTHREAD_BARRIER_SERIAL_THREAD: c_int = 1;
10
10
11
11
pub const PTHREAD_CANCEL_ASYNCHRONOUS: c_int = 0;
12
-
pub const PTHREAD_CANCEL_ENABLE: c_int = 0;
13
-
pub const PTHREAD_CANCEL_DEFERRED: c_int = 0;
14
-
pub const PTHREAD_CANCEL_DISABLE: c_int = 0;
12
+
pub const PTHREAD_CANCEL_ENABLE: c_int = 1;
13
+
pub const PTHREAD_CANCEL_DEFERRED: c_int = 2;
14
+
pub const PTHREAD_CANCEL_DISABLE: c_int = 3;
15
15
pub const PTHREAD_CANCELED: *mut c_void = core::ptr::null_mut();
16
16
17
17
pub const PTHREAD_CREATE_DETACHED: c_int = 0;
···
21
21
pub const PTHREAD_INHERIT_SCHED: c_int = 1;
22
22
23
23
pub const PTHREAD_MUTEX_DEFAULT: c_int = 0;
24
-
pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 0;
25
-
pub const PTHREAD_MUTEX_NORMAL: c_int = 0;
26
-
pub const PTHREAD_MUTEX_RECURSIVE: c_int = 0;
24
+
pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 1;
25
+
pub const PTHREAD_MUTEX_NORMAL: c_int = 2;
26
+
pub const PTHREAD_MUTEX_RECURSIVE: c_int = 3;
27
+
27
28
pub const PTHREAD_MUTEX_ROBUST: c_int = 0;
28
-
pub const PTHREAD_MUTEX_STALLED: c_int = 0;
29
+
pub const PTHREAD_MUTEX_STALLED: c_int = 1;
29
30
30
31
pub const PTHREAD_PRIO_INHERIT: c_int = 0;
31
32
···
102
103
todo!()
103
104
}
104
105
105
-
// #[no_mangle]
106
-
pub extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut c_void {
107
-
todo!()
108
-
}
106
+
pub mod tls;
107
+
pub use tls::*;
109
108
110
109
#[no_mangle]
111
110
pub unsafe extern "C" fn pthread_join(thread: pthread_t, retval: *mut *mut c_void) -> c_int {
···
116
115
}
117
116
Err(pthread::Errno(error)) => error,
118
117
}
119
-
}
120
-
121
-
// #[no_mangle]
122
-
pub extern "C" fn pthread_key_create(key: *mut pthread_key_t, destructor: extern "C" fn(value: *mut c_void)) -> c_int {
123
-
todo!()
124
-
}
125
-
126
-
// #[no_mangle]
127
-
pub extern "C" fn pthread_key_delete(key: pthread_key_t) -> c_int {
128
-
todo!()
129
118
}
130
119
131
120
pub mod mutex;
···
155
144
todo!();
156
145
}
157
146
pub extern "C" fn pthread_setschedprio(thread: pthread_t, prio: c_int) -> c_int {
158
-
todo!();
159
-
}
160
-
pub extern "C" fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int {
161
147
todo!();
162
148
}
163
149
+93
-35
src/header/pthread/mutex.rs
+93
-35
src/header/pthread/mutex.rs
···
1
1
use super::*;
2
2
3
+
use crate::header::errno::EBUSY;
4
+
3
5
// PTHREAD_MUTEX_INITIALIZER
4
6
5
7
#[repr(C)]
6
8
pub struct Mutex {
9
+
pub(crate) inner: crate::sync::Mutex<()>,
7
10
}
8
11
9
12
#[repr(C)]
10
13
pub struct MutexAttr {
14
+
prioceiling: c_int,
15
+
protocol: c_int,
16
+
pshared: c_int,
17
+
robust: c_int,
18
+
ty: c_int,
11
19
}
12
20
21
+
// #[no_mangle]
13
22
pub extern "C" fn pthread_mutex_consistent(mutex: *mut pthread_mutex_t) -> c_int {
14
23
todo!();
15
24
}
16
-
pub extern "C" fn pthread_mutex_destroy(mutex: *mut pthread_mutex_t) -> c_int {
17
-
todo!();
25
+
#[no_mangle]
26
+
pub unsafe extern "C" fn pthread_mutex_destroy(mutex: *mut pthread_mutex_t) -> c_int {
27
+
let _mutex: &pthread_mutex_t = &*mutex;
28
+
0
18
29
}
19
30
31
+
// #[no_mangle]
20
32
pub extern "C" fn pthread_mutex_getprioceiling(mutex: *const pthread_mutex_t, prioceiling: *mut c_int) -> c_int {
21
33
todo!();
22
34
}
23
35
24
-
pub extern "C" fn pthread_mutex_init(mutex: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t) -> c_int {
25
-
todo!();
36
+
#[no_mangle]
37
+
pub unsafe extern "C" fn pthread_mutex_init(mutex: *mut pthread_mutex_t, _attr: *const pthread_mutexattr_t) -> c_int {
38
+
// TODO: attr
39
+
mutex.write(Mutex {
40
+
inner: crate::sync::Mutex::new(()),
41
+
});
42
+
0
26
43
}
27
-
pub extern "C" fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> c_int {
28
-
todo!();
44
+
#[no_mangle]
45
+
pub unsafe extern "C" fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> c_int {
46
+
(&*mutex).inner.manual_lock();
47
+
48
+
0
29
49
}
30
50
51
+
// #[no_mangle]
31
52
pub extern "C" fn pthread_mutex_setprioceiling(mutex: *mut pthread_mutex_t, prioceiling: c_int, old_prioceiling: *mut c_int) -> c_int {
32
53
todo!();
33
54
}
34
55
56
+
// #[no_mangle]
35
57
pub extern "C" fn pthread_mutex_timedlock(mutex: *mut pthread_mutex_t, timespec: *const timespec) -> c_int {
36
58
todo!();
37
59
}
38
-
pub extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c_int {
39
-
todo!();
40
-
}
41
-
pub extern "C" fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> c_int {
42
-
todo!();
60
+
#[no_mangle]
61
+
pub unsafe extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c_int {
62
+
match (&*mutex).inner.manual_try_lock() {
63
+
Ok(_) => 0,
64
+
Err(_) => EBUSY,
65
+
}
43
66
}
44
-
pub extern "C" fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> c_int {
45
-
todo!();
67
+
#[no_mangle]
68
+
pub unsafe extern "C" fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> c_int {
69
+
(&*mutex).inner.manual_unlock();
70
+
0
46
71
}
47
72
48
-
pub extern "C" fn pthread_mutexattr_getprioceiling(attr: *const pthread_mutexattr_t, prioceiling: *mut c_int) -> c_int {
49
-
todo!();
73
+
#[no_mangle]
74
+
pub extern "C" fn pthread_mutexattr_destroy(_attr: *mut pthread_mutexattr_t) -> c_int {
75
+
0
50
76
}
51
77
78
+
#[no_mangle]
79
+
pub unsafe extern "C" fn pthread_mutexattr_getprioceiling(attr: *const pthread_mutexattr_t, prioceiling: *mut c_int) -> c_int {
80
+
prioceiling.write((*attr).prioceiling);
81
+
0
82
+
}
52
83
53
-
pub extern "C" fn pthread_mutexattr_getprotocol(attr: *const pthread_mutexattr_t, protocol: *mut c_int) -> c_int {
54
-
todo!();
84
+
#[no_mangle]
85
+
pub unsafe extern "C" fn pthread_mutexattr_getprotocol(attr: *const pthread_mutexattr_t, protocol: *mut c_int) -> c_int {
86
+
protocol.write((*attr).protocol);
87
+
0
55
88
}
56
89
57
-
pub extern "C" fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t, pshared: *mut c_int) -> c_int {
58
-
todo!();
90
+
#[no_mangle]
91
+
pub unsafe extern "C" fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t, pshared: *mut c_int) -> c_int {
92
+
pshared.write((*attr).pshared);
93
+
0
59
94
}
60
95
61
-
pub extern "C" fn pthread_mutexattr_getrobust(attr: *const pthread_mutexattr_t, robust: *mut c_int) -> c_int {
62
-
todo!();
96
+
#[no_mangle]
97
+
pub unsafe extern "C" fn pthread_mutexattr_getrobust(attr: *const pthread_mutexattr_t, robust: *mut c_int) -> c_int {
98
+
robust.write((*attr).robust);
99
+
0
63
100
}
64
-
pub extern "C" fn pthread_mutexattr_gettype(attr: *const pthread_mutexattr_t, ty: *mut c_int) -> c_int {
65
-
todo!();
101
+
#[no_mangle]
102
+
pub unsafe extern "C" fn pthread_mutexattr_gettype(attr: *const pthread_mutexattr_t, ty: *mut c_int) -> c_int {
103
+
ty.write((*attr).ty);
104
+
0
66
105
}
67
-
pub extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int {
68
-
todo!();
106
+
#[no_mangle]
107
+
pub unsafe extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int {
108
+
attr.write(MutexAttr {
109
+
robust: PTHREAD_MUTEX_STALLED,
110
+
pshared: PTHREAD_PROCESS_PRIVATE,
111
+
protocol: PTHREAD_PRIO_NONE,
112
+
// TODO
113
+
prioceiling: 0,
114
+
ty: PTHREAD_MUTEX_DEFAULT,
115
+
});
116
+
0
69
117
}
70
118
71
-
pub extern "C" fn pthread_mutexattr_setprioceiling(attr: *mut pthread_mutexattr_t, prioceiling: c_int) -> c_int {
72
-
todo!();
119
+
#[no_mangle]
120
+
pub unsafe extern "C" fn pthread_mutexattr_setprioceiling(attr: *mut pthread_mutexattr_t, prioceiling: c_int) -> c_int {
121
+
(*attr).prioceiling = prioceiling;
122
+
0
73
123
}
74
124
75
-
pub extern "C" fn pthread_mutexattr_setprotocol(attr: *mut pthread_mutexattr_t, protocol: c_int) -> c_int {
76
-
todo!();
125
+
#[no_mangle]
126
+
pub unsafe extern "C" fn pthread_mutexattr_setprotocol(attr: *mut pthread_mutexattr_t, protocol: c_int) -> c_int {
127
+
(*attr).protocol = protocol;
128
+
0
77
129
}
78
130
79
-
pub extern "C" fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, pshared: c_int) -> c_int {
80
-
todo!();
131
+
#[no_mangle]
132
+
pub unsafe extern "C" fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, pshared: c_int) -> c_int {
133
+
(*attr).pshared = pshared;
134
+
0
81
135
}
82
136
83
-
pub extern "C" fn pthread_mutexattr_setrobust(attr: *mut pthread_mutexattr_t, robust: c_int) -> c_int {
84
-
todo!();
137
+
#[no_mangle]
138
+
pub unsafe extern "C" fn pthread_mutexattr_setrobust(attr: *mut pthread_mutexattr_t, robust: c_int) -> c_int {
139
+
(*attr).robust = robust;
140
+
0
85
141
}
86
-
pub extern "C" fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, ty: c_int) -> c_int {
87
-
todo!();
142
+
#[no_mangle]
143
+
pub unsafe extern "C" fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, ty: c_int) -> c_int {
144
+
(*attr).ty = ty;
145
+
0
88
146
}
+2
-2
src/header/pthread/rwlock.rs
+2
-2
src/header/pthread/rwlock.rs
···
46
46
#[no_mangle]
47
47
pub unsafe extern "C" fn pthread_rwlock_timedrdlock(rwlock: *mut pthread_rwlock_t, timeout: *const timespec) -> c_int {
48
48
let rwlock: &pthread_rwlock_t = &*rwlock;
49
-
let timeout = NonNull::new(timeout as *mut _).map(|n| n.as_ref());
49
+
let timeout = timeout.as_ref();
50
50
51
51
loop {
52
52
if pthread_rwlock_tryrdlock(rwlock as *const _ as *mut _) == EBUSY {
···
58
58
#[no_mangle]
59
59
pub unsafe extern "C" fn pthread_rwlock_timedwrlock(rwlock: *mut pthread_rwlock_t, timeout: *const timespec) -> c_int {
60
60
let rwlock: &pthread_rwlock_t = &*rwlock;
61
-
let timeout = NonNull::new(timeout as *mut _).map(|n| n.as_ref());
61
+
let timeout = timeout.as_ref();
62
62
63
63
loop {
64
64
if pthread_rwlock_trywrlock(rwlock as *const _ as *mut _) == EBUSY {
+73
src/header/pthread/tls.rs
+73
src/header/pthread/tls.rs
···
1
+
use super::*;
2
+
3
+
// TODO: Hashmap?
4
+
use alloc::collections::BTreeMap;
5
+
6
+
use core::cell::{Cell, RefCell};
7
+
8
+
use crate::header::errno::EINVAL;
9
+
10
+
// TODO: What should this limit be?
11
+
pub const PTHREAD_KEYS_MAX: u32 = 4096 * 32;
12
+
13
+
#[no_mangle]
14
+
pub unsafe extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut c_void {
15
+
let Some(&Record { data, .. }) = DICT.borrow_mut().get(&key) else {
16
+
return core::ptr::null_mut();
17
+
};
18
+
19
+
data
20
+
}
21
+
#[no_mangle]
22
+
pub unsafe extern "C" fn pthread_key_create(key_ptr: *mut pthread_key_t, destructor: extern "C" fn(value: *mut c_void)) -> c_int {
23
+
let key = NEXTKEY.get();
24
+
NEXTKEY.set(key + 1);
25
+
26
+
// TODO
27
+
//if key >= PTHREAD_KEYS_MAX {
28
+
//}
29
+
30
+
DICT.borrow_mut().insert(key, Record {
31
+
data: core::ptr::null_mut(),
32
+
destructor,
33
+
});
34
+
35
+
key_ptr.write(key);
36
+
37
+
0
38
+
}
39
+
40
+
#[no_mangle]
41
+
pub unsafe extern "C" fn pthread_key_delete(key: pthread_key_t) -> c_int {
42
+
if DICT.borrow_mut().remove(&key).is_none() {
43
+
// We don't have to return anything, but it's not less expensive to ignore it.
44
+
return EINVAL;
45
+
}
46
+
47
+
0
48
+
}
49
+
50
+
#[no_mangle]
51
+
pub unsafe extern "C" fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int {
52
+
let mut guard = DICT.borrow_mut();
53
+
54
+
let Some(Record { data, .. }) = guard.get_mut(&key) else {
55
+
// We don't have to return anything, but it's not less expensive to ignore it.
56
+
return EINVAL;
57
+
};
58
+
59
+
*data = value as *mut c_void;
60
+
61
+
0
62
+
}
63
+
64
+
#[thread_local]
65
+
static DICT: RefCell<BTreeMap<u32, Record>> = RefCell::new(BTreeMap::new());
66
+
67
+
struct Record {
68
+
data: *mut c_void,
69
+
destructor: extern "C" fn(value: *mut c_void),
70
+
}
71
+
72
+
#[thread_local]
73
+
static NEXTKEY: Cell<u32> = Cell::new(1);
+2
-2
src/platform/linux/mod.rs
+2
-2
src/platform/linux/mod.rs
···
219
219
e(unsafe { syscall!(FTRUNCATE, fildes, length) }) as c_int
220
220
}
221
221
222
-
fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> c_int {
223
-
unsafe { syscall!(FUTEX, addr, op, val, val2, 0, 0) as c_int }
222
+
fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> Result<c_long, crate::pthread::Errno> {
223
+
e_raw(unsafe { syscall!(FUTEX, addr, op, val, val2, 0, 0)}).map(|r| r as c_long).map_err(|e| Errno(e as c_int))
224
224
}
225
225
226
226
fn futimens(fd: c_int, times: *const timespec) -> c_int {
+1
-1
src/platform/pal/mod.rs
+1
-1
src/platform/pal/mod.rs
···
73
73
74
74
fn ftruncate(fildes: c_int, length: off_t) -> c_int;
75
75
76
-
fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> c_int;
76
+
fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> Result<c_long, crate::pthread::Errno>;
77
77
78
78
fn futimens(fd: c_int, times: *const timespec) -> c_int;
79
79
-65
src/platform/pte.rs
-65
src/platform/pte.rs
···
51
51
52
52
static NEXT_KEY: AtomicU32 = AtomicU32::new(0);
53
53
54
-
unsafe fn locals<'a>() -> &'a mut BTreeMap<c_uint, *mut c_void> {
55
-
&mut *LOCALS.get()
56
-
}
57
-
58
54
#[no_mangle]
59
55
pub unsafe extern "C" fn pte_osThreadStart(handle: pte_osThreadHandle) -> pte_osResult {
60
56
let mut ret = PTE_OS_GENERAL_FAILURE;
···
250
246
Err(()) => PTE_OS_TIMEOUT,
251
247
}
252
248
}
253
-
254
-
#[no_mangle]
255
-
pub unsafe extern "C" fn pte_osSemaphoreCancellablePend(
256
-
handle: pte_osSemaphoreHandle,
257
-
pTimeout: *mut c_uint,
258
-
) -> pte_osResult {
259
-
//TODO: thread cancel
260
-
pte_osSemaphorePend(handle, pTimeout)
261
-
}
262
-
263
-
#[no_mangle]
264
-
pub unsafe extern "C" fn pte_osAtomicExchange(ptarg: *mut c_int, val: c_int) -> c_int {
265
-
intrinsics::atomic_xchg_seqcst(ptarg, val)
266
-
}
267
-
268
-
#[no_mangle]
269
-
pub unsafe extern "C" fn pte_osAtomicCompareExchange(
270
-
pdest: *mut c_int,
271
-
exchange: c_int,
272
-
comp: c_int,
273
-
) -> c_int {
274
-
intrinsics::atomic_cxchg_seqcst_seqcst(pdest, comp, exchange).0
275
-
}
276
-
277
-
#[no_mangle]
278
-
pub unsafe extern "C" fn pte_osAtomicExchangeAdd(pAppend: *mut c_int, value: c_int) -> c_int {
279
-
intrinsics::atomic_xadd_seqcst(pAppend, value)
280
-
}
281
-
282
-
#[no_mangle]
283
-
pub unsafe extern "C" fn pte_osAtomicDecrement(pdest: *mut c_int) -> c_int {
284
-
intrinsics::atomic_xadd_seqcst(pdest, -1) - 1
285
-
}
286
-
287
-
#[no_mangle]
288
-
pub unsafe extern "C" fn pte_osAtomicIncrement(pdest: *mut c_int) -> c_int {
289
-
intrinsics::atomic_xadd_seqcst(pdest, 1) + 1
290
-
}
291
-
292
-
#[no_mangle]
293
-
pub unsafe extern "C" fn pte_osTlsSetValue(index: c_uint, value: *mut c_void) -> pte_osResult {
294
-
locals().insert(index, value);
295
-
PTE_OS_OK
296
-
}
297
-
298
-
#[no_mangle]
299
-
pub unsafe extern "C" fn pte_osTlsGetValue(index: c_uint) -> *mut c_void {
300
-
locals().get_mut(&index).copied().unwrap_or(ptr::null_mut())
301
-
}
302
-
303
-
#[no_mangle]
304
-
pub unsafe extern "C" fn pte_osTlsAlloc(pKey: *mut c_uint) -> pte_osResult {
305
-
*pKey = NEXT_KEY.fetch_add(1, Ordering::Relaxed);
306
-
PTE_OS_OK
307
-
}
308
-
309
-
#[no_mangle]
310
-
pub unsafe extern "C" fn pte_osTlsFree(index: c_uint) -> pte_osResult {
311
-
// XXX free keys
312
-
PTE_OS_OK
313
-
}
+3
-3
src/platform/redox/mod.rs
+3
-3
src/platform/redox/mod.rs
···
333
333
e(syscall::ftruncate(fd as usize, len as usize)) as c_int
334
334
}
335
335
336
-
fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> c_int {
336
+
fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> Result<c_long, crate::pthread::Errno> {
337
337
match unsafe {
338
338
syscall::futex(
339
339
addr as *mut i32,
···
343
343
ptr::null_mut(),
344
344
)
345
345
} {
346
-
Ok(success) => success as c_int,
347
-
Err(err) => -(err.errno as c_int),
346
+
Ok(success) => Ok(success as c_long),
347
+
Err(err) => Err(crate::pthread::Errno(err.errno)),
348
348
}
349
349
}
350
350
+1
-1
src/platform/types.rs
+1
-1
src/platform/types.rs
···
82
82
pub type pthread_barrierattr_t = crate::header::pthread::barrier::BarrierAttr;
83
83
pub type pthread_cond_t = crate::header::pthread::cond::Cond;
84
84
pub type pthread_condattr_t = crate::header::pthread::cond::CondAttr;
85
-
pub type pthread_key_t = *mut c_void;
85
+
pub type pthread_key_t = u32;
86
86
pub type pthread_mutex_t = crate::header::pthread::mutex::Mutex;
87
87
pub type pthread_mutexattr_t = crate::header::pthread::mutex::MutexAttr;
88
88
pub type pthread_once_t = crate::header::pthread::once::Once;
+4
-2
src/pthread/mod.rs
+4
-2
src/pthread/mod.rs
···
48
48
use crate::header::pthread::attr::Attr;
49
49
50
50
/// Positive error codes (EINVAL, not -EINVAL).
51
-
#[derive(Debug)]
51
+
#[derive(Debug, Eq, PartialEq)]
52
+
// TODO: Move to a more generic place.
52
53
pub struct Errno(pub c_int);
53
54
54
55
#[derive(Clone, Copy)]
···
134
135
return Err(Errno(EAGAIN));
135
136
};
136
137
137
-
let _ = (&mut *synchronization_mutex).lock();
138
+
let _ = (&*synchronization_mutex).lock();
139
+
138
140
OS_TID_TO_PTHREAD.lock().insert(os_tid, ForceSendSync(ptr.cast()));
139
141
140
142
core::mem::forget(stack_raii);
+21
-18
src/sync/mod.rs
+21
-18
src/sync/mod.rs
···
28
28
Other,
29
29
}
30
30
31
+
pub unsafe fn futex_wake_ptr(ptr: *mut i32, n: i32) -> usize {
32
+
// TODO: unwrap_unchecked?
33
+
Sys::futex(ptr, FUTEX_WAKE, n, 0).unwrap() as usize
34
+
}
35
+
pub unsafe fn futex_wait_ptr(ptr: *mut i32, value: i32, timeout_opt: Option<×pec>) -> bool {
36
+
// TODO: unwrap_unchecked?
37
+
Sys::futex(ptr, FUTEX_WAIT, value, timeout_opt.map_or(0, |t| t as *const _ as usize)) == Ok(0)
38
+
}
39
+
pub fn futex_wake(atomic: &AtomicInt, n: i32) -> usize {
40
+
unsafe { futex_wake_ptr(atomic.as_mut_ptr(), n) }
41
+
}
42
+
pub fn futex_wait(atomic: &AtomicInt, value: i32, timeout_opt: Option<×pec>) -> bool {
43
+
unsafe { futex_wait_ptr(atomic.as_mut_ptr(), value, timeout_opt) }
44
+
}
45
+
31
46
/// Convenient wrapper around the "futex" system call for
32
47
/// synchronization implementations
33
48
#[repr(C)]
···
41
56
}
42
57
}
43
58
pub fn notify_one(&self) {
44
-
Sys::futex(
45
-
self.atomic.as_mut_ptr(),
46
-
FUTEX_WAKE,
47
-
1,
48
-
0,
49
-
);
59
+
futex_wake(&self.atomic, 1);
50
60
}
51
61
pub fn notify_all(&self) {
52
-
Sys::futex(
53
-
self.atomic.as_mut_ptr(),
54
-
FUTEX_WAKE,
55
-
c_int::max_value(),
56
-
0,
57
-
);
62
+
futex_wake(&self.atomic, i32::MAX);
58
63
}
59
64
pub fn wait_if(&self, value: c_int, timeout_opt: Option<×pec>) {
60
-
Sys::futex(
61
-
self.atomic.as_mut_ptr(),
62
-
FUTEX_WAIT,
63
-
value,
64
-
timeout_opt.map_or(0, |timeout| timeout as *const timespec as usize),
65
-
);
65
+
self.wait_if_raw(value, timeout_opt);
66
+
}
67
+
pub fn wait_if_raw(&self, value: c_int, timeout_opt: Option<×pec>) -> bool {
68
+
futex_wait(&self.atomic, value, timeout_opt)
66
69
}
67
70
68
71
/// A general way to efficiently wait for what might be a long time, using two closures: