@@ -330,16 +330,72 @@ pub fn sys_recv(
330330 }
331331}
332332
333+ /// Bitmask representing notifications from the kernel
334+ ///
335+ /// The raw notification bits are available in [`get_raw_bits`], but
336+ /// higher-level functions make it harder to misuse notifications.
337+ #[ derive( Copy , Clone ) ]
338+ #[ repr( transparent) ]
339+ pub struct NotificationBits ( u32 ) ;
340+
341+ impl NotificationBits {
342+ /// Wraps a `u32`
343+ #[ inline]
344+ pub fn new ( bits : u32 ) -> Self {
345+ Self ( bits)
346+ }
347+
348+ /// Returns the raw notification bitmask
349+ #[ inline]
350+ pub fn get_raw_bits ( & self ) -> u32 {
351+ self . 0
352+ }
353+
354+ /// Checks if a condition signaled by notification bits holds
355+ ///
356+ /// The `cond` function should verify the underlying condition, but as an
357+ /// optimization, it will only be called if any bits set in mask are also
358+ /// set in `self`. This double-check is important, because notification bits
359+ /// can potentially be set even if the underlying condition is not true,
360+ /// such as with extra pended interrupts or inter-task use of `sys_post`.
361+ ///
362+ /// If you find yourself passing `|| true` here, see
363+ /// [`check_notification_mask`].
364+ #[ inline]
365+ pub fn check_condition < F : Fn ( ) -> bool > ( & self , mask : u32 , cond : F ) -> bool {
366+ self . check_notification_mask ( mask) && cond ( )
367+ }
368+
369+ /// Checks whether the given notification mask is active
370+ ///
371+ /// Notifications may occur spuriously; it is recommended to use
372+ /// `check_condition` instead, if there's a way to verify that the event has
373+ /// actually occurred.
374+ #[ inline]
375+ pub fn check_notification_mask ( & self , mask : u32 ) -> bool {
376+ ( self . 0 & mask) != 0
377+ }
378+
379+ /// Checks whether a timer appears to have gone off, because the timer_mask
380+ /// bit is set and the kernel timer is no longer set.
381+ ///
382+ /// `mask` must the notification bitmask for the timer notification
383+ #[ inline]
384+ pub fn has_timer_fired ( & self , timer_mask : u32 ) -> bool {
385+ self . check_condition ( timer_mask, || sys_get_timer ( ) . deadline . is_none ( ) )
386+ }
387+ }
388+
333389/// Convenience wrapper for `sys_recv` for the specific, but common, task of
334390/// listening for notifications. In this specific use, it has the advantage of
335391/// never panicking and not returning a `Result` that must be checked.
336392#[ inline( always) ]
337- pub fn sys_recv_notification ( notification_mask : u32 ) -> u32 {
393+ pub fn sys_recv_notification ( notification_mask : u32 ) -> NotificationBits {
338394 match sys_recv ( & mut [ ] , notification_mask, Some ( TaskId :: KERNEL ) ) {
339395 Ok ( rm) => {
340396 // The notification bits come back from the kernel in the operation
341397 // code field.
342- rm. operation
398+ NotificationBits ( rm. operation )
343399 }
344400 Err ( _) => {
345401 // Safety: Because we passed Some(TaskId::KERNEL), this is defined
0 commit comments