Ejemplo n.º 1
0
bool PoolCreate( MemPool* pPool, uint8_t* pBackingBuffer, uint32_t backingBufferSize, uint32_t numUnits, uint32_t* pFreeBits )
{
  bool retval = false;
  if ( pPool && pBackingBuffer && pFreeBits ) {
    if ( backingBufferSize % numUnits == 0 ) {
      uint32_t i = 0;
      pPool->pBackingStore = pBackingBuffer;
      pPool->numOfUnits = numUnits;
      pPool->pFreeBits = pFreeBits;
      for ( i = 0; i < CEIL_DIV( numUnits, CHAR_BIT * sizeof( uint32_t ) ); i++ ) {
        *( pFreeBits + i ) = (uint32_t)-1;
      }
      
      if ( KMutexCreate( &pPool->mutex, "PoolMutex" ) ) {
        retval = true;
      }
      else {
        LOG( "Couldn't Initialize Mutex" );
      }
    }
    else
    {
      LOG( "Can't cleanly allocate %d units from %d bytes", numUnits, backingBufferSize );
    }
  }
  return retval;
}
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 ], &params ) );
    /*
    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 ], &paramsInterloper ) );
     */
  }
  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 ) );
       */
}