/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
#include <kernel.h> // For Kern
#include "isiroutertrace.h" // For C_TRACE, ASSERT_RESET.. and fault codes
#include "isiinternaldefs.h" // For KAmountOfKernelThreads...
#include "isithreadcontainer.h" // For DISIThreadContainer
// Faults
enum TISIThreadContainerFaults
{
EISIThreadContainerDfcQAllocFailure = 0x01,
EISIThreadContainerDfcQAllocFailure1,
EISIThreadContainerUnknownThreadType,
EISIThreadContainerNULLThreadPtr,
EISIThreadContainerThreadNotFound,
EISIThreadContainerOverflow,
EISIThreadContainerOverflow1,
EISIThreadContainerUnderflow,
EISIThreadContainerUnderflow1,
};
_LIT8( KISIKernelClientThread, "ISIKernelClientThread" );
_LIT8( KISIUserClientThread, "ISIUserClientThread" );
const TInt KDefaultDfcThreadPriority( 27 );
const TUint8 KMaxThreadUsers( 255 );
const TUint8 KMaxThreadNameLength( 25 );
DISIThreadContainer::DISIThreadContainer()
{
C_TRACE( ( _T( "DISIThreadContainer::DISIThreadContainer>" ) ) );
TUint8 nameIndex = 0;
for( TUint8 i( 0 ); i < KAmountOfKernelThreads; i++ )
{
iNameTable[ nameIndex ] = HBuf8::New( KMaxThreadNameLength );
iNameTable[ nameIndex ]->Append( (&KISIKernelClientThread)->Ptr(), (&KISIKernelClientThread)->Length() );
iNameTable[ nameIndex ]->AppendNum( i, EDecimal );
Kern::DfcQCreate( iKClientDfcQueList[ i ], KDefaultDfcThreadPriority, iNameTable[ nameIndex ] );
ASSERT_RESET_ALWAYS( iKClientDfcQueList[ i ], ( EISIThreadContainerDfcQAllocFailure | EDISIThreadContainerTraceId << KClassIdentifierShift ) );
nameIndex++;
}
for( TUint8 i( 0 ); i < KAmountOfUserThreads; i++ )
{
iNameTable[ nameIndex ] = HBuf8::New( KMaxThreadNameLength );
iNameTable[ nameIndex ]->Append( (&KISIUserClientThread)->Ptr(), (&KISIUserClientThread)->Length() );
iNameTable[ nameIndex ]->AppendNum( i, EDecimal );
Kern::DfcQCreate( iUClientDfcQueList[ i ], KDefaultDfcThreadPriority, iNameTable[ nameIndex ] );
ASSERT_RESET_ALWAYS( iUClientDfcQueList[ i ], ( EISIThreadContainerDfcQAllocFailure1 | EDISIThreadContainerTraceId << KClassIdentifierShift ) );
nameIndex++;
}
C_TRACE( ( _T( "DISIThreadContainer::DISIThreadContainer<" ) ) );
}
DISIThreadContainer::~DISIThreadContainer()
{
C_TRACE( ( _T( "DISIThreadContainer::~DISIThreadContainer>" ) ) );
for( TUint8 i( 0 ); i < ( KAmountOfKernelThreads + KAmountOfUserThreads ); i++ )
{
if( iNameTable[ i ] )
{
delete iNameTable[ i ];
iNameTable[ i ] = NULL;
}
}
for( TUint8 i( 0 ); i < KAmountOfKernelThreads; i++ )
{
if( iKClientDfcQueList[ i ] )
{
delete iKClientDfcQueList[ i ];
iKClientDfcQueList[ i ] = NULL;
}
}
for( TUint8 i( 0 ); i < KAmountOfUserThreads; i++ )
{
if( iUClientDfcQueList[ i ] )
{
delete iUClientDfcQueList[ i ];
iUClientDfcQueList[ i ] = NULL;
}
}
C_TRACE( ( _T( "DISIThreadContainer::~DISIThreadContainer<" ) ) );
}
TDfcQue* DISIThreadContainer::AllocateThread( const MISIChannelRouterIf::TISIDfcQThreadType aType )
{
C_TRACE( ( _T( "DISIThreadContainer::AllocateThread %d>" ), aType ) );
TDfcQue* tmpPtr( NULL );
switch( aType )
{
case MISIChannelRouterIf::EISIKernelMainThread:
case MISIChannelRouterIf::EISIKernelRequestCompletionThread:
{
tmpPtr = ReserveKernelThread();
break;
}
case MISIChannelRouterIf::EISIUserMainThread:
case MISIChannelRouterIf::EISIUserRequestCompletionThread:
{
tmpPtr = ReserveUserThread();
break;
}
default:
{
ASSERT_RESET_ALWAYS( 0, ( EISIThreadContainerUnknownThreadType | EDISIThreadContainerTraceId << KClassIdentifierShift ) );
break;
}
}
ASSERT_RESET_ALWAYS( tmpPtr, ( EISIThreadContainerNULLThreadPtr | EDISIThreadContainerTraceId << KClassIdentifierShift ) );
C_TRACE( ( _T( "DISIThreadContainer::AllocateThread %d 0x%x<" ), aType, tmpPtr ) );
return tmpPtr;
}
TDfcQue* DISIThreadContainer::ReserveKernelThread()
{
C_TRACE( ( _T( "DISIThreadContainer::ReservekernelThread>" ) ) );
TUint8 clientCount = iKThreadOccupation[ 0 ];
TUint8 index = 0;
for( TUint8 i( 0 ) ; i < KAmountOfKernelThreads; i++ )
{
if( clientCount > iKThreadOccupation[ i ] )
{
clientCount = iKThreadOccupation[ i ];
index = i;
}
}
++iKThreadOccupation[ index ];
ASSERT_RESET_ALWAYS( iKThreadOccupation[ index ] <= KMaxThreadUsers, ( EISIThreadContainerOverflow | EDISIThreadContainerTraceId << KClassIdentifierShift ) );
C_TRACE( ( _T( "DISIThreadContainer::ReserveKernelThread 0x%x %d %d<" ), iKClientDfcQueList[ index ], iKThreadOccupation[ index ], index ) );
return iKClientDfcQueList[ index ];
}
TDfcQue* DISIThreadContainer::ReserveUserThread()
{
C_TRACE( ( _T( "DISIThreadContainer::ReserveUserThread>" ) ) );
TUint8 clientCount = iUThreadOccupation[ 0 ];
TUint8 index = 0;
for( TUint8 i( 0 ); i < KAmountOfUserThreads; i++ )
{
if( clientCount > iUThreadOccupation[ i ] )
{
clientCount = iUThreadOccupation[ i ];
index = i;
}
}
++iUThreadOccupation[ index ];
ASSERT_RESET_ALWAYS( iUThreadOccupation[ index ] <= KMaxThreadUsers, ( EISIThreadContainerOverflow1 | EDISIThreadContainerTraceId << KClassIdentifierShift ) );
C_TRACE( ( _T( "DISIThreadContainer::ReserveUserThread 0x%x %d %d<" ), iUClientDfcQueList[ index ], iUThreadOccupation[ index ], index ) );
return iUClientDfcQueList[ index ];
}
void DISIThreadContainer::DeallocateThread( TDfcQue* aThread )
{
C_TRACE( ( _T( "DISIThreadContainer::DeallocateThread 0x%x>" ), aThread ) );
TBool found( EFalse );
for( TUint8 i( 0 ) ; i < KAmountOfKernelThreads; i++ )
{
if( aThread == iKClientDfcQueList[ i ] )
{
--iKThreadOccupation[ i ];
ASSERT_RESET_ALWAYS( iKThreadOccupation[ i ] != KMaxThreadUsers, ( EISIThreadContainerUnderflow | EDISIThreadContainerTraceId << KClassIdentifierShift ) );
C_TRACE( ( _T( "DISIThreadContainer DeallocKThread 0x%x %d %d>" ), aThread, iKThreadOccupation[ i ], i ) );
found = ETrue;
break;
}
}
if( !found )
{
for( TUint8 i( 0 ) ; i < KAmountOfUserThreads; i++ )
{
if( aThread == iUClientDfcQueList[ i ] )
{
--iUThreadOccupation[ i ];
ASSERT_RESET_ALWAYS( iUThreadOccupation[ i ] != KMaxThreadUsers, ( EISIThreadContainerUnderflow1 | EDISIThreadContainerTraceId << KClassIdentifierShift ) );
C_TRACE( ( _T( "DISIThreadContainer DeallocUThread 0x%x %d %d>" ), aThread, iUThreadOccupation[ i ], i ) );
found = ETrue;
break;
}
}
}
ASSERT_RESET_ALWAYS( found, ( EISIThreadContainerThreadNotFound | EDISIThreadContainerTraceId << KClassIdentifierShift ) );
C_TRACE( ( _T( "DISIThreadContainer::DeallocateThread 0x%x<" ), aThread ) );
}