1 2 3 4 5 6 7 8 9 10 11 12
13 14 15
16 package xdc.runtime
17
18 /*!
19 * ======== IGateProvider ========
20 * Interface implemented by all gate providers
21 *
22 * Gates are used within the `xdc.runtime` package to serialize access
23 * to data structures that are used by more than one thread.
24 *
25 * Gates are responsible for ensuring that only one out of multiple threads
26 * can access a data structure at a time. There are important scheduling
27 * latency and performance considerations that affect the "type" of gate used
28 * to protect each data structure. For example, the best way to protect a
29 * shared counter is to simply disable all interrupts before the update and
30 * restore the interrupt state after the update; disabling all interrupts
31 * prevents all thread switching, so the update is guaranteed to be "atomic".
32 * Although highly efficient, this method of creating atomic sections causes
33 * serious system latencies when the time required to update the data structure
34 * can't be bounded.
35 *
36 * For example, a memory manager's list of free blocks can grow indefinitely
37 * long during periods of high fragmentation. Searching such a list with
38 * interrupts disabled would cause system latencies to also become unbounded.
39 * In this case, the best solution is to provide a gate that suspends the
40 * execution of threads that try to enter a gate that has already been
41 * entered; i.e., the gate "blocks" the thread until the thread already in the
42 * gate leaves. The time required to enter and leave the gate is greater than
43 * simply enabling and restoring interrupts, but since the time spent within
44 * the gate is relatively large, the overhead caused by entering and leaving
45 * gates will not become a significant percentage of overall system time. More
46 * importantly, threads that do not need to access the shared data structure
47 * are completely unaffected by threads that do access it.
48 *
49 * @a(Notes)
50 * Modules inheriting this interface should treat all names beginning with
51 * `Q_` as reserved words, i.e. the names from that namespace should not
52 * be used. This will allow future version of this interface to define new
53 * constants ("qualities" ) similar to `{@link #Q_BLOCKING}` and
54 * `{@link #Q_PREEMPTING}` without breaking any existing modules.
55 */
56 @DirectCall
57 interface IGateProvider {
58
59 /*!
60 * ======== Q_BLOCKING ========
61 * Blocking quality
62 *
63 * Gates with this "quality" may cause the calling thread to block;
64 * i.e., suspend execution until another thread leaves the gate.
65 */
66 const Int Q_BLOCKING = 1;
67
68 /*!
69 * ======== Q_PREEMPTING ========
70 * Preempting quality
71 *
72 * Gates with this "quality" allow other threads to preempt the thread
73 * that has already entered the gate.
74 */
75 const Int Q_PREEMPTING = 2;
76
77 /*!
78 * ======== query ========
79 * Configuration time test for a particular gate quality
80 *
81 * @param(qual) constant describing a quality
82 * @a(returns) Returns `TRUE` if the gate has the given quality,
83 * and `FALSE` otherwise, which includes the case when the gate does not
84 * recognize the constant describing the quality.
85 */
86 metaonly Bool queryMeta(Int qual);
87
88 /*!
89 * ======== query ========
90 * Runtime test for a particular gate quality
91 *
92 * @param(qual) constant describing a quality
93 * @a(returns) Returns `TRUE` if the gate has the given quality,
94 * and `FALSE` otherwise, which includes the case when the gate does not
95 * recognize the constant describing the quality.
96 */
97 Bool query(Int qual);
98
99 instance:
100
101 /*!
102 * ======== create ========
103 * Create a gate instance
104 */
105 create();
106
107 /*!
108 * ======== enter ========
109 * Enter this gate
110 *
111 * Each gate provider can implement mutual exclusion using different
112 * algorithms; e.g., disabling all scheduling, disabling the scheduling
113 * of all threads below a specified "priority level", suspending the
114 * caller when the gate has been entered by another thread and
115 * re-enabling it when the the other thread leaves the gate. However,
116 * in all cases, after this method returns that caller has exclusive
117 * access to the data protected by this gate.
118 *
119 * A thread may reenter a gate without blocking or failing.
120 *
121 * @a(returns)
122 * Returns a "key" that is used to `{@link #leave}` this gate; this
123 * value is used to restore thread preemption to the state that
124 * existed just prior to entering this gate.
125 */
126 IArg enter();
127
128 /*!
129 * ======== leave ========
130 * Leave this gate
131 *
132 * This method is only called by threads that have previously entered
133 * this gate via `{@link #enter}`. After this method returns, the
134 * caller must not access the data structure protected by this gate
135 * (unless the caller has entered the gate more than once and other
136 * calls to `leave` remain to balance the number of previous
137 * calls to `enter`).
138 *
139 * @param(key) the value returned by a matching call to
140 * `{@link #enter}`
141 */
142 Void leave(IArg key);
143 }
144 145 146
147