static void* _profile_stream_thread(void* arg) { FOUNDATION_UNUSED(arg); thread_yield(); while (!thread_try_wait(4)) { profile_log(STRING_CONST("Thread message")); profile_begin_block(STRING_CONST("Thread block")); { profile_update_block(); profile_begin_block(STRING_CONST("Thread subblock")); { profile_log(STRING_CONST("Sub message")); profile_trylock(STRING_CONST("Trylock")); profile_lock(STRING_CONST("Trylock")); profile_wait(STRING_CONST("Wait")); profile_signal(STRING_CONST("Signal")); thread_sleep(2); profile_unlock(STRING_CONST("Trylock")); profile_log(STRING_CONST("End sub")); } profile_end_block(); profile_begin_block(STRING_CONST("Thread second subblock")); { profile_update_block(); profile_begin_block(STRING_CONST("Thread subblock")); { } profile_end_block(); } profile_end_block(); profile_trylock(STRING_CONST("Trylock")); thread_sleep(1); profile_lock(STRING_CONST("Trylock")); thread_sleep(4); profile_unlock(STRING_CONST("Trylock")); } profile_end_block(); atomic_add64(&_profile_generated_blocks, 14); } return 0; }
static void* _profile_stream_thread( object_t thread, void* arg ) { FOUNDATION_UNUSED( arg ); thread_yield(); while( !thread_should_terminate( thread ) ) { profile_log( "Thread message" ); profile_begin_block( "Thread block" ); { profile_update_block(); profile_begin_block( "Thread subblock" ); { profile_log( "Sub message" ); profile_trylock( "Trylock" ); profile_lock( "Trylock" ); profile_wait( "Wait" ); profile_signal( "Signal" ); thread_sleep( 2 ); profile_unlock( "Trylock" ); profile_log( "End sub" ); } profile_end_block(); profile_trylock( "Trylock" ); thread_sleep( 1 ); profile_lock( "Trylock" ); thread_sleep( 4 ); profile_unlock( "Trylock" ); } profile_end_block(); thread_sleep( 4 ); atomic_add64( &_profile_generated_blocks, 12 ); } return 0; }
static void* _profile_fail_thread(void* arg) { FOUNDATION_UNUSED(arg); thread_sleep(10); while (!thread_try_wait(1)) { profile_log(STRING_CONST("Thread message")); profile_begin_block(STRING_CONST("Thread block")); { profile_update_block(); profile_begin_block(STRING_CONST("Thread subblock")); { profile_log(STRING_CONST("Sub message")); profile_trylock(STRING_CONST("Trylock")); profile_lock(STRING_CONST("Trylock")); profile_wait(STRING_CONST("Wait")); profile_signal(STRING_CONST("Signal")); profile_unlock(STRING_CONST("Trylock")); profile_log(STRING_CONST("End sub")); thread_yield(); } profile_end_block(); } profile_end_block(); } return 0; }
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 }