mirror of
https://git.rtems.org/rtems-docs/
synced 2025-05-15 05:39:11 +08:00
247 lines
7.5 KiB
ReStructuredText
247 lines
7.5 KiB
ReStructuredText
Shared Memory Support Driver
|
|
############################
|
|
|
|
The Shared Memory Support Driver is responsible for providing glue
|
|
routines and configuration information required by the Shared
|
|
Memory Multiprocessor Communications Interface (MPCI). The
|
|
Shared Memory Support Driver tailors the portable Shared
|
|
Memory Driver to a particular target platform.
|
|
|
|
This driver is only required in shared memory multiprocessing
|
|
systems that use the RTEMS mulitprocessing support. For more
|
|
information on RTEMS multiprocessing capabilities and the
|
|
MPCI, refer to the *Multiprocessing Manager* chapter
|
|
of the *RTEMS Application C User's Guide*.
|
|
|
|
Shared Memory Configuration Table
|
|
=================================
|
|
|
|
The Shared Memory Configuration Table is defined in the following
|
|
structure:
|
|
.. code:: c
|
|
|
|
typedef volatile uint32_t vol_u32;
|
|
typedef struct {
|
|
vol_u32 \*address; /* write here for interrupt \*/
|
|
vol_u32 value; /* this value causes interrupt \*/
|
|
vol_u32 length; /* for this length (0,1,2,4) \*/
|
|
} Shm_Interrupt_information;
|
|
struct shm_config_info {
|
|
vol_u32 \*base; /* base address of SHM \*/
|
|
vol_u32 length; /* length (in bytes) of SHM \*/
|
|
vol_u32 format; /* SHM is big or little endian \*/
|
|
vol_u32 (\*convert)(); /* neutral conversion routine \*/
|
|
vol_u32 poll_intr; /* POLLED or INTR driven mode \*/
|
|
void (\*cause_intr)( uint32_t );
|
|
Shm_Interrupt_information Intr; /* cause intr information \*/
|
|
};
|
|
typedef struct shm_config_info shm_config_table;
|
|
|
|
where the fields are defined as follows:
|
|
|
|
*base*
|
|
is the base address of the shared memory buffer used to pass
|
|
messages between the nodes in the system.
|
|
|
|
*length*
|
|
is the length (in bytes) of the shared memory buffer used to pass
|
|
messages between the nodes in the system.
|
|
|
|
*format*
|
|
is either SHM_BIG or SHM_LITTLE to indicate that the neutral format
|
|
of the shared memory area is big or little endian. The format
|
|
of the memory should be chosen to match most of the inter-node traffic.
|
|
|
|
*convert*
|
|
is the address of a routine which converts from native format to
|
|
neutral format. Ideally, the neutral format is the same as the
|
|
native format so this routine is quite simple.
|
|
|
|
*poll_intr*
|
|
is either INTR_MODE or POLLED_MODE to indicate how the node will be
|
|
informed of incoming messages.
|
|
|
|
*cause_intr*
|
|
|
|
*Intr*
|
|
|
|
is the information required to cause an interrupt on a node. This
|
|
structure contains the following fields:
|
|
|
|
*address*
|
|
|
|
is the address to write at to cause an interrupt on that node.
|
|
For a polled node, this should be NULL.
|
|
|
|
*value*
|
|
|
|
is the value to write to cause an interrupt.
|
|
|
|
*length*
|
|
|
|
is the length of the entity to write on the node to cause an interrupt.
|
|
This can be 0 to indicate polled operation, 1 to write a byte, 2 to
|
|
write a sixteen-bit entity, and 4 to write a thirty-two bit entity.
|
|
|
|
Primitives
|
|
==========
|
|
|
|
Convert Address
|
|
---------------
|
|
|
|
The ``Shm_Convert_address`` is responsible for converting an address
|
|
of an entity in the shared memory area into the address that should be
|
|
used from this node. Most targets will simply return the address
|
|
passed to this routine. However, some target boards will have a special
|
|
window onto the shared memory. For example, some VMEbus boards have
|
|
special address windows to access addresses that are normally reserved
|
|
in the CPU's address space.
|
|
.. code:: c
|
|
|
|
void \*Shm_Convert_address( void \*address )
|
|
{
|
|
return the local address version of this bus address
|
|
}
|
|
|
|
Get Configuration
|
|
-----------------
|
|
|
|
The ``Shm_Get_configuration`` routine is responsible for filling in the
|
|
Shared Memory Configuration Table passed to it.
|
|
.. code:: c
|
|
|
|
void Shm_Get_configuration(
|
|
uint32_t localnode,
|
|
shm_config_table \**shmcfg
|
|
)
|
|
{
|
|
fill in the Shared Memory Configuration Table
|
|
}
|
|
|
|
Locking Primitives
|
|
------------------
|
|
|
|
This is a collection of routines that are invoked by the portable
|
|
part of the Shared Memory Driver to manage locks in the shared
|
|
memory buffer area. Accesses to the shared memory must be
|
|
atomic. Two nodes in a multiprocessor system must not be manipulating
|
|
the shared data structures simultaneously. The locking primitives
|
|
are used to insure this.
|
|
|
|
To avoid deadlock, local processor interrupts should be disabled the entire
|
|
time the locked queue is locked.
|
|
|
|
The locking primitives operate on the lock``field`` of the ``Shm_Locked_queue_Control``
|
|
data structure. This structure is defined as follows:
|
|
.. code:: c
|
|
|
|
typedef struct {
|
|
vol_u32 lock; /* lock field for this queue \*/
|
|
vol_u32 front; /* first envelope on queue \*/
|
|
vol_u32 rear; /* last envelope on queue \*/
|
|
vol_u32 owner; /* receiving (i.e. owning) node \*/
|
|
} Shm_Locked_queue_Control;
|
|
|
|
where each field is defined as follows:
|
|
|
|
*lock*
|
|
is the lock field. Every node in the system must agree on how this
|
|
field will be used. Many processor families provide an atomic
|
|
"test and set" instruction that is used to manage this field.
|
|
|
|
*front*
|
|
is the index of the first message on this locked queue.
|
|
|
|
*rear*
|
|
is the index of the last message on this locked queue.
|
|
|
|
*owner*
|
|
is the node number of the node that currently has this structure locked.
|
|
|
|
Initializing a Shared Lock
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The ``Shm_Initialize_lock`` routine is responsible for
|
|
initializing the lock field. This routines usually is implemented
|
|
as follows:
|
|
.. code:: c
|
|
|
|
void Shm_Initialize_lock(
|
|
Shm_Locked_queue_Control \*lq_cb
|
|
)
|
|
{
|
|
lq_cb->lock = LQ_UNLOCKED;
|
|
}
|
|
|
|
Acquiring a Shared Lock
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The ``Shm_Lock`` routine is responsible for
|
|
acquiring the lock field. Interrupts should be
|
|
disabled while that lock is acquired. If the lock
|
|
is currently unavailble, then the locking routine
|
|
should delay a few microseconds to allow the other
|
|
node to release the lock. Doing this reduces bus contention
|
|
for the lock. This routines usually is implemented as follows:
|
|
.. code:: c
|
|
|
|
void Shm_Lock(
|
|
Shm_Locked_queue_Control \*lq_cb
|
|
)
|
|
{
|
|
disable processor interrupts
|
|
set Shm_isrstat to previous interrupt disable level
|
|
while ( TRUE ) {
|
|
atomically attempt to acquire the lock
|
|
if the lock was acquired
|
|
return
|
|
delay some small period of time
|
|
}
|
|
}
|
|
|
|
Releasing a Shared Lock
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The ``Shm_Unlock`` routine is responsible for
|
|
releasing the lock field and reenabling processor
|
|
interrupts. This routines usually is implemented as follows:
|
|
.. code:: c
|
|
|
|
void Shm_Unlock(
|
|
Shm_Locked_queue_Control \*lq_cb
|
|
)
|
|
{
|
|
set the lock to the unlocked value
|
|
reenable processor interrupts to their level prior
|
|
to the lock being acquired. This value was saved
|
|
in the global variable Shm_isrstat
|
|
}
|
|
|
|
Installing the MPCI ISR
|
|
=======================
|
|
|
|
The ``Shm_setvec`` is invoked by the portable portion
|
|
of the shared memory to install the interrupt service routine
|
|
that is invoked when an incoming message is announced. Some
|
|
target boards support an interprocessor interrupt or mailbox
|
|
scheme and this is where the ISR for that interrupt would be
|
|
installed.
|
|
|
|
On an interrupt driven node, this routine would be implemented
|
|
as follows:
|
|
.. code:: c
|
|
|
|
void Shm_setvec( void )
|
|
{
|
|
install the interprocessor communications ISR
|
|
}
|
|
|
|
On a polled node, this routine would be empty.
|
|
|
|
.. COMMENT: COPYRIGHT (c) 1988-2009.
|
|
|
|
.. COMMENT: On-Line Applications Research Corporation (OAR).
|
|
|
|
.. COMMENT: All rights reserved.
|
|
|