#include "../include/sys/ac_sys.h"
#include "../include/ac_eventcount_algo1.h"
int AC_APIDECL
ac_eventcount_algo1_alloc
( ac_eventcount_algo1_t *_this,
ac_eventcount_algo1_shared_t *_shared )
{
int ret;
if ( ! _shared )
{
ac_eventcount_algo1_shared_padded_t *_padded;
_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; }
ret = AC_SYS_IS_MEM_ALIGNED
( _shared,
AC_CPU_WORD_SIZE );
if ( ret )
{
ac_free( _this->shared_mem );
return ac_sys_error( ret );
}
_shared->ec = 0;
_shared->waiters = 0;
ret = pthread_cond_init( &_this->cond, 0 );
if ( ret )
{
ac_free( _this->shared_mem );
return ac_sys_error( ret );
}
ret = pthread_mutex_init( &_this->mutex, 0 );
if ( ret )
{
pthread_mutex_destroy( &_this->mutex );
ac_free( _this->shared_mem );
return ac_sys_error( ret );
}
_this->shared = _shared;
return 0;
}
int AC_APIDECL
ac_eventcount_algo1_free
( ac_eventcount_algo1_t *_this )
{
int ret;
if ( _this->shared->waiters )
{
return ac_sys_error( EBUSY );
}
ret = pthread_cond_destroy( &_this->cond );
if ( ret ) { return ac_sys_error( ret ); }
ret = pthread_mutex_destroy( &_this->mutex );
if ( ret ) { return ac_sys_error( ret ); }
ac_free( _this->shared_mem );
return 0;
}
int AC_APIDECL
ac_prv_eventcount_algo1_signal
( ac_eventcount_algo1_t *_this )
{
ac_intword_t waiters;
ac_eventcount_cmp_t cmp, old;
int ret = pthread_mutex_lock( &_this->mutex );
if ( ret ) { return ac_sys_error( ret ); }
old = _this->shared->ec;
do
{
cmp = old;
old = ac_atomic_cas_acquire
( &_this->shared->ec,
cmp,
( cmp + 1 ) & 0x7FFFFFFF );
}
while ( cmp != old );
waiters = _this->shared->waiters;
_this->shared->waiters = 0;
ret = pthread_mutex_unlock( &_this->mutex );
if ( ret ) { return ac_sys_error( ret ); }
if ( waiters )
{
ret = pthread_cond_broadcast( &_this->cond );
if ( ret ) { return ac_sys_error( ret ); }
}
return 0;
}
int AC_APIDECL
ac_eventcount_algo1_timedwait
( ac_eventcount_algo1_t *_this,
ac_thread_t *_tls,
ac_eventcount_cmp_t cmp,
ac_timeout_t timeout )
{
AC_UNUSED( _tls );
AC_UNUSED( timeout );
if ( ( (ac_eventcount_cmp_t)ac_mb_load_acquire
( &_this->shared->ec ) & 0x7FFFFFFF ) == cmp )
{
int ret = pthread_mutex_lock( &_this->mutex );
if ( ret ) { return ac_sys_error( ret ); }
if ( ( (ac_eventcount_cmp_t)ac_mb_load_naked
( &_this->shared->ec ) & 0x7FFFFFFF ) == cmp )
{
++_this->shared->waiters;
ret = pthread_cond_wait( &_this->cond, &_this->mutex );
if ( ret ) { return ac_sys_error( ret ); }
}
ret = pthread_mutex_unlock( &_this->mutex );
if ( ret ) { return ac_sys_error( ret ); }
}
return 0;
}