blob: 226be9cc84fa0e3afcb702091868a04dae5019b0 [file] [log] [blame]
/* --COPYRIGHT--,ESD
* Copyright (c) 2008 Texas Instruments. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License
* v. 1.0 which accompanies this distribution. The Eclipse Public License is
* available at http://www.eclipse.org/legal/epl-v10.html and the Eclipse
* Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Texas Instruments - initial implementation
* --/COPYRIGHT--*/
package xdc.runtime;
/*!
* ======== Gate ========
* Critical section support
*
* Gates are used by clients to protect concurrent access to critical
* data structures. Critical data structures are those that must be
* updated by at most one thread at a time. All code that needs access
* to a critical data structure "enters" a gate (that's associated with the
* data structure) prior to accessing the data, modifies the data structure,
* then "leaves" the gate.
*
* A gate is responsible for ensuring that at most one thread at a time
* can enter and execute "inside" the gate. There are several
* implementations of gates, with different system executation times and
* latency tradoffs. In addition, some gates must not be entered by certain
* thread types; e.g., a gate that is implemented via a "blocking" semaphore
* must not be called by an interrupt service routine (ISR).
*
* A module can be declared "gated" by adding the `@Gated` attribute to the
* module's XDC spec file. A "gated" module is assigned a module-level gate
* at the configuration time, and that gate is then used to protect critical
* sections in the module's target code. A module-level gate is an instance of
* a module implementing `{@link IGateProvider}` interface. However, gated
* modules do not access their module-level gates directly. They use this
* module to access transparently their module-level gate.
*
* Application code that is not a part of any module also has a
* module-level gate, configured through the module `{@link Main}`.
*
* Each gated module can optionally create gates on an adhoc basis at
* runtime using the same gate module that was used to create the module
* level gate.
*
* Gates that work by disabling all preemption while inside a gate can be
* used to protect data structures accessed by ISRs and other
* threads. But, if the time required to update the data structure is not
* a small constant, this type of gate may violate a system's real-time
* requirements.
*
* Gates have two orthogonal attributes: "blocking" and "preemptible".
* In general, gates that are "blocking" can not be use by code that is
* called by ISRs and gates that are not "preemptible" should only be used to
* to protect data manipulated by code that has small constant execution
* time.
*
*/
@CustomHeader
@DirectCall
module Gate {
/*!
* ======== Ref ========
* Opaque reference to an allocated gate instance
*/
@Encoded typedef xdc.runtime.IGateProvider.Handle Ref;
/*!
* ======== allocInstance ========
* Allocate a gate instance from the current module's gate
*
* This method is used by modules to create gates at runtime using
* the same `IGateProvider` that was used to create the module
* level gate. The parameters passed to the `IGateProvider` are
* specified at configuration time via the
* `{@link Types#Common$ Types.Common$.gateParams}`
* configuration parameter.
*
* @param(eb) `Error` block pointer
*
* If `NULL`, any error in creating the instance will terminate
* the application.
*
* @a(returns)
* Non-`NULL` instance handle is returned if no error occurs; otherwise
* an error is raised in `eb` and `NULL` is returned.
*
* @see IGateProvider
* @see Error
*/
@Macro Ref allocInstance(Error.Block *eb);
/*!
* ======== freeInstance ========
* Free a gate instance to the current module's gatekeeper
*
* @param(gate) non-`NULL` return value from a prior call to
* `{@link #allocInstance}`.
*
* @see #allocInstance
*/
@Macro Void freeInstance(Ref gate);
/*!
* ======== enterInstance ========
* Enter a critical section protected by this gate instance
*
* @param(gate) non-`NULL` return value from a prior call to
* `{@link #allocInstance}`.
*
* @a(returns)
* Returns a "key" value that must be used to leave `gate`
* via `{@link #leaveInstance()}`.
*
*/
@Macro IArg enterInstance(Ref gate);
/*!
* ======== enterModule ========
* Enter a critical section protected by the current module's gate
*
* @a(returns)
* Returns a "key" value that must be used to leave the current module
* gate via `{@link #leaveModule()}`.
*
* @see #leaveModule
*/
@Macro IArg enterModule();
/*!
* ======== enterSystem ========
* Enter a critical section protected by the global System gate
*
* @a(returns)
* Returns a "key" value that must be used to leave the `{@link System}`
* gate via `{@link #leaveSystem()}`.
*
* @see #leaveSystem
*/
IArg enterSystem();
/*!
* ======== leaveInstance ========
* Leave a critical section protected by a gate
*
* @param(gate) non-`NULL` return value from a prior call to
* `{@link #allocInstance}`.
* @param(key) the return value of a prior call to
* `{@link #enterInstance}`
*
* @see #enterInstance
* @see #allocInstance
*/
@Macro Void leaveInstance(Ref gate, IArg key);
/*!
* ======== leaveModule ========
* Leave a critical section protected by the current module's gate
*
* @param(key) the return value of a prior call to `{@link #enterModule}`
*
* @see #enterModule
*/
@Macro Void leaveModule(IArg key);
/*!
* ======== leaveSystem ========
* Leave a critical section protected by the global System gate
*
* @param(key) the return value of a prior call to `{@link #enterSystem}`
*
* @see #enterSystem
*/
Void leaveSystem(IArg key);
/*!
* ======== canBlock ========
* Check if the module level gate can block threads
*
* This type of gate should never be called by clients that must never
* call a "blocking" RTOS operation; e.g., interrupt service
* routines
*
* @a(returns) Returns `TRUE` if the underlying gatekeeper's gate can
* block
*/
@Macro Bool canBlock();
/*!
* ======== canBePreempted ========
* Check if the module level gate allows thread preemption
*
* This type of gate should always be used by clients that protect
* a data structure whose updates require more than a small
* constant amount of time; e.g., update of a memory allocator's free
* list.
*
* @a(returns) Returns `TRUE` if the underlying gate does not disable
* thread preemption.
*/
@Macro Bool canBePreempted();
/*!
* ======== staticAlloc ========
* Assign a statically-allocated gate instance to a state-object field
*
* This method is used to create a gate for static instance objects
* that require a gate.
*
* @param(stateObj) the state object for the instance being created
* @param(fldName) a name of a field within the state object
*
* This parameter names a field that will point to the created gate
* instance to be created. It is a caller's responsibility
* to ensure that the type of `fldName` is a handle to an
* `IGateProvider` instance.
*/
metaonly Void staticAlloc(Any stateObj, String fldName);
}