summaryrefslogtreecommitdiffstats
path: root/library/std/src/sys/itron/wait_flag.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--library/std/src/sys/itron/wait_flag.rs72
1 files changed, 72 insertions, 0 deletions
diff --git a/library/std/src/sys/itron/wait_flag.rs b/library/std/src/sys/itron/wait_flag.rs
new file mode 100644
index 000000000..e432edd20
--- /dev/null
+++ b/library/std/src/sys/itron/wait_flag.rs
@@ -0,0 +1,72 @@
+use crate::mem::MaybeUninit;
+use crate::time::Duration;
+
+use super::{
+ abi,
+ error::{expect_success, fail},
+ time::with_tmos,
+};
+
+const CLEAR: abi::FLGPTN = 0;
+const RAISED: abi::FLGPTN = 1;
+
+/// A thread parking primitive that is not susceptible to race conditions,
+/// but provides no atomic ordering guarantees and allows only one `raise` per wait.
+pub struct WaitFlag {
+ flag: abi::ID,
+}
+
+impl WaitFlag {
+ /// Creates a new wait flag.
+ pub fn new() -> WaitFlag {
+ let flag = expect_success(
+ unsafe {
+ abi::acre_flg(&abi::T_CFLG {
+ flgatr: abi::TA_FIFO | abi::TA_WSGL | abi::TA_CLR,
+ iflgptn: CLEAR,
+ })
+ },
+ &"acre_flg",
+ );
+
+ WaitFlag { flag }
+ }
+
+ /// Wait for the wait flag to be raised.
+ pub fn wait(&self) {
+ let mut token = MaybeUninit::uninit();
+ expect_success(
+ unsafe { abi::wai_flg(self.flag, RAISED, abi::TWF_ORW, token.as_mut_ptr()) },
+ &"wai_flg",
+ );
+ }
+
+ /// Wait for the wait flag to be raised or the timeout to occur.
+ ///
+ /// Returns whether the flag was raised (`true`) or the operation timed out (`false`).
+ pub fn wait_timeout(&self, dur: Duration) -> bool {
+ let mut token = MaybeUninit::uninit();
+ let res = with_tmos(dur, |tmout| unsafe {
+ abi::twai_flg(self.flag, RAISED, abi::TWF_ORW, token.as_mut_ptr(), tmout)
+ });
+
+ match res {
+ abi::E_OK => true,
+ abi::E_TMOUT => false,
+ error => fail(error, &"twai_flg"),
+ }
+ }
+
+ /// Raise the wait flag.
+ ///
+ /// Calls to this function should be balanced with the number of successful waits.
+ pub fn raise(&self) {
+ expect_success(unsafe { abi::set_flg(self.flag, RAISED) }, &"set_flg");
+ }
+}
+
+impl Drop for WaitFlag {
+ fn drop(&mut self) {
+ expect_success(unsafe { abi::del_flg(self.flag) }, &"del_flg");
+ }
+}