/* Copyright 2005 Chris Thomasson */


#include "../include/sys/ac_sys.h"
#include "../include/ac_rwspinlock_algo1.h"




int AC_APIDECL
ac_rwspinlock_algo1_alloc
( ac_rwspinlock_algo1_t *_this,
  ac_rwspinlock_algo1_shared_t *_shared )
{
  int ret;

  if ( ! _shared )
  {
    ac_rwspinlock_algo1_shared_padded_t *_padded;

    /* alloc and align memory */
    _padded = ac_malloc_aligned
              ( &_this->shared_mem,
                sizeof( *_padded ),
                AC_CPU_CACHE_LINE );
    if ( ! _padded ) { return ac_sys_error( ENOMEM ); }
     
    _shared = &_padded->_this;
  }

  else { _this->shared_mem = 0; }

  /* verify shared alignment */
  ret = AC_SYS_IS_MEM_ALIGNED
          ( _shared,
            AC_CPU_WORD_SIZE );
  if ( ret )
  {
    ac_free( _this->shared_mem );
    return ac_sys_error( ret );
  }

  /* init shared */
  _shared->writes = 0;
  _shared->reads = 0;

  /* init read-only */
  _this->shared = _shared;
  
  return 0;
}


int AC_APIDECL
ac_rwspinlock_algo1_free
( ac_rwspinlock_algo1_t *_this )
{
  if ( _this->shared->reads ||
       _this->shared->writes )
  {
    return ac_sys_error( EBUSY );
  }

  ac_free( _this->shared_mem );

  return 0;
}