genericopenlibs/openenvcore/libpthread/src/pthread_key_delete.cpp
changeset 0 e4d67989cc36
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/genericopenlibs/openenvcore/libpthread/src/pthread_key_delete.cpp	Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,132 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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:
+// Name     : pthread_key_delete.cpp
+// Part of  : PThread library
+// pthread_key_delete call is implemented.
+// Version:
+//
+
+
+
+#include <pthread.h>
+#include <errno.h>
+#include "threadglobals.h"
+#include "pthreadmisc.h"
+
+static int _deleteKeyInAllThreads(_global_data_t *glbPtr, int keyNumber)
+{
+    _pthread_node_t *temp;
+    _pkey_node_t *tlsPtr;
+    _pkey_node_t *prevTlsPtr;
+    
+    //For all threads
+    for (temp = glbPtr->start; temp != NULL; temp = temp->next) 
+    {
+        // Lock the TCB
+        temp->lockNode.Wait();
+
+        // Delete in a sorted list
+        for (tlsPtr = temp->tlsHead, prevTlsPtr = NULL; 
+             tlsPtr != NULL; 
+             prevTlsPtr = tlsPtr,tlsPtr = tlsPtr->next)
+        {
+            if (tlsPtr->keyNumber == keyNumber)
+            {
+                if (temp->tlsHead == tlsPtr) //first node case
+                {
+                    temp->tlsHead = tlsPtr->next;
+                    delete tlsPtr;
+                    break; // Inner loop
+                }
+                else
+                {
+                    prevTlsPtr->next = tlsPtr->next;
+                    delete tlsPtr;
+                    break;  //Inner loop
+                }
+
+            }
+            
+        } // Inner for loop end...
+        
+        if (tlsPtr == NULL) // Means not found
+        {
+            // This should never happen; key to be deleted not exists
+            temp->lockNode.Signal();
+            User::Panic(_L("Invalid Key"),0);
+            return -1;            
+        }
+
+        // Unlock TCB node
+        temp->lockNode.Signal();
+    } // end of outer for loop
+    
+    return 0;
+}
+
+EXPORT_C int pthread_key_delete(pthread_key_t key)
+{
+    _global_data_t *glbPtr;
+    _pthread_node_t *selfNodePtr;
+        
+    THR_PRINTF("[pthread] Begin pthread_key_delete\n");
+    
+    if (key >= PTHREAD_KEYS_MAX)
+    {
+        THR_PRINTF("[pthread] End pthread_key_delete\n");
+        return EINVAL;
+    }
+        
+    //Get the TLS value (self node pointer)
+    selfNodePtr = (_pthread_node_t*) _pthread_getTls();
+	//coverity[var_compare_op]
+    if (NULL == selfNodePtr)    // This should never happen
+    {
+        THR_PRINTF("[pthread] FATAL :TLS is not initialized \n");
+        THR_PRINTF("[pthread] Terminating the process\n");
+        RProcess rp;
+        rp.Kill(0);                // Terminate the process
+    }
+    
+	//coverity[var_deref_op]
+    glbPtr = selfNodePtr->glbDataPtr;  // point to global struct
+    glbPtr->lockThreadTable.Wait();    // Acquire the thread table lock
+
+    int idx;
+    idx = key / 32;
+    
+    int bitPos;
+    bitPos = key % 32;
+    
+    if (((glbPtr->statusflag[idx]) & (0x1<<bitPos)) == _KEY_UNUSED)
+    {
+        THR_PRINTF("[pthread] End pthread_key_delete\n");
+        glbPtr->lockThreadTable.Signal();  // release thread table lock
+        return EINVAL;
+    }
+    
+    glbPtr->statusflag[idx] &= ~(0x1<<bitPos);  // Set it to unused. 
+    glbPtr->pthread_key_list[key].destr = NULL;    
+    
+    // Delete the key in all the threads
+    _deleteKeyInAllThreads(glbPtr, key);
+    
+    glbPtr->lockThreadTable.Signal();  // release thread table lock
+    
+    THR_PRINTF("[pthread] End pthread_key_delete\n");
+    return 0;
+    
+}
+
+// End of file