Пример #1
0
DECLARE_TEST( atomic, cas )
{
    int num_threads = 32;
    int ithread;
    object_t threads[32];
    cas_value_t cas_values[32];

    for( ithread = 0; ithread < num_threads; ++ithread )
    {
        threads[ithread] = thread_create( cas_thread, "cas", THREAD_PRIORITY_NORMAL, 0 );
        cas_values[ithread].val_32 = ithread;
        cas_values[ithread].val_64 = ithread;
        cas_values[ithread].val_ptr = (void*)(uintptr_t)ithread;
    }
    for( ithread = 0; ithread < num_threads; ++ithread )
        thread_start( threads[ithread], &cas_values[ithread] );

    test_wait_for_threads_startup( threads, num_threads );

    for( ithread = 0; ithread < num_threads; ++ithread )
        thread_destroy( threads[ithread] );

    test_wait_for_threads_exit( threads, num_threads );

    EXPECT_EQ( val_32, 0 );
    EXPECT_EQ( val_64, 0 );
    EXPECT_EQ( val_ptr, 0 );

    return 0;
}
Пример #2
0
DECLARE_TEST( error, thread )
{
	//Launch 32 threads
	object_t thread[32];
	int i;

	for( i = 0; i < 32; ++i )
	{
		thread[i] = thread_create( error_thread, "error", THREAD_PRIORITY_NORMAL, 0 );
		thread_start( thread[i], 0 );
	}

	test_wait_for_threads_startup( thread, 32 );

	test_wait_for_threads_finish( thread, 32 );

	for( i = 0; i < 32; ++i )
	{
		EXPECT_EQ( thread_result( thread[i] ), 0 );
		thread_destroy( thread[i] );
	}

	test_wait_for_threads_exit( thread, 32 );

	return 0;
}
Пример #3
0
DECLARE_TEST( mutex, sync )
{
	mutex_t* mutex;
	object_t thread[32];
	int ith;

	mutex = mutex_allocate( "test" );
	mutex_lock( mutex );

	for( ith = 0; ith < 32; ++ith )
	{
		thread[ith] = thread_create( mutex_thread, "mutex_thread", THREAD_PRIORITY_NORMAL, 0 );
		thread_start( thread[ith], mutex );
	}

	test_wait_for_threads_startup( thread, 32 );

	for( ith = 0; ith < 32; ++ith )
	{
		thread_terminate( thread[ith] );
		thread_destroy( thread[ith] );
	}

	mutex_unlock( mutex );

	test_wait_for_threads_exit( thread, 32 );

	mutex_deallocate( mutex );

	EXPECT_EQ( thread_counter, 32 * 128 );

	return 0;
}
Пример #4
0
DECLARE_TEST( profile, thread )
{
	object_t thread[32];
	int ith;
	int frame;
	error_t err = error();

	_test_profile_offset = 0;
	atomic_store32( &_test_profile_output_counter, 0 );

	profile_initialize( "test_profile", _test_profile_buffer, 30000/*_test_profile_buffer_size*/ );
	profile_enable( true );
	profile_set_output_wait( 1 );

	log_info( HASH_TEST, "This test will intentionally run out of memory in profiling system" );
	for( ith = 0; ith < 32; ++ith )
	{
		thread[ith] = thread_create( _profile_fail_thread, "profile_thread", THREAD_PRIORITY_NORMAL, 0 );
		thread_start( thread[ith], 0 );
	}

	test_wait_for_threads_startup( thread, 32 );

	for( frame = 0; frame < 1000; ++frame )
	{
		thread_sleep( 16 );
		profile_end_frame( frame );
	}

	for( ith = 0; ith < 32; ++ith )
	{
		thread_terminate( thread[ith] );
		thread_destroy( thread[ith] );
		thread_yield();
	}

	test_wait_for_threads_exit( thread, 32 );

	thread_sleep( 1000 );

	profile_enable( false );
	profile_shutdown();

	err = error();

#if BUILD_ENABLE_PROFILE
	EXPECT_GT( atomic_load32( &_test_profile_output_counter ), 0 );
	//TODO: Implement parsing output results
#else
	EXPECT_EQ( atomic_load32( &_test_profile_output_counter ), 0 );
#endif
	EXPECT_EQ( err, ERROR_NONE );

	return 0;
}
Пример #5
0
DECLARE_TEST( semaphore, threaded )
{
	object_t thread[32];
	int ith;
	int failed_waits;

	semaphore_test_t test;
	semaphore_initialize( &test.read, 0 );
	semaphore_initialize( &test.write, 0 );
	test.loopcount = 128;
	test.counter = 0;
	
	for( ith = 0; ith < 32; ++ith )
	{
		thread[ith] = thread_create( semaphore_waiter, "semaphore_waiter", THREAD_PRIORITY_NORMAL, 0 );
		thread_start( thread[ith], &test );
	}

	test_wait_for_threads_startup( thread, 32 );

	failed_waits = 0;
	for( ith = 0; ith < test.loopcount * 32; ++ith )
	{
		semaphore_post( &test.read );
		thread_yield();
		if( !semaphore_try_wait( &test.write, 200 ) )
		{
			failed_waits++;
			EXPECT_TRUE( semaphore_wait( &test.write ) );
		}
	}

	for( ith = 0; ith < 32; ++ith )
	{
		thread_terminate( thread[ith] );
		thread_destroy( thread[ith] );
		thread_yield();
	}

	test_wait_for_threads_exit( thread, 32 );

	EXPECT_EQ( test.counter, test.loopcount * 32 );
	EXPECT_EQ( failed_waits, 0 );

	semaphore_destroy( &test.read );
	semaphore_destroy( &test.write );
	
	return 0;
}
Пример #6
0
DECLARE_TEST( uuid, threaded )
{
	object_t thread[32];
	int ith, i, jth, j;
	int num_threads = math_clamp( system_hardware_threads() + 1, 3, 32 );

	for( ith = 0; ith < num_threads; ++ith )
	{
		thread[ith] = thread_create( uuid_thread_time, "uuid_thread", THREAD_PRIORITY_NORMAL, 0 );
		thread_start( thread[ith], (void*)(uintptr_t)ith );
	}

	test_wait_for_threads_startup( thread, num_threads );
	
	for( ith = 0; ith < num_threads; ++ith )
	{
		thread_terminate( thread[ith] );
		thread_destroy( thread[ith] );
	}

	test_wait_for_threads_exit( thread, num_threads );

	for( ith = 0; ith < num_threads; ++ith )
	{
		for( i = 0; i < 8192; ++i )
		{
			for( jth = ith + 1; jth < num_threads; ++jth )
			{
				for( j = 0; j < 8192; ++j )
				{
					EXPECT_FALSE( uuid_equal( uuid_thread_store[ith][i], uuid_thread_store[jth][j] ) );
				}
			}
			for( j = i + 1; j < 8192; ++j )
			{
				EXPECT_FALSE( uuid_equal( uuid_thread_store[ith][i], uuid_thread_store[ith][j] ) );
			}
		}
	}
	
	return 0;
}
Пример #7
0
DECLARE_TEST( mutex, signal )
{
	mutex_t* mutex;
	object_t thread[32];
	int ith;

	mutex = mutex_allocate( "test" );
	mutex_lock( mutex );

	for( ith = 0; ith < 32; ++ith )
	{
		thread[ith] = thread_create( thread_wait, "thread_wait", THREAD_PRIORITY_NORMAL, 0 );
		thread_start( thread[ith], mutex );
	}

	mutex_unlock( mutex );

	test_wait_for_threads_startup( thread, 32 );

	while( atomic_load32( &thread_waiting ) < 32 )
		thread_yield();
	thread_sleep( 1000 ); //Hack wait to give threads time to progress from atomic_incr to mutex_wait

	mutex_signal( mutex );

	for( ith = 0; ith < 32; ++ith )
	{
		thread_terminate( thread[ith] );
		thread_destroy( thread[ith] );
	}

	test_wait_for_threads_exit( thread, 32 );

	EXPECT_EQ( atomic_load32( &thread_waited ), 32 );

	EXPECT_FALSE( mutex_wait( mutex, 500 ) );

	mutex_deallocate( mutex );

	return 0;
}
Пример #8
0
DECLARE_TEST( atomic, add )
{
    int num_threads = 32;
    int ithread;
    object_t threads[32];

    for( ithread = 0; ithread < num_threads; ++ithread )
        threads[ithread] = thread_create( add_thread, "add", THREAD_PRIORITY_NORMAL, 0 );
    for( ithread = 0; ithread < num_threads; ++ithread )
        thread_start( threads[ithread], 0 );

    test_wait_for_threads_startup( threads, num_threads );

    for( ithread = 0; ithread < num_threads; ++ithread )
        thread_destroy( threads[ithread] );

    test_wait_for_threads_exit( threads, num_threads );

    EXPECT_EQ( val_32, 0 );
    EXPECT_EQ( val_64, 0 );

    return 0;
}
Пример #9
0
DECLARE_TEST( profile, stream )
{
	object_t thread[32];
	int ith;
	int frame;
	char* filename;

	error();

	filename = path_merge( environment_temporary_directory(), "test.profile" );
	log_infof( HASH_TEST, "Output to profile file: %s", filename );
	fs_make_directory( environment_temporary_directory() );
	_profile_stream = fs_open_file( filename, STREAM_OUT | STREAM_BINARY );
	string_deallocate( filename );

	profile_initialize( "test_profile", _test_profile_buffer, _test_profile_buffer_size );
	profile_set_output( _profile_file_writer );
	profile_set_output_wait( 10 );
	profile_enable( true );

	for( ith = 0; ith < 32; ++ith )
	{
		thread[ith] = thread_create( _profile_stream_thread, "profile_thread", THREAD_PRIORITY_NORMAL, 0 );
		thread_start( thread[ith], 0 );
	}

	test_wait_for_threads_startup( thread, 32 );

	for( frame = 0; frame < 1000; ++frame )
	{
		thread_sleep( 16 );
		profile_log( "This is a really long profile log line that should break into multiple profile blocks automatically without causing any issues whatsoever if everything works as expected which it should or the code needs to be fixed" );
		profile_end_frame( frame++ );
		if( ( frame % 30 ) == 0 )
		{
			profile_enable( false );
			thread_sleep( 10 );
			profile_enable( true );
		}
	}

	for( ith = 0; ith < 32; ++ith )
	{
		thread_terminate( thread[ith] );
		thread_destroy( thread[ith] );
		thread_yield();
	}

	test_wait_for_threads_exit( thread, 32 );

	profile_end_frame( frame++ );
	profile_set_output_wait( 100 );

	thread_sleep( 1000 );

	profile_enable( false );
	profile_shutdown();

	error();

	stream_deallocate( _profile_stream );

	//TODO: Validate that output is sane
	log_debugf( HASH_TEST, "Generated %lld blocks", atomic_load64( &_profile_generated_blocks ) );

	return 0;
}
Пример #10
0
DECLARE_TEST( event, delay_threaded )
{
	object_t thread[32];
	producer_thread_arg_t args[32] = {0};
	event_stream_t* stream;
	event_block_t* block;
	event_t* event;
	tick_t endtime, curtime, payloadtime, begintime, prevtime;
	unsigned int read[32];
	int i;
	bool running = true;
	int num_threads = math_clamp( system_hardware_threads() * 4, 4, 32 );

	stream = event_stream_allocate( 0 );
	begintime = time_current();

	for( i = 0; i < num_threads; ++i )
	{
		args[i].stream = stream;
		args[i].end_time = time_current() + ( time_ticks_per_second() * 5 );
		args[i].max_delay = time_ticks_per_second() * 5;
		args[i].sleep_time = 50;
		args[i].id = i;

		read[i] = 0;
		thread[i] = thread_create( producer_thread, "event_producer", THREAD_PRIORITY_NORMAL, 0 );
		thread_start( thread[i], &args[i] );
	}

	test_wait_for_threads_startup( thread, num_threads );

	while( running )
	{
		running = false;

		for( i = 0; i < num_threads; ++i )
		{
			if( thread_is_running( thread[i] ) )
			{
				running = true;
				break;
			}
		}

		thread_yield();

		prevtime = begintime;
		begintime = time_current();
		block = event_stream_process( stream );
		event = event_next( block, 0 );
		curtime = time_current();

		while( event )
		{
			running = true;
			++read[ event->object ];
			memcpy( &payloadtime, event->payload, sizeof( tick_t ) );

			EXPECT_GE( event_payload_size( event ), 8 );
			EXPECT_LE( event_payload_size( event ), 256 );
			EXPECT_GE( payloadtime, prevtime );
			EXPECT_GE( curtime, payloadtime );

			event = event_next( block, event );
			curtime = time_current();
		}
	}

	endtime = time_current() + ( time_ticks_per_second() * 6 );
	do
	{
		prevtime = begintime;
		begintime = time_current();
		block = event_stream_process( stream );
		event = event_next( block, 0 );
		curtime = time_current();
		while( event )
		{
			++read[ event->object ];
			memcpy( &payloadtime, event->payload, sizeof( tick_t ) );

			EXPECT_GE( event_payload_size( event ), 8 );
			EXPECT_LE( event_payload_size( event ), 256 );
			EXPECT_GE( payloadtime, prevtime );
			EXPECT_GE( curtime, payloadtime );

			event = event_next( block, event );
			curtime = time_current();
		}

		thread_sleep( 10 );

	} while( time_current() < endtime );

	for( i = 0; i < num_threads; ++i )
	{
		unsigned int should_have_read = (unsigned int)((uintptr_t)thread_result( thread[i] ));
		EXPECT_EQ( read[i], should_have_read );
		thread_terminate( thread[i] );
		thread_destroy( thread[i] );
	}

	test_wait_for_threads_exit( thread, num_threads );

	event_stream_deallocate( stream );
	
	return 0;
}