~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/rust/kernel/sync/condvar.rs

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /rust/kernel/sync/condvar.rs (Version linux-6.12-rc7) and /rust/kernel/sync/condvar.rs (Version linux-5.7.19)


  1 // SPDX-License-Identifier: GPL-2.0               
  2                                                   
  3 //! A condition variable.                         
  4 //!                                               
  5 //! This module allows Rust code to use the ke    
  6 //! variable.                                     
  7                                                   
  8 use super::{lock::Backend, lock::Guard, LockCl    
  9 use crate::{                                      
 10     init::PinInit,                                
 11     pin_init,                                     
 12     str::CStr,                                    
 13     task::{MAX_SCHEDULE_TIMEOUT, TASK_INTERRUP    
 14     time::Jiffies,                                
 15     types::Opaque,                                
 16 };                                                
 17 use core::ffi::{c_int, c_long};                   
 18 use core::marker::PhantomPinned;                  
 19 use core::ptr;                                    
 20 use macros::pin_data;                             
 21                                                   
 22 /// Creates a [`CondVar`] initialiser with the    
 23 #[macro_export]                                   
 24 macro_rules! new_condvar {                        
 25     ($($name:literal)?) => {                      
 26         $crate::sync::CondVar::new($crate::opt    
 27     };                                            
 28 }                                                 
 29 pub use new_condvar;                              
 30                                                   
 31 /// A conditional variable.                       
 32 ///                                               
 33 /// Exposes the kernel's [`struct wait_queue_h    
 34 /// atomically release the given lock and go t    
 35 /// it wakes up when notified by another threa    
 36 /// [`CondVar::notify_all`]) or because the th    
 37 /// spuriously.                                   
 38 ///                                               
 39 /// Instances of [`CondVar`] need a lock class    
 40 /// instances is with the [`pin_init`](crate::    
 41 ///                                               
 42 /// # Examples                                    
 43 ///                                               
 44 /// The following is an example of using a con    
 45 ///                                               
 46 /// ```                                           
 47 /// use kernel::sync::{new_condvar, new_mutex,    
 48 ///                                               
 49 /// #[pin_data]                                   
 50 /// pub struct Example {                          
 51 ///     #[pin]                                    
 52 ///     value: Mutex<u32>,                        
 53 ///                                               
 54 ///     #[pin]                                    
 55 ///     value_changed: CondVar,                   
 56 /// }                                             
 57 ///                                               
 58 /// /// Waits for `e.value` to become `v`.        
 59 /// fn wait_for_value(e: &Example, v: u32) {      
 60 ///     let mut guard = e.value.lock();           
 61 ///     while *guard != v {                       
 62 ///         e.value_changed.wait(&mut guard);     
 63 ///     }                                         
 64 /// }                                             
 65 ///                                               
 66 /// /// Increments `e.value` and notifies all     
 67 /// fn increment(e: &Example) {                   
 68 ///     *e.value.lock() += 1;                     
 69 ///     e.value_changed.notify_all();             
 70 /// }                                             
 71 ///                                               
 72 /// /// Allocates a new boxed `Example`.          
 73 /// fn new_example() -> Result<Pin<Box<Example    
 74 ///     Box::pin_init(pin_init!(Example {         
 75 ///         value <- new_mutex!(0),               
 76 ///         value_changed <- new_condvar!(),      
 77 ///     }), GFP_KERNEL)                           
 78 /// }                                             
 79 /// ```                                           
 80 ///                                               
 81 /// [`struct wait_queue_head`]: srctree/includ    
 82 #[pin_data]                                       
 83 pub struct CondVar {                              
 84     #[pin]                                        
 85     pub(crate) wait_queue_head: Opaque<binding    
 86                                                   
 87     /// A condvar needs to be pinned because i    
 88     /// self-referential, so it cannot be safe    
 89     ///                                           
 90     /// [`struct list_head`]: srctree/include/    
 91     #[pin]                                        
 92     _pin: PhantomPinned,                          
 93 }                                                 
 94                                                   
 95 // SAFETY: `CondVar` only uses a `struct wait_    
 96 #[allow(clippy::non_send_fields_in_send_ty)]      
 97 unsafe impl Send for CondVar {}                   
 98                                                   
 99 // SAFETY: `CondVar` only uses a `struct wait_    
100 // concurrently.                                  
101 unsafe impl Sync for CondVar {}                   
102                                                   
103 impl CondVar {                                    
104     /// Constructs a new condvar initialiser.     
105     pub fn new(name: &'static CStr, key: &'sta    
106         pin_init!(Self {                          
107             _pin: PhantomPinned,                  
108             // SAFETY: `slot` is valid while t    
109             // static lifetimes so they live i    
110             wait_queue_head <- Opaque::ffi_ini    
111                 bindings::__init_waitqueue_hea    
112             }),                                   
113         })                                        
114     }                                             
115                                                   
116     fn wait_internal<T: ?Sized, B: Backend>(      
117         &self,                                    
118         wait_state: c_int,                        
119         guard: &mut Guard<'_, T, B>,              
120         timeout_in_jiffies: c_long,               
121     ) -> c_long {                                 
122         let wait = Opaque::<bindings::wait_que    
123                                                   
124         // SAFETY: `wait` points to valid memo    
125         unsafe { bindings::init_wait(wait.get(    
126                                                   
127         // SAFETY: Both `wait` and `wait_queue    
128         unsafe {                                  
129             bindings::prepare_to_wait_exclusiv    
130         };                                        
131                                                   
132         // SAFETY: Switches to another thread.    
133         let ret = guard.do_unlocked(|| unsafe     
134                                                   
135         // SAFETY: Both `wait` and `wait_queue    
136         unsafe { bindings::finish_wait(self.wa    
137                                                   
138         ret                                       
139     }                                             
140                                                   
141     /// Releases the lock and waits for a noti    
142     ///                                           
143     /// Atomically releases the given lock (wh    
144     /// thread to sleep, reacquiring the lock     
145     /// [`CondVar::notify_one`] or [`CondVar::    
146     /// spuriously.                               
147     pub fn wait<T: ?Sized, B: Backend>(&self,     
148         self.wait_internal(TASK_UNINTERRUPTIBL    
149     }                                             
150                                                   
151     /// Releases the lock and waits for a noti    
152     ///                                           
153     /// Similar to [`CondVar::wait`], except t    
154     /// wake up due to signals. It may also wa    
155     ///                                           
156     /// Returns whether there is a signal pend    
157     #[must_use = "wait_interruptible returns i    
158     pub fn wait_interruptible<T: ?Sized, B: Ba    
159         self.wait_internal(TASK_INTERRUPTIBLE,    
160         crate::current!().signal_pending()        
161     }                                             
162                                                   
163     /// Releases the lock and waits for a noti    
164     ///                                           
165     /// Atomically releases the given lock (wh    
166     /// thread to sleep. It wakes up when noti    
167     /// [`CondVar::notify_all`], or when a tim    
168     #[must_use = "wait_interruptible_timeout r    
169     pub fn wait_interruptible_timeout<T: ?Size    
170         &self,                                    
171         guard: &mut Guard<'_, T, B>,              
172         jiffies: Jiffies,                         
173     ) -> CondVarTimeoutResult {                   
174         let jiffies = jiffies.try_into().unwra    
175         let res = self.wait_internal(TASK_INTE    
176                                                   
177         match (res as Jiffies, crate::current!    
178             (jiffies, true) => CondVarTimeoutR    
179             (0, false) => CondVarTimeoutResult    
180             (jiffies, false) => CondVarTimeout    
181         }                                         
182     }                                             
183                                                   
184     /// Calls the kernel function to notify th    
185     fn notify(&self, count: c_int) {              
186         // SAFETY: `wait_queue_head` points to    
187         unsafe {                                  
188             bindings::__wake_up(                  
189                 self.wait_queue_head.get(),       
190                 TASK_NORMAL,                      
191                 count,                            
192                 ptr::null_mut(),                  
193             )                                     
194         };                                        
195     }                                             
196                                                   
197     /// Calls the kernel function to notify on    
198     ///                                           
199     /// This method behaves like `notify_one`,    
200     /// current thread is about to go to sleep    
201     /// CPU.                                      
202     pub fn notify_sync(&self) {                   
203         // SAFETY: `wait_queue_head` points to    
204         unsafe { bindings::__wake_up_sync(self    
205     }                                             
206                                                   
207     /// Wakes a single waiter up, if any.         
208     ///                                           
209     /// This is not 'sticky' in the sense that    
210     /// completely (as opposed to automaticall    
211     pub fn notify_one(&self) {                    
212         self.notify(1);                           
213     }                                             
214                                                   
215     /// Wakes all waiters up, if any.             
216     ///                                           
217     /// This is not 'sticky' in the sense that    
218     /// completely (as opposed to automaticall    
219     pub fn notify_all(&self) {                    
220         self.notify(0);                           
221     }                                             
222 }                                                 
223                                                   
224 /// The return type of `wait_timeout`.            
225 pub enum CondVarTimeoutResult {                   
226     /// The timeout was reached.                  
227     Timeout,                                      
228     /// Somebody woke us up.                      
229     Woken {                                       
230         /// Remaining sleep duration.             
231         jiffies: Jiffies,                         
232     },                                            
233     /// A signal occurred.                        
234     Signal {                                      
235         /// Remaining sleep duration.             
236         jiffies: Jiffies,                         
237     },                                            
238 }                                                 
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php