55 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
66
77use std:: cell:: UnsafeCell ;
8+ use std:: marker:: PhantomData ;
89use std:: mem;
9- use std:: sync:: atomic:: { AtomicU64 , AtomicUsize , Ordering , Ordering :: SeqCst } ;
10- use std:: sync:: Arc ;
10+ #[ cfg( not( target_env = "sgx" ) ) ]
11+ use {
12+ std:: sync:: atomic:: AtomicU64 ,
13+ std:: sync:: Arc ,
14+ } ;
15+ use std:: sync:: atomic:: { AtomicUsize , Ordering , Ordering :: SeqCst } ;
1116
1217use fortanix_sgx_abi:: { FifoDescriptor , WithId } ;
1318
1419use super :: * ;
1520
21+ // `fortanix_sgx_abi::WithId` is not `Copy` because it contains an `AtomicU64`.
22+ // This type has the same memory layout but is `Copy` and can be marked as
23+ // `UserSafeSized` which is needed for the `User::from_raw_parts()` below.
24+ #[ cfg( target_env = "sgx" ) ]
25+ #[ repr( C ) ]
26+ #[ derive( Default , Clone , Copy ) ]
27+ struct UserSafeWithId < T > {
28+ pub id : u64 ,
29+ pub data : T ,
30+ }
31+
32+ #[ cfg( target_env = "sgx" ) ]
33+ unsafe impl < T : UserSafeSized > UserSafeSized for UserSafeWithId < T > { }
34+
35+ #[ cfg( target_env = "sgx" ) ]
36+ unsafe fn _sanity_check_with_id ( ) {
37+ use std:: mem:: size_of;
38+ let _: [ u8 ; size_of :: < fortanix_sgx_abi:: WithId < ( ) > > ( ) ] = [ 0u8 ; size_of :: < UserSafeWithId < ( ) > > ( ) ] ;
39+ }
40+
41+ #[ cfg( target_env = "sgx" ) ]
42+ #[ repr( transparent) ]
43+ #[ derive( Copy , Clone ) ]
44+ struct WrapUsize ( usize ) ;
45+
46+ #[ cfg( target_env = "sgx" ) ]
47+ unsafe impl UserSafeSized for WrapUsize { }
48+
49+ #[ cfg( not( target_env = "sgx" ) ) ]
1650pub fn bounded < T , S > ( len : usize , s : S ) -> ( Sender < T , S > , Receiver < T , S > )
1751where
1852 T : Transmittable ,
2559 ( tx, rx)
2660}
2761
62+ #[ cfg( not( target_env = "sgx" ) ) ]
2863pub fn bounded_async < T , S > ( len : usize , s : S ) -> ( AsyncSender < T , S > , AsyncReceiver < T , S > )
2964where
3065 T : Transmittable ,
@@ -37,11 +72,43 @@ where
3772 ( tx, rx)
3873}
3974
75+ #[ cfg( all( test, target_env = "sgx" ) ) ]
76+ pub ( crate ) fn bounded < T , S > ( len : usize , s : S ) -> ( Sender < T , S > , Receiver < T , S > )
77+ where
78+ T : Transmittable ,
79+ S : Synchronizer ,
80+ {
81+ use std:: ops:: DerefMut ;
82+ use std:: os:: fortanix_sgx:: usercalls:: alloc:: User ;
83+
84+ // Allocate [WithId<T>; len] in userspace
85+ // WARNING: This creates dangling memory in userspace, use in tests only!
86+ let mut data = User :: < [ UserSafeWithId < T > ] > :: uninitialized ( len) ;
87+ data. deref_mut ( ) . iter_mut ( ) . for_each ( |v| v. copy_from_enclave ( & UserSafeWithId :: default ( ) ) ) ;
88+
89+ // WARNING: This creates dangling memory in userspace, use in tests only!
90+ let offsets = User :: < WrapUsize > :: new_from_enclave ( & WrapUsize ( 0 ) ) ;
91+ let offsets = offsets. into_raw ( ) as * const AtomicUsize ;
92+
93+ let descriptor = FifoDescriptor {
94+ data : data. into_raw ( ) as _ ,
95+ len,
96+ offsets,
97+ } ;
98+
99+ let inner = unsafe { Fifo :: from_descriptor ( descriptor) } ;
100+ let tx = Sender { inner : inner. clone ( ) , synchronizer : s. clone ( ) } ;
101+ let rx = Receiver { inner, synchronizer : s } ;
102+ ( tx, rx)
103+ }
104+
105+ #[ cfg( not( target_env = "sgx" ) ) ]
40106pub ( crate ) struct FifoBuffer < T > {
41107 data : Box < [ WithId < T > ] > ,
42108 offsets : Box < AtomicUsize > ,
43109}
44110
111+ #[ cfg( not( target_env = "sgx" ) ) ]
45112impl < T : Transmittable > FifoBuffer < T > {
46113 fn new ( len : usize ) -> Self {
47114 assert ! (
@@ -57,16 +124,18 @@ impl<T: Transmittable> FifoBuffer<T> {
57124 }
58125}
59126
60- enum Storage < T > {
127+ enum Storage < T : ' static > {
128+ #[ cfg( not( target_env = "sgx" ) ) ]
61129 Shared ( Arc < FifoBuffer < T > > ) ,
62- Static ,
130+ Static ( PhantomData < & ' static T > ) ,
63131}
64132
65133impl < T > Clone for Storage < T > {
66134 fn clone ( & self ) -> Self {
67135 match self {
136+ #[ cfg( not( target_env = "sgx" ) ) ]
68137 Storage :: Shared ( arc) => Storage :: Shared ( arc. clone ( ) ) ,
69- Storage :: Static => Storage :: Static ,
138+ Storage :: Static ( p ) => Storage :: Static ( * p ) ,
70139 }
71140 }
72141}
@@ -94,42 +163,23 @@ impl<T: Transmittable> Fifo<T> {
94163 "Fifo len should be a power of two"
95164 ) ;
96165 #[ cfg( target_env = "sgx" ) ] {
97- use std:: os:: fortanix_sgx:: usercalls:: alloc:: { User , UserRef } ;
98-
99- // `fortanix_sgx_abi::WithId` is not `Copy` because it contains an `AtomicU64`.
100- // This type has the same memory layout but is `Copy` and can be marked as
101- // `UserSafeSized` which is needed for the `User::from_raw_parts()` below.
102- #[ repr( C ) ]
103- #[ derive( Clone , Copy ) ]
104- pub struct WithId < T > {
105- pub id : u64 ,
106- pub data : T ,
107- }
108- unsafe impl < T : UserSafeSized > UserSafeSized for WithId < T > { }
109-
110- unsafe fn _sanity_check_with_id ( ) {
111- use std:: mem:: size_of;
112- let _: [ u8 ; size_of :: < fortanix_sgx_abi:: WithId < ( ) > > ( ) ] = [ 0u8 ; size_of :: < WithId < ( ) > > ( ) ] ;
113- }
114-
115- #[ repr( transparent) ]
116- #[ derive( Copy , Clone ) ]
117- struct WrapUsize ( usize ) ;
118- unsafe impl UserSafeSized for WrapUsize { }
166+ use std:: os:: fortanix_sgx:: usercalls:: alloc:: User ;
119167
120168 // check pointers are outside enclave range, etc.
121- let data = User :: < [ WithId < T > ] > :: from_raw_parts ( descriptor. data as _ , descriptor. len ) ;
169+ let data = User :: < [ UserSafeWithId < T > ] > :: from_raw_parts ( descriptor. data as _ , descriptor. len ) ;
122170 mem:: forget ( data) ;
123171 UserRef :: from_ptr ( descriptor. offsets as * const WrapUsize ) ;
172+
124173 }
125174 let data_slice = std:: slice:: from_raw_parts ( descriptor. data , descriptor. len ) ;
126175 Self {
127176 data : & * ( data_slice as * const [ WithId < T > ] as * const [ UnsafeCell < WithId < T > > ] ) ,
128177 offsets : & * descriptor. offsets ,
129- storage : Storage :: Static ,
178+ storage : Storage :: Static ( PhantomData :: default ( ) ) ,
130179 }
131180 }
132181
182+ #[ cfg( not( target_env = "sgx" ) ) ]
133183 fn from_arc ( fifo : Arc < FifoBuffer < T > > ) -> Self {
134184 unsafe {
135185 Self {
@@ -142,10 +192,11 @@ impl<T: Transmittable> Fifo<T> {
142192
143193 /// Consumes `self` and returns a DescriptorGuard.
144194 /// Panics if `self` was created using `from_descriptor`.
195+ #[ cfg( not( target_env = "sgx" ) ) ]
145196 pub ( crate ) fn into_descriptor_guard ( self ) -> DescriptorGuard < T > {
146197 let arc = match self . storage {
147198 Storage :: Shared ( arc) => arc,
148- Storage :: Static => panic ! ( "Sender/Receiver created using `from_descriptor()` cannot be turned into DescriptorGuard." ) ,
199+ Storage :: Static ( _ ) => panic ! ( "Sender/Receiver created using `from_descriptor()` cannot be turned into DescriptorGuard." ) ,
149200 } ;
150201 let descriptor = FifoDescriptor {
151202 data : self . data . as_ptr ( ) as _ ,
@@ -176,9 +227,11 @@ impl<T: Transmittable> Fifo<T> {
176227 } ;
177228
178229 // 4. Write the data, then the `id`.
179- let slot = unsafe { & mut * self . data [ new. write_offset ( ) ] . get ( ) } ;
180- slot. data = val. data ;
181- slot. id . store ( val. id , SeqCst ) ;
230+ unsafe {
231+ let slot = & mut * self . data [ new. write_offset ( ) ] . get ( ) ;
232+ T :: write ( & mut slot. data , & val. data ) ;
233+ slot. id . store ( val. id , SeqCst ) ;
234+ }
182235
183236 // 5. If the queue was empty in step 1, signal the reader to wake up.
184237 Ok ( was_empty)
@@ -209,7 +262,8 @@ impl<T: Transmittable> Fifo<T> {
209262 } ;
210263
211264 // 6. Read the data, then store `0` in the `id`.
212- let val = Identified { id, data : slot. data } ;
265+ let data = unsafe { T :: read ( & slot. data ) } ;
266+ let val = Identified { id, data } ;
213267 slot. id . store ( 0 , SeqCst ) ;
214268
215269 // 7. Store the new read offset, retrieving the old offsets.
0 commit comments