1 2 3 4 5 6 7 8 9 10 11 12
13 package xdc.runtime;
14
15 /*!
16 * ======== Gate ========
17 * Critical section support
18 *
19 * Gates are used by clients to protect concurrent access to critical
20 * data structures. Critical data structures are those that must be
21 * updated by at most one thread at a time. All code that needs access
22 * to a critical data structure "enters" a gate (that's associated with the
23 * data structure) prior to accessing the data, modifies the data structure,
24 * then "leaves" the gate.
25 *
26 * A gate is responsible for ensuring that at most one thread at a time
27 * can enter and execute "inside" the gate. There are several
28 * implementations of gates, with different system executation times and
29 * latency tradoffs. In addition, some gates must not be entered by certain
30 * thread types; e.g., a gate that is implemented via a "blocking" semaphore
31 * must not be called by an interrupt service routine (ISR).
32 *
33 * A module can be declared "gated" by adding the `@Gated` attribute to the
34 * module's XDC spec file. A "gated" module is assigned a module-level gate
35 * at the configuration time, and that gate is then used to protect critical
36 * sections in the module's target code. A module-level gate is an instance of
37 * a module implementing `{@link IGateProvider}` interface. However, gated
38 * modules do not access their module-level gates directly. They use this
39 * module to access transparently their module-level gate.
40 *
41 * Application code that is not a part of any module also has a
42 * module-level gate, configured through the module `{@link Main}`.
43 *
44 * Each gated module can optionally create gates on an adhoc basis at
45 * runtime using the same gate module that was used to create the module
46 * level gate.
47 *
48 * Gates that work by disabling all preemption while inside a gate can be
49 * used to protect data structures accessed by ISRs and other
50 * threads. But, if the time required to update the data structure is not
51 * a small constant, this type of gate may violate a system's real-time
52 * requirements.
53 *
54 * Gates have two orthogonal attributes: "blocking" and "preemptible".
55 * In general, gates that are "blocking" can not be use by code that is
56 * called by ISRs and gates that are not "preemptible" should only be used to
57 * to protect data manipulated by code that has small constant execution
58 * time.
59 *
60 */
61 @CustomHeader
62 @DirectCall
63 module Gate {
64
65 /*!
66 * ======== Ref ========
67 * Opaque reference to an allocated gate instance
68 */
69 @Encoded typedef xdc.runtime.IGateProvider.Handle Ref;
70
71 /*!
72 * ======== allocInstance ========
73 * Allocate a gate instance from the current module's gate
74 *
75 * This method is used by modules to create gates at runtime using
76 * the same `IGateProvider` that was used to create the module
77 * level gate. The parameters passed to the `IGateProvider` are
78 * specified at configuration time via the
79 * `{@link Types#Common$ Types.Common$.gateParams}`
80 * configuration parameter.
81 *
82 * @param(eb) `Error` block pointer
83 *
84 * If `NULL`, any error in creating the instance will terminate
85 * the application.
86 *
87 * @a(returns)
88 * Non-`NULL` instance handle is returned if no error occurs; otherwise
89 * an error is raised in `eb` and `NULL` is returned.
90 *
91 * @see IGateProvider
92 * @see Error
93 */
94 @Macro Ref allocInstance(Error.Block *eb);
95
96 /*!
97 * ======== freeInstance ========
98 * Free a gate instance to the current module's gatekeeper
99 *
100 * @param(gate) non-`NULL` return value from a prior call to
101 * `{@link #allocInstance}`.
102 *
103 * @see #allocInstance
104 */
105 @Macro Void freeInstance(Ref gate);
106
107 /*!
108 * ======== enterInstance ========
109 * Enter a critical section protected by this gate instance
110 *
111 * @param(gate) non-`NULL` return value from a prior call to
112 * `{@link #allocInstance}`.
113 *
114 * @a(returns)
115 * Returns a "key" value that must be used to leave `gate`
116 * via `{@link #leaveInstance()}`.
117 *
118 */
119 @Macro IArg enterInstance(Ref gate);
120
121 /*!
122 * ======== enterModule ========
123 * Enter a critical section protected by the current module's gate
124 *
125 * @a(returns)
126 * Returns a "key" value that must be used to leave the current module
127 * gate via `{@link #leaveModule()}`.
128 *
129 * @see #leaveModule
130 */
131 @Macro IArg enterModule();
132
133 /*!
134 * ======== enterSystem ========
135 * Enter a critical section protected by the global System gate
136 *
137 * @a(returns)
138 * Returns a "key" value that must be used to leave the `{@link System}`
139 * gate via `{@link #leaveSystem()}`.
140 *
141 * @see #leaveSystem
142 */
143 IArg enterSystem();
144
145 /*!
146 * ======== leaveInstance ========
147 * Leave a critical section protected by a gate
148 *
149 * @param(gate) non-`NULL` return value from a prior call to
150 * `{@link #allocInstance}`.
151 * @param(key) the return value of a prior call to
152 * `{@link #enterInstance}`
153 *
154 * @see #enterInstance
155 * @see #allocInstance
156 */
157 @Macro Void leaveInstance(Ref gate, IArg key);
158
159 /*!
160 * ======== leaveModule ========
161 * Leave a critical section protected by the current module's gate
162 *
163 * @param(key) the return value of a prior call to `{@link #enterModule}`
164 *
165 * @see #enterModule
166 */
167 @Macro Void leaveModule(IArg key);
168
169 /*!
170 * ======== leaveSystem ========
171 * Leave a critical section protected by the global System gate
172 *
173 * @param(key) the return value of a prior call to `{@link #enterSystem}`
174 *
175 * @see #enterSystem
176 */
177 Void leaveSystem(IArg key);
178
179 /*!
180 * ======== canBlock ========
181 * Check if the module level gate can block threads
182 *
183 * This type of gate should never be called by clients that must never
184 * call a "blocking" RTOS operation; e.g., interrupt service
185 * routines
186 *
187 * @a(returns) Returns `TRUE` if the underlying gatekeeper's gate can
188 * block
189 */
190 @Macro Bool canBlock();
191
192 /*!
193 * ======== canBePreempted ========
194 * Check if the module level gate allows thread preemption
195 *
196 * This type of gate should always be used by clients that protect
197 * a data structure whose updates require more than a small
198 * constant amount of time; e.g., update of a memory allocator's free
199 * list.
200 *
201 * @a(returns) Returns `TRUE` if the underlying gate does not disable
202 * thread preemption.
203 */
204 @Macro Bool canBePreempted();
205
206 /*!
207 * ======== staticAlloc ========
208 * Assign a statically-allocated gate instance to a state-object field
209 *
210 * This method is used to create a gate for static instance objects
211 * that require a gate.
212 *
213 * @param(stateObj) the state object for the instance being created
214 * @param(fldName) a name of a field within the state object
215 *
216 * This parameter names a field that will point to the created gate
217 * instance to be created. It is a caller's responsibility
218 * to ensure that the type of `fldName` is a handle to an
219 * `IGateProvider` instance.
220 */
221 metaonly Void staticAlloc(Any stateObj, String fldName);
222 }
223 224 225
226