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 @RomConsts
64
65 module Gate {
66
67 /*!
68 * ======== Ref ========
69 * Opaque reference to an allocated gate instance
70 */
71 @Encoded typedef xdc.runtime.IGateProvider.Handle Ref;
72
73 /*!
74 * ======== allocInstance ========
75 * Allocate a gate instance from the current module's gate
76 *
77 * This method is used by modules to create gates at runtime using
78 * the same `IGateProvider` that was used to create the module
79 * level gate. The parameters passed to the `IGateProvider` are
80 * specified at configuration time via the
81 * `{@link Types#Common$ Types.Common$.gateParams}`
82 * configuration parameter.
83 *
84 * @param(eb) `Error` block pointer
85 *
86 * If `NULL`, any error in creating the instance will terminate
87 * the application.
88 *
89 * @a(returns)
90 * Non-`NULL` instance handle is returned if no error occurs; otherwise
91 * an error is raised in `eb` and `NULL` is returned.
92 *
93 * @see IGateProvider
94 * @see Error
95 */
96 @Macro Ref allocInstance(Error.Block *eb);
97
98 /*!
99 * ======== freeInstance ========
100 * Free a gate instance to the current module's gatekeeper
101 *
102 * @param(gate) non-`NULL` return value from a prior call to
103 * `{@link #allocInstance}`.
104 *
105 * @see #allocInstance
106 */
107 @Macro Void freeInstance(Ref gate);
108
109 /*!
110 * ======== enterInstance ========
111 * Enter a critical section protected by this gate instance
112 *
113 * @param(gate) non-`NULL` return value from a prior call to
114 * `{@link #allocInstance}`.
115 *
116 * @a(returns)
117 * Returns a "key" value that must be used to leave `gate`
118 * via `{@link #leaveInstance()}`.
119 *
120 */
121 @Macro IArg enterInstance(Ref gate);
122
123 /*!
124 * ======== enterModule ========
125 * Enter a critical section protected by the current module's gate
126 *
127 * @a(returns)
128 * Returns a "key" value that must be used to leave the current module
129 * gate via `{@link #leaveModule()}`.
130 *
131 * @see #leaveModule
132 */
133 @Macro IArg enterModule();
134
135 /*!
136 * ======== enterSystem ========
137 * Enter a critical section protected by the global System gate
138 *
139 * @a(returns)
140 * Returns a "key" value that must be used to leave the `{@link System}`
141 * gate via `{@link #leaveSystem()}`.
142 *
143 * @see #leaveSystem
144 */
145 IArg enterSystem();
146
147 /*!
148 * ======== leaveInstance ========
149 * Leave a critical section protected by a gate
150 *
151 * @param(gate) non-`NULL` return value from a prior call to
152 * `{@link #allocInstance}`.
153 * @param(key) the return value of a prior call to
154 * `{@link #enterInstance}`
155 *
156 * @see #enterInstance
157 * @see #allocInstance
158 */
159 @Macro Void leaveInstance(Ref gate, IArg key);
160
161 /*!
162 * ======== leaveModule ========
163 * Leave a critical section protected by the current module's gate
164 *
165 * @param(key) the return value of a prior call to `{@link #enterModule}`
166 *
167 * @see #enterModule
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 Void leaveSystem(IArg key);
180
181 /*!
182 * ======== canBlock ========
183 * Check if the module level gate can block threads
184 *
185 * This type of gate should never be called by clients that must never
186 * call a "blocking" RTOS operation; e.g., interrupt service
187 * routines
188 *
189 * @a(returns) Returns `TRUE` if the underlying gatekeeper's gate can
190 * block
191 */
192 @Macro Bool canBlock();
193
194 /*!
195 * ======== canBePreempted ========
196 * Check if the module level gate allows thread preemption
197 *
198 * This type of gate should always be used by clients that protect
199 * a data structure whose updates require more than a small
200 * constant amount of time; e.g., update of a memory allocator's free
201 * list.
202 *
203 * @a(returns) Returns `TRUE` if the underlying gate does not disable
204 * thread preemption.
205 */
206 @Macro Bool canBePreempted();
207
208 /*!
209 * ======== staticAlloc ========
210 * Assign a statically-allocated gate instance to a state-object field
211 *
212 * This method is used to create a gate for static instance objects
213 * that require a gate.
214 *
215 * @param(stateObj) the state object for the instance being created
216 * @param(fldName) a name of a field within the state object
217 *
218 * This parameter names a field that will point to the created gate
219 * instance to be created. It is a caller's responsibility
220 * to ensure that the type of `fldName` is a handle to an
221 * `IGateProvider` instance.
222 */
223 metaonly Void staticAlloc(Any stateObj, String fldName);
224 }
225 226 227
228