Пример #1
0
static void _log_outputf( uint64_t context, int severity, const char* prefix, const char* format, va_list list, void* std )
{
	log_timestamp_t timestamp = _log_make_timestamp();
	uint64_t tid = thread_id();
	unsigned int pid = thread_hardware();
	int need, more, remain, size = 383;
	char local_buffer[385];
	char* buffer = local_buffer;
	while(1)
	{
		//This is guaranteed to always fit in minimum size of 383 bytes defined above, so need is always > 0
		if( _log_prefix )
			need = snprintf( buffer, size, "[%u:%02u:%02u.%03u] <%" PRIx64 ":%d> %s", timestamp.hours, timestamp.minutes, timestamp.seconds, timestamp.milliseconds, tid, pid, prefix );
		else
			need = snprintf( buffer, size, "%s", prefix );

		remain = size - need;
		{
			va_list clist;
			va_copy( clist, list );
			more = vsnprintf( buffer + need, remain, format, clist );
			va_end( clist );
		}
			
		if( ( more > -1 ) && ( more < remain ) )
		{
			buffer[need+more] = '\n';
			buffer[need+more+1] = 0;

#if FOUNDATION_PLATFORM_WINDOWS
			OutputDebugStringA( buffer );
#endif

#if FOUNDATION_PLATFORM_ANDROID
			if( _log_stdout )
				__android_log_write( ANDROID_LOG_DEBUG + severity - 1, environment_application()->short_name, buffer );
#else
			if( _log_stdout && std )
				fprintf( std, "%s", buffer );
#endif

			if( _log_callback )
				_log_callback( context, severity, buffer );

			break;
		}

		if( ( more > -1 ) && ( need > -1 ) )
			size = more + need + 1;
		else
			size *= 2;

		if( buffer != local_buffer )
			memory_deallocate( buffer );
		buffer = memory_allocate( size + 2, 0, MEMORY_TEMPORARY );
	}
	if( buffer != local_buffer )
		memory_deallocate( buffer );
}
Пример #2
0
void profile_begin_block( const char* message )
{
	uint32_t parent;
	if( !_profile_enable )
		return;

	parent = get_thread_profile_block();
	if( !parent )
	{
		//Allocate new master block
		profile_block_t* block = _profile_allocate_block();
		uint32_t blockindex;
		if( !block )
			return;
		blockindex = BLOCK_INDEX( block );
		block->data.id = atomic_add32( &_profile_counter, 1 );
		string_copy( block->data.name, message, MAX_MESSAGE_LENGTH );
		block->data.processor = thread_hardware();
		block->data.thread = (uint32_t)thread_id();
		block->data.start  = time_current() - _profile_ground_time;
		set_thread_profile_block( blockindex );
	}
	else
	{
		//Allocate new child block
		profile_block_t* parentblock;
		profile_block_t* subblock = _profile_allocate_block();
		uint32_t subindex;
		if( !subblock )
			return;
		subindex = BLOCK_INDEX( subblock );
		parentblock = GET_BLOCK( parent );
		subblock->data.id = atomic_add32( &_profile_counter, 1 );
		subblock->data.parentid = parentblock->data.id;
		string_copy( subblock->data.name, message, MAX_MESSAGE_LENGTH );
		subblock->data.processor = thread_hardware();
		subblock->data.thread = (uint32_t)thread_id();
		subblock->data.start  = time_current() - _profile_ground_time;
		subblock->previous = parent;
		subblock->sibling = parentblock->child;
		if( parentblock->child )
			GET_BLOCK( parentblock->child )->previous = subindex;
		parentblock->child = subindex;
		set_thread_profile_block( subindex );
	}
}
Пример #3
0
void profile_end_block( void )
{
	uint32_t block_index = get_thread_profile_block();
	profile_block_t* block;
	if( !_profile_enable || !block_index )
		return;

	block = GET_BLOCK( block_index );
	block->data.end = time_current() - _profile_ground_time;

	if( block->previous )
	{
		unsigned int processor;
		profile_block_t* current = block;
		profile_block_t* previous = GET_BLOCK( block->previous );
		profile_block_t* parent;
		unsigned int current_index = block_index;
		unsigned int parent_index;
		while( previous->child != current_index )
		{
			current_index = current->previous; //Walk sibling list backwards
			current = GET_BLOCK( current_index );
			previous = GET_BLOCK( current->previous );
#if PROFILE_ENABLE_SANITY_CHECKS
			FOUNDATION_ASSERT( current_index != 0 );
			FOUNDATION_ASSERT( current->previous != 0 );
#endif
		}
		parent_index = current->previous; //Previous now points to parent
		parent = GET_BLOCK( parent_index );
#if PROFILE_ENABLE_SANITY_CHECKS
		FOUNDATION_ASSERT( parent_index != block_index );
#endif
		set_thread_profile_block( parent_index );

		processor = thread_hardware();
		if( parent->data.processor != processor )
		{
			const char* message = parent->data.name;
			//Thread migrated, split into new block
			profile_end_block();
			profile_begin_block( message );
		}
	}
	else
	{
		_profile_put_root_block( block_index );
		set_thread_profile_block( 0 );
	}
}
Пример #4
0
static void _profile_put_message_block( uint32_t id, const char* message )
{
	profile_block_t* subblock = 0;
	int len = (int)string_length( message );

	//Allocate new master block
	profile_block_t* block = _profile_allocate_block();
	if( !block )
		return;
	block->data.id = id;
	block->data.processor = thread_hardware();
	block->data.thread = (uint32_t)thread_id();
	block->data.start  = time_current() - _profile_ground_time;
	block->data.end = atomic_add32( &_profile_counter, 1 );
	memcpy( block->data.name, message, ( len >= MAX_MESSAGE_LENGTH ) ? MAX_MESSAGE_LENGTH : len );

	len -= MAX_MESSAGE_LENGTH;
	message += MAX_MESSAGE_LENGTH;
	subblock = block;

	while( len > 0 )
	{
		//add subblock
		profile_block_t* cblock = _profile_allocate_block();
		uint16_t cblock_index;
		if( !cblock )
			return;
		cblock_index = BLOCK_INDEX( cblock );
		cblock->data.id = id + 1;
		cblock->data.parentid = (uint32_t)subblock->data.end;
		cblock->data.processor = block->data.processor;
		cblock->data.thread = block->data.thread;
		cblock->data.start  = block->data.start;
		cblock->data.end    = atomic_add32( &_profile_counter, 1 );
		memcpy( cblock->data.name, message, ( len >= MAX_MESSAGE_LENGTH ) ? MAX_MESSAGE_LENGTH : len );

		cblock->sibling = subblock->child;
		if( cblock->sibling )
			GET_BLOCK( cblock->sibling )->previous = cblock_index;
		subblock->child = cblock_index;
		cblock->previous = BLOCK_INDEX( subblock );
		subblock = cblock;

		len -= MAX_MESSAGE_LENGTH;
		message += MAX_MESSAGE_LENGTH;
	}

	_profile_put_simple_block( BLOCK_INDEX( block ) );
}
Пример #5
0
void profile_end_frame( uint64_t counter )
{
	profile_block_t* block;
	if( !_profile_enable )
		return;

	//Allocate new master block
	block = _profile_allocate_block();
	if( !block )
		return;
	block->data.id = PROFILE_ID_ENDFRAME;
	block->data.processor = thread_hardware();
	block->data.thread = (uint32_t)thread_id();
	block->data.start  = time_current() - _profile_ground_time;
	block->data.end = counter;

	_profile_put_simple_block( BLOCK_INDEX( block ) );
}
Пример #6
0
void profile_update_block( void )
{
	char* message;
	unsigned int processor;
	uint32_t block_index = get_thread_profile_block();
	profile_block_t* block;
	if( !_profile_enable || !block_index )
		return;

	block = GET_BLOCK( block_index );
	message = block->data.name;
	processor = thread_hardware();
	if( block->data.processor == processor )
		return;

	//Thread migrated to another core, split into new block
	profile_end_block();
	profile_begin_block( message );
}