pub struct BufferCollectionTokenProxy { /* private fields */ }

Implementations§

source§

impl BufferCollectionTokenProxy

source

pub fn new(channel: AsyncChannel) -> Self

Create a new Proxy for fuchsia.sysmem/BufferCollectionToken.

source

pub fn take_event_stream(&self) -> BufferCollectionTokenEventStream

Get a Stream of events from the remote end of the protocol.

§Panics

Panics if the event stream was already taken.

source

pub fn sync(&self) -> QueryResponseFut<()>

Ensure that previous messages, including Duplicate() messages on a token, collection, or group, have been received server side.

Calling BufferCollectionToken.Sync() on a token that isn’t/wasn’t a valid sysmem token risks the Sync() hanging forever. See ValidateBufferCollectionToken() for one way to mitigate the possibility of a hostile/fake BufferCollectionToken at the cost of one round trip. Another way is to pass the token to BindSharedCollection(), which also validates the token as part of exchanging it for a BufferCollection channel, and BufferCollection Sync() can then be used.

After a Sync(), it’s then safe to send the client end of token_request to another participant knowing the server will recognize the token when it’s sent into BindSharedCollection() by the other participant.

Other options include waiting for each token.Duplicate() to complete individually (using separate call to token.Sync() after each), or calling Sync() on BufferCollection after the token has been turned in via BindSharedCollection().

Another way to mitigate is to avoid calling Sync() on the token, and instead later deal with potential failure of BufferCollection.Sync() if the original token was invalid. This option can be preferable from a performance point of view, but requires client code to delay sending tokens duplicated from this token until after client code has converted the duplicating token to a BufferCollection and received successful response from BufferCollection.Sync().

Prefer using BufferCollection.Sync() instead, when feasible (see above). When BufferCollection.Sync() isn’t feasible, the caller must already know that this token is/was valid, or BufferCollectionToken.Sync() may hang forever. See ValidateBufferCollectionToken() to check token validity first if the token isn’t already known to be (is/was) valid.

source

pub fn close(&self) -> Result<(), Error>

On a BufferCollectionToken channel:

Normally a participant will convert a BufferCollectionToken into a BufferCollection view, but a participant is also free to Close() the token (and then close the channel immediately or shortly later in response to server closing its end), which avoids causing logical buffer collection failure.  Normally an unexpected token channel close will cause logical buffer collection failure (the only exceptions being certain cases involving AttachToken() or SetDispensable()).

On a BufferCollection channel:

By default the server handles unexpected failure of a BufferCollection by failing the whole logical buffer collection. Partly this is to expedite closing VMO handles to reclaim memory when any participant fails. If a participant would like to cleanly close a BufferCollection view without causing logical buffer collection failure, the participant can send Close() before closing the client end of the BufferCollection channel. If this is the last BufferCollection view, the logical buffer collection will still go away. The Close() can occur before or after SetConstraints(). If before SetConstraints(), the buffer collection won’t require constraints from this node in order to allocate. If after SetConstraints(), the constraints are retained and aggregated along with any subsequent logical allocation(s), despite the lack of channel connection.

On a BufferCollectionTokenGroup channel:

By default, unexpected failure of a BufferCollectionTokenGroup will trigger failure of the logical BufferCollectionTokenGroup and will propagate failure to its parent. To close a BufferCollectionTokenGroup channel without failing the logical group or propagating failure, send Close() before closing the channel client endpoint.

If Close() occurs before AllChildrenPresent(), the logical buffer collection will still fail despite the Close() (because sysmem can’t be sure whether all relevant children were created, so it’s ambiguous whether all relevant constraints will be provided to sysmem). If Close() occurs after AllChildrenPresent(), the children and all their constraints remain intact (just as they would if the BufferCollectionTokenGroup channel had remained open), and the close doesn’t trigger or propagate failure.

source

pub fn set_name(&self, priority: u32, name: &str) -> Result<(), Error>

Set a name for VMOs in this buffer collection. The name may be truncated shorter. The name only affects VMOs allocated after it’s set - this call does not rename existing VMOs. If multiple clients set different names then the larger priority value will win.

source

pub fn set_debug_client_info(&self, name: &str, id: u64) -> Result<(), Error>

Set information about the current client that can be used by sysmem to help debug leaking memory and hangs waiting for constraints. |name| can be an arbitrary string, but the current process name (see fsl::GetCurrentProcessName()) is a good default. |id| can be an arbitrary id, but the current process ID (see fsl::GetCurrentProcessKoid()) is a good default.

Also used when verbose logging is enabled (see SetVerboseLogging()) to indicate which client is closing their channel first, leading to sub-tree failure (which can be normal if the purpose of the sub-tree is over, but if happening earlier than expected, the client-channel-specific name can help diagnose where the failure is first coming from, from sysmem’s point of view).

By default (unless overriden by this message or using Allocator.SetDebugClientInfo()), a Node will copy info from its parent Node at the time the child Node is created. While this can be better than nothing, it’s often better for each participant to use Node.SetDebugClientInfo() or Allocator.SetDebugClientInfo() to keep the info directly relevant to the current client. Also, SetVerboseLogging() can be used to help disambiguate if a Node is suspected of having info that was copied from its parent.

source

pub fn set_debug_timeout_log_deadline(&self, deadline: i64) -> Result<(), Error>

Sysmem logs a warning if not all clients have set constraints 5 seconds after creating a collection. Clients can call this method to change when the log is printed. If multiple client set the deadline, it’s unspecified which deadline will take effect.

source

pub fn set_verbose_logging(&self) -> Result<(), Error>

Verbose logging includes constraints set via SetConstraints() from each client along with info set via SetDebugClientInfo() and the structure of the tree of Node(s).

Normally sysmem prints only a single line complaint when aggregation fails, with just the specific detailed reason that aggregation failed, with minimal context. While this is often enough to diagnose a problem if only a small change was made and the system had been working before the small change, it’s often not particularly helpful for getting a new buffer collection to work for the first time. Especially with more complex trees of nodes, involving things like AttachToken(), SetDispensable(), BufferCollectionTokenGroup nodes, and associated sub-trees of nodes, verbose logging may help in diagnosing what the tree looks like and why it’s failing a logical allocation, or why a tree or sub-tree is failing sooner than expected.

The intent of the extra logging is to be acceptable from a performance point of view, if only enabled on a low number of buffer collections. If we’re not tracking down a bug, we shouldn’t send this message.

If too many participants leave verbose logging enabled, we may end up needing to require that system-wide sysmem verbose logging be permitted via some other setting, to avoid sysmem spamming the log too much due to this message.

This may be a NOP for some nodes due to intentional policy associated with the node, if we don’t trust a node enough to let it turn on verbose logging.

source

pub fn get_node_ref(&self) -> QueryResponseFut<Event>

This gets an event handle that can be used as a parameter to IsAlternateFor() called on any Node. The client will not be granted the right to signal this event, as this handle should only be used as proof that the client obtained this handle from this Node.

Because this is a get not a set, no Sync() is needed between the GetNodeRef() and the call to IsAlternateFor(), despite the two calls potentially being on different channels.

See also IsAlternateFor().

source

pub fn is_alternate_for( &self, node_ref: Event ) -> QueryResponseFut<NodeIsAlternateForResult>

This checks whether the calling node is in a subtree rooted at a different child token of a common parent BufferCollectionTokenGroup, in relation to the passed-in node_ref.

This call is for assisting with admission control de-duplication, and with debugging.

The node_ref must be obtained using GetNodeRef() of a BufferCollectionToken, BufferCollection, or BufferCollectionTokenGroup.

The node_ref can be a duplicated handle; it’s not necessary to call GetNodeRef() for every call to IsAlternateFor().

If a calling token may not actually be a valid token at all due to a potentially hostile/untrusted provider of the token, call ValidateBufferCollectionToken() first instead of potentially getting stuck indefinitely if IsAlternateFor() never responds due to a calling token not being a real token (not really talking to sysmem). Another option is to call BindSharedCollection with this token first which also validates the token along with converting it to a BufferCollection, then call BufferCollection IsAlternateFor().

error values:

ZX_ERR_NOT_FOUND means the node_ref wasn’t found within the same logical buffer collection as the calling Node. Before logical allocation and within the same logical allocation sub-tree, this essentially means that the node_ref was never part of this logical buffer collection, since before logical allocation all node_refs that come into existence remain in existence at least until logical allocation (including Node(s) that have done a Close() and closed their channel), and for ZX_ERR_NOT_FOUND to be returned, this Node’s channel needs to still be connected server side, which won’t be the case if the whole logical allocation has failed. After logical allocation or in a different logical allocation sub-tree there are additional potential reasons for this error. For example a different logical allocation (separated from this Node(s) logical allocation by an AttachToken() or SetDispensable()) can fail its sub-tree deleting those Node(s), or a BufferCollectionTokenGroup may exist and may select a different child sub-tree than the sub-tree the node_ref is in causing deletion of the node_ref Node. The only time sysmem keeps a Node around after that Node has no corresponding channel is when Close() is used and the Node’s sub-tree has not yet failed. Another reason for this error is if the node_ref is an eventpair handle with sufficient rights, but isn’t actually a real node_ref obtained from GetNodeRef().

ZX_ERR_INVALID_ARGS means the caller passed a node_ref that isn’t an eventpair handle, or doesn’t have the needed rights expected on a real node_ref.

No other failing status codes are returned by this call. However, sysmem may add additional codes in future, so the client should have sensible default handling for any failing status code.

On success, is_alternate has the following meaning:

  • true - The first parent node in common between the calling node and the node_ref Node is a BufferCollectionTokenGroup. This means that the calling Node and the node_ref Node will not have both their constraints apply - rather sysmem will choose one or the other of the constraints - never both. This is because only one child of a BufferCollectionTokenGroup is selected during logical allocation, with only that one child’s sub-tree contributing to constraints aggregation.
  • false - The first parent node in common between the calling Node and the node_ref Node is not a BufferCollectionTokenGroup. Currently, this means the first parent node in common is a BufferCollectionToken or BufferCollection (regardless of not Close()ed or Close()ed). This means that the calling Node and the node_ref Node may have both their constraints apply during constraints aggregation of the logical allocation, if both Node(s) are selected by any parent BufferCollectionTokenGroup(s) involved. In this case, there is no BufferCollectionTokenGroup that will directly prevent the two Node(s) from both being selected and their constraints both aggregated, but even when false, one or both Node(s) may still be eliminated from consideration if one or both Node(s) has a direct or indirect parent BufferCollectionTokenGroup which selects a child sub-tree other than the sub-tree containing the calling Node or node_ref Node.
source

pub fn deprecated_sync(&self) -> QueryResponseFut<()>

source

pub fn deprecated_close(&self) -> Result<(), Error>

source

pub fn deprecated_set_name( &self, priority: u32, name: &str ) -> Result<(), Error>

source

pub fn deprecated_set_debug_client_info( &self, name: &str, id: u64 ) -> Result<(), Error>

source

pub fn deprecated_set_debug_timeout_log_deadline( &self, deadline: i64 ) -> Result<(), Error>

source

pub fn duplicate_sync( &self, rights_attenuation_masks: &[Rights] ) -> QueryResponseFut<Vec<ClientEnd<BufferCollectionTokenMarker>>>

This method can be used to add more participants prior to creating a shared BufferCollection. A new token will be returned for each entry in the rights_attenuation_masks array. The return value is the client ends of each new participant token.

If the calling token may not actually be a valid token at all due to a potentially hostile/untrusted provider of the token, consider using ValidateBufferCollectionToken() first instead of potentially getting stuck indefinitely if DuplicateSync() never responds due to the calling token not being a real token.

In contrast to Duplicate(), no Sync() (see “protocol Node”) is needed after calling this method.

All tokens must be turned in via BindSharedCollection() or Close() for a BufferCollection to be successfully created.

In each entry of rights_attenuation_masks, rights bits that are zero will be absent in the buffer VMO rights obtainable via the corresponding returned token. This allows an initiator or intermediary participant to attenuate the rights available to a participant. This does not allow a participant to gain rights that the participant doesn’t already have. The value ZX_RIGHT_SAME_RIGHTS can be used to specify that no attenuation should be applied.

source

pub fn duplicate( &self, rights_attenuation_mask: u32, token_request: ServerEnd<BufferCollectionTokenMarker> ) -> Result<(), Error>

This method can be used to add a participant prior to creating a shared BufferCollection. It should only be used instead of DuplicateSync in performance sensitive cases where it would be undesireable to wait for sysmem to respond as part of each duplicate.

After sending one or more Duplicate() messages, and before sending the created tokens to other participants (or to other Allocator channels), the client should send a Sync() and wait for its response. The Sync() call can be made on the token, or on the BufferCollection obtained by passing this token to BindSharedCollection(). Either will ensure that the server knows about the tokens created via Duplicate() before the other participant sends the token to the server via separate Allocator channel.

All tokens must be turned in via BindSharedCollection() or Close() for a BufferCollection to be successfully created.

When a client calls BindSharedCollection() to turn in a BufferCollectionToken, the server will process all Duplicate() messages before closing down the BufferCollectionToken. This allows the client to Duplicate() and immediately turn in the BufferCollectionToken using BindSharedCollection, then later transfer the client end of token_request to another participant - the server will notice the existence of the token_request before considering this BufferCollectionToken fully closed.

rights_attenuation_mask rights bits that are zero in this mask will be absent in the buffer VMO rights obtainable via the client end of token_request. This allows an initiator or intermediary participant to attenuate the rights available to a participant. This does not allow a participant to gain rights that the participant doesn’t already have. The value ZX_RIGHT_SAME_RIGHTS can be used to specify that no attenuation should be applied.

These values for rights_attenuation_mask result in no attenuation:

  • ZX_RIGHT_SAME_RIGHTS (preferred)
  • 0xFFFFFFFF (this is reasonable when an attenuation mask is computed)
  • 0 (deprecated - do not use 0 - an ERROR will go to the log)

token_request is the server end of a BufferCollectionToken channel. The client end of this channel acts as another participant in creating the shared BufferCollection.

source

pub fn set_dispensable(&self) -> Result<(), Error>

A dispensable token can fail after buffers are logically allocated without causing failure of its parent (if any).

The dispensable token participates in constraints aggregation along with its parent before logical buffer allocation. If the dispensable token fails before buffers are logically allocated, the failure propagates to the dispensable token’s parent.

After buffers are logically allocated, failure of the dispensable token (or any child of the dispensable token) does not propagate to the dispensable token’s parent. Failure does propagate from a normal child of a dispensable token to the dispensable token. Failure of a child is blocked from reaching its parent if the child is attached, or if the child is dispensable and the failure occurred after logical allocation.

A dispensable token can be used in cases where a participant needs to provide constraints, but after buffers are allocated, the participant can fail without causing buffer collection failure from the parent’s point of view.

In contrast, AttachToken() can be used to create a token which does not participate in constraints aggregation with its parent, and whose failure at any time does not propagate to its parent, and whose delay providing constraints does not prevent the parent from completing its buffer allocation.

An initiator may in some scenarios choose to initially use a dispensable token for a given instance of a participant, and then later if the first instance of that participant fails, a new second instance of that participant my be given a token created with AttachToken().

If a client uses this message, the client should not rely on the client’s own BufferCollectionToken or BufferCollection channel to close from the server end due to abrupt failure of any BufferCollectionToken or BufferCollection that the client has SetDispensable() and given out to another process. For this reason, the client should take extra care to notice failure of that other process via other means.

While it is possible (and potentially useful) to SetDispensable() on a direct child of a BufferCollectionTokenGroup, it isn’t possible to later replace a failed dispensable token that was a direct child of a group with a new token using AttachToken() (since there’s no AttachToken() on a group). Instead, to enable AttachToken() replacement in this case, create an additional non-dispensable token (node) that’s a direct child of the group and make the existing dispensable token a child of the additional token (node). This way, the additional token (node) that is a direct child of the group has BufferCollection.AttachToken() which can be used to replace the failed dispensable token.

SetDispensable() on an already-dispensable token is idempotent.

source

pub fn create_buffer_collection_token_group( &self, group_request: ServerEnd<BufferCollectionTokenGroupMarker> ) -> Result<(), Error>

Most sysmem clients and many participants don’t need to care about this message or about BufferCollectionTokenGroup(s) in general.

A BufferCollectionTokenGroup is used to create a 1 of N OR among N child tokens. The child tokens which are not selected during aggregation will fail (close), which a potential participant should notice when their BufferCollection channel client endpoint sees PEER_CLOSED, allowing the participant to clean up the speculative usage that didn’t end up happening (similarly to a normal BufferCollection server end closing on failure of a logical buffer collection).

See comments on protocol BufferCollectionTokenGroup.

Any rights_attenuation_mask or AttachToken()/SetDispensable() to be applied to the whole group can be achieved with a token for this purpose as a direct parent of the group.

group_request - the server end of a BufferCollectionTokenGroup channel to be served by sysmem.

Trait Implementations§

source§

impl BufferCollectionTokenProxyInterface for BufferCollectionTokenProxy

§

type SyncResponseFut = QueryResponseFut<()>

source§

fn sync(&self) -> Self::SyncResponseFut

source§

fn close(&self) -> Result<(), Error>

source§

fn set_name(&self, priority: u32, name: &str) -> Result<(), Error>

source§

fn set_debug_client_info(&self, name: &str, id: u64) -> Result<(), Error>

source§

fn set_debug_timeout_log_deadline(&self, deadline: i64) -> Result<(), Error>

source§

fn set_verbose_logging(&self) -> Result<(), Error>

§

type GetNodeRefResponseFut = QueryResponseFut<Event>

source§

fn get_node_ref(&self) -> Self::GetNodeRefResponseFut

§

type IsAlternateForResponseFut = QueryResponseFut<Result<bool, i32>>

source§

fn is_alternate_for(&self, node_ref: Event) -> Self::IsAlternateForResponseFut

§

type DeprecatedSyncResponseFut = QueryResponseFut<()>

source§

fn deprecated_sync(&self) -> Self::DeprecatedSyncResponseFut

source§

fn deprecated_close(&self) -> Result<(), Error>

source§

fn deprecated_set_name(&self, priority: u32, name: &str) -> Result<(), Error>

source§

fn deprecated_set_debug_client_info( &self, name: &str, id: u64 ) -> Result<(), Error>

source§

fn deprecated_set_debug_timeout_log_deadline( &self, deadline: i64 ) -> Result<(), Error>

§

type DuplicateSyncResponseFut = QueryResponseFut<Vec<ClientEnd<BufferCollectionTokenMarker>>>

source§

fn duplicate_sync( &self, rights_attenuation_masks: &[Rights] ) -> Self::DuplicateSyncResponseFut

source§

fn duplicate( &self, rights_attenuation_mask: u32, token_request: ServerEnd<BufferCollectionTokenMarker> ) -> Result<(), Error>

source§

fn set_dispensable(&self) -> Result<(), Error>

source§

fn create_buffer_collection_token_group( &self, group_request: ServerEnd<BufferCollectionTokenGroupMarker> ) -> Result<(), Error>

source§

impl Clone for BufferCollectionTokenProxy

source§

fn clone(&self) -> BufferCollectionTokenProxy

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for BufferCollectionTokenProxy

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Proxy for BufferCollectionTokenProxy

§

type Protocol = BufferCollectionTokenMarker

The protocol which this Proxy controls.
source§

fn from_channel(inner: AsyncChannel) -> Self

Create a proxy over the given channel.
source§

fn into_channel(self) -> Result<AsyncChannel, Self>

Attempt to convert the proxy back into a channel. Read more
source§

fn as_channel(&self) -> &AsyncChannel

Get a reference to the proxy’s underlying channel. Read more
§

fn into_client_end(self) -> Result<ClientEnd<Self::Protocol>, Self>

Attempt to convert the proxy back into a client end. Read more
§

fn is_closed(&self) -> bool

Returns true if the proxy has received the PEER_CLOSED signal.
§

fn on_closed(&self) -> OnSignals<'_, Unowned<'_, Handle>>

Returns a future that completes when the proxy receives the PEER_CLOSED signal.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> Encode<Ambiguous1> for T

§

unsafe fn encode( self, _encoder: &mut Encoder<'_>, _offset: usize, _depth: Depth ) -> Result<(), Error>

Encodes the object into the encoder’s buffers. Any handles stored in the object are swapped for Handle::INVALID. Read more
§

impl<T> Encode<Ambiguous2> for T

§

unsafe fn encode( self, _encoder: &mut Encoder<'_>, _offset: usize, _depth: Depth ) -> Result<(), Error>

Encodes the object into the encoder’s buffers. Any handles stored in the object are swapped for Handle::INVALID. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more