sl@0: /*
sl@0: * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: * All rights reserved.
sl@0: * This component and the accompanying materials are made available
sl@0: * under the terms of "Eclipse Public License v1.0"
sl@0: * which accompanies this distribution, and is available
sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: *
sl@0: * Initial Contributors:
sl@0: * Nokia Corporation - initial contribution.
sl@0: *
sl@0: * Contributors:
sl@0: *
sl@0: * Description:
sl@0: * Name     : threadglobals.h
sl@0: * Part of  : PThread library
sl@0: * Data structures needed for ptherad library
sl@0: * Version:
sl@0: *
sl@0: */
sl@0: 
sl@0: 
sl@0: 
sl@0: #ifndef THREADGLOBALS_H
sl@0: #define THREADGLOBALS_H
sl@0: 
sl@0: #include <pthread.h>
sl@0: #include <e32std.h>
sl@0: #include <limits.h>
sl@0: #include "sysif.h"
sl@0: 
sl@0: #include <e32debug.h>
sl@0: 
sl@0: //the semaphore structure 
sl@0: struct _sem_t
sl@0: {
sl@0: 	enum sem_state
sl@0: 	{
sl@0: 		EInitialized,
sl@0: 		EDestroyed,
sl@0: 		EInvalid,
sl@0: 	};
sl@0: 	sem_state iState;
sl@0: 	int  iCount; //iCount and iMutex pair needed 
sl@0: 	             //because of need for implementing trywait
sl@0: 	RMutex 	iMutex; 
sl@0: 	RSemaphore iSemaphore;
sl@0: 	/*******************************************************************
sl@0: 	Overloading new and delete operators so that they will
sl@0: 	allocate and deallocare memory from/to the private heap of backend
sl@0: 	********************************************************************/
sl@0: 	inline TAny* operator new(TUint aSize, TAny* aBase) __NO_THROW
sl@0: 		{
sl@0: 		Mem::FillZ(aBase, aSize); return aBase;
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize) __NO_THROW
sl@0: 		{
sl@0: 		return Backend()->Alloc(aSize);
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize, TLeave)
sl@0: 		{
sl@0: 		TAny* ptr = Backend()->Alloc(aSize);
sl@0: 		if (ptr == NULL)
sl@0: 			{
sl@0: 			User::Leave(KErrNoMemory);
sl@0: 			}
sl@0: 		return ptr;
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize, TUint aExtraSize) __NO_THROW
sl@0: 		{
sl@0: 		return Backend()->Alloc(aSize + aExtraSize);
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize, TLeave, TUint aExtraSize)
sl@0: 		{
sl@0: 		TAny* ptr = Backend()->Alloc(aSize + aExtraSize);
sl@0: 		if (ptr == NULL)
sl@0: 			{
sl@0: 			User::Leave(KErrNoMemory);
sl@0: 			}
sl@0: 		return ptr;
sl@0: 		}
sl@0: 	
sl@0: 	inline void operator delete(TAny *aPtr) __NO_THROW
sl@0: 		{
sl@0: 		Backend()->Free( aPtr );
sl@0: 		}
sl@0: };
sl@0: 
sl@0: typedef struct _sem_node
sl@0: {
sl@0:     struct _sem_node *next;
sl@0:     _sem_t *sem;
sl@0: 	/*******************************************************************
sl@0: 	Overloading new and delete operators so that they will
sl@0: 	allocate and deallocare memory from/to the private heap of backend
sl@0: 	********************************************************************/
sl@0: 	inline TAny* operator new(TUint aSize, TAny* aBase) __NO_THROW
sl@0: 		{
sl@0: 		Mem::FillZ(aBase, aSize); return aBase;
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize) __NO_THROW
sl@0: 		{
sl@0: 		return Backend()->Alloc(aSize);
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize, TLeave)
sl@0: 		{
sl@0: 		TAny* ptr = Backend()->Alloc(aSize);
sl@0: 		if (ptr == NULL)
sl@0: 			{
sl@0: 			User::Leave(KErrNoMemory);
sl@0: 			}
sl@0: 		return ptr;
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize, TUint aExtraSize) __NO_THROW
sl@0: 		{
sl@0: 		return Backend()->Alloc(aSize + aExtraSize);
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize, TLeave, TUint aExtraSize)
sl@0: 		{
sl@0: 		TAny* ptr = Backend()->Alloc(aSize + aExtraSize);
sl@0: 		if (ptr == NULL)
sl@0: 			{
sl@0: 			User::Leave(KErrNoMemory);
sl@0: 			}
sl@0: 		return ptr;
sl@0: 		}
sl@0: 	
sl@0: 	inline void operator delete(TAny *aPtr) __NO_THROW
sl@0: 		{
sl@0: 		Backend()->Free( aPtr );
sl@0: 		}
sl@0: }_sem_node_t;
sl@0: 
sl@0: 
sl@0: // Thread default attributes
sl@0: #define DEFAULT_STACK_SIZE   0x2000
sl@0: #define DEFAULT_DETACH_STATE PTHREAD_CREATE_JOINABLE
sl@0: 
sl@0: #define THR_DISABLE_PTHREAD_TRACE 1
sl@0: 
sl@0: #define DEFAULT_THREAD_PRIORITY 100
sl@0: 
sl@0: #ifdef THR_DISABLE_PTHREAD_TRACE 
sl@0: 
sl@0: #define THR_PRINTF(string) \
sl@0: {\
sl@0: }
sl@0: 
sl@0: #else  //THR_DISABLE_PTHREAD_TRACE
sl@0: 
sl@0: #define THR_PRINTF(string) \
sl@0: {\
sl@0: 	#ifdef _DEBUG \
sl@0:     RDebug::Printf(string);\
sl@0:     #endif \ //_DEBUG
sl@0: }
sl@0: 
sl@0: #endif  //THR_DISABLE_PTHREAD_TRACE
sl@0: 
sl@0: #define THR_NULL_ASSERT(x,val,format) \
sl@0: { \
sl@0:     if ( (x) == NULL )  \
sl@0:     { \
sl@0:         THR_PRINTF(format); \
sl@0:         return ((void*)0); \
sl@0:     } \
sl@0: } 
sl@0: 
sl@0: #define STAT_FLAG_SIZE (PTHREAD_KEYS_MAX / 32)    
sl@0: 
sl@0: /* thread state.  */
sl@0: enum 
sl@0: {
sl@0:     _THREAD_RUNNING,
sl@0:     _THREAD_ZOMBIE
sl@0: };
sl@0: 
sl@0: /* Key status */
sl@0: enum
sl@0: {
sl@0:     _KEY_UNUSED,
sl@0:     _KEY_USED
sl@0: };
sl@0: 
sl@0: /* MainFlag */
sl@0: enum
sl@0: {
sl@0:     _MAIN_THREAD=0,
sl@0:     _NON_MAIN_THREAD
sl@0: };
sl@0: 
sl@0: typedef struct
sl@0: {
sl@0:     destructor_routine destr;
sl@0: }_pthread_key_node;
sl@0: 
sl@0: // TLS Keys link list node
sl@0: typedef struct _pkey_node
sl@0: {
sl@0:     int keyNumber;
sl@0:     struct _pkey_node *next;
sl@0:     void *tls;    
sl@0: 	/*******************************************************************
sl@0: 	Overloading new and delete operators so that they will
sl@0: 	allocate and deallocare memory from/to the private heap of backend
sl@0: 	********************************************************************/
sl@0: 	inline TAny* operator new(TUint aSize, TAny* aBase) __NO_THROW
sl@0: 		{
sl@0: 		Mem::FillZ(aBase, aSize); return aBase;
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize) __NO_THROW
sl@0: 		{
sl@0: 		return Backend()->Alloc(aSize);
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize, TLeave)
sl@0: 		{
sl@0: 		TAny* ptr = Backend()->Alloc(aSize);
sl@0: 		if (ptr == NULL)
sl@0: 			{
sl@0: 			User::Leave(KErrNoMemory);
sl@0: 			}
sl@0: 		return ptr;
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize, TUint aExtraSize) __NO_THROW
sl@0: 		{
sl@0: 		return Backend()->Alloc(aSize + aExtraSize);
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize, TLeave, TUint aExtraSize)
sl@0: 		{
sl@0: 		TAny* ptr = Backend()->Alloc(aSize + aExtraSize);
sl@0: 		if (ptr == NULL)
sl@0: 			{
sl@0: 			User::Leave(KErrNoMemory);
sl@0: 			}
sl@0: 		return ptr;
sl@0: 		}
sl@0: 	
sl@0: 	inline void operator delete(TAny *aPtr) __NO_THROW
sl@0: 		{
sl@0: 		Backend()->Free( aPtr );
sl@0: 		}
sl@0: }_pkey_node_t;
sl@0: 
sl@0: typedef struct _pthread_node _pthread_node_t;
sl@0: #ifdef __X86GCC__
sl@0: // MinGW GCC compiler does not like typedef struct definitions with no tag
sl@0: typedef struct _global_data_tag
sl@0: #else
sl@0: typedef struct _global_data_t
sl@0: #endif //__X86GCC__
sl@0: {
sl@0:     _pthread_node_t *start;
sl@0:     unsigned int threadCount;
sl@0:     RMutex lockThreadTable;
sl@0:     RMutex globalLockForMutex;
sl@0:     // TLS Keys
sl@0:     _pthread_key_node pthread_key_list[PTHREAD_KEYS_MAX];
sl@0:     unsigned int statusflag[STAT_FLAG_SIZE];
sl@0:     // Semaphore list
sl@0:     _sem_node_t *semStart;
sl@0:     RMutex lockSemTable;
sl@0: 	/*******************************************************************
sl@0: 	Overloading new and delete operators so that they will
sl@0: 	allocate and deallocare memory from/to the private heap of backend
sl@0: 	********************************************************************/
sl@0:     
sl@0: 	inline TAny* operator new(TUint aSize, TAny* aBase) __NO_THROW
sl@0: 		{
sl@0: 		Mem::FillZ(aBase, aSize); return aBase;
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize) __NO_THROW
sl@0: 		{
sl@0: 		return Backend()->Alloc(aSize);
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize, TLeave)
sl@0: 		{
sl@0: 		TAny* ptr = Backend()->Alloc(aSize);
sl@0: 		if (ptr == NULL)
sl@0: 			{
sl@0: 			User::Leave(KErrNoMemory);
sl@0: 			}
sl@0: 		return ptr;
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize, TUint aExtraSize) __NO_THROW
sl@0: 		{
sl@0: 		return Backend()->Alloc(aSize + aExtraSize);
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize, TLeave, TUint aExtraSize)
sl@0: 		{
sl@0: 		TAny* ptr = Backend()->Alloc(aSize + aExtraSize);
sl@0: 		if (ptr == NULL)
sl@0: 			{
sl@0: 			User::Leave(KErrNoMemory);
sl@0: 			}
sl@0: 		return ptr;
sl@0: 		}
sl@0: 	
sl@0: 	inline void operator delete(TAny *aPtr) __NO_THROW
sl@0: 		{
sl@0: 		Backend()->Free( aPtr );
sl@0: 		}
sl@0: 		
sl@0: 	inline void operator delete(TAny *aPtr, TLeave)
sl@0: 		{
sl@0: 		Backend()->Free( aPtr );
sl@0: 		return;
sl@0: 		}
sl@0: 		
sl@0: 	inline void operator delete(TAny *aPtr, TAny* aBase) __NO_THROW
sl@0: 		{
sl@0: 		aBase = aBase;
sl@0: 		Backend()->Free( aPtr );
sl@0: 		return;
sl@0: 		}
sl@0: 		
sl@0: 	inline void operator delete(TAny *aPtr, TUint aExtraSize) __NO_THROW
sl@0: 		{
sl@0: 		aExtraSize = aExtraSize;
sl@0: 		Backend()->Free( aPtr );
sl@0: 		return;
sl@0: 		}
sl@0: 		
sl@0: 	inline void operator delete(TAny *aPtr, TLeave, TUint aExtraSize)
sl@0: 		{
sl@0: 		aExtraSize = aExtraSize;
sl@0: 		Backend()->Free( aPtr );
sl@0: 		return;
sl@0: 		}
sl@0: 		
sl@0: 	_global_data_t();
sl@0: 	~_global_data_t();
sl@0: 
sl@0: }_global_data_t;
sl@0: 
sl@0: 
sl@0: _global_data_t* GetGlobals();
sl@0: #define glbHeadNode GetGlobals()
sl@0: 
sl@0: typedef struct _pthread_node
sl@0: {
sl@0:     struct _pthread_node *next;
sl@0:     RMutex lockNode;
sl@0:     _global_data_t *glbDataPtr;
sl@0:     unsigned int detachState;
sl@0:     unsigned int threadState;
sl@0:     void *returnValue;
sl@0:     TBool hasAnyThreadJoined;
sl@0:     RThread rtHandle;
sl@0:     unsigned int threadId;
sl@0: //    void  *tls[PTHREAD_KEYS_MAX];
sl@0:     _pkey_node_t *tlsHead;
sl@0:     int priority;
sl@0:     int mainFlag;
sl@0:     void *cleanStackPtr;
sl@0: 	/*******************************************************************
sl@0: 	Overloading new and delete operators so that they will
sl@0: 	allocate and deallocare memory from/to the private heap of backend
sl@0: 	********************************************************************/
sl@0: 	inline TAny* operator new(TUint aSize, TAny* aBase) __NO_THROW
sl@0: 		{
sl@0: 		Mem::FillZ(aBase, aSize); return aBase;
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize) __NO_THROW
sl@0: 		{
sl@0: 		return Backend()->Alloc(aSize);
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize, TLeave)
sl@0: 		{
sl@0: 		TAny* ptr = Backend()->Alloc(aSize);
sl@0: 		if (ptr == NULL)
sl@0: 			{
sl@0: 			User::Leave(KErrNoMemory);
sl@0: 			}
sl@0: 		return ptr;
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize, TUint aExtraSize) __NO_THROW
sl@0: 		{
sl@0: 		return Backend()->Alloc(aSize + aExtraSize);
sl@0: 		}
sl@0: 		
sl@0: 	inline TAny* operator new(TUint aSize, TLeave, TUint aExtraSize)
sl@0: 		{
sl@0: 		TAny* ptr = Backend()->Alloc(aSize + aExtraSize);
sl@0: 		if (ptr == NULL)
sl@0: 			{
sl@0: 			User::Leave(KErrNoMemory);
sl@0: 			}
sl@0: 		return ptr;
sl@0: 		}
sl@0: 	
sl@0: 	inline void operator delete(TAny *aPtr) __NO_THROW
sl@0: 		{
sl@0: 		Backend()->Free( aPtr );
sl@0: 		}
sl@0: }_pthread_node_t;
sl@0: 
sl@0: 
sl@0: 
sl@0: 
sl@0: #endif //THREADGLOBALS_H