//TODO: Not sure if this implementation is correct. What does is mean to delete the Thread //Does Joining the thread make sure that the thread is deleted? Need to check with the Pthread API bool KThreadDelete( KThread* pThread ) { return KThreadJoin( pThread ); }
static void StartThread( void* arg ) { KMutex locks[NESTING_DEPTH - 1]; DonorThreadParams donorParams[ NESTING_DEPTH ]; TestData* pTestData = ( TestData* ) arg; for (uint32_t i = 0; i < NESTING_DEPTH - 1; i++) { char tmp[30]; bool workerMutexCreateResult = false; sprintf_s( tmp, sizeof(tmp), "Mutex %d", i ); workerMutexCreateResult = KMutexCreate( &locks[ i ], tmp ); } KMutexLock( &locks[0], WAIT_FOREVER ); ConsoleLogLine( "%s got lock, My Priority: %d", s_data.threads[0].threadName, KThreadGetPriority( &pTestData->threads[ 0 ] ) ); for ( uint32_t i = 1; i < NESTING_DEPTH; i++) { char name[16]; int thread_priority; snprintf (name, sizeof name, "thread %d", i); thread_priority = PRI_MIN + i * 3; donorParams[ i ].lockPair.first = i < NESTING_DEPTH - 1 ? locks + i : NULL; donorParams[ i ].lockPair.second = locks + i - 1; donorParams[ i ].i = i; donorParams[ i ].pThread = &pTestData->threads[ i ]; donorParams[ i ].pTestData = pTestData; KThreadCreateParams params = { .fn = DonorThreadFunction, .pStack = pTestData->stacks[ i ], .pThreadName = name, .stackSizeInBytes = sizeof( pTestData->stacks[ i ] ), .threadArg = &donorParams[i], .threadPriority = thread_priority }; ConsoleLogLine( "Starting %s with priority: %d", name, thread_priority ); TEST_ASSERT( KThreadCreate( &pTestData->threads[ i ], ¶ms ) ); /* ConsoleLogLine ("%s should have priority %d. Actual priority: %d.", name, thread_priority, KThreadGetPriority( &pTestData->threads[ i ] ) ); snprintf (name, sizeof name, "interloper %d", i); interloperParams[ i ].i = i; interloperParams[ i ].pThread = &pTestData->interloperThreads[ i ]; interloperParams[ i ].pTestData = pTestData; KThreadCreateParams paramsInterloper = { .fn = InterloperThreadFunction, .pStack = pTestData->interloperStacks[ i ], .pThreadName = name, .stackSizeInBytes = sizeof( pTestData->interloperStacks[ i ] ), .threadArg = &interloperParams[ i ], .threadPriority = thread_priority - 1, }; TEST_ASSERT( KThreadCreate( &pTestData->interloperThreads[ i ], ¶msInterloper ) ); */ } TEST_ASSERT_EQUAL_INT( NESTING_DEPTH - 1, pTestData->currentThreadIndexToRelease ); KMutexUnlock( &locks[ 0 ] ); /* ConsoleLogLine("%s finishing with priority %d.\n", KThreadGetName( &pTestData->threads[ 0 ] ), KThreadGetPriority( &pTestData->threads[ 0 ] ) ); */ TEST_ASSERT( KThreadJoin( &pTestData->threads[ 1 ] ) && KThreadJoin( &pTestData->interloperThreads[ 1 ] ) ); } static void TestPriorityDonateChain( void ) { TestData* pTestData = &s_data; pTestData->currentThreadIndexToRelease = 0; KThreadCreateParams startThread = { .fn = StartThread, .pStack = pTestData->stacks[ 0 ], .pThreadName = "StartThread", .stackSizeInBytes = THREAD_STACK_SIZE, .threadArg = pTestData, .threadPriority = PRI_MIN, }; pTestData->currentThreadIndexToRelease = 0; bool startThreadCreateResult = KThreadCreate( &pTestData->threads[ 0 ], &startThread ); TEST_ASSERT( startThreadCreateResult ); //Test ends when StartThread Ends bool waitForStartThreadEnd = KThreadJoin( &pTestData->threads[ 0 ] ); TEST_ASSERT( waitForStartThreadEnd ); } static void DonorThreadFunction( void *args ) { DonorThreadParams* pParams = ( DonorThreadParams* )args; if (pParams->lockPair.first) KMutexLock(pParams->lockPair.first, WAIT_FOREVER ); ConsoleLogLine( "%s priority %d, Actual priority: %d\n", KThreadGetName( pParams->pThread ), KThreadGetPriority( pParams->pThread ) ); TEST_ASSERT_EQUAL_INT( pParams->i - 1, pParams->pTestData->currentThreadIndexToRelease ); pParams->pTestData->currentThreadIndexToRelease = pParams->i; KMutexLock(pParams->lockPair.second, WAIT_FOREVER ); TEST_ASSERT_EQUAL_INT( NESTING_DEPTH - pParams->i, pParams->pTestData->currentThreadIndexToRelease ); pParams->pTestData->currentThreadIndexToRelease = NESTING_DEPTH - ( pParams->i + 1 ); KMutexUnlock(pParams->lockPair.second); /* ConsoleLogLine ("%s should have priority %d. Actual priority: %d\n", KThreadGetName( pParams->pThread ), (NESTING_DEPTH - 1) * 3, KThreadGetPriority( pParams->pThread ) ); */ if (pParams->lockPair.first) KMutexUnlock(pParams->lockPair.first); /* ConsoleLogLine("%s finishing with priority %d.\n", KThreadGetName( pParams->pThread ), KThreadGetPriority( pParams->pThread ) ); */ }