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