TABLE OF CONTENTS


librkl/RPN kernel library locks and barriers [ package ]

[ 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)

librkl/AcquireIdLock [ Functions ]

[ 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)   //

librkl/AcquireLock [ Functions ]

[ 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)   //

librkl/allocate_safe_shared_memory [ Functions ]

[ 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)   //

librkl/ReleaseIdLock [ Functions ]

[ 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)   //

librkl/ReleaseLock [ Functions ]

[ 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)   //

librkl/setup_locks_and_barriers [ Functions ]

[ 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)   //

librkl/simple_node_barrier [ Functions ]

[ 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)   //