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
27 * are important scheduling latency and performance considerations that
28 * affect the "type" of gate used to protect each data structure. For
29 * example, the best way to protect a shared counter is to simply disable
30 * all interrupts before the update and restore the interrupt state after
31 * the update; disabling all interrupts prevents all thread switching, so
32 * the update is guaranteed to be "atomic". Although highly efficient, this
33 * method of creating atomic sections causes serious system latencies when
34 * the time required to update the data structure 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
42 * already in the gate leaves. The time required to enter and leave the
43 * gate is greater than simply enabling and restoring interrupts, but since
44 * the time spent within the gate is relatively large, the overhead caused by
45 * entering and leaving gates will not become a significant percentage of
46 * overall system time. More importantly, threads that do not need to
47 * access the shared data structure are completely unaffected by threads
48 * that do access it.
49 *
50 * @a(Notes)
51 * Modules inheriting this interface should treat all names beginning with
52 * `Q_` as reserved words, i.e. the names from that namespace should not
53 * be used. This will allow future version of this interface to define new
54 * constants ("qualities" ) similar to `{@link #Q_BLOCKING}` and
55 * `{@link #Q_PREEMPTING}` without breaking any existing modules.
56 */
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