1
1
// SPDX-License-Identifier: GPL-2.0
2
2
3
- use core:: { alloc:: AllocError , mem:: size_of} ;
3
+ use core:: {
4
+ alloc:: AllocError ,
5
+ mem:: size_of,
6
+ sync:: atomic:: { AtomicU32 , Ordering } ,
7
+ } ;
4
8
use kernel:: {
5
9
bindings,
6
10
file:: File ,
@@ -120,11 +124,13 @@ impl InnerThread {
120
124
fn push_existing_work ( & mut self , owork : Option < Arc < ThreadError > > , code : u32 ) {
121
125
// TODO: Write some warning when the following fails. It should not happen, and
122
126
// if it does, there is likely something wrong.
123
- if let Some ( mut work) = owork {
124
- if let Some ( work_mut) = Arc :: get_mut ( & mut work) {
125
- work_mut. error_code = code;
126
- self . push_work ( work) ;
127
- }
127
+ if let Some ( work) = owork {
128
+ // `error_code` is written to with relaxed semantics because the queue onto which it is
129
+ // being inserted is protected by a lock. The release barrier when the lock is released
130
+ // by the caller matches with the acquire barrier of the future reader to guarantee
131
+ // that `error_code` is visible.
132
+ work. error_code . store ( code, Ordering :: Relaxed ) ;
133
+ self . push_work ( work) ;
128
134
}
129
135
}
130
136
@@ -824,15 +830,15 @@ impl GetLinks for Thread {
824
830
}
825
831
826
832
struct ThreadError {
827
- error_code : u32 ,
833
+ error_code : AtomicU32 ,
828
834
return_fn : fn ( & mut InnerThread , Arc < ThreadError > ) ,
829
835
links : Links < dyn DeliverToRead > ,
830
836
}
831
837
832
838
impl ThreadError {
833
839
fn new ( return_fn : fn ( & mut InnerThread , Arc < ThreadError > ) ) -> Self {
834
840
Self {
835
- error_code : BR_OK ,
841
+ error_code : AtomicU32 :: new ( BR_OK ) ,
836
842
return_fn,
837
843
links : Links :: new ( ) ,
838
844
}
@@ -841,7 +847,9 @@ impl ThreadError {
841
847
842
848
impl DeliverToRead for ThreadError {
843
849
fn do_work ( self : Arc < Self > , thread : & Thread , writer : & mut UserSlicePtrWriter ) -> Result < bool > {
844
- let code = self . error_code ;
850
+ // See `ThreadInner::push_existing_work` for the reason why `error_code` is up to date even
851
+ // though we use relaxed semantics.
852
+ let code = self . error_code . load ( Ordering :: Relaxed ) ;
845
853
846
854
// Return the `ThreadError` to the thread.
847
855
( self . return_fn ) ( & mut * thread. inner . lock ( ) , self ) ;
0 commit comments