1 |
1026 |
ivang |
@c
|
2 |
|
|
@c COPYRIGHT (c) 1988-2002.
|
3 |
|
|
@c On-Line Applications Research Corporation (OAR).
|
4 |
|
|
@c All rights reserved.
|
5 |
|
|
@c
|
6 |
|
|
@c shmsupp.t,v 1.5 2002/01/17 21:47:44 joel Exp
|
7 |
|
|
@c
|
8 |
|
|
|
9 |
|
|
@chapter Shared Memory Support Driver
|
10 |
|
|
|
11 |
|
|
The Shared Memory Support Driver is responsible for providing glue
|
12 |
|
|
routines and configuration information required by the Shared
|
13 |
|
|
Memory Multiprocessor Communications Interface (MPCI). The
|
14 |
|
|
Shared Memory Support Driver tailors the portable Shared
|
15 |
|
|
Memory Driver to a particular target platform.
|
16 |
|
|
|
17 |
|
|
This driver is only required in shared memory multiprocessing
|
18 |
|
|
systems that use the RTEMS mulitprocessing support. For more
|
19 |
|
|
information on RTEMS multiprocessing capabilities and the
|
20 |
|
|
MPCI, refer to the @b{Multiprocessing Manager} chapter
|
21 |
|
|
of the @b{RTEMS Application C User's Guide}.
|
22 |
|
|
|
23 |
|
|
@section Shared Memory Configuration Table
|
24 |
|
|
|
25 |
|
|
The Shared Memory Configuration Table is defined in the following
|
26 |
|
|
structure:
|
27 |
|
|
|
28 |
|
|
@example
|
29 |
|
|
@group
|
30 |
|
|
typedef volatile rtems_unsigned32 vol_u32;
|
31 |
|
|
|
32 |
|
|
typedef struct @{
|
33 |
|
|
vol_u32 *address; /* write here for interrupt */
|
34 |
|
|
vol_u32 value; /* this value causes interrupt */
|
35 |
|
|
vol_u32 length; /* for this length (0,1,2,4) */
|
36 |
|
|
@} Shm_Interrupt_information;
|
37 |
|
|
|
38 |
|
|
struct shm_config_info @{
|
39 |
|
|
vol_u32 *base; /* base address of SHM */
|
40 |
|
|
vol_u32 length; /* length (in bytes) of SHM */
|
41 |
|
|
vol_u32 format; /* SHM is big or little endian */
|
42 |
|
|
vol_u32 (*convert)(); /* neutral conversion routine */
|
43 |
|
|
vol_u32 poll_intr; /* POLLED or INTR driven mode */
|
44 |
|
|
void (*cause_intr)( rtems_unsigned32 );
|
45 |
|
|
Shm_Interrupt_information Intr; /* cause intr information */
|
46 |
|
|
@};
|
47 |
|
|
|
48 |
|
|
typedef struct shm_config_info shm_config_table;
|
49 |
|
|
@end group
|
50 |
|
|
@end example
|
51 |
|
|
|
52 |
|
|
where the fields are defined as follows:
|
53 |
|
|
|
54 |
|
|
@table @b
|
55 |
|
|
@item base
|
56 |
|
|
is the base address of the shared memory buffer used to pass
|
57 |
|
|
messages between the nodes in the system.
|
58 |
|
|
|
59 |
|
|
@item length
|
60 |
|
|
is the length (in bytes) of the shared memory buffer used to pass
|
61 |
|
|
messages between the nodes in the system.
|
62 |
|
|
|
63 |
|
|
@item format
|
64 |
|
|
is either SHM_BIG or SHM_LITTLE to indicate that the neutral format
|
65 |
|
|
of the shared memory area is big or little endian. The format
|
66 |
|
|
of the memory should be chosen to match most of the inter-node traffic.
|
67 |
|
|
|
68 |
|
|
@item convert
|
69 |
|
|
is the address of a routine which converts from native format to
|
70 |
|
|
neutral format. Ideally, the neutral format is the same as the
|
71 |
|
|
native format so this routine is quite simple.
|
72 |
|
|
|
73 |
|
|
@item poll_intr
|
74 |
|
|
is either INTR_MODE or POLLED_MODE to indicate how the node will be
|
75 |
|
|
informed of incoming messages.
|
76 |
|
|
|
77 |
|
|
@item cause_intr
|
78 |
|
|
|
79 |
|
|
@item Intr
|
80 |
|
|
is the information required to cause an interrupt on a node. This
|
81 |
|
|
structure contains the following fields:
|
82 |
|
|
@table @b
|
83 |
|
|
@item address
|
84 |
|
|
is the address to write at to cause an interrupt on that node.
|
85 |
|
|
For a polled node, this should be NULL.
|
86 |
|
|
|
87 |
|
|
@item value
|
88 |
|
|
is the value to write to cause an interrupt.
|
89 |
|
|
|
90 |
|
|
@item length
|
91 |
|
|
is the length of the entity to write on the node to cause an interrupt.
|
92 |
|
|
This can be 0 to indicate polled operation, 1 to write a byte, 2 to
|
93 |
|
|
write a sixteen-bit entity, and 4 to write a thirty-two bit entity.
|
94 |
|
|
@end table
|
95 |
|
|
@end table
|
96 |
|
|
|
97 |
|
|
@section Primitives
|
98 |
|
|
|
99 |
|
|
@subsection Convert Address
|
100 |
|
|
|
101 |
|
|
The @code{Shm_Convert_address} is responsible for converting an address
|
102 |
|
|
of an entity in the shared memory area into the address that should be
|
103 |
|
|
used from this node. Most targets will simply return the address
|
104 |
|
|
passed to this routine. However, some target boards will have a special
|
105 |
|
|
window onto the shared memory. For example, some VMEbus boards have
|
106 |
|
|
special address windows to access addresses that are normally reserved
|
107 |
|
|
in the CPU's address space.
|
108 |
|
|
|
109 |
|
|
@example
|
110 |
|
|
@group
|
111 |
|
|
void *Shm_Convert_address( void *address )
|
112 |
|
|
@{
|
113 |
|
|
return the local address version of this bus address
|
114 |
|
|
@}
|
115 |
|
|
@end group
|
116 |
|
|
@end example
|
117 |
|
|
|
118 |
|
|
@subsection Get Configuration
|
119 |
|
|
|
120 |
|
|
The @code{Shm_Get_configuration} routine is responsible for filling in the
|
121 |
|
|
Shared Memory Configuration Table passed to it.
|
122 |
|
|
|
123 |
|
|
@example
|
124 |
|
|
@group
|
125 |
|
|
void Shm_Get_configuration(
|
126 |
|
|
rtems_unsigned32 localnode,
|
127 |
|
|
shm_config_table **shmcfg
|
128 |
|
|
)
|
129 |
|
|
@{
|
130 |
|
|
fill in the Shared Memory Configuration Table
|
131 |
|
|
@}
|
132 |
|
|
@end group
|
133 |
|
|
@end example
|
134 |
|
|
|
135 |
|
|
@subsection Locking Primitives
|
136 |
|
|
|
137 |
|
|
This is a collection of routines that are invoked by the portable
|
138 |
|
|
part of the Shared Memory Driver to manage locks in the shared
|
139 |
|
|
memory buffer area. Accesses to the shared memory must be
|
140 |
|
|
atomic. Two nodes in a multiprocessor system must not be manipulating
|
141 |
|
|
the shared data structures simultaneously. The locking primitives
|
142 |
|
|
are used to insure this.
|
143 |
|
|
|
144 |
|
|
To avoid deadlock, local processor interrupts should be disabled the entire
|
145 |
|
|
time the locked queue is locked.
|
146 |
|
|
|
147 |
|
|
The locking primitives operate on the lock
|
148 |
|
|
@code{field} of the @code{Shm_Locked_queue_Control}
|
149 |
|
|
data structure. This structure is defined as follows:
|
150 |
|
|
|
151 |
|
|
@example
|
152 |
|
|
@group
|
153 |
|
|
typedef struct @{
|
154 |
|
|
vol_u32 lock; /* lock field for this queue */
|
155 |
|
|
vol_u32 front; /* first envelope on queue */
|
156 |
|
|
vol_u32 rear; /* last envelope on queue */
|
157 |
|
|
vol_u32 owner; /* receiving (i.e. owning) node */
|
158 |
|
|
@} Shm_Locked_queue_Control;
|
159 |
|
|
@end group
|
160 |
|
|
@end example
|
161 |
|
|
|
162 |
|
|
where each field is defined as follows:
|
163 |
|
|
|
164 |
|
|
@table @b
|
165 |
|
|
@item lock
|
166 |
|
|
is the lock field. Every node in the system must agree on how this
|
167 |
|
|
field will be used. Many processor families provide an atomic
|
168 |
|
|
"test and set" instruction that is used to manage this field.
|
169 |
|
|
|
170 |
|
|
@item front
|
171 |
|
|
is the index of the first message on this locked queue.
|
172 |
|
|
|
173 |
|
|
@item rear
|
174 |
|
|
is the index of the last message on this locked queue.
|
175 |
|
|
|
176 |
|
|
@item owner
|
177 |
|
|
is the node number of the node that currently has this structure locked.
|
178 |
|
|
|
179 |
|
|
@end table
|
180 |
|
|
|
181 |
|
|
@subsubsection Initializing a Shared Lock
|
182 |
|
|
|
183 |
|
|
The @code{Shm_Initialize_lock} routine is responsible for
|
184 |
|
|
initializing the lock field. This routines usually is implemented
|
185 |
|
|
as follows:
|
186 |
|
|
|
187 |
|
|
@example
|
188 |
|
|
@group
|
189 |
|
|
void Shm_Initialize_lock(
|
190 |
|
|
Shm_Locked_queue_Control *lq_cb
|
191 |
|
|
)
|
192 |
|
|
@{
|
193 |
|
|
lq_cb->lock = LQ_UNLOCKED;
|
194 |
|
|
@}
|
195 |
|
|
@end group
|
196 |
|
|
@end example
|
197 |
|
|
|
198 |
|
|
@subsubsection Acquiring a Shared Lock
|
199 |
|
|
|
200 |
|
|
The @code{Shm_Lock} routine is responsible for
|
201 |
|
|
acquiring the lock field. Interrupts should be
|
202 |
|
|
disabled while that lock is acquired. If the lock
|
203 |
|
|
is currently unavailble, then the locking routine
|
204 |
|
|
should delay a few microseconds to allow the other
|
205 |
|
|
node to release the lock. Doing this reduces bus contention
|
206 |
|
|
for the lock. This routines usually is implemented as follows:
|
207 |
|
|
|
208 |
|
|
@example
|
209 |
|
|
@group
|
210 |
|
|
void Shm_Lock(
|
211 |
|
|
Shm_Locked_queue_Control *lq_cb
|
212 |
|
|
)
|
213 |
|
|
@{
|
214 |
|
|
disable processor interrupts
|
215 |
|
|
set Shm_isrstat to previous interrupt disable level
|
216 |
|
|
|
217 |
|
|
while ( TRUE ) @{
|
218 |
|
|
atomically attempt to acquire the lock
|
219 |
|
|
if the lock was acquired
|
220 |
|
|
return
|
221 |
|
|
delay some small period of time
|
222 |
|
|
@}
|
223 |
|
|
@}
|
224 |
|
|
@end group
|
225 |
|
|
@end example
|
226 |
|
|
|
227 |
|
|
@subsubsection Releasing a Shared Lock
|
228 |
|
|
|
229 |
|
|
The @code{Shm_Unlock} routine is responsible for
|
230 |
|
|
releasing the lock field and reenabling processor
|
231 |
|
|
interrupts. This routines usually is implemented as follows:
|
232 |
|
|
|
233 |
|
|
@example
|
234 |
|
|
@group
|
235 |
|
|
void Shm_Unlock(
|
236 |
|
|
Shm_Locked_queue_Control *lq_cb
|
237 |
|
|
)
|
238 |
|
|
@{
|
239 |
|
|
set the lock to the unlocked value
|
240 |
|
|
reenable processor interrupts to their level prior
|
241 |
|
|
to the lock being acquired. This value was saved
|
242 |
|
|
in the global variable Shm_isrstat
|
243 |
|
|
@}
|
244 |
|
|
@end group
|
245 |
|
|
@end example
|
246 |
|
|
|
247 |
|
|
@section Installing the MPCI ISR
|
248 |
|
|
|
249 |
|
|
The @code{Shm_setvec} is invoked by the portable portion
|
250 |
|
|
of the shared memory to install the interrupt service routine
|
251 |
|
|
that is invoked when an incoming message is announced. Some
|
252 |
|
|
target boards support an interprocessor interrupt or mailbox
|
253 |
|
|
scheme and this is where the ISR for that interrupt would be
|
254 |
|
|
installed.
|
255 |
|
|
|
256 |
|
|
On an interrupt driven node, this routine would be implemented
|
257 |
|
|
as follows:
|
258 |
|
|
|
259 |
|
|
@example
|
260 |
|
|
@group
|
261 |
|
|
void Shm_setvec( void )
|
262 |
|
|
@{
|
263 |
|
|
install the interprocessor communications ISR
|
264 |
|
|
@}
|
265 |
|
|
@end group
|
266 |
|
|
@end example
|
267 |
|
|
|
268 |
|
|
On a polled node, this routine would be empty.
|
269 |
|
|
|