CTLSStorageInstance *CTLSStorageInstance::AllocateInstance(tlsindextype iValueCount, unsigned int uiInitializationFlags)
{
	size_t nSizeRequired = sizeof(CTLSStorageInstance);

	CTLSStorageInstance *psiNewInstance = (CTLSStorageInstance *)AllocateMemoryBlock(nSizeRequired);
	
	if (psiNewInstance)
	{
		new(psiNewInstance) CTLSStorageInstance(iValueCount, uiInitializationFlags);
	}
	
	return psiNewInstance;
}
CTLSStorageArray *CTLSStorageArray::AllocateInstance(tlsindextype iValueCount)
{
	const size_t nHeaderSize = CTLSStorageArray::GetHeaderSize();
	const size_t nBlockSize = CTLSStorageBlock::GetRequiredSize(iValueCount);
	size_t nRequiredSize = nHeaderSize + nBlockSize * TLS_ARRAY_ELEMENT__MAX;

	CTLSStorageArray *psaNewInstance = (CTLSStorageArray *)AllocateMemoryBlock(nRequiredSize);
	
	if (psaNewInstance)
	{
		memset(psaNewInstance, 0, nRequiredSize);
		new((CTLSStorageArray *)psaNewInstance) CTLSStorageArray();

		psaNewInstance->AssignAllBlocksHostArray(iValueCount);
	}

	return psaNewInstance;
}
BufferPool_Generic_c::BufferPool_Generic_c(     BufferManager_Generic_t   Manager,
						BufferDataDescriptor_t   *Descriptor, 
						unsigned int              NumberOfBuffers,
						unsigned int              Size,
						void                     *MemoryPool[3],
						void                     *ArrayOfMemoryBlocks[][3],
						char			 *DeviceMemoryPartitionName )
{
unsigned int            i,j;
BufferStatus_t          Status;
Buffer_Generic_t        Buffer;
unsigned int            ItemSize;

//

    InitializationStatus        = BufferError;

    //
    // Initialize class data
    //

    this->Manager               = Manager;
    Next                        = NULL;

    OS_InitializeMutex( &Lock );
    OS_InitializeEvent( &BufferReleaseSignal );

    ReferenceCount		= 0;

    BufferDescriptor            = NULL;
    this->NumberOfBuffers       = 0;
    CountOfBuffers              = 0;
    this->Size                  = 0;

    ListOfBuffers               = NULL;
    FreeBuffer                  = NULL;
    this->MemoryPool[0]         = NULL;
    this->MemoryPool[1]         = NULL;
    this->MemoryPool[2]         = NULL;
    MemoryPoolAllocator         = NULL;
    MemoryPoolAllocatorDevice   = ALLOCATOR_INVALID_DEVICE;
    memset( MemoryPartitionName, 0x00, ALLOCATOR_MAX_PARTITION_NAME_SIZE );
    if( DeviceMemoryPartitionName != NULL )
	strncpy( MemoryPartitionName, DeviceMemoryPartitionName, ALLOCATOR_MAX_PARTITION_NAME_SIZE-1 );

    BufferBlock                 = NULL;
    ListOfMetaData              = NULL;

    AbortGetBuffer              = false;
    BufferReleaseSignalWaitedOn = false;

    CountOfReferencedBuffers	= 0;
    TotalAllocatedMemory	= 0;
    TotalUsedMemory		= 0;

    //
    // Record parameters
    //

    this->BufferDescriptor      = Descriptor;
    this->NumberOfBuffers       = NumberOfBuffers;
    this->Size                  = Size;

    if( MemoryPool != NULL )
    {
	this->MemoryPool[0]     = MemoryPool[0];
	this->MemoryPool[1]     = MemoryPool[1];
	this->MemoryPool[2]     = MemoryPool[2];
    }

    //
    // Shall we create the buffer class instances
    //

    if( NumberOfBuffers != NOT_SPECIFIED )
    {
	//
	// Get a ring to hold the free buffers
	//

	FreeBuffer      = new RingGeneric_c(NumberOfBuffers);
	if( (FreeBuffer == NULL) || (FreeBuffer->InitializationStatus != RingNoError) )
	{
	    report( severity_error, "BufferPool_Generic_c::BufferPool_Generic_c - Failed to create free buffer ring.\n" );
	    TidyUp();
	    return;
	}

	//
	// Can we allocate the memory for the buffers
	//

	if( Descriptor->AllocateOnPoolCreation )
	{
	    Status      = CheckMemoryParameters( Descriptor, true, Size, MemoryPool, ArrayOfMemoryBlocks, DeviceMemoryPartitionName, 
						 "BufferPool_Generic_c::BufferPool_Generic_c", &ItemSize );
	    if( Status != BufferNoError )
	    {
		TidyUp();
		return;
	    }

	    //
	    // Create a buffer block descriptor record
	    //

	    BufferBlock                         = new struct BlockDescriptor_s;
	    if( BufferBlock == NULL )
	    {
		report( severity_error, "BufferPool_Generic_c::BufferPool_Generic_c - Failed to allocate block descriptor.\n" );
		TidyUp();
		return;
	    }

	    BufferBlock->Descriptor                     = Descriptor;
	    BufferBlock->AttachedToPool                 = true;
	    BufferBlock->Size                           = ItemSize * NumberOfBuffers;
	    BufferBlock->MemoryAllocatorDevice          = ALLOCATOR_INVALID_DEVICE;

	    Status      = AllocateMemoryBlock( BufferBlock, true, 0, NULL, MemoryPool, ArrayOfMemoryBlocks, DeviceMemoryPartitionName, 
						"BufferPool_Generic_c::BufferPool_Generic_c" );
	    if( Status != BufferNoError )
	    {
		TidyUp();
		return;
	    }
	}

	//
	// Now create the buffers
	//

	for( i=0; i<NumberOfBuffers; i++ )
	{
	    Buffer              = new Buffer_Generic_c( Manager, this, Descriptor );
	    if( (Buffer == NULL) || (Buffer->InitializationStatus != BufferNoError) )
	    {
		InitializationStatus            = BufferInsufficientMemoryForBuffer;
		if( Buffer != NULL )
		{
		    InitializationStatus        = Buffer->InitializationStatus;
		    delete Buffer;
		}

		report( severity_error, "BufferPool_Generic_c::BufferPool_Generic_c - Failed to create buffer (%08x)\n", InitializationStatus );
		TidyUp();
		return;
	    }

	    Buffer->Next        = ListOfBuffers;
	    Buffer->Index       = i;
	    ListOfBuffers       = Buffer;

	    FreeBuffer->Insert( (unsigned int)Buffer );

	    //
	    // Have we allocated the buffer data block
	    //

	    if( Descriptor->AllocateOnPoolCreation )
	    {
		Buffer->DataSize                                = 0;
		Buffer->BufferBlock->AttachedToPool             = true;
		Buffer->BufferBlock->Size                       = ItemSize;
		Buffer->BufferBlock->MemoryAllocatorDevice      = ALLOCATOR_INVALID_DEVICE;
		Buffer->BufferBlock->Address[CachedAddress]     = NULL;
		Buffer->BufferBlock->Address[UnCachedAddress]   = NULL;
		Buffer->BufferBlock->Address[PhysicalAddress]   = NULL;

		if( Descriptor->AllocationSource == AllocateIndividualSuppliedBlocks )
		{
		    for( j=0; j<3; j++ )
			Buffer->BufferBlock->Address[j]         = ArrayOfMemoryBlocks[i][j];
		}
		else
		{
		    for( j=0; j<3; j++ )
			if( BufferBlock->Address[j] != NULL )
			    Buffer->BufferBlock->Address[j]     = (unsigned char *)BufferBlock->Address[j] + (i * ItemSize);
		}
	    }
	}
    }

    //
    // If we have pool memory, and we have not used it already, then we need to initialize the allocation mechanism.
    //

    if( (MemoryPool != NULL) && !Descriptor->AllocateOnPoolCreation )
    {
#if 0
	MemoryPoolAllocator     = new AllocatorSimple_c( Size, Descriptor->AllocationUnitSize, (unsigned char *)MemoryPool[PhysicalAddress] );
#else
	MemoryPoolAllocator     = new AllocatorSimple_c( Size, 1, (unsigned char *)MemoryPool[PhysicalAddress] );
#endif
	if( (MemoryPoolAllocator == NULL) || (MemoryPoolAllocator->InitializationStatus != AllocatorNoError) )
	{
	    report( severity_error, "BufferPool_Generic_c::BufferPool_Generic_c - Failed to initialize MemoryPool allocator\n" );
	    TidyUp();
	    return;
	}
    }

//

    InitializationStatus        = BufferNoError;
}
BufferStatus_t   BufferPool_Generic_c::GetBuffer(
						Buffer_t         *Buffer,
						unsigned int      OwnerIdentifier,
						unsigned int      RequiredSize,
						bool              NonBlocking,
						bool		  RequiredSizeIsLowerBound )
{
unsigned int		 i;
BufferStatus_t		 Status;
RingStatus_t		 RingStatus;
unsigned int		 ItemSize;
Buffer_Generic_t	 LocalBuffer;
unsigned long long	 EntryTime;

    //
    // Initialize the input parameters, and clear the abort flag
    //

    *Buffer             = NULL;
    AbortGetBuffer      = false;

    //
    // Perform simple parameter checks.
    //

    if( !BufferDescriptor->AllocateOnPoolCreation && (BufferDescriptor->AllocationSource != NoAllocation) )
    {
	Status  = CheckMemoryParameters( BufferDescriptor, false, RequiredSize, MemoryPool, NULL, MemoryPartitionName, 
					"BufferPool_Generic_c::GetBuffer", &ItemSize );
	if( Status != BufferNoError )
	    return Status;
    }

    //
    // Get a buffer - two different paths depending on whether or not there are a fixed number of buffers
    //

    if( NumberOfBuffers == NOT_SPECIFIED )
    {
	LocalBuffer             = new Buffer_Generic_c( Manager, this, BufferDescriptor );
	if( (LocalBuffer == NULL) || (LocalBuffer->InitializationStatus != BufferNoError) )
	{
	    if( LocalBuffer != NULL )
		delete LocalBuffer;

	    report( severity_error, "BufferPool_Generic_c::GetBuffer - Failed to create buffer\n" );
	    return BufferFailedToCreateBuffer;
	}

	OS_LockMutex( &Lock );
	LocalBuffer->Next       = ListOfBuffers;
	LocalBuffer->Index      = CountOfBuffers++;
	ListOfBuffers           = LocalBuffer;
	OS_UnLockMutex( &Lock );
    }
    else
    {
	OS_LockMutex( &Lock );
	EntryTime		= OS_GetTimeInMicroSeconds();
	do
	{
	    OS_ResetEvent( &BufferReleaseSignal );

	    RingStatus	= FreeBuffer->Extract( (unsigned int *)(&LocalBuffer), RING_NONE_BLOCKING );

	    if( !NonBlocking && !AbortGetBuffer && (RingStatus != RingNoError) )
	    {
		BufferReleaseSignalWaitedOn     = true;
		OS_UnLockMutex( &Lock );

		OS_WaitForEvent( &BufferReleaseSignal, BUFFER_MAXIMUM_EVENT_WAIT );

		OS_LockMutex( &Lock );
		BufferReleaseSignalWaitedOn	= false;
	    }

	    /*if( (OS_GetTimeInMicroSeconds() - EntryTime) > BUFFER_MAX_EXPECTED_WAIT_PERIOD )
	    {
		report( severity_info, "BufferPool_Generic_c::GetBuffer - Waiting for a buffer of type %04x - '%s'\n", BufferDescriptor->Type, 
				(BufferDescriptor->TypeName == NULL) ? "Unnamed" : BufferDescriptor->TypeName );
		EntryTime	= OS_GetTimeInMicroSeconds();
	    }*/

		if( (OS_GetTimeInMicroSeconds() - EntryTime) > BUFFER_MAX_EXPECTED_WAIT_PERIOD )
	    {
		report( severity_info, "BufferPool_Generic_c::GetBuffer - Waiting for a buffer of type %04x - '%s'\n", BufferDescriptor->Type, 
				(BufferDescriptor->TypeName == NULL) ? "Unnamed" : BufferDescriptor->TypeName );
		EntryTime	= OS_GetTimeInMicroSeconds();
	    }

	} while( !NonBlocking && !AbortGetBuffer && (RingStatus != RingNoError) );
	OS_UnLockMutex( &Lock );

	if( RingStatus != RingNoError )
	    return BufferNoFreeBufferAvailable;
    }

    //
    // Deal with the memory
    //

    if( !BufferDescriptor->AllocateOnPoolCreation && (BufferDescriptor->AllocationSource != NoAllocation) )
    {
	LocalBuffer->BufferBlock->AttachedToPool        = true;
	LocalBuffer->BufferBlock->Size                  = ItemSize;

	Status                                          = AllocateMemoryBlock( LocalBuffer->BufferBlock, false, 0, MemoryPoolAllocator,
										MemoryPool, NULL,  MemoryPartitionName, 
										"BufferPool_Generic_c::GetBuffer",
										RequiredSizeIsLowerBound );
	if( Status != BufferNoError )
	    return Status;

    }

    LocalBuffer->DataSize               = 0;

    //
    // Record the owner identifier
    //


    LocalBuffer->OwnerIdentifier[0]     = OwnerIdentifier;
    LocalBuffer->ReferenceCount         = 1;

    for( i=1; i<MAX_BUFFER_OWNER_IDENTIFIERS; i++ )
	LocalBuffer->OwnerIdentifier[i] = UNSPECIFIED_OWNER;

    //
    // Initalize Attached buffers
    //

    for( i=0; i<MAX_ATTACHED_BUFFERS; i++ )
	LocalBuffer->AttachedBuffers[i] = NULL;

    //
    // Increment the global reference count
    //

    OS_LockMutex( &Lock );
    ReferenceCount++;
    CountOfReferencedBuffers++;
    OS_UnLockMutex( &Lock );

    //
    // Set the return value
    //

    *Buffer     = LocalBuffer;

    return BufferNoError;
}
BufferStatus_t   BufferPool_Generic_c::AttachMetaData(
						MetaDataType_t    Type,
						unsigned int      Size,
						void             *MemoryPool,
						void             *ArrayOfMemoryBlocks[],
						char		 *DeviceMemoryPartitionName )
{
BufferStatus_t           Status;
unsigned int             ItemSize;
BufferDataDescriptor_t  *Descriptor;
BlockDescriptor_t        Block;
BlockDescriptor_t        SubBlock;
Buffer_Generic_t         Buffer;

    //
    // Check to see if it is already attached
    //

    for( Block	 = ListOfMetaData;
	 Block	!= NULL;
	 Block	 = Block->Next )
	if( Block->Descriptor->Type == Type )
	{
	    report( severity_info, "BufferPool_Generic_c::AttachMetaData - Meta data already attached.\n" );
	    return BufferNoError;
	}

    //
    // Get the descriptor
    //

    Status      = Manager->GetDescriptor( Type, MetaDataTypeBase, &Descriptor );
    if( Status != BufferNoError )
	return Status;

    //
    // Check the parameters and associated information to see if we can do this
    //

    Status      = CheckMemoryParameters( Descriptor, true, Size, MemoryPool, ArrayOfMemoryBlocks, DeviceMemoryPartitionName,
						 "BufferPool_Generic_c::AttachMetaData", &ItemSize );
    if( Status != BufferNoError )
	return Status;

    //
    // Create a new block descriptor record
    //

    Block       = new struct BlockDescriptor_s;
    if( Block == NULL )
    {
	report( severity_error, "BufferPool_Generic_c::AttachMetaData - Unable to create a block descriptor record.\n" );
	return BufferInsufficientMemoryForMetaData;
    }

    Block->Descriptor                   = Descriptor;
    Block->AttachedToPool               = true;
    Block->Size                         = ItemSize * NumberOfBuffers;
    Block->MemoryAllocatorDevice        = ALLOCATOR_INVALID_DEVICE;

    Status      = AllocateMemoryBlock( Block, true, 0, NULL, MemoryPool, ArrayOfMemoryBlocks, DeviceMemoryPartitionName, 
					"BufferPool_Generic_c::AttachMetaData" );
    if( Status != BufferNoError )
    {
	delete Block;
	return Status;
    }

    OS_LockMutex( &Lock );
    Block->Next                         = ListOfMetaData;
    ListOfMetaData                      = Block;
    OS_UnLockMutex( &Lock );

    //
    // Now loop assigning values to each buffer
    //

    for( Buffer  = ListOfBuffers;
	 Buffer != NULL;
	 Buffer  = Buffer->Next )
    {
	SubBlock        = new struct BlockDescriptor_s;
	if( SubBlock == NULL )
	{
	    report( severity_error, "BufferPool_Generic_c::AttachMetaData - Unable to create a block descriptor record.\n" );
	    return BufferInsufficientMemoryForMetaData;
	}

	SubBlock->Descriptor                    = Descriptor;
	SubBlock->AttachedToPool                = true;
	SubBlock->Size                          = ItemSize;
	SubBlock->MemoryAllocatorDevice         = ALLOCATOR_INVALID_DEVICE;
	SubBlock->Address[CachedAddress]        = NULL;
	SubBlock->Address[UnCachedAddress]      = NULL;
	SubBlock->Address[PhysicalAddress]      = NULL;

	if( Descriptor->AllocationSource == AllocateIndividualSuppliedBlocks )
	    SubBlock->Address[CachedAddress]    = ArrayOfMemoryBlocks[Buffer->Index];
	else
	    SubBlock->Address[CachedAddress]    = (unsigned char *)Block->Address[CachedAddress] + (Buffer->Index * ItemSize);

	OS_LockMutex( &Lock );
	SubBlock->Next                          = Buffer->ListOfMetaData;
	Buffer->ListOfMetaData                  = SubBlock;
	OS_UnLockMutex( &Lock );
    }

//

    return BufferNoError;
}