1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#[cfg(test)]
use stdarch_test::assert_instr;

extern "C" {
    #[link_name = "llvm.wasm.memory.atomic.wait32"]
    fn llvm_atomic_wait_i32(ptr: *mut i32, exp: i32, timeout: i64) -> i32;
    #[link_name = "llvm.wasm.memory.atomic.wait64"]
    fn llvm_atomic_wait_i64(ptr: *mut i64, exp: i64, timeout: i64) -> i32;
    #[link_name = "llvm.wasm.memory.atomic.notify"]
    fn llvm_atomic_notify(ptr: *mut i32, cnt: i32) -> i32;
}

/// 对应 wasm 的 [`memory.atomic.wait32` 指令][instr]
///
/// 如果 `ptr` 指向的内存等于 `expression` (原子执行此操作),则调用此函数时,它将阻塞当前线程。
///
///
/// 参数 `timeout_ns` 是调用线程将被阻塞的最大纳秒数 (如果被阻塞的话)。
/// 如果超时为负,则调用线程将永远被阻塞。
///
/// 一旦调用线程被阻塞,调用线程只能通过调用 `wake` 内部函数来唤醒。
/// 一旦线程被阻塞,在 `ptr` 后面更改内存将不会唤醒线程。
///
/// # 返回值
///
/// * 0 - 表示线程被阻塞,然后被唤醒
/// * 1-`ptr` 的加载值与 `expression` 不匹配,线程未阻塞
/// * 2 - 线程被阻塞,但超时已过期。
///
/// [instr]: https://webassembly.github.io/threads/core/syntax/instructions.html#syntax-instr-atomic-memory
///
///
///
///
#[inline]
#[cfg_attr(test, assert_instr(memory.atomic.wait32))]
#[target_feature(enable = "atomics")]
#[doc(alias("memory.atomic.wait32"))]
pub unsafe fn memory_atomic_wait32(ptr: *mut i32, expression: i32, timeout_ns: i64) -> i32 {
    llvm_atomic_wait_i32(ptr, expression, timeout_ns)
}

/// 对应 wasm 的 [`memory.atomic.wait64` 指令][instr]
///
/// 如果 `ptr` 指向的内存等于 `expression` (原子执行此操作),则调用此函数时,它将阻塞当前线程。
///
///
/// 参数 `timeout_ns` 是调用线程将被阻塞的最大纳秒数 (如果被阻塞的话)。
/// 如果超时为负,则调用线程将永远被阻塞。
///
/// 一旦调用线程被阻塞,调用线程只能通过调用 `wake` 内部函数来唤醒。
/// 一旦线程被阻塞,在 `ptr` 后面更改内存将不会唤醒线程。
///
/// # 返回值
///
/// * 0 - 表示线程被阻塞,然后被唤醒
/// * 1-`ptr` 的加载值与 `expression` 不匹配,线程未阻塞
/// * 2 - 线程被阻塞,但超时已过期。
///
/// [instr]: https://webassembly.github.io/threads/core/syntax/instructions.html#syntax-instr-atomic-memory
///
///
///
///
#[inline]
#[cfg_attr(test, assert_instr(memory.atomic.wait64))]
#[target_feature(enable = "atomics")]
#[doc(alias("memory.atomic.wait64"))]
pub unsafe fn memory_atomic_wait64(ptr: *mut i64, expression: i64, timeout_ns: i64) -> i32 {
    llvm_atomic_wait_i64(ptr, expression, timeout_ns)
}

/// 对应 wasm 的 [`memory.atomic.notify` 指令][instr]
///
/// 该函数将通知 `ptr` 指示的地址上阻塞的多个线程。
/// 先前被上述 `i32_atomic_wait` 和 `i64_atomic_wait` 函数阻塞的线程将被唤醒。
///
///
/// `waiters` 参数指示应唤醒的等待者数量 (最大值)。
/// 如果值为零,则不会唤醒任何等待者。
///
/// # 返回值
///
/// 返回实际被通知的等待者的数量。
///
/// [instr]: https://webassembly.github.io/threads/core/syntax/instructions.html#syntax-instr-atomic-memory
#[inline]
#[cfg_attr(test, assert_instr(memory.atomic.notify))]
#[target_feature(enable = "atomics")]
#[doc(alias("memory.atomic.notify"))]
pub unsafe fn memory_atomic_notify(ptr: *mut i32, waiters: u32) -> u32 {
    llvm_atomic_notify(ptr, waiters as i32) as u32
}