[ Top ] [ package ]
DESCRIPTION
set of routines to implement locks and barriers that can be used between threads belonging to the same process or between processes running on the same shared memory node (MPI, etc...)
EXAMPLES
============= increment under lock =============
static volatile int my_lock = 0;
int kount;
......
AcquireLock(&my_lock); // acquire lock
kount++; // increment variable under lock
ReleaseLock(&my_lock); // release lock
......
AcquireIdLock(&my_lock, id); // acquire lock number id (0 -> maxitems-1 , see setup_locks_and_barriers)
kount++; // increment variable under lock
ReleaseIdLock(&my_lock, id); // release lock number id
============= get a block of shared memory =============
void *ptr
int sid, localrank;
int size = ....;
.....
ierr = MPI_Comm_rank(MY_World,&localrank); // rank of this PE on this SMP node
if(localrank == 0){
ptr = allocate_safe_shared_memory(&sid, size); // create a shared memory segment and get it's address
ierr = MPI_Bcast(&sid,1,MPI_INTEGER,0,MY_World); // broadcast the segment's id
}else{ // other PEs
ierr = MPI_Bcast(&sid,1,MPI_INTEGER,0,MY_World); // get the segment's id
ptr = shmat(sid,NULL,0); // get the shared memory segment's address
}
ierr = MPI_Barrier(MY_World); // wait for all PEs to have attached the segment
============= setup of a block of shared memory for barriers and locks =============
int *next;
next = (int *) setup_locks_and_barriers(ptr, size, 16); // 16 locks, 16 barriers, point next to area that follows
// only on rank 0 normally
============= an intra-node barrier =============
ierr = MPI_Comm_rank(MY_World,&localsize); // how many PEs in MY_World on this SMP node
.....
simple_node_barrier(0, localsize); // use barrier 0 (0 -> maxitems-1 , see setup_locks_and_barriers)
[ Top ] [ Functions ]
Synopsis
acquire a lock, using 4 byte variable at address lock
the variable pointed to by lock must have been initialized to zero
and will be set to id when lock is acquired
lock : address of lock variable
id : identifier for this thread/process
Fortran interface
subroutine AcquireIdLock(lock, id) bind(C,name='AcquireIdLock')
import :: C_INT
integer(C_INT), intent(INOUT) :: lock
integer(C_INT), intent(IN), value :: id
end subroutine AcquireIdLock
ARGUMENTS
void AcquireIdLock(volatile int32_t *lock, int32_t id) //
[ Top ] [ Functions ]
Synopsis
acquire a lock, using 4 byte variable at address lock
the variable pointed to by lock must have been initialized to zero
lock : address of lock variable
Fortran interface
subroutine AcquireLock(lock) bind(C,name='AcquireLock')
import :: C_INT
integer(C_INT), intent(INOUT) :: lock
end subroutine AcquireLock
ARGUMENTS
void AcquireLock(volatile int32_t *lock) //
[ Top ] [ Functions ]
Synopsis
allocate a shared memory segment of size Bytes segment will be preventively marked for deletion (only works on linux) return address and id of shared memory segment (in sid) in case of error id is <0 and the returned address is NULL
ARGUMENTS
void *allocate_safe_shared_memory(int32_t *sid, uint32_t size) //
[ Top ] [ Functions ]
Synopsis
release a lock acquired via AcquireIdLock using 4 byte variable at address lock
attempting to release a lock that was not acquired with this id will result in a deadlock
lock : address of lock variable
id : identifier for this thread/process
Fortran interface
subroutine ReleaseIdLock(lock, id) bind(C,name='ReleaseIdLock')
import :: C_INT
integer(C_INT), intent(INOUT) :: lock
integer(C_INT), intent(IN), value :: id
end subroutine ReleaseIdLock
ARGUMENTS
void ReleaseIdLock(volatile int32_t *lock, int32_t id) //
[ Top ] [ Functions ]
Synopsis
release a lock acquired via AcquireLock using 4 byte variable at address lock
attempting to release a lock that is not acquired will result in a deadlock
Fortran interface
subroutine ReleaseLock(lock) bind(C,name='ReleaseLock')
import :: C_INT
integer(C_INT), intent(INOUT) :: lock
end subroutine ReleaseLock
ARGUMENTS
void ReleaseLock(volatile int32_t *lock) //
[ Top ] [ Functions ]
Synopsis
use memory pointed to by p to set up control tables for maxitems locks and barriers if there is not enough memory, return NULL p : base address size : amount of available memory in bytes maxitems : number of locks/barriers to allocate (will be rounded down to a multiple of 16) return the next available address (above tables)
ARGUMENTS
void *setup_locks_and_barriers(void *p, uint32_t size, uint32_t maxitems) //
[ Top ] [ Functions ]
Synopsis
implement a barrier between threads or processes (on the same SMP node)
unsophisticated version (uses "flag flip")
id : barrier (0 -> maxitems-1) is to be used (see setup_locks_and_barriers)
maxcount : number of threads/processes for this barrier
the function will return 0 upon success, 1 in case of error (invalid id)
Fortran interface
function simple_node_barrier(id, maxcount) result(status) bind(C,name='simple_node_barrier')
import :: C_INT
integer(C_INT), intent(IN), value :: id, maxcount
integer(C_INT) :: status
end function simple_node_barrier
ARGUMENTS
uint32_t simple_node_barrier(int32_t id, int32_t maxcount) //