Software Reflective Memory from Citrus Controls Software Solutions for Reflective Memory
Home AmirusMM Purchase Support Consulting
 

 

Up
Installer FAQ
ManagerFAQ
ConsultantFAQ
ProgrammerFAQ

 

Frequently Asked Questions

Programmers


Table of Contents

  1. Q. How does it work?
  2. Q. How do I use reflective memory?
  3. Q. What kind of data can I keep in reflective memory?
  4. Q. Can I share data in reflective memory between different application processes on the same system?
  5. Q. Do I need to serialize access to shared data in reflective memory?
  6. Q. How do I ensure that remote memory is updated consistently?
  7. Q. What happens when a new node joins an existing Ring?

Q. How does it work?

A. AmirusMM is a peer-to-peer system which ‘reflects’ memory to all nodes configured in a cooperative network.  In a typical configuration, the memory defined as part of the reflective memory area is set up as Read-Only, as far a the operating system is concerned.  When an application writes to this memory location, a fault exception is generated which triggers code to store the change in a transmit FIFO before actually writing the data into memory.  The transmit FIFO is drained when the node is given “permission to talk” by other nodes in the network.  As other nodes talk on the network, the local node updates its copy of the local memory.

Back to Top

Q. How do I use reflective memory?

A. You use it in the same way as you would use ordinary memory, but first you must connect to it using a special subroutine call.  This subroutine returns a pointer to the memory as it is mapped, just as malloc would return a memory address when allocating ordinary memory.  How much memory gets mapped is determined by the configuration, which is established before any applications that use the memory are started.  The size of the memory area is returned in the map call.

Memory regions are referred to by name, and you can determine their specific characteristics by a subroutine call if you are interested,

If you are using MATLAB, an optional interface hides these details, allowing you to read and write scalars and arrays through MATLAB class objects. If you are using Visual Basic .NET, there is an optional interface to simplify data management too, since VB.NET gives you limited options to arrange data at specific memory locations.

Back to Top

Q. What kind of data can I keep in reflective memory?

A. You can keep any kind of information you like in AmirusMM memory except program stacks.  Any instruction which reads or writes data into memory can be used, but implicit references to memory through the stack pointer (SP) are forbidden.

If you execute an instruction which attempts an implicit write (PUSH, CALL, ENTER, etc., with the processor stack pointer (SP) set to an AmirusMM address), your thread will generate a write protection violation. If this exception is not caught, the thread will exit.

Back to Top

Q. Can I share data in reflective memory between different application processes on the same system?

A. Yes. AmirusMM shared memory can be used as ordinary shared memory between different applications.  Each application may map the memory into different addresses in its own address space, but it is the same memory.

But unlike ordinary shared memory, applications sharing Amirus memory can request that they be notified when another process writes to memory. A subroutine call requests this notification on a per-process basis.

Back to Top

Q. Do I need to serialize access to shared data in reflective memory?

A. If you are writing to the same memory from different applications or machines, yes.  The usual methods are needed to make sure that different threads don’t fall over themselves when writing to mirror memory on a local system. If you need to lock memory throughout the system (including memory on other nodes too), you must use the global locking API in addition to the local mechanisms. If you don't do this, or don't rigorously enforce a design where nodes talk only to their own areas of memory, memory on different nodes can become inconsistent.

The API provides for 32 global locks, numbered 0 through 31. You can request access to a lock at either "Shared" or "Exclusive" level. "Shared" locks are granted even if other nodes also have the lock "Shared"; however, they are not granted if another node has the lock "Exclusive". "Exclusive" locks are granted only if no other node has the lock.

Typically, you use a "Shared" lock if you are attempting read-only access and want to guarantee that no other node is writing into the memory area. Other nodes just reading (who will also have the "Shared" lock) can proceed in parallel. You use the "Exclusive" lock if you want read-write access to the area -- you won't be granted the lock until all readers release their "Shared" lock.

The locking facility is "advisory" -- you must ensure that all processes accessing the memory area use the same convention for memory access. There is nothing to prevent a process writing to any memory location if it has the ability to map the shared memory in use. Establishing a convention that you must have (for example) Lock 13 to access structure _fred is all that is required to ensure coherent access. This is similar to locking semantics found on some versions of Unix.

Conflicting lock requests are granted in round-robin order, which ensures that each node has an equal share of lock access. Locks owned by a node that fails automatically become available again for other nodes to request. There is no deadlock detection available at system level; however, lock requests can have associated timeouts, allowing you to implement your own deadlock resolution protocol if you so wish.

Back to Top

Q. How do I ensure that remote memory is updated consistently?

A. One way is to use "Synchronized" memory. Synchronized memory guarantees that changes you make to local memory are propagated to every node before the writing thread on the local node executes the next instruction. This adds a significant time penalty to your local process, as it is suspended until all other nodes have been updated.

The AmirusMMsystem guarantees that the order of writes on one system is the same as the perceived order of reads on each and every remote system. This is true even if the remote systems have multiple processors. .

Unless you are using "Synchronized" memory, there is no guarantee that the remote machines will be updated at the same time - you could (and generally will be) proceeding with the next instruction in sequence while the other machines are still seeing the old data.

Note that you can maintain consistency through enforcing a system-wide policy of requiring shared memory areas to be accessed through the lock facility. This is generally a better mechanism to use, since it provides for enhanced parallelism. "Synchronized" memory is conceptually closer to synchronization mechanisms available to hardware reflective memory users, and is primarily provided as an aid for migrating hardware RM applications.

Back to Top

Q. What happens when a new node joins an existing Ring?

A. When a new node joins an existing Ring, several complex operations are performed to make sure that the memory contents in the joining member are consistent with those in all other nodes.

First, all active client programs on existing Ring members are stalled at their next write. This ensures that no more data is written into the pending buffers for transmission around the Ring. Active client programs which are reading Mirror Memory, or those not accessing memory at all are unaffected.

Next, all nodes proceed until all data they have in their output FIFO's has been transmitted to each existing Ring member. The system maintains any locks which are owned by the existing nodes. As the memory in each Ring member reaches an internally consistent state, an invitation to join the Ring is issued to the node (or nodes) which plan to join.

The existing nodes then transmit -- round robin -- the zero-compressed contents of their memory areas. Joining nodes take this data and use it to initialize their memory. Existing nodes monitor each others transmission to check it for consistency. Inconsistent memory is tagged in the system error log file. Note that inconsistent memory can arise if incorrect (or non-existent) locking calls have been made by programs writing into the same memory locations.

Finally, when all memory in the existing nodes have been properly initialized, any stalled active client programs are released and processing continues.

Nodes leaving the system by design drain all their output FIFO's prior to leaving the Ring and wait until all other members have seen the data. Any locks that that node might have been granted are released. A node leaves the system by design when the controlling server program exits -- typically 10 minutes after the last client process on that node terminates, although this timeout interval is configurable. A node also leaves by design if it follows the standard system shutdown procedure.

Nodes leaving the system because of a network outage or system failure cause a Ring timeout, which delays data transmission by some 20 milliseconds (configurable). During the recovery, the remaining nodes ensure overall consistency by exchanging previously cached packets from the failing node. Any locks that the failing node might have possessed are granted instead to any surviving node that is requesting them in round-robin order. In this way, data consistency is assured in any network configuration and in all possible failure scenarios, including partial connections (where some machines might become invisible to some, but not all, others).

Back to Top
 

Take a two minute tour of Amirus' advanced features!

 Comments about this web site? Please let us know.
 Copyright © 2003, 2004 Citrus Controls Incorporated
 Last modified: Monday January 26, 2004