void render_buffer_lock(object_t id, unsigned int lock) { render_buffer_t* buffer = GET_BUFFER(id); if (render_buffer_ref(id) != id) return; if (lock & RENDERBUFFER_LOCK_WRITE) { atomic_incr32(&buffer->locks); buffer->access = buffer->store; } else if (lock & RENDERBUFFER_LOCK_READ) { atomic_incr32(&buffer->locks); buffer->access = buffer->store; } buffer->flags |= (lock & RENDERBUFFER_LOCK_BITS); }
static profile_block_t* _profile_allocate_block( void ) { //Grab block from free list, avoiding ABA issues by //using high 16 bit as a loop counter profile_block_t* block; uint32_t free_block_tag, free_block, next_block_tag; do { free_block_tag = atomic_load32( &_profile_free ); free_block = free_block_tag & 0xffff; next_block_tag = GET_BLOCK( free_block )->child; next_block_tag |= ( atomic_incr32( &_profile_loopid ) & 0xffff ) << 16; } while( free_block && !atomic_cas32( &_profile_free, next_block_tag, free_block_tag ) ); if( !free_block ) { static atomic32_t has_warned = {0}; if( atomic_cas32( &has_warned, 1, 0 ) ) log_error( 0, ERROR_OUT_OF_MEMORY, ( _profile_num_blocks < 65535 ) ? "Profile blocks exhausted, increase profile memory block size" : "Profile blocks exhausted, decrease profile output wait time" ); return 0; } block = GET_BLOCK( free_block ); memset( block, 0, sizeof( profile_block_t ) ); return block; }
static void* thread_waiter(void* arg) { mutex_t* mutex = arg; atomic_incr32(&thread_waiting); if (mutex_try_wait(mutex, 30000)) { atomic_incr32(&thread_waited); mutex_unlock(mutex); } else { log_warn(HASH_TEST, WARNING_SUSPICIOUS, STRING_CONST("Thread timeout")); } return 0; }
static void _profile_free_block( uint32_t block, uint32_t leaf ) { uint32_t last_tag, block_tag; do { block_tag = block | ( ( atomic_incr32( &_profile_loopid ) & 0xffff ) << 16 ); last_tag = atomic_load32( &_profile_free ); GET_BLOCK( leaf )->child = last_tag & 0xffff; } while( !atomic_cas32( &_profile_free, block_tag, last_tag ) ); }
static void* thread_wait( object_t thread, void* arg ) { mutex_t* mutex = arg; FOUNDATION_UNUSED( thread ); FOUNDATION_UNUSED( arg ); atomic_incr32( &thread_waiting ); if( mutex_wait( mutex, 30000 ) ) { atomic_incr32( &thread_waited ); mutex_unlock( mutex ); } else { log_warn( HASH_TEST, WARNING_SUSPICIOUS, "Thread timeout" ); } return 0; }
static void* inc_thread(void* arg) { int loop = 0; int icount = 0; FOUNDATION_UNUSED(arg); while (!thread_try_wait(0) && (loop < 65535)) { for (icount = 0; icount < 256; ++icount) { atomic_incr32(&val_32); atomic_incr64(&val_64); } ++loop; thread_yield(); } return 0; }
void* inc_thread( object_t thread, void* arg ) { int loop = 0; int icount = 0; while( !thread_should_terminate( thread ) && ( loop < 65535 ) ) { for( icount = 0; icount < 256; ++icount ) { atomic_incr32( &val_32 ); atomic_incr64( &val_64 ); } ++loop; thread_yield(); } return 0; }
uuid_t uuid_generate_time( void ) { uuid_time_t time_uuid; uuid_convert_t convert; int64_t current_time; int32_t current_counter; tick_t current_tick; int in = 0; uint32_t clock_seq = 0; uint64_t host_id = 0; //Allows creation of 10000 unique timestamps per millisecond current_time = time_system(); current_counter = atomic_incr32( &_uuid_last_counter ) % 10000; current_tick = ( (tick_t)current_time * 10000ULL ) + current_counter + 0x01B21DD213814000ULL; //Convert to 100ns since UUID UTC base time, October 15 1582, and add counter //We have no state so clock sequence is random clock_seq = random32(); time_uuid.time_low = (uint32_t)( current_tick & 0xFFFFFFFFULL ); time_uuid.time_mid = (uint16_t)( ( current_tick >> 32ULL ) & 0xFFFFULL ); time_uuid.time_hi_and_version = (uint16_t)( current_tick >> 48ULL ); time_uuid.clock_seq_low = ( clock_seq & 0xFF ); time_uuid.clock_seq_hi_and_reserved = ( ( clock_seq & 0x3F00 ) >> 8 ); //If hardware node ID is null, use random and set identifier (multicast) bit host_id = system_hostid(); if( host_id ) { for( in = 0; in < 6; ++in ) time_uuid.node[5-in] = (uint8_t)( ( host_id >> ( 8ULL * in ) ) & 0xFF ); } else { for( in = 0; in < 6; ++in )
static void test_profile_output( void* buffer, uint64_t size ) { FOUNDATION_UNUSED( buffer ); FOUNDATION_UNUSED( size ); atomic_incr32( &_test_profile_output_counter ); }
bool mutex_try_wait(mutex_t* mutex, unsigned int milliseconds) { #if FOUNDATION_PLATFORM_WINDOWS DWORD ret; #elif FOUNDATION_PLATFORM_POSIX || FOUNDATION_PLATFORM_PNACL struct timeval now; struct timespec then; #endif #if FOUNDATION_PLATFORM_WINDOWS #if !BUILD_DEPLOY profile_wait(STRING_ARGS(mutex->name)); #endif atomic_incr32(&mutex->waiting); ret = WaitForSingleObject(mutex->event, milliseconds); if (ret == WAIT_OBJECT_0) mutex_lock(mutex); if (atomic_decr32(&mutex->waiting) == 0) ResetEvent(mutex->event); return ret == WAIT_OBJECT_0; #elif FOUNDATION_PLATFORM_POSIX || FOUNDATION_PLATFORM_PNACL mutex_lock(mutex); if (mutex->pending) { mutex->pending = false; return true; } if (!milliseconds) { mutex_unlock(mutex); return false; } --mutex->lockcount; bool was_signal = false; if (milliseconds == 0xFFFFFFFF) { int ret = pthread_cond_wait(&mutex->cond, &mutex->mutex); if (ret == 0) { was_signal = true; } else { string_const_t errmsg = system_error_message(ret); log_errorf(0, ERROR_SYSTEM_CALL_FAIL, STRING_CONST("Unable to wait on mutex '%.*s': %.*s (%d)"), STRING_FORMAT(mutex->name), STRING_FORMAT(errmsg), ret); } } else { int ret; gettimeofday(&now, 0); then.tv_sec = now.tv_sec + (time_t)(milliseconds / 1000); then.tv_nsec = (now.tv_usec * 1000) + (long)(milliseconds % 1000) * 1000000L; while (then.tv_nsec >= 1000000000L) { ++then.tv_sec; then.tv_nsec -= 1000000000L; } ret = pthread_cond_timedwait(&mutex->cond, &mutex->mutex, &then); if (ret == 0) { was_signal = true; } else if (ret != ETIMEDOUT) { string_const_t errmsg = system_error_message(ret); log_errorf(0, ERROR_SYSTEM_CALL_FAIL, STRING_CONST("Unable to wait (timed) on mutex '%.*s': %.*s (%d)"), STRING_FORMAT(mutex->name), STRING_FORMAT(errmsg), ret); } } ++mutex->lockcount; mutex->lockedthread = thread_id(); if (was_signal) mutex->pending = false; else mutex_unlock(mutex); return was_signal; #else # error mutex_wait not implemented #endif }
bool mutex_wait( mutex_t* mutex, unsigned int timeout ) { #if FOUNDATION_PLATFORM_WINDOWS DWORD ret; #elif FOUNDATION_PLATFORM_POSIX struct timeval now; struct timespec then; #endif FOUNDATION_ASSERT( mutex ); #if FOUNDATION_PLATFORM_WINDOWS #if !BUILD_DEPLOY profile_wait( mutex->name ); #endif atomic_incr32( &mutex->waiting ); ret = WaitForSingleObject( mutex->event, ( timeout == 0 ) ? INFINITE : timeout ); if( ret == WAIT_OBJECT_0 ) mutex_lock( mutex ); if( atomic_decr32( &mutex->waiting ) == 0 ) ResetEvent( mutex->event ); return ret == WAIT_OBJECT_0; #elif FOUNDATION_PLATFORM_POSIX mutex_lock( mutex ); if( mutex->pending ) { mutex->pending = false; return true; } --mutex->lockcount; bool was_signal = false; if( !timeout ) { int ret = pthread_cond_wait( &mutex->cond, &mutex->mutex ); if( ret == 0 ) { was_signal = true; } else { log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to wait on mutex '%s': %s (%d)", mutex->name, system_error_message( ret ), ret ); } } else { int ret; gettimeofday( &now, 0 ); then.tv_sec = now.tv_sec + ( timeout / 1000 ); then.tv_nsec = ( now.tv_usec * 1000 ) + (long)( timeout % 1000 ) * 1000000L; while( then.tv_nsec > 999999999 ) { ++then.tv_sec; then.tv_nsec -= 1000000000L; } ret = pthread_cond_timedwait( &mutex->cond, &mutex->mutex, &then ); if( ret == 0 ) { was_signal = true; } else if( ret != ETIMEDOUT ) { log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to wait (timed) on mutex '%s': %s (%d)", mutex->name, system_error_message( ret ), ret ); } } ++mutex->lockcount; mutex->lockedthread = thread_id(); if( was_signal ) mutex->pending = false; else mutex_unlock( mutex ); return was_signal; #else # error mutex_wait not implemented #endif }
object_t library_load( const char* name ) { library_t* library; hash_t namehash; unsigned int i, size; uint64_t id; #if FOUNDATION_PLATFORM_WINDOWS char* dllname; HANDLE dll; #endif //Locate already loaded library library = 0; namehash = string_hash( name ); for( i = 0, size = objectmap_size( _library_map ); i < size; ++i ) { library = objectmap_raw_lookup( _library_map, i ); if( library && ( library->namehash == namehash ) ) { FOUNDATION_ASSERT( string_equal( library->name, name ) ); atomic_incr32( &library->ref ); return library->id; } } error_context_push( "loading library", name ); //Try loading library #if FOUNDATION_PLATFORM_WINDOWS dllname = string_format( "%s.dll", name ); dll = LoadLibraryA( dllname ); if( !dll ) { #if FOUNDATION_PLATFORM_ARCH_X86 string_deallocate( dllname ); dllname = string_format( "%s32.dll", name ); dll = LoadLibraryA( dllname ); #elif FOUNDATION_PLATFORM_ARCH_X86_64 string_deallocate( dllname ); dllname = string_format( "%s64.dll", name ); dll = LoadLibraryA( dllname ); #endif } string_deallocate( dllname ); if( !dll ) { log_warnf( 0, WARNING_SUSPICIOUS, "Unable to load DLL '%s': %s", name, system_error_message( 0 ) ); error_context_pop(); return 0; } #elif FOUNDATION_PLATFORM_POSIX # if FOUNDATION_PLATFORM_APPLE char* libname = string_format( "lib%s.dylib", name ); # else char* libname = string_format( "lib%s.so", name ); # endif void* lib = dlopen( libname, RTLD_LAZY ); string_deallocate( libname ); #if FOUNDATION_PLATFORM_ANDROID if( !lib ) { libname = string_format( "%s/lib%s.so", environment_executable_directory(), name ); lib = dlopen( libname, RTLD_LAZY ); string_deallocate( libname ); } #endif if( !lib ) { log_warnf( 0, WARNING_SUSPICIOUS, "Unable to load dynamic library '%s': %s", name, dlerror() ); error_context_pop(); return 0; } #else log_errorf( 0, ERROR_NOT_IMPLEMENTED, "Dynamic library loading not implemented for this platform: %s", name ); error_context_pop(); return 0; #endif id = objectmap_reserve( _library_map ); if( !id ) { #if FOUNDATION_PLATFORM_WINDOWS FreeLibrary( dll ); #elif FOUNDATION_PLATFORM_POSIX dlclose( lib ); #endif log_errorf( 0, ERROR_OUT_OF_MEMORY, "Unable to allocate new library '%s', map full", name ); error_context_pop(); return 0; } library = memory_allocate_zero( sizeof( library_t ), 0, MEMORY_PERSISTENT ); library->ref = 1; library->id = id; library->namehash = string_hash( name ); string_copy( library->name, name, 32 ); #if FOUNDATION_PLATFORM_WINDOWS library->dll = dll; #elif FOUNDATION_PLATFORM_POSIX library->lib = lib; #endif objectmap_set( _library_map, id, library ); error_context_pop(); return library->id; }