unsafe fn inner<S: Syscalls, CONFIG: subscribe::Config>(
            driver_num: u32,
            subscribe_num: u32,
            upcall_fcn: Register,
            upcall_data: Register,
        ) -> Result<(), ErrorCode> {
            // Safety: syscall4's documentation indicates it can be used to call
            // Subscribe. These arguments follow TRD104. kernel_upcall has the
            // required signature. This function's preconditions mean that
            // upcall is a reference to an instance of U that will remain valid
            // until the 'scope lifetime is alive The existence of the
            // Subscribe<'scope, Self, DRIVER_NUM, SUBSCRIBE_NUM> guarantees
            // that if this Subscribe succeeds then the upcall will be cleaned
            // up before the 'scope lifetime ends, guaranteeing that upcall is
            // still alive when kernel_upcall is invoked.
            let [r0, r1, _, _] = unsafe {
                S::syscall4::<{ syscall_class::SUBSCRIBE }>([
                    driver_num.into(),
                    subscribe_num.into(),
                    upcall_fcn,
                    upcall_data,
                ])
            };

            let return_variant: ReturnVariant = r0.as_u32().into();
            // TRD 104 guarantees that Subscribe returns either Success with 2
            // U32 or Failure with 2 U32. We check the return variant by
            // comparing against Failure with 2 U32 for 2 reasons:
            //
            //   1. On RISC-V with compressed instructions, it generates smaller
            //      code. FAILURE_2_U32 has value 2, which can be loaded into a
            //      register with a single compressed instruction, whereas
            //      loading SUCCESS_2_U32 uses an uncompressed instruction.
            //   2. In the event the kernel malfuctions and returns a different
            //      return variant, the success path is actually safer than the
            //      failure path. The failure path assumes that r1 contains an
            //      ErrorCode, and produces UB if it has an out of range value.
            //      Incorrectly assuming the call succeeded will not generate
            //      unsoundness, and will likely lead to the application
            //      hanging.
            if return_variant == return_variant::FAILURE_2_U32 {
                // Safety: TRD 104 guarantees that if r0 is Failure with 2 U32,
                // then r1 will contain a valid error code. ErrorCode is
                // designed to be safely transmuted directly from a kernel error
                // code.
                return Err(unsafe { core::mem::transmute(r1.as_u32() as u16) });
            }

            // r0 indicates Success with 2 u32s. Confirm the null upcall was
            // returned, and it if wasn't then call the configured function.
            // We're relying on the optimizer to remove this branch if
            // returned_nonnull_upcall is a no-op.
            // Note: TRD 104 specifies that the null upcall has address 0,
            // not necessarily a null pointer.
            let returned_upcall: usize = r1.into();
            if returned_upcall != 0usize {
                CONFIG::returned_nonnull_upcall(driver_num, subscribe_num);
            }
            Ok(())
        }
// Inner function that does the majority of the work. This is not
// monomorphized over DRIVER_NUM and SUBSCRIBE_NUM to keep code size
// small.
//
// Safety: upcall_fcn must be kernel_upcall<S, IDS, U> and upcall_data
// must be a reference to an instance of U that will remain valid as
// long as the 'scope lifetime is alive. Can only be called if a
// Subscribe<'scope, S, driver_num, subscribe_num> exists.
Inner function that does the majority of the work. This is not
monomorphized over DRIVER_NUM and SUBSCRIBE_NUM to keep code size
small.

upcall_fcn must be kernel_upcall and upcall_data
must be a reference to an instance of U that will remain valid as
long as the 'scope lifetime is alive. Can only be called if a
Subscribe<'scope, S, driver_num, subscribe_num> exists.
Inner function that does the majority of the work . This is not monomorphized over DRIVER_NUM and SUBSCRIBE_NUM to keep code size small . upcall_fcn must be kernel_upcall and upcall_data must be a reference to an instance of U that will remain valid as long as the ' scope lifetime is alive . Can only be called if a Subscribe< ' scope S driver_num subscribe_num > exists .
unsafe fn inner<S: Syscalls, CONFIG: subscribe::Config>(
            driver_num: u32,
            subscribe_num: u32,
            upcall_fcn: Register,
            upcall_data: Register,
        ) -> Result<(), ErrorCode> {
            // Safety: syscall4's documentation indicates it can be used to call
            // Subscribe. These arguments follow TRD104. kernel_upcall has the
            // required signature. This function's preconditions mean that
            // upcall is a reference to an instance of U that will remain valid
            // until the 'scope lifetime is alive The existence of the
            // Subscribe<'scope, Self, DRIVER_NUM, SUBSCRIBE_NUM> guarantees
            // that if this Subscribe succeeds then the upcall will be cleaned
            // up before the 'scope lifetime ends, guaranteeing that upcall is
            // still alive when kernel_upcall is invoked.
            let [r0, r1, _, _] = unsafe {
                S::syscall4::<{ syscall_class::SUBSCRIBE }>([
                    driver_num.into(),
                    subscribe_num.into(),
                    upcall_fcn,
                    upcall_data,
                ])
            };
            let return_variant: ReturnVariant = r0.as_u32().into();
            // TRD 104 guarantees that Subscribe returns either Success with 2
            // U32 or Failure with 2 U32. We check the return variant by
            // comparing against Failure with 2 U32 for 2 reasons:
            //
            //   1. On RISC-V with compressed instructions, it generates smaller
            //      code. FAILURE_2_U32 has value 2, which can be loaded into a
            //      register with a single compressed instruction, whereas
            //      loading SUCCESS_2_U32 uses an uncompressed instruction.
            //   2. In the event the kernel malfuctions and returns a different
            //      return variant, the success path is actually safer than the
            //      failure path. The failure path assumes that r1 contains an
            //      ErrorCode, and produces UB if it has an out of range value.
            //      Incorrectly assuming the call succeeded will not generate
            //      unsoundness, and will likely lead to the application
            //      hanging.
            if return_variant == return_variant::FAILURE_2_U32 {
                // Safety: TRD 104 guarantees that if r0 is Failure with 2 U32,
                // then r1 will contain a valid error code. ErrorCode is
                // designed to be safely transmuted directly from a kernel error
                // code.
                return Err(unsafe { core::mem::transmute(r1.as_u32() as u16) });
            }
            // r0 indicates Success with 2 u32s. Confirm the null upcall was
            // returned, and it if wasn't then call the configured function.
            // We're relying on the optimizer to remove this branch if
            // returned_nonnull_upcall is a no-op.
            // Note: TRD 104 specifies that the null upcall has address 0,
            // not necessarily a null pointer.
            let returned_upcall: usize = r1.into();
            if returned_upcall != 0usize {
                CONFIG::returned_nonnull_upcall(driver_num, subscribe_num);
            }
            Ok(())
        }
unsafe fn inner < S : Syscalls , CONFIG : subscribe :: Config > ( driver_num : u32 , subscribe_num : u32 , upcall_fcn : Register , upcall_data : Register , ) -> Result < ( ) , ErrorCode > { // Safety: syscall4's documentation indicates it can be used to call // Subscribe. These arguments follow TRD104. kernel_upcall has the // required signature. This function's preconditions mean that // upcall is a reference to an instance of U that will remain valid // until the 'scope lifetime is alive The existence of the // Subscribe<'scope, Self, DRIVER_NUM, SUBSCRIBE_NUM> guarantees // that if this Subscribe succeeds then the upcall will be cleaned // up before the 'scope lifetime ends, guaranteeing that upcall is // still alive when kernel_upcall is invoked. let [ r0 , r1 , _ , _ ] = unsafe { S :: syscall4 :: < { syscall_class :: SUBSCRIBE } > ( [ driver_num . into ( ) , subscribe_num . into ( ) , upcall_fcn , upcall_data , ] ) } ; let return_variant : ReturnVariant = r0 . as_u32 ( ) . into ( ) ; // TRD 104 guarantees that Subscribe returns either Success with 2 // U32 or Failure with 2 U32. We check the return variant by // comparing against Failure with 2 U32 for 2 reasons: // //   1. On RISC-V with compressed instructions, it generates smaller //      code. FAILURE_2_U32 has value 2, which can be loaded into a //      register with a single compressed instruction, whereas //      loading SUCCESS_2_U32 uses an uncompressed instruction. //   2. In the event the kernel malfuctions and returns a different //      return variant, the success path is actually safer than the //      failure path. The failure path assumes that r1 contains an //      ErrorCode, and produces UB if it has an out of range value. //      Incorrectly assuming the call succeeded will not generate //      unsoundness, and will likely lead to the application //      hanging. if return_variant == return_variant :: FAILURE_2_U32 { // Safety: TRD 104 guarantees that if r0 is Failure with 2 U32, // then r1 will contain a valid error code. ErrorCode is // designed to be safely transmuted directly from a kernel error // code. return Err ( unsafe { core :: mem :: transmute ( r1 . as_u32 ( ) as u16 ) } ) ; } // r0 indicates Success with 2 u32s. Confirm the null upcall was // returned, and it if wasn't then call the configured function. // We're relying on the optimizer to remove this branch if // returned_nonnull_upcall is a no-op. // Note: TRD 104 specifies that the null upcall has address 0, // not necessarily a null pointer. let returned_upcall : usize = r1 . into ( ) ; if returned_upcall != 0usize { CONFIG :: returned_nonnull_upcall ( driver_num , subscribe_num ) ; } Ok ( ( ) ) }
Inner function that does the majority of the work.
Inner function that does the majority of the work .
driver_num
u32
subscribe_num
u32
upcall_fcn
Register
upcall_data
Register
driver_num
u32
subscribe_num
u32
upcall_fcn
Register
upcall_data
Register