os/ossrv/genericopenlibs/openenvcore/libpthread/src/pthreadmisc.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // Name     : pthreadmisc.cpp
    15 // Part of  : PThread library
    16 // Thread Miscellaneous functions are implemented in this file.
    17 // Version:
    18 //
    19 
    20 
    21 
    22 #include <pthread.h>
    23 #include <stdio.h>
    24 #include <errno.h>
    25 #include <e32base.h>
    26 #include "threadglobals.h"
    27 
    28 #define THREAD_NAME_WIDTH 8
    29 #define THREAD_COUNT_ZERO 0
    30 #define MAX_THREAD_CREATE_FAILURE_COUNT 20
    31 #define MAX_THREAD_NAME_LEN 255
    32 
    33 #ifdef __EPOC32__
    34 class XPthreadTLSCleanup
    35 	{
    36 public:
    37 	~XPthreadTLSCleanup()
    38 		{
    39 		Dll::FreeTls();
    40 		}
    41 	};
    42 
    43 // Create a global here. It's desctructor invoked on libpthread unload will reset libpthread's TLS
    44 XPthreadTLSCleanup gPthreadTLSCleanup;
    45 #endif
    46 
    47 int _copy_already_defined_keys(_pthread_node_t* prev_node, _pthread_node_t* new_node);
    48 
    49 // Internal Function
    50 // return : NULL - means no memory
    51 void* _pthread_getTls()
    52 {
    53     _pthread_node_t *selfNodePtr;
    54     _global_data_t *glbPtr = glbHeadNode;
    55     
    56     THR_PRINTF("[pthread] Begin _pthread_getTls\n");
    57     // Get the TLS contents. 
    58     TAny *tlsAddr = Dll::Tls();
    59     
    60     // If TLS is already initialised then just return the node address
    61     if (NULL != tlsAddr)
    62     {
    63         THR_PRINTF("[pthread] End _pthread_getTls\n");
    64         return ((void*) tlsAddr);
    65     }
    66     
    67     // Create node for main thread and also global data structure.
    68     selfNodePtr = new _pthread_node_t;
    69     THR_NULL_ASSERT(selfNodePtr,NULL,
    70           "[pthread] FATAL: Memory alloc failed for threadnode");
    71     
    72     //Initialize the node
    73     selfNodePtr->next = NULL;
    74     if (selfNodePtr->lockNode.CreateLocal() != KErrNone)
    75     {
    76         delete selfNodePtr;
    77         THR_PRINTF("[pthread] FATAL :Mutex create failed");
    78         return ((void*)NULL);        
    79     }
    80     selfNodePtr->glbDataPtr = glbPtr;
    81     selfNodePtr->detachState = PTHREAD_CREATE_JOINABLE;
    82     selfNodePtr->threadState = _THREAD_RUNNING;
    83     selfNodePtr->returnValue = NULL;
    84     selfNodePtr->hasAnyThreadJoined = EFalse;
    85     selfNodePtr->threadId = (TUint)selfNodePtr->rtHandle.Id();
    86     selfNodePtr->priority = DEFAULT_THREAD_PRIORITY; 
    87     selfNodePtr->mainFlag = _MAIN_THREAD;
    88     selfNodePtr->tlsHead = NULL;
    89     selfNodePtr->cleanStackPtr = NULL; //added to solve memory leak problem
    90 
    91 //    Insert the node in to the global linked list and increment thread count.
    92     glbPtr->lockThreadTable.Wait();
    93 	//copy the already defined keys
    94 	if( _copy_already_defined_keys(glbPtr->start, selfNodePtr))
    95 	{
    96 		delete selfNodePtr;
    97         THR_PRINTF("[pthread] FATAL :failed copying defined keys");
    98 		
    99 		glbPtr->lockThreadTable.Signal();
   100         return NULL;
   101 	}
   102     selfNodePtr->next = glbPtr->start;
   103     
   104 	glbPtr->start = selfNodePtr;
   105     glbPtr->threadCount++;
   106 	
   107     glbPtr->lockThreadTable.Signal();
   108         
   109     //Set node address to TLS
   110     Dll::SetTls((TAny*)selfNodePtr);
   111     THR_PRINTF("[pthread] End _pthread_getTls\n");
   112     
   113     // libc needs to know whether application is multithreaded or not...
   114     __isthreaded = 1;
   115     
   116     return ((void*) selfNodePtr);
   117 }
   118 
   119 int _copy_already_defined_keys(_pthread_node_t* prev_node, _pthread_node_t* new_node)
   120 {
   121 	if(!prev_node || !new_node)
   122 		return 0;
   123 
   124 	_pkey_node_t *tlsPtr;
   125 	_pkey_node_t *newTlsPtr, *prevTlsPtr=NULL;
   126     for (tlsPtr = prev_node->tlsHead; tlsPtr != NULL; tlsPtr = tlsPtr->next)
   127 	{
   128 		newTlsPtr = new _pkey_node_t;
   129 		if (NULL == newTlsPtr)
   130         {
   131             return -1;
   132         }
   133 		if(new_node->tlsHead == NULL)
   134 			new_node->tlsHead = newTlsPtr;
   135 		else{
   136 			prevTlsPtr->next = newTlsPtr;
   137 		}
   138         newTlsPtr->tls = NULL;
   139         newTlsPtr->keyNumber = tlsPtr->keyNumber;
   140 		prevTlsPtr = newTlsPtr;
   141 	}
   142 	 
   143 	return 0;
   144 }
   145 
   146 // This function has to be called holding global lock and node lock.
   147 // Before returning all lock will be opened
   148 void _pthread_deleteNode(_pthread_node_t *selfNodePtr, 
   149                            _global_data_t *glbPtr,
   150                            void ** retValPtr)
   151 {
   152     _pthread_node_t *tempPtr;
   153     _pthread_node_t *prevPtr = NULL;
   154     
   155     THR_PRINTF("[pthread] Begin _pthread_deleteNode\n");
   156     // Traverse through the list, till node which has to be deleted is found
   157     for (tempPtr = glbPtr->start; 
   158          ((tempPtr != selfNodePtr) && (tempPtr != NULL)); 
   159          tempPtr = tempPtr->next)
   160     {
   161         prevPtr = tempPtr;             // Store the previous node ptr
   162     }
   163     
   164     if (NULL == tempPtr)              //Not found; this should never happen
   165     {
   166         THR_PRINTF("[pthread] FATAL: Unable to delete the node");
   167         selfNodePtr->lockNode.Signal();
   168         glbPtr->lockThreadTable.Signal();  //release global lock
   169         return;
   170     }
   171     if (tempPtr == glbPtr->start)       // Deleting first node
   172     {
   173         glbPtr->start = tempPtr->next;  //Update the link list
   174     }
   175     else
   176     {
   177         prevPtr->lockNode.Wait();       //Acquire the previous node lock
   178         prevPtr->next = tempPtr->next;  //Update the link list
   179         prevPtr->lockNode.Signal();     //Release the previous node lock
   180     }
   181     
   182     if (NULL != retValPtr)               // Get the return value
   183     {
   184         *retValPtr = selfNodePtr->returnValue;
   185     }
   186 
   187     selfNodePtr->lockNode.Signal();     // Unlock & Free the node 
   188     selfNodePtr->lockNode.Close();
   189     selfNodePtr->rtHandle.Close();
   190     
   191     delete selfNodePtr;
   192 
   193     //--(glbPtr->threadCount);           // Update the thread count
   194     //if (THREAD_COUNT_ZERO == glbPtr->threadCount)
   195     //{
   196     //    RProcess rp;
   197     //    rp.Kill(0);                    // Terminate the process
   198     //}
   199     
   200     glbPtr->lockThreadTable.Signal();  // release thread table lock
   201     THR_PRINTF("[pthread] End of _pthread_deleteNode\n");
   202 }
   203 
   204 
   205 void* _getKeyValueSetNull(int keyNumber,_pkey_node_t *tlsPtr)
   206 {
   207     void* retVal;
   208     for ( ; tlsPtr != NULL; tlsPtr = tlsPtr->next)
   209     {
   210         if (tlsPtr->keyNumber == keyNumber)
   211         {
   212                 retVal = tlsPtr->tls;
   213                 tlsPtr->tls = NULL;
   214                 return (retVal);
   215         }
   216     }
   217     //This should never happen; hence dest function will not be called
   218     return NULL;
   219 }
   220 // Before calling this function, global lock and node lock must be open
   221 void _pthread_destroyKeys(_global_data_t *glbPtr,
   222                             _pthread_node_t *selfNodePtr)
   223 {
   224     int loopvar;
   225     int allempty;
   226     int keyNumber;
   227     destructor_routine dest;
   228     void *arg;
   229     
   230     glbPtr->lockThreadTable.Wait();    // Acquire the thread table lock
   231     selfNodePtr->lockNode.Wait();      // Lock the TCB
   232 
   233     for (loopvar = 0, allempty = 1;
   234         allempty && (loopvar < PTHREAD_DESTRUCTOR_ITERATIONS);loopvar++) 
   235     {
   236         allempty = 0; // Assuming all keys are not used.
   237         
   238         for (keyNumber = 0; keyNumber < PTHREAD_KEYS_MAX; keyNumber++)
   239         {
   240             int temp;
   241             temp = keyNumber / 32;
   242             
   243             int bitPos;
   244             bitPos = keyNumber % 32;
   245         
   246             if (((glbPtr->statusflag[temp]) & (0x1<<bitPos)) &&      //Key used
   247                 (glbPtr->pthread_key_list[keyNumber].destr != NULL))
   248             {
   249                 if ((arg = _getKeyValueSetNull(keyNumber,selfNodePtr->tlsHead)) != NULL)
   250                 {
   251                     dest = glbPtr->pthread_key_list[keyNumber].destr;
   252                 
   253                     selfNodePtr->lockNode.Signal();    // Unlock TCB node
   254                     glbPtr->lockThreadTable.Signal();  // release thread table lock
   255 
   256                     dest(arg);  //Call destructor
   257 
   258                     glbPtr->lockThreadTable.Wait();// Acquire the thread table lock
   259                     selfNodePtr->lockNode.Wait();      // Lock the TCB
   260                     
   261                     allempty = 1;   // Atleast one key was used
   262                 }
   263             }
   264         }
   265     }
   266     
   267     selfNodePtr->lockNode.Signal();    // Unlock TCB node
   268     glbPtr->lockThreadTable.Signal();  // release thread table lock
   269 }
   270 
   271 // End of File