/* **============================================================================== ** ** Open Management Infrastructure (OMI) ** ** Copyright (c) Microsoft Corporation ** ** Licensed under the Apache License, Version 2.0 (the "License"); you may not ** use this file except in compliance with the License. You may obtain a copy ** of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABLITY OR NON-INFRINGEMENT. ** ** See the Apache 2 License for the specific language governing permissions ** and limitations under the License. ** **============================================================================== */ #include #include #include #include #include #include /* Include network headers */ #if defined(CONFIG_OS_WINDOWS) #elif defined(CONFIG_POSIX) # include # include #endif #if defined(_MSC_VER) #undef BEGIN_EXTERNC #undef END_EXTERNC #define BEGIN_EXTERNC #define END_EXTERNC #endif using namespace std; static void setUp() { } static void cleanup() { } struct ThreadParam { int args[2]; bool thread_id_match; ThreadHandle t; }; BEGIN_EXTERNC static void* MI_CALL proc(void* param) { ThreadParam* p = (ThreadParam*)param; ut::sleep_ms( 1 ); // delay comparison p->thread_id_match = (ThreadSelf() == p->t); p->args[0] = 1; // thread started ut::sleep_ms( 40 ); p->args[1] = 1; // done with sleep return 0; } END_EXTERNC static void TestThreadCreateWait() { ThreadParam param = {{0,0},false}; UT_ASSERT(MI_RESULT_OK == Thread_Create( proc, ¶m, ¶m.t)); UT_ASSERT(ThreadSelf() != param.t); for( int i = 0; !param.args[0]; i++ ) { ut::sleep_ms( 1 ); // give 1/2 of a sec to start UT_ASSERT( i < 500 ); } // wait for completion and check that UT_ASSERT(MI_RESULT_OK == Thread_Destroy( param.t, MI_TRUE )); UT_ASSERT( 1 == param.args[1] ); UT_ASSERT(param.thread_id_match); } static void TestThreadCreateDontWait() { ThreadParam param = {{0,0},false}; UT_ASSERT(MI_RESULT_OK == Thread_Create( proc, ¶m, ¶m.t)); UT_ASSERT(ThreadSelf() != param.t); for( int i = 0; !param.args[0]; i++ ) { ut::sleep_ms( 1 ); // give 1/2 of a sec to start UT_ASSERT( i < 500 ); } //UT_ASSERT( 0 == param.args[1] ); // don't wait for completion and check that UT_ASSERT(MI_RESULT_OK == Thread_Destroy( param.t, MI_FALSE )); //UT_ASSERT( 0 == param.args[1] ); // keep local variable alive until thread is done with it for( int i = 0; !param.args[1]; i++ ) { ut::sleep_ms( 1 ); // give 1/2 of a sec to finish UT_ASSERT( i < 500 ); } UT_ASSERT(param.thread_id_match); } struct ThreadMutexParam { int args[2]; Mutex mt; }; BEGIN_EXTERNC static void* MI_CALL procMutext(void* param) { ThreadMutexParam* p = (ThreadMutexParam*)param; ut::sleep_ms( 1 ); for ( int i = 0; i < 10000; i++ ) { Mutex_Lock(&p->mt); // args has to be identical if mutext works properly UT_ASSERT(p->args[0] == p->args[1]); p->args[1] = rand(); p->args[0] = p->args[1]; Mutex_Unlock(&p->mt); } return 0; } END_EXTERNC static void TestMutex() { ThreadMutexParam param = {{0,0}}; UT_ASSERT(MI_RESULT_OK == Mutex_Init(¶m.mt)); ThreadHandle t[2]; UT_ASSERT(MI_RESULT_OK == Thread_Create( procMutext, ¶m, &t[0])); UT_ASSERT(MI_RESULT_OK == Thread_Create( procMutext, ¶m, &t[1])); // don't wait for completion and check that UT_ASSERT(MI_RESULT_OK == Thread_Destroy( t[0], MI_TRUE )); UT_ASSERT(MI_RESULT_OK == Thread_Destroy( t[1], MI_TRUE )); UT_ASSERT(MI_RESULT_OK == Mutex_Destroy(¶m.mt)); } static void RunTests() { UT_TEST(TestThreadCreateWait); UT_TEST(TestThreadCreateDontWait); UT_TEST(TestMutex); } UT_ENTRY_POINT(RunTests);