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 entered;
41 * i.e., the gate "blocks" the thread until the thread already in the gate
42 * leaves. The time required to enter and leave the gate is greater than simply
43 * enabling and restoring interrupts, but since the time spent within the gate is
44 * relatively large, the overhead caused by entering and leaving gates will not
45 * become a significant percentage of overall system time. More importantly,
46 * threads that do not need to access the shared data structure are completely
47 * 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
67 const Int Q_BLOCKING = 1;
68
69 /*!
70 * ======== Q_PREEMPTING ========
71 * Preempting quality
72 *
73 * Gates with this "quality" allow other threads to preempt the thread
74 * that has already entered the gate.
75 */
76
77 const Int Q_PREEMPTING = 2;
78
79 /*!
80 * ======== query ========
81 * Configuration time test for a particular gate quality
82 *
83 * @param(qual) constant describing a quality
84 * @a(returns) Returns `TRUE` if the gate has the given quality,
85 * and `FALSE` otherwise, which includes the case when the gate does not
86 * recognize the constant describing the quality.
87 */
88 metaonly Bool queryMeta(Int qual);
89
90 /*!
91 * ======== query ========
92 * Runtime test for a particular gate quality
93 *
94 * @param(qual) constant describing a quality
95 * @a(returns) Returns `TRUE` if the gate has the given quality,
96 * and `FALSE` otherwise, which includes the case when the gate does not
97 * recognize the constant describing the quality.
98 */
99
100 Bool query(Int qual);
101
102 instance:
103
104 /*!
105 * ======== create ========
106 * Create a gate instance
107 */
108 create();
109
110 /*!
111 * ======== enter ========
112 * Enter this gate
113 *
114 * Each gate provider can implement mutual exclusion using different
115 * algorithms; e.g., disabling all scheduling, disabling the scheduling
116 * of all threads below a specified "priority level", suspending the caller
117 * when the gate has been entered by another thread and re-enabling it when
118 * the the other thread leaves the gate. However, in all cases, after this
119 * method returns that caller has exclusive access to the data protected by
120 * this gate.
121 *
122 * A thread may reenter a gate without blocking or failing.
123 *
124 * @a(returns)
125 * Returns a "key" that is used to `{@link #leave}` this gate; this value
126 * is used to restore thread preemption to the state that existed just
127 * prior to entering this gate.
128 */
129 IArg enter();
130
131 /*!
132 * ======== leave ========
133 * Leave this gate
134 *
135 * This method is only called by threads that have previously entered this
136 * gate via `{@link #enter}`. After this method returns, the caller must
137 * not access the data structure protected by this gate (unless the caller
138 * has entered the gate more than once and other calls to `leave` remain
139 * to balance the number of previous calls to `enter`).
140 *
141 * @param(key) the value returned by a matching call to `{@link #enter}`
142 */
143 Void leave(IArg key);
144 }
145 146 147
148