#include "ga.h"
/* Instead of using a static variable, we could attach these to 
   a communicator, using a communicator attribute */
static MPI_Win *GA_mutex_wins = 0;
static int      GA_mutex_nwins = 0;

int ga_create_mutexes( int num )
{
    int size, nwin, i;

    MPI_Comm_size( MPI_COMM_WORLD, &size );
    
    nwin = (num + size - 1) / size;
    
    GA_mutex_wins = (MPI_Win *)malloc( nwin * sizeof(MPI_Win) );
    if (!GA_mutex_wins) return 1;
    
    for (i=0; i<nwin; i++) {
	if (num < size) size = num;
	MPE_Mutex_create( MPI_COMM_WORLD, size, &GA_mutex_wins[i] );
	num -= size;
    }
    
    GA_mutex_nwins = nwin;
    return 0;
}

int ga_destroy_mutexes( void )
{
  int i;

  for (i=0; i<GA_mutex_nwins; i++) {
    MPI_Lock_free( &GA_mutex_wins[i] );
  }

  free( GA_mutex_wins );
  return 0;
}

void ga_lock( int n )
{
  int size, rank, win_num;

  MPI_Comm_size( MPI_COMM_WORLD, &size );
  win_num = n / size;
  rank    = n % size;
  MPE_Mutex_lock( rank, GA_mutex_wins[win_num] );
}

void ga_unlock( int n )
{
  int size, rank, win_num;

  MPI_Comm_size( MPI_COMM_WORLD, &size );
  win_num = n / size;
  rank    = n % size;
  MPE_Mutex_unlock( rank, GA_mutex_wins[win_num] );
}
