00001 // Copyright (c) 2000, Compaq Computer Corporation 00002 // Copyright (C) 2001, Compaq Computer Corporation 00003 // 00004 // This file is part of Vesta. 00005 // 00006 // Vesta is free software; you can redistribute it and/or 00007 // modify it under the terms of the GNU Lesser General Public 00008 // License as published by the Free Software Foundation; either 00009 // version 2.1 of the License, or (at your option) any later version. 00010 // 00011 // Vesta is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 // Lesser General Public License for more details. 00015 // 00016 // You should have received a copy of the GNU Lesser General Public 00017 // License along with Vesta; if not, write to the Free Software 00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 00020 // File: ThreadData.C 00021 00022 #include "ThreadData.H" 00023 #include <pthread.h> 00024 00025 using Basics::OBufStream; 00026 00027 static pthread_key_t threadDataKey; 00028 00029 Basics::mutex ThreadData::mu; 00030 ThreadData* ThreadData::head; 00031 00032 extern "C" 00033 { 00034 static void 00035 ThreadDataDelete(void* vdata) 00036 { 00037 ThreadData* data = (ThreadData*) vdata; 00038 ThreadData::mu.lock(); 00039 if (data->prev) { 00040 data->prev->next = data->next; 00041 } else { 00042 data->head = data->next; 00043 } 00044 if (data->next) { 00045 data->next->prev = data->prev; 00046 } 00047 if(recordCallStack) { 00048 assert(data->callStack != NULL); 00049 delete data->callStack; 00050 data->callStack = NULL; // help out the garbage collector 00051 } else { 00052 assert(data->callStack == NULL); 00053 } 00054 delete data; 00055 ThreadData::mu.unlock(); 00056 } 00057 } 00058 00059 // Create thread-specific data for the current thread 00060 ThreadData* 00061 ThreadDataCreate(int id, CacheEntry::IndicesApp *threadCIs) 00062 { 00063 ThreadData* data = (ThreadData*) pthread_getspecific(threadDataKey); 00064 if (data) ThreadDataDelete(data); 00065 data = NEW(ThreadData); 00066 data->id = id; 00067 data->funcCallDepth = -1; 00068 assert(threadCIs != 0); 00069 data->orphanCIs = threadCIs; 00070 data->traceRes = NULL; 00071 if (recordCallStack) { 00072 data->callStack = NEW(Exprs); 00073 } else { 00074 data->callStack = NULL; 00075 } 00076 data->parent = NULL; 00077 data->parentCallStackSize = 0; 00078 pthread_setspecific(threadDataKey, (void*) data); 00079 ThreadData::mu.lock(); 00080 data->prev = NULL; 00081 if (data->head) data->head->prev = data; 00082 data->next = data->head; 00083 data->head = data; 00084 ThreadData::mu.unlock(); 00085 return data; 00086 } 00087 00088 // Get thread-specific data for the current thread 00089 ThreadData* 00090 ThreadDataGet() 00091 { 00092 return (ThreadData*) pthread_getspecific(threadDataKey); 00093 } 00094 00095 // Initialize module. Must call from main thread. 00096 void 00097 ThreadDataInit() 00098 { 00099 pthread_key_create(&threadDataKey, ThreadDataDelete); 00100 ThreadData* thdata = ThreadDataCreate(0, NEW(CacheEntry::IndicesApp)); 00101 if (recordTrace) { 00102 thdata->traceRes = NEW(OBufStream); 00103 } 00104 }