DECLARE_TEST(objectmap, thread) { objectmap_t* map; thread_t thread[32]; size_t ith; size_t num_threads = math_clamp(system_hardware_threads() * 4, 4, 32); map = objectmap_allocate((num_threads + 1) * 512); for (ith = 0; ith < num_threads; ++ith) thread_initialize(&thread[ith], objectmap_thread, map, STRING_CONST("objectmap_thread"), THREAD_PRIORITY_NORMAL, 0); for (ith = 0; ith < num_threads; ++ith) thread_start(&thread[ith]); test_wait_for_threads_startup(thread, num_threads); test_wait_for_threads_finish(thread, num_threads); for (ith = 0; ith < num_threads; ++ith) EXPECT_EQ(thread[ith].result, 0); for (ith = 0; ith < num_threads; ++ith) thread_finalize(&thread[ith]); objectmap_deallocate(map); return 0; }
DECLARE_TEST(atomic, cas) { size_t num_threads = math_clamp(system_hardware_threads() * 4, 4, 32); size_t ithread; thread_t threads[32]; cas_value_t cas_values[32]; for (ithread = 0; ithread < num_threads; ++ithread) { cas_values[ithread].val_32 = (int32_t)ithread; cas_values[ithread].val_64 = (int64_t)ithread; cas_values[ithread].val_ptr = (void*)(uintptr_t)ithread; thread_initialize(&threads[ithread], cas_thread, &cas_values[ithread], STRING_CONST("cas"), THREAD_PRIORITY_NORMAL, 0); } for (ithread = 0; ithread < num_threads; ++ithread) thread_start(&threads[ithread]); test_wait_for_threads_startup(threads, num_threads); test_wait_for_threads_finish(threads, num_threads); for (ithread = 0; ithread < num_threads; ++ithread) thread_finalize(&threads[ithread]); EXPECT_EQ(atomic_load32(&val_32), 0); EXPECT_EQ(atomic_load64(&val_64), 0); EXPECT_EQ(atomic_loadptr(&val_ptr), 0); return 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; }
DECLARE_TEST(atomic, add) { size_t num_threads = math_clamp(system_hardware_threads() * 4, 4, 32); size_t ithread; thread_t threads[32]; for (ithread = 0; ithread < num_threads; ++ithread) thread_initialize(&threads[ithread], add_thread, 0, STRING_CONST("add"), THREAD_PRIORITY_NORMAL, 0); for (ithread = 0; ithread < num_threads; ++ithread) thread_start(&threads[ithread]); test_wait_for_threads_startup(threads, num_threads); test_wait_for_threads_finish(threads, num_threads); for (ithread = 0; ithread < num_threads; ++ithread) thread_finalize(&threads[ithread]); EXPECT_EQ(atomic_load32(&val_32), 0); EXPECT_EQ(atomic_load64(&val_64), 0); return 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; }