osal_rs/freertos/
semaphore.rs

1/***************************************************************************
2 *
3 * osal-rs
4 * Copyright (C) 2023/2026 Antonio Salsi <passy.linux@zresa.it>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 *
18 ***************************************************************************/
19
20use core::fmt::{Debug, Display};
21use core::ops::Deref;
22use core::ptr::null_mut;
23
24use super::ffi::{SemaphoreHandle, pdFAIL, pdFALSE};
25use super::system::System;
26use super::types::{BaseType, UBaseType};
27use crate::traits::{SemaphoreFn, SystemFn, ToTick};
28use crate::utils::{Error, Result, OsalRsBool};
29use crate::{vSemaphoreDelete, xSemaphoreCreateCounting, xSemaphoreGive, xSemaphoreGiveFromISR, xSemaphoreTake, xSemaphoreTakeFromISR};
30
31pub struct Semaphore (SemaphoreHandle);
32
33unsafe impl Send for Semaphore {}
34unsafe impl Sync for Semaphore {}
35
36
37impl SemaphoreFn for Semaphore {
38    fn new(max_count: UBaseType, initial_count: UBaseType) -> Result<Self> {
39        let handle = xSemaphoreCreateCounting!(max_count, initial_count);
40        if handle.is_null() {
41            Err(Error::OutOfMemory)
42        } else {
43            Ok(Self (handle))
44        }
45    }
46
47    fn new_with_count(initial_count: UBaseType) -> Result<Self> {
48        let handle = xSemaphoreCreateCounting!(UBaseType::MAX, initial_count);
49        if handle.is_null() {
50            Err(Error::OutOfMemory)
51        } else {
52            Ok(Self (handle))
53        }
54    }
55
56    fn wait(&self, ticks_to_wait: impl ToTick) -> OsalRsBool {
57        if xSemaphoreTake!(self.0, ticks_to_wait.to_ticks()) != pdFAIL {
58            OsalRsBool::True
59        } else {
60            OsalRsBool::False
61        }
62    }
63
64    fn wait_from_isr(&self) -> OsalRsBool {
65        let mut higher_priority_task_woken: BaseType = pdFALSE;
66        if xSemaphoreTakeFromISR!(self.0, &mut higher_priority_task_woken) != pdFAIL {
67
68            System::yield_from_isr(higher_priority_task_woken);
69
70            OsalRsBool::True
71        } else {
72
73            OsalRsBool::False
74        }
75    }
76    
77    fn signal(&self) -> OsalRsBool {
78        if xSemaphoreGive!(self.0) != pdFAIL {
79            OsalRsBool::True
80        } else {
81            OsalRsBool::False
82        }
83    }
84    
85    fn signal_from_isr(&self) -> OsalRsBool {
86        let mut higher_priority_task_woken: BaseType = pdFALSE;
87        if xSemaphoreGiveFromISR!(self.0, &mut higher_priority_task_woken) != pdFAIL {
88            
89            System::yield_from_isr(higher_priority_task_woken);
90
91            OsalRsBool::True
92        } else {
93            OsalRsBool::False
94        }
95    }
96    
97    fn delete(&mut self) {
98        vSemaphoreDelete!(self.0);
99        self.0 = null_mut();
100    }
101
102
103}
104
105
106impl Drop for Semaphore {
107    fn drop(&mut self) {
108        if self.0.is_null() {
109            return;
110        }
111        self.delete();
112    }
113}
114
115impl Deref for Semaphore {
116    type Target = SemaphoreHandle;
117
118    fn deref(&self) -> &Self::Target {
119        &self.0
120    }
121}
122
123impl Debug for Semaphore {
124    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
125        f.debug_struct("Semaphore")
126            .field("handle", &self.0)
127            .finish()
128    }
129}
130
131impl Display for Semaphore {
132    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
133        write!(f, "Semaphore {{ handle: {:?} }}", self.0)
134    }
135}