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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // Name : pthreadmisc.cpp
15 // Part of : PThread library
16 // Thread Miscellaneous functions are implemented in this file.
26 #include "threadglobals.h"
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
34 class XPthreadTLSCleanup
43 // Create a global here. It's desctructor invoked on libpthread unload will reset libpthread's TLS
44 XPthreadTLSCleanup gPthreadTLSCleanup;
47 int _copy_already_defined_keys(_pthread_node_t* prev_node, _pthread_node_t* new_node);
50 // return : NULL - means no memory
51 void* _pthread_getTls()
53 _pthread_node_t *selfNodePtr;
54 _global_data_t *glbPtr = glbHeadNode;
56 THR_PRINTF("[pthread] Begin _pthread_getTls\n");
57 // Get the TLS contents.
58 TAny *tlsAddr = Dll::Tls();
60 // If TLS is already initialised then just return the node address
63 THR_PRINTF("[pthread] End _pthread_getTls\n");
64 return ((void*) tlsAddr);
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");
73 selfNodePtr->next = NULL;
74 if (selfNodePtr->lockNode.CreateLocal() != KErrNone)
77 THR_PRINTF("[pthread] FATAL :Mutex create failed");
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
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))
97 THR_PRINTF("[pthread] FATAL :failed copying defined keys");
99 glbPtr->lockThreadTable.Signal();
102 selfNodePtr->next = glbPtr->start;
104 glbPtr->start = selfNodePtr;
105 glbPtr->threadCount++;
107 glbPtr->lockThreadTable.Signal();
109 //Set node address to TLS
110 Dll::SetTls((TAny*)selfNodePtr);
111 THR_PRINTF("[pthread] End _pthread_getTls\n");
113 // libc needs to know whether application is multithreaded or not...
116 return ((void*) selfNodePtr);
119 int _copy_already_defined_keys(_pthread_node_t* prev_node, _pthread_node_t* new_node)
121 if(!prev_node || !new_node)
124 _pkey_node_t *tlsPtr;
125 _pkey_node_t *newTlsPtr, *prevTlsPtr=NULL;
126 for (tlsPtr = prev_node->tlsHead; tlsPtr != NULL; tlsPtr = tlsPtr->next)
128 newTlsPtr = new _pkey_node_t;
129 if (NULL == newTlsPtr)
133 if(new_node->tlsHead == NULL)
134 new_node->tlsHead = newTlsPtr;
136 prevTlsPtr->next = newTlsPtr;
138 newTlsPtr->tls = NULL;
139 newTlsPtr->keyNumber = tlsPtr->keyNumber;
140 prevTlsPtr = newTlsPtr;
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,
152 _pthread_node_t *tempPtr;
153 _pthread_node_t *prevPtr = NULL;
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)
161 prevPtr = tempPtr; // Store the previous node ptr
164 if (NULL == tempPtr) //Not found; this should never happen
166 THR_PRINTF("[pthread] FATAL: Unable to delete the node");
167 selfNodePtr->lockNode.Signal();
168 glbPtr->lockThreadTable.Signal(); //release global lock
171 if (tempPtr == glbPtr->start) // Deleting first node
173 glbPtr->start = tempPtr->next; //Update the link list
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
182 if (NULL != retValPtr) // Get the return value
184 *retValPtr = selfNodePtr->returnValue;
187 selfNodePtr->lockNode.Signal(); // Unlock & Free the node
188 selfNodePtr->lockNode.Close();
189 selfNodePtr->rtHandle.Close();
193 //--(glbPtr->threadCount); // Update the thread count
194 //if (THREAD_COUNT_ZERO == glbPtr->threadCount)
197 // rp.Kill(0); // Terminate the process
200 glbPtr->lockThreadTable.Signal(); // release thread table lock
201 THR_PRINTF("[pthread] End of _pthread_deleteNode\n");
205 void* _getKeyValueSetNull(int keyNumber,_pkey_node_t *tlsPtr)
208 for ( ; tlsPtr != NULL; tlsPtr = tlsPtr->next)
210 if (tlsPtr->keyNumber == keyNumber)
212 retVal = tlsPtr->tls;
217 //This should never happen; hence dest function will not be called
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)
227 destructor_routine dest;
230 glbPtr->lockThreadTable.Wait(); // Acquire the thread table lock
231 selfNodePtr->lockNode.Wait(); // Lock the TCB
233 for (loopvar = 0, allempty = 1;
234 allempty && (loopvar < PTHREAD_DESTRUCTOR_ITERATIONS);loopvar++)
236 allempty = 0; // Assuming all keys are not used.
238 for (keyNumber = 0; keyNumber < PTHREAD_KEYS_MAX; keyNumber++)
241 temp = keyNumber / 32;
244 bitPos = keyNumber % 32;
246 if (((glbPtr->statusflag[temp]) & (0x1<<bitPos)) && //Key used
247 (glbPtr->pthread_key_list[keyNumber].destr != NULL))
249 if ((arg = _getKeyValueSetNull(keyNumber,selfNodePtr->tlsHead)) != NULL)
251 dest = glbPtr->pthread_key_list[keyNumber].destr;
253 selfNodePtr->lockNode.Signal(); // Unlock TCB node
254 glbPtr->lockThreadTable.Signal(); // release thread table lock
256 dest(arg); //Call destructor
258 glbPtr->lockThreadTable.Wait();// Acquire the thread table lock
259 selfNodePtr->lockNode.Wait(); // Lock the TCB
261 allempty = 1; // Atleast one key was used
267 selfNodePtr->lockNode.Signal(); // Unlock TCB node
268 glbPtr->lockThreadTable.Signal(); // release thread table lock