next up previous contents
Next: Statistics collection Up: Porting Applications to RSIM Previous: RSIM applications library

Synchronization support for multiprocessor applications

 

The RSIM applications library supports three types of multiprocessor synchronization primitives - locks, flags (or pauses), and barriers. To use the lock and flag synchronization functions, the application must include the header file <locks.h>; for barriers, the application must include <treebar.h>.

Locks are supported through a test-and-test-and-set mechanism. The lock functions act on a single integer in a shared region (one allocated with shmalloc). These locks should be declared volatile in order to prevent the compiler from optimizing accesses to them. The macro GETLOCK(int *lock) takes a pointer to the lock as an argument and spins with a test-and-test-and-set loop until the lock is available. The macro FREELOCK(int *lock) takes a pointer to the lock as an argument and frees the lock. Both of these macros invoke functions which perform the necessary operations. These macros also include the MEMBAR instructions required for release consistency. All instructions within a lock acquire form an aggregate class of type ACQ for statistics purposes, while instructions within a lock release are aggregated as REL.

Flags are supported through an ordinary spinning mechanism. The macro WAITFLAG(int *flag, int val) spins on the flag pointed to by flag until the integer value held in that address reaches the value of val. Similarly, the macro WRITEFLAG(int *flag, int val) sets the value addressed by flag to val. The functions associated with both of these macros include the necessary MEMBAR instructions for RC. Flag instructions are not aggregated by default, as these are often used in code to form novel synchronization types (such as prefix-summing trees). If the user desires to have flags counted as an aggregate class, he or she must explicitly place a START_<agg> and END_<agg> around flag macros, where <agg> represents one of the aggregate classes discussed in Section 5.4. The aggregate class SPIN is provided specifically for this purpose; alternatively, the USR<num> aggregates can be used to isolate several independent flags.

The only type of barrier supported is a simple binary tree barrier. A tree barrier is a structure of type TreeBar and can be declared as an ordinary global variable. The function TreeBarInit(TreeBar *bar, int numprocs) is used to initialize the tree barrier to a barrier that requires the specified number of processors. This function should be called before the fork() system call is invoked. When synchronizing, each processor should call the macro TREEBAR(TreeBar *bar, int pid), where pid is the processor's unique ID number (initially determined through getpid()). The function called by this macro includes the necessary MEMBAR instructions. All instructions within a barrier are aggregated as type BAR.

The set of PARMACS macros provided with the RSIM distribution (described in Section 2.4) defines all the synchronization macros used in SPLASH and SPLASH-2 applications.

The user will need to provide any other synchronization desired (such as more advanced mutual exclusion mechanisms or barriers). The user should be careful to place the appropriate MEMBARs in any such synchronizing libraries. The macros ACQ_MEMBAR and REL_MEMBAR are provided in the header file <traps.h> for the user's convenience: ACQ_MEMBAR should be inserted after an acquire, while REL_MEMBAR should be placed before a release operation to ensure that the appropriate fence operations are used with the RC model.


next up previous contents
Next: Statistics collection Up: Porting Applications to RSIM Previous: RSIM applications library

Vijay Sadananda Pai
Thu Aug 7 14:18:56 CDT 1997